Android实现Activity、Service与Broadcaster三大组件之间互相调用的方法详解

时间:2021-07-14 23:20:45

本文实例讲述了android实现activity、service与broadcaster三大组件之间互相调用的方法。分享给大家供大家参考,具体如下:

我们研究两个问题,

1、service如何通过broadcaster更改activity的一个textview。
(研究这个问题,考虑到service从服务器端获得消息之后,将msg返回给activity)

2、activity如何通过binder调用service的一个方法。
(研究这个问题,考虑到与服务器端交互的动作,打包至service,activity只呈现界面,调用service的方法)

结构图见如下:

Android实现Activity、Service与Broadcaster三大组件之间互相调用的方法详解

效果图如下:

Android实现Activity、Service与Broadcaster三大组件之间互相调用的方法详解

点击“start service”按钮,启动service,然后更改activity的ui。

Android实现Activity、Service与Broadcaster三大组件之间互相调用的方法详解

点击“send msg to server”按钮调用service的方法,显示notificationbar

代码:

1、新建一个myservice类,继承service

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
package com.ljq.activity;
import android.app.notification;
import android.app.notificationmanager;
import android.app.pendingintent;
import android.app.service;
import android.content.context;
import android.content.intent;
import android.graphics.color;
import android.os.binder;
import android.os.ibinder;
public class myservice extends service {
 private notificationmanager notificationmanager = null;
 private final ibinder binder = new localbinder();
 @override
 public void oncreate() {
 sendmsgtoactivty("service is oncreating.\n");
 }
 @override
 public ibinder onbind(intent intent) {
 string msg = "activity is sendding message to service,\n service send msg to server!\n";
 sendmsgtoactivty(msg);
 return binder;
 }
 /**
 * 把信息传递给activity
 *
 * @param msg
 */
 private void sendmsgtoactivty(string msg) {
 intent intent = new intent("com.android.yao.msg");
 intent.putextra("msg", msg);
 this.sendbroadcast(intent);
 }
 @override
 public void ondestroy() {
 super.ondestroy();
 if(notificationmanager!=null){
  notificationmanager.cancel(0);
  notificationmanager=null;
 }
 }
 /**
 * 在状态栏显示通知
 *
 * @param msg
 */
 private void shownotification(string msg) {
 notificationmanager = (notificationmanager) getsystemservice(context.notification_service);
 // 定义notification的各种属性
 notification notification =new notification(r.drawable.icon,
     "a message coming!", system.currenttimemillis());
 //flag_auto_cancel  该通知能被状态栏的清除按钮给清除掉
 //flag_no_clear   该通知不能被状态栏的清除按钮给清除掉
 //flag_ongoing_event 通知放置在正在运行
 //flag_insistent   是否一直进行,比如音乐一直播放,知道用户响应
 notification.flags |= notification.flag_ongoing_event; // 将此通知放到通知栏的"ongoing"即"正在运行"组中
 notification.flags |= notification.flag_no_clear; // 表明在点击了通知栏中的"清除通知"后,此通知不清除,经常与flag_ongoing_event一起使用
 notification.flags |= notification.flag_show_lights;
 //default_all   使用所有默认值,比如声音,震动,闪屏等等
 //default_lights 使用默认闪光提示
 //default_sounds 使用默认提示声音
 //default_vibrate 使用默认手机震动,需加上<uses-permission android:name="android.permission.vibrate" />权限
 notification.defaults = notification.default_lights;
 //叠加效果常量
 //notification.defaults=notification.default_lights|notification.default_sound;
 notification.ledargb = color.blue;
 notification.ledonms =5000; //闪光时间,毫秒
 // 设置通知的事件消息
 //intent notificationintent =new intent(mainactivity.this, mainactivity.class); // 点击该通知后要跳转的activity
 intent notificationintent = new intent(getapplicationcontext(), mainactivity.class); // 加载类,如果直接通过类名,会在点击时重新加载页面,无法恢复最后页面状态。
 notificationintent.setflags(intent.flag_activity_single_top);
 pendingintent contentitent = pendingintent.getactivity(this, 0, notificationintent, 0);
 notification.setlatesteventinfo(this, "message", "message:" + msg, contentitent);
 // 把notification传递给notificationmanager
 notificationmanager.notify(0, notification);
 }
 /**
 * 从activity获取信息
 *
 * @param msg
 */
 public void receivermsgtoactivity(string msg){
 sendmsgtoactivty("\n receivermsgtoactivity:"+msg);
 }
 public void sendmsgtoserver(string msg) {
 shownotification(msg);
 }
 public class localbinder extends binder {
 public myservice getservice() {
  return myservice.this;
 }
 }
}

2、新建mybroadcastreceiver类,继承broadcastreceiver,用来发送intent启动服务

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.ljq.activity;
import android.content.broadcastreceiver;
import android.content.context;
import android.content.intent;
/**
 * 发送intent启动服务
 *
 * @author jiqinlin
 *
 */
public class mybroadcastreceiver extends broadcastreceiver {
 @override
 public void onreceive(context context, intent intent) {
 intent service = new intent(context, myservice.class);
 context.startservice(service);
 }
}

3、新建mainactivity类,其实是一个activity,用来呈现界面

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package com.ljq.activity;
import java.util.list;
import android.app.activity;
import android.app.activitymanager;
import android.content.broadcastreceiver;
import android.content.componentname;
import android.content.context;
import android.content.intent;
import android.content.intentfilter;
import android.content.serviceconnection;
import android.os.bundle;
import android.os.ibinder;
import android.util.log;
import android.view.view;
import android.widget.textview;
public class mainactivity extends activity implements view.onclicklistener {
 private string msg = "";
 private textview txtmsg;
 private updatereceiver receiver;
 private myservice myservice;
 private final static string tag=mainactivity.class.getsimplename();
 @override
 public void oncreate(bundle savedinstancestate) {
 super.oncreate(savedinstancestate);
 setcontentview(r.layout.main);
 txtmsg = (textview) this.findviewbyid(r.id.txtmsg);
 this.findviewbyid(r.id.btnstart).setonclicklistener(this);
 this.findviewbyid(r.id.btnsend).setonclicklistener(this);
 //订阅广播intent
 receiver = new updatereceiver();
 intentfilter filter = new intentfilter();
 filter.addaction("com.android.yao.msg");
 this.registerreceiver(receiver, filter);
 //初始化时启动服务
 //intent intent = new intent(mainactivity.this, myservice.class);
 //this.bindservice(intent, conn, bind_auto_create);
 }
 @override
 protected void ondestroy() {
 super.ondestroy();
 //结束服务
 if(conn!=null){
  unbindservice(conn);
  myservice=null;
 }
 }
 public class updatereceiver extends broadcastreceiver {
 @override
 public void onreceive(context context, intent intent) {
  //获取service传过来的信息
  msg = intent.getstringextra("msg");
  txtmsg.append(msg);
 }
 }
 private serviceconnection conn = new serviceconnection() {
 @override
 public void onserviceconnected(componentname name, ibinder service) {
  myservice = ((myservice.localbinder) service).getservice();
  log.i(tag, "onserviceconnected myservice: "+myservice);
 }
 @override
 public void onservicedisconnected(componentname name) {
  myservice = null;
 }
 };
 @override
 public void onclick(view v) {
 intent intent = new intent(mainactivity.this, myservice.class);
 switch (v.getid()) {
 case r.id.btnstart:
  //判断服务是否启动
  if(false==isservicerunning(this, myservice.class.getname())){
  log.i(tag, "start "+myservice.class.getsimplename()+" service");
  this.bindservice(intent, conn, bind_auto_create);
  }
  log.i(tag, myservice.class.getname()+" run status: "+isservicerunning(this, myservice.class.getname()));
  break;
 case r.id.btnsend:
  //判断服务是否启动
  if(false==isservicerunning(this, myservice.class.getname())){
  log.i(tag, "start "+myservice.class.getsimplename()+" service");
  this.bindservice(intent, conn, bind_auto_create);
  }
  log.i(tag, myservice.class.getname()+" run status: "+isservicerunning(this, myservice.class.getname()));
  log.i(tag, "onclick myservice: "+myservice); //第一次启动服务时此处为null(小编认为虽然服务已启动成功,但是还没全部初始化)
  if(myservice!=null){
    myservice.sendmsgtoserver("i am sending msg to server");
    //从activity传递信息给service
    myservice.receivermsgtoactivity("this is a msg");
   }
  break;
 }
 }
 /**
 * 判断服务是否正在运行
 *
 * @param context
 * @param classname 判断的服务名字:包名+类名
 * @return true在运行 false 不在运行
 */
 public static boolean isservicerunning(context context, string classname) {
 boolean isrunning = false;
 activitymanager activitymanager = (activitymanager) context
  .getsystemservice(context.activity_service);
 //获取所有的服务
 list<activitymanager.runningserviceinfo> services= activitymanager.getrunningservices(integer.max_value);
 if(services!=null&&services.size()>0){
  for(activitymanager.runningserviceinfo service : services){
  if(classname.equals(service.service.getclassname())){
   isrunning=true;
   break;
  }
  }
 }
 return isrunning;
 }
}

4、main.xml布局文件

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0" encoding="utf-8"?>
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:orientation="vertical" android:layout_width="fill_parent"
 android:layout_height="fill_parent">
 <textview android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:id="@+id/txtmsg" />
 <linearlayout
 xmlns:android="http://schemas.android.com/apk/res/android"
 android:orientation="horizontal"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content">
 <button android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:text="start service"
  android:id="@+id/btnstart"/>
 <button android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:text="send msg to server"
  android:id="@+id/btnsend"/>
 </linearlayout>
</linearlayout>

5、清单文件androidmanifest.xml,用来配置组件等信息

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
   package="com.ljq.activity"
   android:versioncode="1"
   android:versionname="1.0">
  <application android:icon="@drawable/icon" android:label="@string/app_name">
    <activity android:name=".mainactivity"
         android:label="@string/app_name">
      <intent-filter>
        <action android:name="android.intent.action.main" />
        <category android:name="android.intent.category.launcher" />
      </intent-filter>
    </activity>
    <service android:name=".myservice"/>
    <receiver android:name=".mybroadcastreceiver" />
  </application>
  <uses-sdk android:minsdkversion="7" />
</manifest>

希望本文所述对大家android程序设计有所帮助。