用intent进行包内的IPC跨进程通信 by 高焕堂

来源:互联网 发布:python黑客论坛 编辑:程序博客网 时间:2024/05/17 09:13
本文来自人人网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的详细沟通法,由另外的文章说明之