Android10-广播和服务(二)

1.进程的概念

1:在Android中,大多数的应用都跑在一个Linux进程中(也可以跑在多个进程中,只是少数),所有的组件(Activity、Service、BroadcastReceiver、ContentProvider)都运行在一个线程中(主线程)。
2:四大组件进行耗时的操作都需要开启子线程,如联网操作。

2.进程的优先级

1:Foreground process,前台进程。Activity正在和用户进行交互,即onResumen方法被调用;或者广播接受者正在执行onReceiver方法;Service正在执行声明周期方法。前台进程几乎不会被系统杀死。
2:Visible process,可视进程。Activity正处于onPause状态,可见但是不能被操作。当前台进程内存不足的时候回杀死可视进程。
3:Service process,服务进程。使用startService开启了一个服务,并且运行在后台,没有其他组件处于Visible process和Foreground process状态。服务进程也很少会被杀死。
4:Background process,后台进程。Activity处于onStop状态,但是没有被销毁。通常会有大量的应用处于后台状态。系统使用LRU算法来保存这些应用,使得最早使用的先被杀死。
5:Empty process,空进程。没有任何组件运行,空进程的作用和数据库连接池起到的作用相似,最容易被杀死。

3.服务-Service

1:Service可以长时间的运行在后台,比在后台运行的Activity优先级高。
2:Service和Activity的声明周期类型,但是没有Activity与用户交互的部分。所以没有onResume、onPause、onStop方法。Service有onCreate、onStartCommand、onDestory方法。
3:当第一次开启服务是会执行onCreate、onStartCommand,再次开启只执行onStartCommand。
4:Service的创建和Activity一样,都是通过Intent进行创建。而且需要在清单文件中进行注册。
public class MyService extends Service {

	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void onCreate() {
		super.onCreate();
		System.out.println("onCreate");
	}
	
	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		System.out.println("onStartCommand");
		return super.onStartCommand(intent, flags, startId);
	}
	
	@Override
	public void onDestroy() {
		super.onDestroy();
		System.out.println("onDestroy");
	}
}

public void start(View v){
    Intent intent = new Intent(this,MyService.class);
    startService(intent);
}

public void stop(View v){
    Intent intent = new Intent(this,MyService.class);
    stopService(intent);
}
<service android:name="com.my.androidpro8.MyService"></service>

4.开机录音电话监听

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }


    public void start(View v){
    	Intent intent = new Intent(this,RecordService.class);
    	startService(intent);
    }
    
    public void stop(View v){
    	Intent intent = new Intent(this,RecordService.class);
    	stopService(intent);
    }
}

public class RecordService extends Service {

	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void onCreate() {
		//使用上下文创建打电话的管理器
		TelephonyManager manager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
		//进行电话的监听,第一个参数是一个监听对象,第二个参数是监听的状态
		MyPhoneStateListener listener = new MyPhoneStateListener();
		manager.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);
	}
	
	private class MyPhoneStateListener extends PhoneStateListener {
		
		private MediaRecorder recorder;

		/*
		 * (non-Javadoc)
		 * @see android.telephony.PhoneStateListener#onCallStateChanged(int, java.lang.String)
		 * 这个方法,可以通过state参数来判断,电话的状态
		 * 有三种状态,
		 * CALL_STATE_IDLE 空闲
		 * CALL_STATE_RINGING 有人打进电话,但没有接,响铃
		 * CALL_STATE_OFFHOOK 正在通话
		 */
		@Override
		public void onCallStateChanged(int state, String incomingNumber) {
			super.onCallStateChanged(state, incomingNumber);
			
			if(state == TelephonyManager.CALL_STATE_IDLE){
				System.out.println("空闲");
				//使用try-catch处理,响铃之后,直接挂了
                //这样不会走recorder.start();方法,如果进行stop,会出现错误
                //因为recorder是按照指定的流程执行的
                try {
                    recorder.stop();
                    //重置recorder 可以再次通过setAudioSource使用
                    recorder.reset();   // You can reuse the object by going back to setAudioSource() step
                    recorder.release(); // Now the object cannot be reused
                } catch (Exception e) {
                    // TODO: handle exception
                }
			}else if(state == TelephonyManager.CALL_STATE_RINGING){
				System.out.println("响铃");
				recorder = new MediaRecorder();
				//设置音频的输入源,MIC只是对自己的录音,VOICE_CALL是双方的录音
				recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
				//设置音频输出的保存格式 3gp
				recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
				//设置音频的编码 
				recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
				//设置音频的保存路径
				recorder.setOutputFile(getCacheDir() + "/" + incomingNumber + ".3gp");
				//开始准备
				try {
					recorder.prepare();
				} catch (IllegalStateException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}else if(state == TelephonyManager.CALL_STATE_OFFHOOK){
				System.out.println("通话");
				//开始录音
				recorder.start();   // Recording is now started
			}
		}
	}
}

public class MyBroadcateReceiver extends BroadcastReceiver {

	@Override
	public void onReceive(Context context, Intent intent) {
		//开机之后注册这个服务,进行电话监控
		Intent intent2 = new Intent(context,RecordService.class);
		context.startService(intent2);
	}

}
<!-- 电话监听权限 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<!-- 录音权限 -->
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<!-- 开机广播 -->
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<!-- 通过intent-filter拦截到启动启动的消息之后,使用MyBroadcateReceiver的onReceive方法进行广播 -->
<receiver android:name="com.my.androidpro28.MyBroadcateReceiver">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
    </intent-filter>
</receiver>
<service android:name="com.my.androidpro28.RecordService"></service>

5.onBind绑定服务

1:绑定服务,使得服务和当前的Activity进行绑定。所以应该在当前Activity的onDestory方法中调用服务unbindService方法进行解绑。
2:使用onBind创建服务。开启服务的时候会走onCreate、onBind(这个方法只执行一次)、onServiceConnected(如果onBind方法方法不为null),服务的销毁会走onDestroy方法。其中服务不能进行二次销毁,会抛出异常。在使用onBind创建服务时,不会调用onBind创建服务方法。
3:ServiceConnection。实现这个接口之后,可以监听服务和当前Activity的绑定。
4:IBinder。实现这个接口可以选择extends Binder,这是一个内部类,他又外部类的引用,所以我们可以通过这个类实现当前Activity和Service之间的通信。
public class MainActivity extends Activity {

    private MyServiceConnection conn;
    private MyBinder myBinder;

	@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }


    public void start(View v){
    	Intent service = new Intent(this,MyService.class);
    	conn = new MyServiceConnection();
    	//通过Service的onBind开启
    	//第一个参数是这个类的Intent
    	//ServiceConnection第二个参数,用来监听应用服务的状态,即服务和Activity是否绑定
    	//开启服务的选项,一般选择BIND_AUTO_CREATE,会自动创建Service
    	bindService(service, conn, BIND_AUTO_CREATE);
    }
    
    
    public void stop(View v){
    	//进行服务的解绑
    	unbindService(conn);
    }
    
    @Override
    protected void onDestroy() {
    	// TODO Auto-generated method stub
    	super.onDestroy();
    	//关闭服务,接触和当前Activity的绑定
    	unbindService(conn);
    }
    
    public void toast(View v){
    	myBinder.showToast1("hello");
    	myBinder.showToast2("hello hello");
    }
    
    private class MyServiceConnection implements ServiceConnection {

		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			//当onBind的返回值不是null的时候,会调用这个方法
			System.out.println("onServiceConnected");
			myBinder = (MyBinder) service;
		}

		@Override
		public void onServiceDisconnected(ComponentName name) {
			//正常退出服务不会调用
			System.out.println("onServiceDisconnected");
		}
    	
    }
}

public class MyService extends Service {

	@Override
	public IBinder onBind(Intent intent) {
		System.out.println("onBind");
		MyBinder myBinder = new MyBinder();
		return myBinder;
	}
	
	public void showToast(String s){
		Toast.makeText(getApplicationContext(), s, Toast.LENGTH_SHORT).show();
	}
	
	public class MyBinder extends Binder {
		public void showToast1(String s){
			showToast(s);
		}
		
		public void showToast2(String s){
			Toast.makeText(getApplicationContext(), s, Toast.LENGTH_SHORT).show();
		}
	}

	@Override
	public void onCreate() {
		System.out.println("onCreate");
		super.onCreate();
	}
	
	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		System.out.println("onStartCommand");
		return super.onStartCommand(intent, flags, startId);
	}
	
	@Override
	public void onDestroy() {
		System.out.println("onDestroy");
		super.onDestroy();
	}
}

6.混合式音乐播放器

1:bindService保证当前Activity可以使用音乐提供的服务。
2:startService保证当前Activity不可见(后台播放),可以播放音乐。
3:startService会依次执行onCreate、onStartCommand方法。每执行一次startService就会执行一次onStartCommand方法。
4:bindService会依次执行onCreate、onBind、onServiceConnected方法。如果使用混合式开启服务,执行bindService,如果已经创建了服务对象就不会执行onCreate方法,但是依然会执行onBind,onBind也只在第一次执行bindService后执行。如果onBind方法返回值不是null,则会执行onServiceConnected,而且每次执行bindService都会执行一次bonServiceConnected。
5:混合式开启服务,只有unbindService、stopService都执行了,才会执行Service的onDestory方法。
public class MainActivity extends Activity {
	
	private MyBinder myBinder;
	private MyServiceConnection conn;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        Intent intent = new Intent(this,MusicPlayerService.class);
        conn = new MyServiceConnection();
        
        //混合使用两种方式开启音乐服务
        //bindService保证当前Activity可以使用音乐提供的服务
        //startService保证当前Activity不可见(后台播放),可以播放音乐
        bindService(intent, conn, BIND_AUTO_CREATE);
        startService(intent);
    }
    
    public void pre(View v){
		myBinder.myPre();
	}
	public void pause(View v){
		myBinder.myPause();
	}
	public void play(View v){
		myBinder.myPlay();
	}
	public void next(View v){
		myBinder.myNext();
	}
	
	@Override
	protected void onDestroy() {
		// 当前音乐不可见后,只是将当前Activity和服务进行解绑
		unbindService(conn);
		super.onDestroy();
		System.out.println("on-------------------------");
	}
    
    private class MyServiceConnection implements ServiceConnection {

		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			//当onBind返回Binder之后执行这个方法
			myBinder = (MyBinder) service;
		}

		@Override
		public void onServiceDisconnected(ComponentName name) {
			
		}
    	
    }
}

public class MusicPlayerService extends Service {

	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		return new MyBinder();
	}
	
	public class MyBinder extends Binder {
		public void myPre(){
			pre();
		}
		
		public void myPause(){
			pause();
		}
		
		public void myPlay(){
			play();
		}
		
		public void myNext(){
			next();
		}
	}
	
	public void pre(){
		System.out.println("播放上一首");
	}
	public void pause(){
		System.out.println("停止播放");
	}
	public void play(){
		System.out.println("开始播放");
	}
	public void next(){
		System.out.println("播放下一首");
	}

	@Override
	public void onCreate() {
		// TODO Auto-generated method stub
		super.onCreate();
		System.out.println("开始播放音乐");
	}
	
	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		System.out.println("onStartCommand");
		return super.onStartCommand(intent, flags, startId);
	}
	
	@Override
	public void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
		System.out.println("onDestroy-----");
	}
}

7.AIDL

1:AIDL,Android Inferface Definition Language,安卓接口定义语言。Android系统中的进程之间不能共享内存,为了可以跨进程通信,可以采用RPC(远程过程调用,Remote Procedure Call),而AIDL解决RPC的问题,保证了跨进程的方法调用。
2:IPC,inter process communication,进程间通信。每一个安卓应用运行在独立的进程中,所以应用之间的通信就是进程间的通信。如Activity、BroadcastReceiver采用Intent携带数据进行通信。

8.跨应用调用

public class MainActivity extends Activity {
	
	private IService iService;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        //使用隐式意图,进行Intent服务的过滤
        Intent intent = new Intent();
        intent.setAction("com.my.remoteService");
        
        MyServiceConnection conn = new MyServiceConnection();
        //跨应用调用这个服务
        bindService(intent, conn, BIND_AUTO_CREATE);
    }


    public void remoteCall(View v) throws RemoteException{
    	iService.callMethod();
    }
    
    public class MyServiceConnection implements ServiceConnection {

		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			//这个时候,只是跨应用的开启服务,不能使用这个Service提供的服务
	        //要使用它提供的服务,就要在这个应用中也创建提供服务应用的同名包,然后将aidl文件复制过来
			//使用Stub的静态方法传入IBinder就可以获取,自己在服务中所写的内部类,用来调用服务
			iService = Stub.asInterface(service);
		}

		@Override
		public void onServiceDisconnected(ComponentName name) {
			
		}
    	
    }
}

public class RemoteService extends Service{

	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		return new MyBinder();
	}
	
	//Stub extend Binder implements IService,所以可以直接extends Stub
	public class MyBinder extends Stub {

		@Override
		public void callMethod() {
			method();
		}
		
	}

	public void method(){
		System.out.println("method");
	}
}

//将接口.java文件改为.aidl文件,这个文件不能使用public关键字,如果没有问题就会在gen目录下生成IService.java
interface IService {

	void callMethod();
}
<!-- 声明服务,同时配置intent-filter,使得其他应用可以使用隐式意图调用开启这个服务 -->
<service android:name="com.my.myservice.RemoteService" >
    <intent-filter>
        <action android:name="com.my.remoteService" />
    </intent-filter>
</service>
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值