Android软件开发之应用程序之间的通信介绍(十八)

139
回复
1157500
查看
  [复制链接]

249

主题

278

帖子

17

安币

初级码农

Rank: 1

发表于 2011-9-3 00:28:57 | 显示全部楼层 |阅读模式
Android软件开发之应用程序之间的通信介绍


Android 开发中在程序之间通讯的接口做的还是非常丰富的 本例主要向大家介绍程序之间是如何进行沟通,有哪几种沟通方式 如何来实现沟通。

1.使用handler传递消息

        handler 大家可以把它想象成主线程(UI线程)的一个子线程,它可以给主线程(UI线程)发送数据从而更新主线程(UI线程)的UI与逻辑,handler 是一个子线程所以它的耗时操作不会阻塞主线程,大家都知道在android的开发中如果代码中某个地方阻塞主线程超过5秒的话系统会提示ANR (系统提示强制关闭)所以在耗时操作上我们可以考虑开启一个子线程避免ANR。  handler会向主线程发送消息 会以队列的形式排列着配合等待主线程更新UI 逻辑 等等。


下面这个例子诠释了这一点 利用handler传递消息来更新主线程的UI显示内容 点击按钮后每过一秒通过handler发送消息更新UI线程显示的时间 直到显示时间更新到10 然后结束这个线程。
  1. public class HandlerActivity extends Activity implements Runnable{

  2.     /**更新时间**/
  3.     public final static int UPDATE_TIME =0;
  4.     /**更新时间成功**/
  5.     public final static int UPDATE_COMPLETED =1;
  6.    
  7.     /**记录显示时间 超过10秒结束线程**/
  8.     private int mShowNumber = 0;
  9.    
  10.     /**开始计时按钮**/
  11.     private Button mButton = null;
  12.    
  13.     /**计时显示内容**/
  14.     private TextView mTextView = null;
  15.    
  16.     /**线程**/
  17.     private Thread mThread = null;
  18.    
  19.     /**线程关闭的标志**/
  20.     private boolean mRunning = false;
  21.    
  22.     Handler handler = new Handler() {
  23.         @Override
  24.         public void handleMessage(Message msg) {
  25.             
  26.             Bundle bundle= msg.getData();
  27.             //通过key的名称拿到它的值
  28.             String  number = bundle.getString("number");
  29.             //msg.what为handler接收到的消息编号
  30.             switch(msg.what) {
  31.             case UPDATE_TIME:
  32.                 mTextView.setText("正在更新时间" + number);
  33.                 break;
  34.             case UPDATE_COMPLETED:
  35.                 mTextView.setText("更新完毕");
  36.                 break;
  37.             }
  38.             super.handleMessage(msg);
  39.         }
  40.     };

  41.     @Override
  42.     protected void onCreate(Bundle savedInstanceState) {
  43.         setContentView(R.layout.handler);
  44.        
  45.         /**拿到button 与  TextView 对象**/
  46.         mButton = (Button)findViewById(R.id.button0);
  47.         mTextView = (TextView)findViewById(R.id.textView0);
  48.         mThread = new Thread(this);
  49.        
  50.         mButton.setOnClickListener(new OnClickListener() {
  51.             @Override
  52.             public void onClick(View arg0) {
  53.                 /**点击按钮后开始线程开始计时**/
  54.                 mRunning = true;
  55.                 mThread.start();
  56.             }
  57.         });
  58.        
  59.         mTextView.setText("点击按钮开始更新时间");
  60.         super.onCreate(savedInstanceState);
  61.     }

  62.     public void ShowDialog(String string) {
  63.         AlertDialog.Builder builder = new AlertDialog.Builder(
  64.                 HandlerActivity.this);
  65.         builder.setIcon(R.drawable.icon);
  66.         builder.setTitle(string);
  67.         builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
  68.             public void onClick(DialogInterface dialog, int whichButton) {
  69.                 finish();
  70.             }
  71.         });
  72.         builder.show();
  73.     }



  74.     @Override
  75.     public void run() {

  76.         while (mRunning) {
  77.             try {
  78.                 mShowNumber++;
  79.                 /** 把须要的数据放入bandle中 **/
  80.                 Bundle bandle = new Bundle();
  81.                 bandle.putString("number", String.valueOf(mShowNumber));

  82.                 /** 设置这条信息的编号为更新时间 **/
  83.                 /** 将bandle写入message中 **/
  84.                 /** 最后将这个message发送出去 **/
  85.                 /** mShowNumber小于10更新时间 否则更新完毕 **/
  86.                 Message msg = new Message();
  87.                 if(mShowNumber <=10) {
  88.                     msg.what = UPDATE_TIME;
  89.                 }else {
  90.                     mRunning = false;
  91.                     msg.what = UPDATE_COMPLETED;  
  92.                 }
  93.                 msg.setData(bandle);
  94.                 handler.sendMessage(msg);
  95.                 Thread.sleep(1000);
  96.             } catch (InterruptedException e) {
  97.                 e.printStackTrace();
  98.             }
  99.         }
  100.     }
  101. }
复制代码
2.Notifation通知栏信息
       Notifation通知栏会在屏幕上方向用户提示信息 但是不会打断用户正在阅读的内容,除非用户手动将 Notifation通知栏拉下。 Notifation的好处就是在于不会影响用户的操作,比如用户正在阅读非常重要的信息这时候帮他直接打开一个activity会非常不合适 因为直接影响到了他当时的操作行为 所以Notifation就出来了。建议大家在开发中遇到可能打断用户使用的情况下都去使用Notifation通知栏。



屏幕上方为弹出的Notifation通知栏



将Notifation通知栏拉下后会出现相应的信息
  1. public class NotificationActivity extends Activity {
  2.     NotificationManager mManager = null;
  3.     Notification notification =null;
  4.     @Override
  5.     protected void onCreate(Bundle savedInstanceState) {
  6.         setContentView(R.layout.notification);

  7.         // 得到通知消息的管理器对象,负责管理 Notification 的发送与清除消息等
  8.         mManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
  9.         // 创建Notification对象 参数分别代表 通知栏 中显示的图标 显示的标题 显示的时间
  10.         notification = new Notification(R.drawable.jay,
  11.                 "Android专业开发群", System.currentTimeMillis());
  12.        
  13.         // 设置在通知栏中点击后Notification自动消失
  14.         notification.flags = Notification.FLAG_AUTO_CANCEL;
  15.        
  16.         //设置点击后转跳的新activity
  17.         Intent intent = new Intent(this, MyShowActivity.class);
  18.         intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP| Intent.FLAG_ACTIVITY_NEW_TASK);

  19.         //通过bundle可以带一些数据过去 这里将字符串传递了过去
  20.         Bundle bundle = new Bundle();
  21.         bundle.putString("name", "从Notification转跳过来的");
  22.         intent.putExtras(bundle);
  23.        
  24.         //设置通知栏中显示的内容
  25.         PendingIntent contentIntent = PendingIntent.getActivity(this,
  26.                 R.string.app_name, intent, PendingIntent.FLAG_UPDATE_CURRENT);
  27.         notification.setLatestEventInfo(this, "Android专业开发群",
  28.                 "QQ群号 164257885", contentIntent);
  29.        

  30.         Button button0 = (Button)findViewById(R.id.button0);
  31.         button0.setOnClickListener(new OnClickListener() {
  32.             
  33.             @Override
  34.             public void onClick(View arg0) {
  35.                 //打开这个Notification通知
  36.                 mManager.notify(0, notification);
  37.             }
  38.         });
  39.        
  40.         Button button1 = (Button)findViewById(R.id.button1);
  41.         button1.setOnClickListener(new OnClickListener() {
  42.             
  43.             @Override
  44.             public void onClick(View arg0) {
  45.                 //关闭这个Notification通知
  46.                 mManager.cancelAll();
  47.             }
  48.         });
  49.        
  50.         super.onCreate(savedInstanceState);
  51.     }

  52. }
复制代码
3.广播的发送与接收

Android开发中如果须要对两个完全没关系的程序之间进行通信 就可以使用发送广播与接收广播的机制来实现 ,例如程序A发送了一个广播 程序B接受到 做一些事情 这样就达到了相互的通讯。

调用sendBroadcast() 传入intent  后 来发送广播
  1. public class BroadcastActivity extends Activity {


  2.    
  3.     Button mButton0 = null;
  4.     Button mButton1 = null;

  5.     @Override
  6.     protected void onCreate(Bundle savedInstanceState) {
  7.         setContentView(R.layout.broadcast);
  8.        
  9.         mButton0 = (Button)findViewById(R.id.button0);
  10.         mButton0.setOnClickListener(new OnClickListener() {
  11.             
  12.             @Override
  13.             public void onClick(View arg0) {
  14.                 Intent intent = new Intent(MyService.SEND_OK_MESSAGE);
  15.                 intent.putExtra("name", "您发送了OK这条广播哦");
  16.                 sendBroadcast(intent);
  17.             }
  18.         });

  19.         mButton1 = (Button)findViewById(R.id.button1);
  20.         mButton1.setOnClickListener(new OnClickListener() {
  21.             
  22.             @Override
  23.             public void onClick(View arg0) {
  24.                 Intent intent = new Intent(MyService.SEND_CANCLE_MESSAGE);
  25.                 intent.putExtra("name", "您发送了Cancle这条广播哦");
  26.                 sendBroadcast(intent);
  27.             }
  28.         });
  29.        
  30.         //启动Service
  31.         Intent i = new Intent(this, MyService.class);
  32.         startService(i);
  33.         super.onCreate(savedInstanceState);
  34.     }
  35. }
复制代码
接收广播的话 我们开启一个service 在service中通过BroadcastReceiver 来接收广播 前提是须要接收的广播须要在onStart()中注册一下 在AndroidManifest.xml中可以过滤只接收须要接收的广播、
  1.                 <service android:name=".MyService">
  2.                         <intent-filter>
  3.                                 <action android:name="cn.m15.xys.MyService"></action>
  4.                         </intent-filter>
  5.                         <intent-filter>
  6.                                 <action android:name="send.ok.message" />
  7.                                 <action android:name="send.cancle.message" />
  8.                         </intent-filter>
  9.                 </service>
复制代码
在onStart()中注册了程序中所需要的两个广播
  1. public class MyService extends Service {

  2.     public final static String SEND_OK_MESSAGE = "send.ok.message";
  3.     public final static String SEND_CANCLE_MESSAGE = "send.cancle.message";
  4.    
  5.     private BroadcastReceiver myBroadCast = new BroadcastReceiver() {

  6.         @Override
  7.         public void onReceive(Context context, Intent intent) {
  8.             String action = intent.getAction();
  9.             if (action.equals(SEND_OK_MESSAGE)) {
  10.                 Toast.makeText(context, "接收到了一条广播为" + SEND_OK_MESSAGE, Toast.LENGTH_LONG).show();
  11.             }else if(action.equals(SEND_CANCLE_MESSAGE)) {
  12.                 Toast.makeText(context, "接收到了一条广播为" + SEND_CANCLE_MESSAGE, Toast.LENGTH_LONG).show();
  13.             }
  14.         }

  15.     };

  16.     @Override
  17.     public void onCreate() {
  18.         super.onCreate();
  19.     }

  20.     @Override
  21.     public void onStart(Intent intent, int startId) {
  22.         //注册这两个广播
  23.         IntentFilter myFilter = new IntentFilter();
  24.         myFilter.addAction(SEND_OK_MESSAGE);
  25.         myFilter.addAction(SEND_CANCLE_MESSAGE);
  26.         this.registerReceiver(myBroadCast, myFilter);
  27.         super.onStart(intent, startId);
  28.     }
  29.     @Override
  30.     public IBinder onBind(Intent arg0) {
  31.         return null;
  32.     }

  33. }
复制代码
这里注意一下 service如果没有起来 我们是接收不到广播的 所以一定要保证接收的时候service是开启的,上例中的service是在打开activity时开启的 但是如果用户把手机关掉然后在开机 , 这样的话service就不是打开状态 这样就非常危险了因为这时scrvice就接收不到任何消息了除非用户再次进activity 才会帮他打开scrvice 所以我们可以在用户开机后就直接将scrvice打开,具体的实现方式如下

在AndroidManifest.xml中注册一个开机广播  这个广播系统只会在开机发出而且只会发出一次 所以我们接收这个广播就可以知道手机是否为开机状态
  1.         <receiver android:name=".MyBootReceiver" >
  2.        <intent-filter>
  3.           <action android:name="android.intent.action.BOOT_COMPLETED" />
  4.       </intent-filter>
  5.     </receiver>
复制代码
注意加入权限
  1.         <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
复制代码
在BroadcastRecevier中接收开机广播  然后打开service 就可以实现开机启动service。
  1. public class MyBootReceiver extends BroadcastReceiver {
  2.    /**开机广播**/
  3.     static final String BOOT_COMPLETED = "android.intent.action.BOOT_COMPLETED";

  4.     @Override
  5.     public void onReceive(Context context, Intent intent) {
  6.         /**如果为开机广播则开启service**/
  7.         if (intent.getAction().equals(BOOT_COMPLETED)) {
  8.             Intent i = new Intent(context, MyService.class);
  9.             context.startService(i);
  10.         }

  11.     }
  12. }
复制代码
3.Activity与Activity之间的转跳

在软件应用的开发中肯定会有多个Activity     这样它们之间就会存在相互转跳的关系      转跳的实现方式还是使用Intent  然后startActivity  ,当然转跳的话是可以带数据过去的。比如从A跳到B 可以把A中的一些数据通过Intent传递给B 。

       读下面这段代码 大家会发现intent与bandle 传递数值的方式基本一样为什么还要分成两个呢? 确实他们两个传递的数值的方式非常类似, 他们两个的区别就是Intent属于把零散的数据传递过去 而bundle则是把零散的数据先放入bundle 然后在传递过去。我举一个例子 比如我们现在有3个activity  A.B.C  须要把A的数据穿给B然后在穿给C ,如果使用intent一个一个传递 须要在A类中一个一个传递给B 然后B类中获取到所有数值  然后在一个一个传递给C  这样很麻烦 但是 如果是bundle的话 B类中直接将bundler传递给C 不用一个一个获得具体的值  然后在C类中直接取得解析数值。

传递
  1.         /**Activity之间传递值**/
  2.         Button botton3 = (Button)findViewById(R.id.button3);
  3.         botton3.setOnClickListener(new OnClickListener() {
  4.             
  5.             @Override
  6.             public void onClick(View arg0) {
  7.                  Intent intent = new Intent(mContext,ShowActivity.class);
  8.                  //使用intent.putExtra()直接传递
  9.                  intent.putExtra("name", "雨松MOMO");
  10.                  intent.putExtra("age", 25);
  11.                  intent.putExtra("boy", true);
  12.                
  13.                  //把数值放进bundle 然后在把整个bundle通过intent.putExtra()传递
  14.                  Bundle bundle = new Bundle();
  15.                  bundle.putString("b_name", "小可爱");
  16.                  bundle.putInt("b_age", 23);
  17.                  bundle.putBoolean("b_boy", false);
  18.                  //在这里把整个bundle 放进intent中
  19.                  intent.putExtras(bundle);
  20.                  //开启一个新的 activity 将intent传递过去
  21.                  startActivity(intent);
  22.             }
  23.         });   
复制代码
接收
  1. public class ShowActivity extends Activity {
  2.    
  3.     @Override
  4.     protected void onCreate(Bundle savedInstanceState) {
  5.         setContentView(R.layout.my);
  6.        
  7.         Intent intent = getIntent();
  8.        
  9.         String name = intent.getStringExtra("name");
  10.         //第二个参数为默认值 意思就是如果在intent中拿不到的话
  11.         //就用默认值
  12.         int age  = intent.getIntExtra("age", 0);
  13.         boolean isboy = intent.getBooleanExtra("boy", false);
  14.         TextView textView0 = (TextView)findViewById(R.id.text0);
  15.        
  16.         textView0.setText("姓名  " + name + "年龄 " + age + "男孩?  " + isboy);
  17.        
  18.        
  19.         Bundle bundle = intent.getExtras();
  20.         name = bundle.getString("b_name");
  21.         //第二个参数为默认值 意思就是如果在bundle中拿不到的话
  22.         //就用默认值
  23.         age = bundle.getInt("b_age",0);
  24.         isboy = bundle.getBoolean("b_boy", false);
  25.        
  26.         TextView textView1 = (TextView)findViewById(R.id.text1);
  27.        
  28.         textView1.setText("姓名  " + name + "年龄 " + age + "男孩?  " + isboy);
  29.        
  30.         super.onCreate(savedInstanceState);
  31.     }

  32. }
复制代码
最后还是那句老话如果你还是觉得我写的不够详细 看的不够爽 不要紧我把源代码的下载地址贴出来 欢迎大家一起讨论学习

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x

0

主题

21

帖子

13

安币

初级码农

Rank: 1

QQ达人

发表于 2011-9-15 12:38:33 | 显示全部楼层
感谢楼主发布。谢谢。

0

主题

380

帖子

715

安币

代码手工艺人

Rank: 4

发表于 2011-9-3 20:11:41 | 显示全部楼层
学习了~!

4

主题

211

帖子

316

安币

攻城狮

Rank: 3Rank: 3

发表于 2011-9-5 16:42:15 | 显示全部楼层
撒有拉拉撒有拉拉撒有拉拉撒有拉拉撒有拉拉撒有拉拉撒有拉拉撒有拉拉撒有拉拉撒有拉拉撒有拉拉

14

主题

360

帖子

204

安币

攻城狮

Rank: 3Rank: 3

发表于 2011-9-7 14:43:00 | 显示全部楼层
Android软件开发之应用程序之间的通信介绍(十八)

12

主题

128

帖子

304

安币

程序猿

Rank: 2

QQ达人

发表于 2011-9-11 23:01:49 | 显示全部楼层
好,支持下

0

主题

74

帖子

144

安币

程序猿

Rank: 2

发表于 2011-9-12 16:11:10 | 显示全部楼层
学习学习,太有用了!

1

主题

25

帖子

12

安币

初级码农

Rank: 1

发表于 2011-9-13 13:32:55 | 显示全部楼层
支持支持。

0

主题

49

帖子

19

安币

程序猿

Rank: 2

QQ达人

发表于 2011-9-13 16:32:19 | 显示全部楼层
好东西,顶起。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

领先的中文移动开发者社区
18620764416
7*24全天服务
意见反馈:1294855032@qq.com

扫一扫关注我们

Powered by Discuz! X3.2© 2001-2019 Comsenz Inc.( 粤ICP备15117877号 )