Android Service与Activity通信方式 And Service不被杀死
1.Service是Android四大组件之一,下面对Service进行一个简单的介绍,什么生命周期一些基础那些就直接跳过了
Service的启动方式有两种:1.直接启动(startService) 2.绑定启动(bindService)。
1)具体在什么情况下用直接启动还是用绑定启动呢?
如果你只是想要启动一个后台服务长期进行某项任务那么使用 startService 便可以了。如果你想要与正在运行的 Service 取得联系,那么有两种方法,一种是使用 broadcast ,另外是使用 bindService ,前者的缺点是如果交流较为频繁,容易造成性能上的问题,并且 BroadcastReceiver 本身执行代码的时间是很短的(也许执行到一半,后面的代码便不会执行),而后者则没有这些问题,因此我们肯定选择bindService(这个时候你便同时在使用 startService 和 bindService 了,这在 Activity 中更新 Service 的某些运行状态是相当有用的)。另外如果你的服务只是公开一个远程接口,供连接上的客服端(android 的 Service 是C/S架构)远程调用执行方法。这个时候你可以不让服务一开始就运行,而只用 bindService ,这样在第一次 bindService 的时候才会创建服务的实例运行它,这会节约很多系统资源,特别是如果你的服务是Remote Service,那么该效果会越明显(当然在 Service 创建的时候会花去一定时间,你应当注意到这点)。
2.Activity和Service通信方式一
1)采用IBinder来进行通信,IBinder是Android专门用来进程通讯的。
这里实现一个简单的效果,在Service中完成一个加法计算,计算完成后,将值返还给Activity进行打印。( 别忘了对Service在AndroidManifest.xml进行注册)
Service:(这里应该将MyBinder中的方法全部定义在接口里面,来继承接口实现)
1 public class MyService extends Service { 2 3 @Override 4 public IBinder onBind(Intent intent) { 5 // intent获取从Activity传来的数据 6 // 别忘了要返回定义binder实例, 如果返回就不能建立连接 7 return new MyBinder(); 8 } 9 10 public class MyBinder extends Binder { 11 12 // 加法 13 public int add(int a, int b) { 14 return a + b; 15 } 16 17 public MyService getService() { 18 return MyService.this; 19 } 20 21 } 22 23 @Override 24 public void onCreate() { 25 super.onCreate(); 26 } 27 28 @Override 29 public void onDestroy() { 30 super.onDestroy(); 31 } 32 33 }
Activity:
1 public class MainActivity extends Activity { 2 3 private MyService.MyBinder binder; 4 ServiceConnection connection; 5 6 @Override 7 protected void onCreate(Bundle savedInstanceState) { 8 super.onCreate(savedInstanceState); 9 setContentView(R.layout.activity_main); 10 11 connection = new ServiceConnection() { 12 13 @Override 14 public void onServiceDisconnected(ComponentName name) { 15 16 } 17 18 @Override 19 public void onServiceConnected(ComponentName name, IBinder service) { 20 // 获取被绑定service中的binder 21 binder = (MyService.MyBinder) service; 22 23 System.out.println("从service返回来的数据->" + binder.add(5, 3)); 24 25 } 26 }; 27 28 Intent intent = new Intent("android.intent.mysecondservice"); 29 bindService(intent, connection, BIND_AUTO_CREATE); 30 31 } 32 33 }
最后打印出的结果:
2)在Service中开启一个线程模拟网络下载,将下载量在MainActivity中动态的打印出来(这里的IAddCount 接口是为后面去掉Activity中的线程,这里占时没有用的)
Service:
1 public class MyService extends Service { 2 private int count; 3 private ServiceBinder binder; 4 private boolean isGoOn = true; 5 private IAddCount addCount; 6 7 public interface IAddCount { 8 public void showCount(int count); 9 10 } 11 12 @Override 13 public IBinder onBind(Intent intent) { 14 System.out.println("从activity传过来的数据是-->>" 15 + intent.getStringExtra("data")); 16 17 return binder; 18 } 19 20 public void setIAddCount(IAddCount addCount) { 21 this.addCount = addCount; 22 } 23 24 public class ServiceBinder extends Binder { 25 26 public int getCount() { 27 return count; 28 } 29 30 public MyService getService() { 31 return MyService.this; 32 } 33 34 } 35 36 @Override 37 public void onCreate() { 38 super.onCreate(); 39 System.out.println("MyService---onCreate()"); 40 binder = new ServiceBinder(); 41 42 new Thread(new Runnable() { 43 44 @Override 45 public void run() { 46 47 while (isGoOn) { 48 try { 49 Thread.sleep(1000); 50 count++; 51 if (count == 5) { 52 isGoOn = false; 53 } 54 } catch (InterruptedException e) { 55 e.printStackTrace(); 56 } 57 58 } 59 60 } 61 }).start(); 62 63 } 64 65 @Override 66 public void onDestroy() { 67 super.onDestroy(); 68 System.out.println("MyService---onDestroy"); 69 70 } 71 72 }
MainActivity:
1 public class MainActivity extends Activity { 2 3 private MyService.MyBinder binder; 4 ServiceConnection connection; 5 6 @Override 7 protected void onCreate(Bundle savedInstanceState) { 8 super.onCreate(savedInstanceState); 9 setContentView(R.layout.activity_main); 10 11 connection = new ServiceConnection() { 12 13 @Override 14 public void onServiceDisconnected(ComponentName name) { 15 16 } 17 18 @Override 19 public void onServiceConnected(ComponentName name, IBinder service) { 20 // 获取被绑定service中的binder 21 binder = (MyService.MyBinder) service; 22 23 System.out.println("从service返回来的数据->" + binder.add(5, 3)); 24 25 } 26 }; 27 28 Intent intent = new Intent("android.intent.mysecondservice"); 29 bindService(intent, connection, BIND_AUTO_CREATE); 30 31 } 32 33 }
打印出的结果是:
3)这里在获取Service的数据的时候,是在Activity中开了一个线程与Service中的线程去对应,然后动态的去提取数据的,其实可以采用接口回调的方法来实现,不用去在开线程的
Service:
1 public class MyService extends Service { 2 private int count; 3 private ServiceBinder binder; 4 private boolean isGoOn = true; 5 private IAddCount addCount; 6 7 public interface IAddCount { 8 public void showCount(int count); 9 10 } 11 12 @Override 13 public IBinder onBind(Intent intent) { 14 System.out.println("从activity传过来的数据是-->>" 15 + intent.getStringExtra("data")); 16 17 return binder; 18 } 19 20 public void setIAddCount(IAddCount addCount) { 21 this.addCount = addCount; 22 } 23 24 public class ServiceBinder extends Binder { 25 26 public int getCount() { 27 return count; 28 } 29 30 public MyService getService() { 31 return MyService.this; 32 } 33 34 } 35 36 @Override 37 public void onCreate() { 38 super.onCreate(); 39 System.out.println("MyService---onCreate()"); 40 binder = new ServiceBinder(); 41 42 new Thread(new Runnable() { 43 44 @Override 45 public void run() { 46 47 while (isGoOn) { 48 try { 49 Thread.sleep(1000); 50 count++; 51 if (count == 5) { 52 isGoOn = false; 53 } 54 } catch (InterruptedException e) { 55 e.printStackTrace(); 56 } 57 58 } 59 60 } 61 }).start(); 62 63 } 64 65 @Override 66 public void onDestroy() { 67 super.onDestroy(); 68 System.out.println("MyService---onDestroy"); 69 70 } 71 72 }
MainActivity:
1 public class SecondActivity extends Activity implements OnClickListener { 2 3 private Button btn; 4 private int count; 5 MyService.ServiceBinder binder; 6 private boolean isBack = true; 7 private MyService myService; 8 9 @Override 10 protected void onCreate(Bundle savedInstanceState) { 11 super.onCreate(savedInstanceState); 12 setContentView(R.layout.activity_second); 13 btn = (Button) findViewById(R.id.btn222); 14 btn.setOnClickListener(this); 15 } 16 17 @Override 18 public void onClick(View v) { 19 20 switch (v.getId()) { 21 case R.id.btn222: 22 23 Intent intent = new Intent("android.intent.myservice"); 24 intent.putExtra("data", "我是从activity传过来的数据"); 25 ServiceConnection sercon = new ServiceConnection() { 26 27 @Override 28 public void onServiceDisconnected(ComponentName name) { 29 30 } 31 32 @Override 33 public void onServiceConnected(ComponentName name, 34 IBinder service) { 35 binder = (MyService.ServiceBinder) service; 36 myService = binder.getService(); 37 // 实例化接口 38 myService.setIAddCount(new IAddCount() { 39 // ************************************// 40 // 接口回调 41 @Override 42 public void showCount(int count) { 43 System.out.println("接口回调返回的数据是-->>" + count); 44 } 45 }); 46 } 47 }; 48 bindService(intent, sercon, BIND_AUTO_CREATE); 49 System.out.println("输出的数据是-->>" + count); 50 51 // new Thread() { 52 // @Override 53 // public void run() { 54 // try { 55 // while (isBack) { 56 // Thread.sleep(1000); 57 // count = binder.getCount(); 58 // if (count == 5) { 59 // isBack = false; 60 // } 61 // 62 // Message msg = myHandler.obtainMessage(); 63 // msg.arg1 = count; 64 // myHandler.sendMessage(msg); 65 // } 66 // 67 // } catch (InterruptedException e) { 68 // e.printStackTrace(); 69 // } 70 // 71 // } 72 // 73 // }.start(); 74 75 break; 76 } 77 78 } 79 80 Handler myHandler = new Handler() { 81 public void handleMessage(android.os.Message msg) { 82 83 System.out.println("在activity中获取到的数据是->" + msg.arg1); 84 85 }; 86 87 }; 88 89 }
运行后的效果和上图一样的
4)通过broadcast(广播)的形式
在Activity中动态注册一个广播接收器,然后service将数据广播给Activity中的接收器即可
1 public class MainActivity extends Activity { 2 private ProgressBar mProgressBar; 3 private Intent mIntent; 4 private MsgReceiver msgReceiver; 5 6 7 @Override 8 protected void onCreate(Bundle savedInstanceState) { 9 super.onCreate(savedInstanceState); 10 setContentView(R.layout.activity_main); 11 12 //动态注册广播接收器 13 msgReceiver = new MsgReceiver(); 14 IntentFilter intentFilter = new IntentFilter(); 15 intentFilter.addAction("com.example.communication.RECEIVER"); 16 registerReceiver(msgReceiver, intentFilter); 17 18 19 mProgressBar = (ProgressBar) findViewById(R.id.progressBar1); 20 Button mButton = (Button) findViewById(R.id.button1); 21 mButton.setOnClickListener(new OnClickListener() { 22 23 @Override 24 public void onClick(View v) { 25 //启动服务 26 mIntent = new Intent("com.example.communication.MSG_ACTION"); 27 startService(mIntent); 28 } 29 }); 30 31 } 32 33 34 @Override 35 protected void onDestroy() { 36 //停止服务 37 stopService(mIntent); 38 //注销广播 39 unregisterReceiver(msgReceiver); 40 super.onDestroy(); 41 } 42 43 44 /** 45 * 广播接收器 46 * @author len 47 * 48 */ 49 public class MsgReceiver extends BroadcastReceiver{ 50 51 @Override 52 public void onReceive(Context context, Intent intent) { 53 //拿到进度,更新UI 54 int progress = intent.getIntExtra("progress", 0); 55 mProgressBar.setProgress(progress); 56 } 57 58 } 59 60 }
Service :
1 public class MsgService extends Service { 2 /** 3 * 进度条的最大值 4 */ 5 public static final int MAX_PROGRESS = 100; 6 /** 7 * 进度条的进度值 8 */ 9 private int progress = 0; 10 11 private Intent intent = new Intent("com.example.communication.RECEIVER"); 12 13 14 /** 15 * 模拟下载任务,每秒钟更新一次 16 */ 17 public void startDownLoad(){ 18 new Thread(new Runnable() { 19 20 @Override 21 public void run() { 22 while(progress < MAX_PROGRESS){ 23 progress += 5; 24 25 //发送Action为com.example.communication.RECEIVER的广播 26 intent.putExtra("progress", progress); 27 sendBroadcast(intent); 28 29 try { 30 Thread.sleep(1000); 31 } catch (InterruptedException e) { 32 e.printStackTrace(); 33 } 34 35 } 36 } 37 }).start(); 38 } 39 40 41 42 @Override 43 public int onStartCommand(Intent intent, int flags, int startId) { 44 startDownLoad(); 45 return super.onStartCommand(intent, flags, startId); 46 } 47 48 49 50 @Override 51 public IBinder onBind(Intent intent) { 52 return null; 53 }
Activity调用 bindService (Intent service, ServiceConnection conn, int flags)方法,得到Service对象的一个引用,这样Activity可以直接调用到Service中的方法,如果要主动通知Activity,我 们可以利用回调方法
Service向Activity发送消息,可以使用广播,当然Activity要注册相应的接收器。比如Service要向多个Activity发送同样的消息的话,用这种方法就更好
参考地址:http://blog.csdn.net/xiaanming/article/details/9750689
http://blog.csdn.net/zhouyongyang621/article/details/5861495
关于怎样让服务不被杀死
这个倒是有点流氓软件的意思,但有些特定情况还是需要服务能保持开启不被杀死,当然这样做我还是在程序里添加了关闭服务的按钮,也就是开启了就杀不死,除非在软件里关闭。
服务不被杀死分3种来讨论
1.系统根据资源分配情况杀死服务
2.用户通过settings->Apps->Running->Stop方式杀死服务
3.用户通过settings->Apps->Downloaded->Force Stop方式杀死服务
第一种情况:
用户不干预,完全靠系统来控制,办法有很多。比如onStartCommand()方法的返回值设为START_STICKY,服务就会在资源紧张的时候被杀掉,然后在资源足够的时候再恢复。当然也可设置为前台服务,使其有高的优先级,在资源紧张的时候也不会被杀掉。
第二种情况:
用户干预,主动杀掉运行中的服务。这个过程杀死服务会通过服务的生命周期,也就是会调用onDestory()方法,这时候一个方案就是在onDestory()中发送广播开启自己。这样杀死服务后会立即启动。如下:
1 @Override 2 public void onCreate() { 3 // TODO Auto-generated method stub 4 super.onCreate(); 5 6 mBR = new BroadcastReceiver() { 7 @Override 8 public void onReceive(Context context, Intent intent) { 9 // TODO Auto-generated method stub 10 Intent a = new Intent(ServiceA.this, ServiceA.class); 11 startService(a); 12 } 13 }; 14 mIF = new IntentFilter(); 15 mIF.addAction("listener"); 16 registerReceiver(mBR, mIF); 17 } 18 19 @Override 20 public void onDestroy() { 21 // TODO Auto-generated method stub 22 super.onDestroy(); 23 24 Intent intent = new Intent(); 25 intent.setAction("listener"); 26 sendBroadcast(intent); 27 28 unregisterReceiver(mBR); 29 }
当然,从理论上来讲这个方案是可行的,实验一下也可以。但有些情况下,发送的广播在消息队列中排的靠后,就有可能服务还没接收到广播就销毁了(这是 我对实验结果的猜想,具体执行步骤暂时还不了解)。所以为了能让这个机制完美运行,可以开启两个服务,相互监听,相互启动。服务A监听B的广播来启动B, 服务B监听A的广播来启动A。经过实验,这个方案可行,并且用360杀掉后几秒后服务也还是能自启的。到这里再说一句,如果不是某些功能需要的服务,不建 议这么做,会降低用户体验。
第三种情况:
强制关闭就没有办法。这个好像是从包的level去关的,并不走完整的生命周期。所以在服务里加代码是无法被调用的。处理这个情况的唯一方法是屏蔽掉force stop和uninstall按钮,让其不可用。方法自己去找吧。当然有些手机自带的清理功能就是从这个地方清理的,比如华为的清理。所以第三种情况我也没有什么更好的办法了。

浙公网安备 33010602011771号