zoukankan      html  css  js  c++  java
  • 安卓基础干货(八):安卓进程的学习

    服务和进程优先级

    • 什么是服务?

      windows下的服务:没有界面、长期运行在后台的应用程序;

      android下的服务:应用程序的一个组件,没有界面activity,长期运行在后台;

      进程:是应用程序运行的载体。

      进程与应用程序之间的关系: linux操作系统创建一个进程,这个进程负责运行dalvik虚拟机,Android的应用程序都是运行在dalvik虚拟机上的。

    • 进程的生命周期:

      1、应用程序一启动的时候就创建了进程;

      2、当应用程序退出的时候进程并没有退出;

      3、只有手工停止这个进程,进程才会结束;

      操作系统尽量长时间的运行应用程序的进程,为了保证内从空间不被大量占用,它会按照进程的优先级,从低到高一级一级的杀死进程,直到内存空间被清理的差不多。

    进程的等级:

    1. Foreground process(前台进程)

       应用程序,用户正在操作,activity的onresume方法被执行了,可以相应点击事件。
      
    2. Visible process (可视进程)

       应用程序的ui界面,用户还可以看到,但是不能操作了。
      
    3. Service process (服务进程)

       应用程序没有界面,但是有一个后台的服务还处于运行状态
      
    4. Background process(后台进程)

       应用程序没有服务处于运行状态,应用程序被最小化了,activity执行了onstop方法
      
    5. Empty process(空进程)

       没有任何组件运行,所有的activity都关闭了,任务栈清空了
      

    服务的特点

    • 服务的特点:

        服务被创建时调用onCreate、onStartCommand;
        服务只能被创建一次,可以开启多次onStartCommand;
        服务只能被停止一次; 
        没有onPause、onStop、onResume、onRestart方法,因为service没有界面,长期运行在后台。
      
    • 生命周期的方法:

        onCreate:服务被创建的时候调用这个方法;
        onStartCommand :开启服务
        onDestroy:销毁服务
      

    电话监听器的模板代码(重点)

    • 步骤:

        1、在工程中添加一个服务Service,重写onCreate方法;
        2、在清单文件中配置服务;
        3、在activity中开启服务;
        4、在onCreate方法中使用TelephonyManager监听电话的状态;
        5、在清单配置文件中添加权限
      
    • 示例代码:

      1、在工程中添加一个服务Service,重新onCreate方法:

        public class DHQTService extends Service {
        	/**
        	* 当服务被创建的时候调用这个方法
        	*/
        	@Override
        	public void onCreate() {
        	System.out.println("=========onCreate=========");
        	super.onCreate();
        	
        	TelephonyManager tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
        	
        	tm.listen(new MyListener(), PhoneStateListener.LISTEN_CALL_STATE);
        	
        	}
        }
      

      2、在清单文件中配置服务:

        <service android:name="com.itheima.dhqtq.DHQTService"></service>
      

      3、在activity中开启服务:

        service = new Intent(this,DHQTService.class);
        //开启服务
        startService(service);	
      

      4、在onCreate方法中使用TelephonyManager监听电话的状态:

        /**
         * 当服务被创建的时候调用这个方法
         */
        @Override
        public void onCreate() {
        	System.out.println("=========onCreate=========");
        	super.onCreate();
      
        	TelephonyManager tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
      
        	tm.listen(new MyListener(), PhoneStateListener.LISTEN_CALL_STATE);
      
        }
      
      
        /**
        *自定义一个电话状态监听,监听电话
        */
        private class mylistener extends phonestatelistener {
      
        	private MediaRecorder r;
      
        	@Override
        	public void onCallStateChanged(int state, String incomingNumber) {
      
        		try {
        			// super.onCallStateChanged(state, incomingNumber);
        			System.out.println("====state===============" + state);
        			switch (state) {
        			case TelephonyManager.CALL_STATE_IDLE:// 闲置状态
        				System.out.println("关闭录音机,上传音频文件..................");
        				if(r != null){
        					r.stop();
        					r.release();
        					r = null;
        					//上传文件
        				}
        				break;
      
        			case TelephonyManager.CALL_STATE_RINGING:// 闲置状态
        				System.out.println("准备好录音机,准备录音..................");
      
        				r = new MediaRecorder();
        				
        				r.setAudioSource(MediaRecorder.AudioSource.MIC);
        				r.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
        				
        				//r.setOutputFile("/mnt/sdcard/info.3gp");
        				r.setOutputFile(Environment.getExternalStorageDirectory()+"/info.3gp");
        				r.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
        				r.prepare(); 
      
        				break;
      
        			case TelephonyManager.CALL_STATE_OFFHOOK:// 闲置状态
        				System.out.println("开始录音..................");
        				r.start();
        				break;
      
        			}
        		} catch (Exception e) {
        			e.printStackTrace();
        		}
        	}
        }
      

      5、在清单配置文件中添加权限:

        <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
        <uses-permission android:name="android.permission.RECORD_AUDIO"/>
        <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
      

    start开启服务的生命周期(重点)

    • 服务的特点:

      服务被创建时调用onCreate、onStartCommand;

      服务只能被创建一次,可以开启多次onStartCommand;

      服务只能被停止一次;

      没有onPause、onStop、onResume、onRestart方法,因为service没有界面,长期运行在后台。

    • 生命周期的方法:

        onCreate:服务被创建的时候调用这个方法;
        onStartCommand :开启服务
        onDestroy:销毁服务
      

    bind方式开启服务的生命周期(重点)

    bindService绑定服务、unBindService解除绑定的服务;
    服务是在被绑定的时候被创建,调用oncreate、onbind方法;
    服务只能被绑定一次;
    服务只能被解除一次,接触绑定的时候调用onUnbind、onDestrory方法,如果多次解除绑定会抛出异常;
    

    推荐的方式:

    startService:开启并创建一个服务,服务长期运行在后台;
    bindService:绑定服务,可以调用服务里面的方法;
    unBindService:解除服务,停止服务里面的方法;
    stopService:停止服务,销毁服务对象;
    

    为什么要引入bindservice的API

    为了调用服务中的业务逻辑方法。

    绑定服务调用服务方法的过程

    通过bindservice方式实现调用服务里面业务逻辑方法:

    步骤:

    1、在服务类中创建一个中间人MyBinder,继承了Binder,Binder实现了IBinder接口:
    	public class MyBinder extends Binder{
    	}
    
    2、在服务类里面创建了一个MyBinder的成员变量:
    	private MyBinder myBinder;
    
    3、在MyBinder类中写一个方法用于调用服务的业务逻辑方法:
    	public class MyBinder extends Binder{
    	
    		//使用中间人调用服务里的方法
    		public void callMethodInService(){
    			methodInService();
    		}
    		
    	}
    
    4、在activity中bindService时,定义了ServiceConnection,在这个连接中实现了两个:
    
    	private class MyConn implements ServiceConnection {
    		/**
    		 * 服务连接成功时调用这个方法
    		 */
    		@Override
    		public void onServiceConnected(ComponentName name, IBinder service) {
    			//得到服务绑定成功后返回的中间人MyBinder对象
    			myBinder = (MyBinder) service;
    
    		}
    
    		/**
    		 * 服务断开成功时调用这个方法
    		 */
    		@Override
    		public void onServiceDisconnected(ComponentName name) {
    			System.out.println("-------onServiceDisconnected-------");
    		}
    	}
    
    5、通过在activity中通过中间人条用服务的业务逻辑方法:
    	myBinder.callMethodInService();
    

    绑定服务抽取接口(重点)

    接口(interface): 对外开放暴露的功能,但是不会暴露功能实现的细节;
    让中间人实现服务接口的目的:只对外暴露接口里面业务逻辑方法,隐藏中间人里面的其他方法;

    步骤:
    1、创建一个服务的接口类,里面包含需要对外暴露的业务逻辑方法:
    	public interface IService {
    	public void callMethodInService();
    }
    
    2、让服务中的中间人实现了服务的接口类:
    	private class MyBinder extends Binder implements IService{
    	
    	//(实现服务接口中的方法)使用中间人调用服务里的方法
    	public void callMethodInService(){
    		methodInService();
    	   }
    	}
    
    3、在activity中声明接口的成员变量:
    	private IService myBinder;
    
    4、强制转换成服务的接口类型
    	private class MyConn implements ServiceConnection {
    
    	/**
    	 * 服务连接成功时调用这个方法
    	 */
    	@Override
    	public void onServiceConnected(ComponentName name, IBinder service) {
    		//强制转换成服务的接口类型
    		myBinder = (IService) service;
    	}
    
     5、在activity中通过接口的成员变量调用服务的业务逻辑方法:
    	public void call(View view){
    	myBinder.callMethodInService();
    
    }
    

    绑定服务的应用场景

    应用场景:

    1、需要在后台运行一定的业务逻辑,而且需要与服务器端交互数据,都是写在服务里面的。

    2、天气预报、股票行情软件;

    利用服务注册广播接收者

    操作频繁的广播事件,如果只是在清单配置文件配置,是不生效的。需要使用代码注册才能生效;

    步骤:
    // 注册广播接收者
    // 1、得到广播接收者的对象
    
    ScreenBroadCastReceiver screenReceiver = new ScreenBroadCastReceiver();
    
    // 2、创建一个intentFilter对象
    IntentFilter filter = new IntentFilter();
    
    // 3、注册接收的事件类型
    filter.addAction("android.intent.action.SCREEN_ON");
    filter.addAction("android.intent.action.SCREEN_OFF");
    
    // 4、注册广播接收者
    this.registerReceiver(screenReceiver, filter);
    

    远程服务aidl的写法(重点)

    本地服务:写在自己的应用程序的工程里的服务 ,使用自己应用程序的进程运行这个服务;

    远程服务:写在别的应用程序的工程里的服务,使用别的应用程序的进程运行这个服务(安装在同一个手机上的应用程序);

    IPC: Inter Process Communication(进程间的通讯);

    aidl: Android Interface definition language 安卓接口定义语言;

    aidl的接口类里面不需要public 、protected、private 等修饰符,默认是公开共享;

    步骤:
    1、创建一个服务的接口类,里面包含需要对外暴露的业务逻辑方法:	
    2、让服务中的中间人实现了服务的接口类:
    3、修改并拷贝接口文件:
    4、在本地服务的工程中的activity里,绑定服务:
    5、通过接口调用远程服务的方法:
  • 相关阅读:
    jQuery笔记(1)
    [bzoj 1878][SDOI2009]HH的项链
    [bzoj 1968][Ahoi2005]COMMON 约数研究
    [bzoj 1899][ZJOI2004]lunch 午餐
    [bzoj 1090][SCOI2003]字符串折叠
    CodeForces 1029E div3
    [bzoj 1270][BeijingWc2008]雷涛的小猫
    [bzoj 1260][CQOI 2007]涂色paint
    [AtCoder ARC101D/ABC107D] Median of Medians
    [luogu 1070]道路游戏(NOIP2009T4)
  • 原文地址:https://www.cnblogs.com/fanchcho/p/9233979.html
Copyright © 2011-2022 走看看