Android Activity/Service/Broadcaster三大组件之间互相调用

Android Activity/Service/Broadcaster三大组件之间互相调用

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

2、Activity如何通过Binder调用Service的一个方法。
(研究这个问题,考虑到与服务器端交互的动作,打包至Service,Activity只呈现界面,调用Service的方法)
 
结构图见如下:

 

效果图如下:

 

u
点击“start service”按钮,启动Service,然后更改Activity的UI。

点击“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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
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
18
19
20
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
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
19
20
<? 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 >

 本案例代码下载地址

事实上,用Binder也可实现将值从Servcie传送至Activity。。。有兴趣的同志可以去看看这篇文章–>Android与Activity交互的本地服务示例

 

你可能感兴趣的:(Android Activity/Service/Broadcaster三大组件之间互相调用)