1 进程概念的介绍
【1】安卓下四大组件都是运行在主线程中的,运行一个应用系统会开一个应用开一个linux进程和一个main线程。
【2】服务是在后台运行的,没有界面
进程的优先级:
【1】Foreground process 前台进程 优先级最高,相当于activity执行了onResume方法,用户正在交互
【2】Visible process 可视进程 一直影响用户看得见,相当于activity执行了onPause方法
【3】service process 服务进程 通过startServer开启了一个服务
【4】background process 后台进程 相当于activity执行了onStop方法,界面不可见,但是activity并没有被销毁
【5】Empty process 空进程 不会维持任何组件运行
一般只会杀死第四和第五个进程。
2 start方式启动服务的特点
【1】定义一个类继承
【2】第一次点击开启服务的时候,服务执行onCreate方法和onStart方法
【3】第二次点击按钮,再次开启服务,服务执行onStrat方法
【4】服务一旦开启,服务就会在后台长期运行,就算应用退出了也服务也存在,直到用户手工停止。
补充:子线程也是在后台运行的。但是当用户退出了应用之后,这个应用就变成了空进程,但是子线程还是在运行当中的,不过因为空进程的优先级较低
子线程很容易就会被杀死。
3 电话窃听器
【1】smsManager 短信管理者,可以获取与短信相关的状态信息
【2】TelephoneManager 电话管理者,可以获取与电话状态相关的信息
实现步骤:
【1】定义一个服务,开启服务,记得在清单文件中配置
【2】在服务的onCreate方法中获取TelephoneManager
TelephonyManager tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
【3】注册电话监听
tm.listen(new MyPhoneStateListener(), PhoneStateListener.LISTEN_CALL_STATE);
【4】定义一个类,用来监听电话的状态
private class MyPhoneStateListener extends PhoneStateListener{
@Override
public void onCallStateChanged(int state, String incomingNumber) {
// TODO Auto-generated method stub
super.onCallStateChanged(state, incomingNumber);
switch (state){
case TelephonyManager.CALL_STATE_IDLE://空闲状态,没来电
break;
case TelephonyManager.CALL_STATE_OFFHOOK://接听
break;
case TelephonyManager.CALL_STATE_RINGING://电话响铃
break;
}
}
}
【5】录音功能private class MyPhoneStateListener extends PhoneStateListener{
MediaRecorder recorder;
@Override
public void onCallStateChanged(int state, String incomingNumber) {
// TODO Auto-generated method stub
super.onCallStateChanged(state, incomingNumber);
switch (state){
case TelephonyManager.CALL_STATE_IDLE://空闲状态,没来电
if(recorder != null){
recorder.stop();
recorder.reset();
recorder.release();
}
break;
case TelephonyManager.CALL_STATE_OFFHOOK://接听
break;
case TelephonyManager.CALL_STATE_RINGING://电话响铃
recorder = new MediaRecorder();
recorder.setAudioChannels(MediaRecorder.AudioSource.MIC);
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
recorder.setOutputFile("/mnt/sdcard//luyin.3gp");
try {
recorder.prepare();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
}
}
}【6】把注册服务方到广播之中
public class BootReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context arg0, Intent arg1) {
// TODO Auto-generated method stub
Intent intent1 = new Intent(arg0,PhoneService.class);
arg0.startService(intent1);
}
}4 使用服务注册特殊的广播接收者
操作特别频繁地广播事件,比如屏幕的解锁和锁屏。
【1】定义广播接受者
public class ScreenReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context arg0, Intent arg1) {
// TODO Auto-generated method stub
String action = arg1.getAction();
if("android.intent.action.SCREEN_OFF".equals(action)){
System.out.println("锁屏了");
}else if("android.intent.action.SCREEN_ON".equals(action)){
System.out.println("解锁了");
}
}
}
【2】写一个服务,用来注册广播接受者public class ScreenService extends Service {
ScreenReceiver receiver;
@Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
receiver = new ScreenReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction("android.intent.action.SCREEN_OFF");
filter.addAction("android.intent.action.SCREEN_ON");
registerReceiver(receiver, filter);
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
unregisterReceiver(receiver);
}
}【3】在mainActivity的oncreate方法里开启服务public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(this,ScreenService.class);
startService(intent);
/*
* <receiver android:name=".ScreenReceiver">
<intent-filter >
<action android:name="android.intent.action.SCREEN_OFF"/>
<action android:name="android.intent.action.SCREEN_ON"/>
</intent-filter>
</receiver>
以上是静态注册,现在要动态注册
*/
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
}
}【4】在清单文件配置服务
5 通过bindService开启服务
通过startService方法来启动服务:先调用服务的onCreate方法,然后再调用onStartCommand方法
通过bindService方法来启动服务:先调用服务的onCreate方法,然后再调用onBind方法。而且,如果onBind方法的返回值是null,则不执行监视服务状态那个类的onServiceConnected方法。而且bindService只能绑定一次,也只能解绑一次。在Activity销毁的时候,服务也会被销毁。在这个时候,logcat会出现一段报错,注意意思是说
Activity leaked。这个是因为在Activity销毁的时候没有解绑服务,只需要在Activity的onDestory方法中解绑服务即可。还有,通过此方法启动服务,在设置页面是找不到此服务的。通过startService方法启动服务可以找到。
6 为什么引入bindService?
因为要使用服务里边定义的方法。想要使用服务的方法,并不能直接new一个对象,因为此对象不在谷歌提供的上下文环境中,会出现空指针异常。
7 通过bindService方式调用服务方法里边的过程
【1】在服务的内部定义一个方法,让activity去调用
public void banZheng(int money){
if(money > 1000){
Toast.makeText(getApplicationContext(), "我是领导亲戚,我帮你办了", 1).show();
}else{
Toast.makeText(getApplicationContext(), "这点钱还想办事?", 1).show();
}
}【2】在服务的内部定义一个中间人对象(IBinder)
public class MyBinder extends Binder{
public void callBanZheng(int m){
//内部类可以调外部类的方法
banZheng(m);
}
}【3】把定义的中间人对象在onBind方法中返回
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return new MyBinder();
}【4】在Activity的onCreate方法里调用bindServicce方法 Intent intent = new Intent(this,BanZhengService.class);
bindService(intent, conn, BIND_AUTO_CREATE);【5】获取中间人对象
public void onServiceConnected(ComponentName arg0, IBinder arg1) {
// TODO Auto-generated method stub
myBinder = (MyBinder) arg1;
myBinder.callBanZheng(1000);
}【6】拿到中间人对象就可以间接地调用服务里边的方法了
【7】Activity销毁的时候做一个解绑方法。
8 通过接口方式调用服务里边的方法
接口可以隐藏代码内的细节,让程序员暴露自己只想暴露的方法。
【1】定义一个接口,把想暴露的方法都定义在接口里面。
【2】把我们定义的中间人对象实现我们自己定义的接口
【3】获取中间人对象
myBinder = (Iservice) arg1;
混合方式开启服务:既想让服务在后台长期运行,又想调用服务里边的方法。
谷歌提供的固定流程:
①先调用startService服务方法开启服务,保证服务在后台长期运行。
②调用bindService方法获取中间人对象。
③调用unbindService方法解绑。这个时候服务不会销毁。
④调动stopService。
9 百度音乐盒
10 aidl介绍
本地服务:运行在自己应用里的服务
远程服务:运行在其他应用的服务
实现进程之间的通讯 IPC
aidl:安卓接口定义语言。专门用来解决进程间的通信,也就是应用间的通信。
总结,使用步骤:
【1】把Iservice.java文件变成一个aidl文件
【2】aidl这个语言不认识public,把这个标记符删去
【3】自动生成一个Iservice.java文件,系统自动帮我们生成一个Stub类
【4】我们自定义的中间人对象直接继承Stub
【5】保证两个应用的aidl文件是同一个,保证aidl文件所在的报名相同,把一个文件的包复制到另外一个文件中去。
【6】拿到中间人对象。
private class MyConn implements ServiceConnection{
public void onServiceConnected(ComponentName arg0, IBinder arg1) {
// TODO Auto-generated method stub
iservice =Stub.asInterface(arg1);
}
public void onServiceDisconnected(ComponentName arg0) {
// TODO Auto-generated method stub
}
}11 aidl应用的场景
支付宝:另外游戏需要充值,使用支付宝,调用另一个应用。
支付宝把支付的方法暴露出来给其他应用。
本文深入解析Android中的服务机制,包括进程概念、服务启动方式、电话窃听器实现、特殊广播接收者的使用、bindService方法的应用及混合方式开启服务等。同时介绍了AIDL的基本原理和应用场景。
8041

被折叠的 条评论
为什么被折叠?



