用intent進行包內的IPC跨進程通信 by 高煥堂

本文來自人人網android開發交流羣

在Android裏,一個Package可以含有多個Activity,這些Activity可以在同一個進程(Process)裏執行;也可以在不同的進程裏執行。基於linux的安全限制,以及進程的基本特性(例如,不同進程的地址空間是獨立的),Activity-a與Activity-b在同一個進程裏執行時,兩者溝通方便也快速。但是,當Activity-a與Activity-b分別在不同的進程裏執行時,兩者溝通就屬於IPC跨進程溝通了,不如前者方便,也慢些。例如:

# package xom.misoo.pkzz;   
# import android.app.Activity;   
# import android.content.Intent;   
# import android.os.Bundle;   
# import android.view.View;   
# import android.view.View.OnClickListener;   
# import android.widget.Button;   
# import android.widget.LinearLayout;   
#   
# public class ac01 extends Activity implements OnClickListener {   
#     private Button btn, btn4;   
#     public static ac01 appRef = null;   
#     private String feedback_data;   
#            
#     @Override  
#     public void onCreate(Bundle savedInstanceState) {   
#         super.onCreate(savedInstanceState);   
#         appRef = this;   
#         setContentView(R.layout.main);   
#         this.show_layout_01();   
#         }   
#     @Override  
#     public void onResume(){   
#         super.onResume();   
#         setTitle(feedback_data);   
#     }   
#     void show_layout_01(){   
#         LinearLayout layout = new LinearLayout(this);   
#         layout.setOrientation(LinearLayout.VERTICAL);   
#     
#         btn = new Button(this);   
#         btn.setBackgroundResource(R.drawable.water);   
#         btn.setText("Edit");   
#         btn.setOnClickListener(this);   
#         LinearLayout.LayoutParams param = new LinearLayout.LayoutParams(150, 40);   
#         param.topMargin = 5;   
#         layout.addView(btn, param);   
#                  
#         btn4 = new Button(this);   
#         btn4.setBackgroundResource(R.drawable.face);   
#         btn4.setText("Exit");   
#         btn4.setOnClickListener(this);   
#         layout.addView(btn4, param);   
#         setContentView(layout);    
#     }   
#     public void setData(String x){   
#         feedback_data = x;   
#     }   
#     public void onClick(View v){   
#           if (v == btn){   
#                 Intent intent = new Intent(this, Activity_1.class);   
#                 this.startActivity(intent);   
#             }   
#           if(v.equals(btn4))   
#                this.finish();   
#      }   
# }       
#   
#   
#   
# package xom.misoo.pkzz;   
# import android.app.Activity;   
# import android.os.Bundle;   
# import android.view.View;   
# import android.view.View.OnClickListener;   
# import android.widget.Button;   
# import android.widget.LinearLayout;   
#   
# public class Activity_1 extends Activity implements OnClickListener {   
#     private Button btn;   
#     @Override  
#     public void onCreate(Bundle icicle) {   
#         super.onCreate(icicle);   
#         LinearLayout layout = new LinearLayout(this);   
#         layout.setOrientation(LinearLayout.VERTICAL);   
#     
#         btn = new Button(this);   
#         btn.setBackgroundResource(R.drawable.music);   
#         btn.setText("Edit");   
#         btn.setOnClickListener(this);   
#         LinearLayout.LayoutParams param = new LinearLayout.LayoutParams(150, 40);   
#         param.topMargin = 5;   
#         layout.addView(btn, param);   
#         setContentView(layout);   
#         ac01.appRef.setData("feedback from Activity_1.");   
#     }   
#     public void onClick(View arg0) {   
#         finish();   
#     }   
# }   

其 中的指令:ac01.appRef.setData("feedback from Activity_1.");只有ac01與Activity_1兩者都在同一個地址空間(即進程)纔會有效。如果將AndroidManifest.xml裏的<Activity>敘述修改爲:
<activity android:name=".Activity_1" android:process=":remote">
         <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                 <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>

其令Activity_1在獨立的進行裏執行,則上述指令:ac01.appRef.setData("feedback fromActivity_1."); 就不對了。
   那麼,這種跨進程的情形下,該如何溝通呢?

   使用SharedPreference

可以使用:
import android.content.SharedPreferences.Editor;

於是,可在Activity_1裏撰寫指令如下:

# public class Activity_1 extends Activity implements OnClickListener {   
#     private Button btn;   
#     @Override  
#     public void onCreate(Bundle icicle) {   
#         super.onCreate(icicle);   
#         …………………(省略)   
#         Editor passwdfile = getSharedPreferences("ITEM", 0).edit();    
#         passwdfile.putString("ITEM","feedback from Activity_1.");    
#         passwdfile.commit();   
#     }   
#     …………………(省略)   
# } 
並且,在ac01裏撰寫指令如下:  
# public class ac01 extends Activity implements OnClickListener {   
#    ………………………   
# @Override  
#     public void onCreate(Bundle savedInstanceState) {   
#         super.onCreate(savedInstanceState);   
#          ………………………   
#         }   
#     @Override  
#     public void onResume(){   
#         super.onResume();   
#            SharedPreferences passwdfile = getSharedPreferences(    
#                       "ITEM", 0);    
#            String im = passwdfile.getString("ITEM", null);    
#             setTitle(im);   
#         }   
#     …………………………   
# }      
這樣就能Activity_1就能將數據傳遞給ac01了。  
上述的ac01類別還可寫爲: 
# public class ac01 extends Activity implements OnClickListener {   
#      ……………………   
#     @Override  
#     public void onCreate(Bundle savedInstanceState) {   
#         super.onCreate(savedInstanceState);   
#          ……………………   
#         }   
#       ………………………   
#      @Override  
#      protected void onActivityResult(int requestCode, int resultCode, Intent data)   
#         {   
#          SharedPreferences passwdfile = getSharedPreferences(    
#                  "ITEM", 0);    
#          String im = passwdfile.getString("ITEM", null);    
#          setTitle(im);   
#         }   
#   
#     public void onClick(View v){   
#              ……………………   
#                Intent intent = new Intent(Intent.ACTION_EDIT, null);   
#                 this.startActivityForResult(intent, 0);   
#              ……………………   
#             }   
#         }     

 這兩寫法一樣都能讓Activity_1傳回數據。
  
   使用Intent對象

雖然透過Intent並非最快速,但卻是最有彈性的。無論是同一進程或是跨進程的溝通都可以使用它。例如:

# package com.misoo.pkzz;   
# import android.app.Activity;   
# import android.content.Intent;   
# import android.content.SharedPreferences;   
# import android.os.Bundle;   
# import android.view.View;   
# import android.view.View.OnClickListener;   
# import android.widget.Button;   
# import android.widget.LinearLayout;   
#   
# public class ac01 extends Activity implements OnClickListener {   
#     private Button btn, btn2, btn4;   
#     public static ac01 appRef = null;   
#     private final static String KKK = "AnyKey";    
#        
#     @Override  
#     public void onCreate(Bundle savedInstanceState) {   
#         super.onCreate(savedInstanceState);   
#         appRef = this;   
#         setContentView(R.layout.main);   
#         this.show_layout_01();   
#         }   
#     void show_layout_01(){   
#         LinearLayout layout = new LinearLayout(this);   
#         layout.setOrientation(LinearLayout.VERTICAL);   
#     
#         btn = new Button(this);   
#         btn.setBackgroundResource(R.drawable.water);   
#         btn.setText("Edit");   
#         btn.setOnClickListener(this);   
#         LinearLayout.LayoutParams param = new LinearLayout.LayoutParams(150, 40);   
#         param.topMargin = 5;   
#         layout.addView(btn, param);   
#            
#         btn2 = new Button(this);   
#         btn2.setBackgroundResource(R.drawable.x_blue);   
#         btn2.setText("shared data");   
#         btn2.setOnClickListener(this);   
#         layout.addView(btn2, param);   
#            
#         btn4 = new Button(this);   
#         btn4.setBackgroundResource(R.drawable.face);   
#         btn4.setText("Exit");   
#         btn4.setOnClickListener(this);   
#         layout.addView(btn4, param);   
#         setContentView(layout);    
#     }   
#      @Override  
#      protected void onActivityResult(int requestCode, int resultCode, Intent data)   
#         {   
#          SharedPreferences passwdfile = getSharedPreferences(    
#                  "ITEM", 0);    
#          String im = passwdfile.getString("ITEM", null);    
#          setTitle(im);   
#         }   
#   
#     public void onClick(View v){   
#           if (v == btn){   
#                 Intent intent = new Intent(Intent.ACTION_VIEW, null);   
#                 intent.putExtra(com.misoo.pkzz.ac01.KKK, "Ax004::Intent Extra Msg.");   
#                 this.startActivityForResult(intent, 0);   
#             }   
#           if(v.equals(btn2)){   
#               SharedPreferences passwdfile = getSharedPreferences(    
#                         "ITEM", 0);    
#               String im = passwdfile.getString("ITEM", null);    
#               setTitle(im);   
#           }   
#           if(v.equals(btn4))   
#                this.finish();   
#      }   
# }       
#   
#   
#   
# package com.misoo.pkzz;   
# import android.app.Activity;   
# import android.content.SharedPreferences.Editor;   
# import android.os.Bundle;   
# import android.view.View;   
# import android.view.View.OnClickListener;   
# import android.widget.Button;   
# import android.widget.LinearLayout;   
#   
# public class Activity_1 extends Activity implements OnClickListener {   
#     private Button btn;   
#     @Override  
#     public void onCreate(Bundle icicle) {   
#         super.onCreate(icicle);   
#         LinearLayout layout = new LinearLayout(this);   
#         layout.setOrientation(LinearLayout.VERTICAL);   
#     
#         btn = new Button(this);   
#         btn.setBackgroundResource(R.drawable.x_yellow);   
#         btn.setText("Edit");   
#         btn.setOnClickListener(this);   
#         LinearLayout.LayoutParams param = new LinearLayout.LayoutParams(150, 40);   
#         param.topMargin = 5;   
#         layout.addView(btn, param);   
#         setContentView(layout);   
#         //-----------------------------------   
#         String ss = this.getIntent().getStringExtra("AnyKey");   
#         //-----------------------------------   
#         Editor passwdfile = getSharedPreferences("ITEM", 0).edit();    
#         passwdfile.putString("ITEM",ss);    
#         passwdfile.commit();   
#        
#     }   
#   
#     public void onClick(View arg0) {   
#         finish();   
#     }   
# }   
#   
#   
#   
# <?xml version="1.0" encoding="utf-8"?>   
# <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
#       package="com.misoo.pkzz"  
#       android:versionCode="1"  
#       android:versionName="1.0.0">   
#     <application android:icon="@drawable/icon" android:label="@string/app_name">   
#         <activity android:name=".ac01"  
#                   android:label="@string/app_name">   
#             <intent-filter>   
#                 <action android:name="android.intent.action.MAIN" />   
#                 <category android:name="android.intent.category.LAUNCHER" />   
#             </intent-filter>   
#         </activity>   
#         <activity android:name=".Activity_1" android:process=":remote">   
#          <intent-filter>   
#                 <action android:name="android.intent.action.VIEW" />   
#                  <category android:name="android.intent.category.DEFAULT" />   
#             </intent-filter>   
#         </activity>   
#     </application>   
# </manifest>   

這ac01透過Intent傳遞數據給Activity_1,而Activity_1則將之存入SharePreferences裏,再回傳給ac01類別。


摘錄結語

上述談到的情境是:
  其ac01與Activity_1屬於同一個Package。
  其ac01與Activity_1 在同一個進程裏執行,或者,各再獨立的進程裏執行。

然而,如果ac01與Activity_1分別屬於不同的Package時,又如何呢?此時,就不能藉由SharePreferences來傳遞數據了,因爲SharePreferences是屬於某Package內的。至於IPC的詳細溝通法,由另外的文章說明之



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章