android 学习随笔十八(广播与服务 )
1、广播接收者注册
- 清单文件注册(Android四大组件都要在清单文件中注册)
一旦应用部署,广播接收者就生效了,直到用户手动停止应用或者应用被删除
- 广播接收者可以使用代码注册
需要广播接收者运行时,使用代码注册,不需要时,可以使用代码解除注册
特殊广播接收者,必须代码注册。电量改变、屏幕开关,必须使用代码注册
2、注册广播接收者
//创建广播接收者对象
receiver = new ScreenOnOffReceiver();
//通过IntentFilter对象指定广播接收者接收什么类型的广播
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_SCREEN_ON);
//注册广播接收者
registerReceiver(receiver, filter);
* 解除注册广播接收者
unregisterReceiver(receiver);
* 解除注册之后,广播接收者将失去作用
1 package com.itheima.register; 2 3 import android.content.BroadcastReceiver; 4 import android.content.Context; 5 import android.content.Intent; 6 7 public class ScreenOnOFFReceiver extends BroadcastReceiver { 8 9 @Override 10 public void onReceive(Context context, Intent intent) { 11 12 String action = intent.getAction(); 13 if(Intent.ACTION_SCREEN_ON.equals(action)){ 14 System.out.println("屏幕开啦啦"); 15 } 16 else if(Intent.ACTION_SCREEN_OFF.equals(action)){ 17 System.out.println("屏幕关哇哇"); 18 } 19 20 } 21 22 }
1 package com.itheima.register; 2 3 import android.app.Service; 4 import android.content.Intent; 5 import android.content.IntentFilter; 6 import android.os.IBinder; 7 8 public class RegisterService extends Service { 9 10 private ScreenOnOFFReceiver receiver; 11 12 @Override 13 public IBinder onBind(Intent intent) { 14 // TODO Auto-generated method stub 15 return null; 16 } 17 18 @Override 19 public void onCreate() { 20 super.onCreate(); 21 //1.创建广播接收者对象 22 receiver = new ScreenOnOFFReceiver(); 23 //2.创建意图过滤器对象 24 IntentFilter filter = new IntentFilter(); 25 //指定接收什么广播 26 filter.addAction(Intent.ACTION_SCREEN_OFF); 27 filter.addAction(Intent.ACTION_SCREEN_ON); 28 //3.注册广播接收者 29 registerReceiver(receiver, filter); 30 31 } 32 33 @Override 34 public void onDestroy() { 35 super.onDestroy(); 36 //反注册广播接收者 37 unregisterReceiver(receiver); 38 } 39 40 }
1 package com.itheima.register; 2 3 import android.os.Bundle; 4 import android.app.Activity; 5 import android.content.Intent; 6 import android.view.Menu; 7 import android.view.View; 8 9 public class MainActivity extends Activity { 10 11 @Override 12 protected void onCreate(Bundle savedInstanceState) { 13 super.onCreate(savedInstanceState); 14 setContentView(R.layout.activity_main); 15 } 16 17 18 public void start(View v){ 19 Intent intent = new Intent(this, RegisterService.class); 20 startService(intent); 21 } 22 public void stop(View v){ 23 Intent intent = new Intent(this, RegisterService.class); 24 stopService(intent); 25 } 26 27 }
服务注册广播
3、服务的分类
- 本地服务:服务和启动它的组件在同一个进程
- 远程服务:服务和启动它的组件不在同一个进程
- 远程服务只能隐式启动,类似隐式启动Activity,在清单文件中配置Service标签时,必须配置intent-filter子节点,并指定action子节点
远程服务
1 package com.itheima.remoteservice; 2 3 import com.itheima.remoteservice.PublicBusiness.Stub; 4 5 import android.app.Service; 6 import android.content.Intent; 7 import android.os.Binder; 8 import android.os.IBinder; 9 10 public class RemoteService extends Service{ 11 12 @Override 13 public IBinder onBind(Intent intent) { 14 System.out.println("绑定"); 15 return new FengMiShu(); 16 } 17 18 class FengMiShu extends Stub{ 19 20 @Override 21 public void qianXian() { 22 // TODO Auto-generated method stub 23 remoteBanZheng(); 24 } 25 26 } 27 28 @Override 29 public boolean onUnbind(Intent intent) { 30 System.out.println("解绑"); 31 return super.onUnbind(intent); 32 } 33 34 @Override 35 public void onCreate() { 36 System.out.println("创建"); 37 super.onCreate(); 38 } 39 40 @Override 41 public int onStartCommand(Intent intent, int flags, int startId) { 42 System.out.println("开始"); 43 return super.onStartCommand(intent, flags, startId); 44 } 45 46 @Override 47 public void onDestroy() { 48 System.out.println("摧毁"); 49 super.onDestroy(); 50 } 51 52 public void remoteBanZheng(){ 53 System.out.println("苗领导在国外远程办证"); 54 } 55 56 }
1 package com.itheima.remoteservice; 2 3 import android.os.Bundle; 4 import android.app.Activity; 5 import android.view.Menu; 6 7 public class MainActivity extends Activity { 8 9 @Override 10 protected void onCreate(Bundle savedInstanceState) { 11 super.onCreate(savedInstanceState); 12 setContentView(R.layout.activity_main); 13 } 14 15 16 @Override 17 public boolean onCreateOptionsMenu(Menu menu) { 18 // Inflate the menu; this adds items to the action bar if it is present. 19 getMenuInflater().inflate(R.menu.main, menu); 20 return true; 21 } 22 23 }
1 <?xml version="1.0" encoding="utf-8"?> 2 <manifest xmlns:android="http://schemas.android.com/apk/res/android" 3 package="com.itheima.remoteservice" 4 android:versionCode="1" 5 android:versionName="1.0" > 6 7 <uses-sdk 8 android:minSdkVersion="8" 9 android:targetSdkVersion="17" /> 10 11 <application 12 android:allowBackup="true" 13 android:icon="@drawable/ic_launcher" 14 android:label="@string/app_name" 15 android:theme="@style/AppTheme" > 16 <activity 17 android:name="com.itheima.remoteservice.MainActivity" 18 android:label="@string/app_name" > 19 <intent-filter> 20 <action android:name="android.intent.action.MAIN" /> 21 22 <category android:name="android.intent.category.LAUNCHER" /> 23 </intent-filter> 24 </activity> 25 <service android:name="com.itheima.remoteservice.RemoteService"> 26 <intent-filter > 27 <action android:name="com.itheima.remote"/> 28 </intent-filter> 29 </service> 30 </application> 31 32 </manifest>
调用远程服务操作
package com.itheima.runremoteservice; public interface PublicBusiness { void qianXian(); }
1 package com.itheima.runremoteservice; 2 3 import android.os.Bundle; 4 import android.os.IBinder; 5 import android.app.Activity; 6 import android.content.ComponentName; 7 import android.content.Intent; 8 import android.content.ServiceConnection; 9 import android.view.Menu; 10 import android.view.View; 11 12 public class MainActivity extends Activity { 13 14 public PublicBusiness pb; 15 private MyConn conn; 16 17 @Override 18 protected void onCreate(Bundle savedInstanceState) { 19 super.onCreate(savedInstanceState); 20 setContentView(R.layout.activity_main); 21 22 conn = new MyConn(); 23 } 24 25 26 public void start(View v){ 27 Intent intent = new Intent(); 28 intent.setAction("com.itheima.remote"); 29 startService(intent); 30 } 31 public void stop(View v){ 32 Intent intent = new Intent(); 33 intent.setAction("com.itheima.remote"); 34 stopService(intent); 35 } 36 public void bind(View v){ 37 Intent intent = new Intent(); 38 intent.setAction("com.itheima.remote"); 39 bindService(intent, conn, BIND_AUTO_CREATE); 40 } 41 42 public void unbind(View v){ 43 unbindService(conn); 44 } 45 class MyConn implements ServiceConnection{ 46 47 @Override 48 public void onServiceConnected(ComponentName name, IBinder service) { 49 pb = (PublicBusiness) service; 50 51 } 52 53 @Override 54 public void onServiceDisconnected(ComponentName name) { 55 // TODO Auto-generated method stub 56 57 } 58 59 } 60 61 public void banZheng(View v){ 62 pb.qianXian(); 63 } 64 }
4、AIDL Android interface definition language,在Android中用于进程间通讯
* 安卓接口定义语言
* 作用:跨进程通信
* 应用场景:远程服务中的中间人对象,其他应用是拿不到的,那么在通过绑定服务获取中间人对象时,就无法强制转换,使用aidl,就可以在其他应用中拿到中间人类所实现的接口
步骤
远程服务
1. 把接口文件的后缀名改成aidl(在gen目录下会根据aidl文件生成一个.java文件)
2. aidl文件中所有东西都是public的,不需要也不能自己定义访问修饰符
3. 中间人对象继承Stub,这个对象已经继承了Binder并实现了PublicBusiness接口(自定义接口)
启动调用远程服务
1. 把远程服务项目的aidl文件复制到启动调用远程服务项目(先创建一个和服务aidl所在包相同的包名),然后aidl所在的包名远程服务和启动调用远程服务项目必须一致(在gen目录下会根据aidl文件生成一个.java文件)
2. 把启动调用远程服务项目获取到的中间人对象使用Stub.asInterface强转
public void onServiceConnected(ComponentName name, IBinder service) {
pb = Stub.asInterface(service);
}
例:
- 支付宝远程服务
1. 定义支付宝的服务,在服务中定义pay方法
2. 定义中间人对象,把pay方法抽取成接口
3. 把抽取出来的接口后缀名改成aidl
4. 中间人对象直接继承Stub对象
5. 注册这个支付宝服务,定义它的intent-Filter
- 需要支付的应用
1. 把刚才定义好的aidl文件拷贝过来,注意aidl文件所在的包名必须跟原包名一致
2. 远程绑定支付宝的服务,通过onServiceConnected方法我们可以拿到中间人对象
3. 把中间人对象通过Stub.asInterface方法强转成定义了pay方法的接口
4. 调用中间人的pay方法
1 package com.itheima.paybaby; 2 3 import com.itheima.paybaby.PayInterface.Stub; 4 5 import android.app.Service; 6 import android.content.Intent; 7 import android.os.IBinder; 8 import android.os.RemoteException; 9 10 public class PayService extends Service { 11 12 @Override 13 public IBinder onBind(Intent intent) { 14 // TODO Auto-generated method stub 15 return new PayController(); 16 } 17 18 class PayController extends Stub{ 19 20 @Override 21 public void pay() throws RemoteException { 22 PayService.this.pay(); 23 24 } 25 26 } 27 28 private void pay() { 29 System.out.println("检查支付环境"); 30 System.out.println("加密账号密码"); 31 System.out.println("上传账号密码"); 32 System.out.println("完成支付"); 33 34 } 35 }
1 package com.itheima.paybaby; 2 3 import android.os.Bundle; 4 import android.app.Activity; 5 import android.view.Menu; 6 7 public class MainActivity extends Activity { 8 9 @Override 10 protected void onCreate(Bundle savedInstanceState) { 11 super.onCreate(savedInstanceState); 12 setContentView(R.layout.activity_main); 13 } 14 15 16 @Override 17 public boolean onCreateOptionsMenu(Menu menu) { 18 // Inflate the menu; this adds items to the action bar if it is present. 19 getMenuInflater().inflate(R.menu.main, menu); 20 return true; 21 } 22 23 }
调用
1 package com.itheima.naocangame; 2 3 import com.itheima.paybaby.PayInterface; 4 import com.itheima.paybaby.PayInterface.Stub; 5 6 import android.os.Bundle; 7 import android.os.IBinder; 8 import android.os.RemoteException; 9 import android.app.Activity; 10 import android.content.ComponentName; 11 import android.content.Intent; 12 import android.content.ServiceConnection; 13 import android.view.Menu; 14 import android.view.View; 15 16 public class MainActivity extends Activity { 17 18 PayInterface pi; 19 @Override 20 protected void onCreate(Bundle savedInstanceState) { 21 super.onCreate(savedInstanceState); 22 setContentView(R.layout.activity_main); 23 24 //绑定远程服务 25 Intent intent = new Intent("com.itheima.babypay"); 26 bindService(intent, new ServiceConnection() { 27 28 @Override 29 public void onServiceDisconnected(ComponentName name) { 30 // TODO Auto-generated method stub 31 32 } 33 34 @Override 35 public void onServiceConnected(ComponentName name, IBinder service) { 36 pi = Stub.asInterface(service); 37 38 } 39 }, BIND_AUTO_CREATE); 40 41 } 42 43 44 public void click(View v){ 45 try { 46 pi.pay(); 47 } catch (RemoteException e) { 48 // TODO Auto-generated catch block 49 e.printStackTrace(); 50 } 51 } 52 53 }
5、进程优先级
- 五种前台进程
1. activity执行了onresume方法,获得焦点
2. 拥有一个跟正在与用户交互的activity绑定的服务
3. 拥有一个服务执行了startForeground()方法
4. 拥有一个正在执行onCreate()、onStart()或者onDestroy()方法中的任意一个的服务
5. 拥有一个正在执行onReceive方法的广播接收者
- 两种可见进程
1. activity执行了onPause方法,失去焦点,但是可见
2. 拥有一个跟可见或前台activity绑定的服务