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、通过接口调用远程服务的方法:
  • 相关阅读:
    linux 短信收发
    sama5d3 环境检测 adc测试
    【Codeforces 723C】Polycarp at the Radio 贪心
    【Codeforces 723B】Text Document Analysis 模拟
    【USACO 2.2】Preface Numbering (找规律)
    【Codeforces 722C】Destroying Array (数据结构、set)
    【USACO 2.1】Hamming Codes
    【USACO 2.1】Healthy Holsteins
    【USACO 2.1】Sorting A Three-Valued Sequence
    【USACO 2.1】Ordered Fractions
  • 原文地址:https://www.cnblogs.com/fanchcho/p/9233979.html
Copyright © 2011-2022 走看看