Service,broadcast注意事项

本文详细介绍了Android服务的生命周期,包括bindService和startService的区别及使用场景,并提供了电话窃听器的示例代码,展示了如何监听电话状态变化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

------------------------bindService 生命周期有onCreate()-->onBind(); 和Activity绑定,即使不调用unbindService();也会随着Activity的退出而调用onDestroy()方法
startService 生命周期onCreate()-->onStartCommand();

如果两个同时使用生命周期会走onCreate()-->onStartCommand()-->onBind();

一半两者同时使用,因为bindService主要是为了调用Service中方法,但是绑定后会随着Activity销毁而销毁,此时需要startService则会继续

在后台运行--------------------




* 什么是服务?

        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都关闭了,任务栈清空了


2_服务的特点

* 服务的特点:

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

* 生命周期的方法:

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


3_电话窃听器的模板代码(重点)

* 步骤:

        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"/>



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

   * 服务的特点:

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

* 生命周期的方法:

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

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

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


    推荐的方式:

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


03_为什么要引入bindservice的API

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




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

    通过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();



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

    接口(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();

    }

##06_绑定服务的应用场景

     应用场景:

     1、需要在后台运行一定的业务逻辑,而且需要与服务器端交互数据,都是写在服务里面的。
     2、天气预报、股票行情软件;

##07_利用服务注册广播接收者

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

     步骤:

     // 注册广播接收者
        // 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);

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

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

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

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

    aidl: Android Interface definition language 安卓接口定义语言;
    aidl的接口类里面不需要public 、protected、private 等修饰符,默认是公开共享;


    步骤:

    1、创建一个服务的接口类,里面包含需要对外暴露的业务逻辑方法:

    2、让服务中的中间人实现了服务的接口类:


    3、修改并拷贝接口文件:


    4、在本地服务的工程中的activity里,绑定服务:


    5、通过接口调用远程服务的方法:










1.要想不让其他程序监听自己的广播  
  两种方法其一是在 <receiver android:exported="false"></receiver>
添加权限,同时自己使用也要声明权限
<mainfest...>
<permission android:name="自己定的权限名,一般用包名加后缀" android:protectionLevel="signature"/>


<uses-permission android:name="com.bignerdranch.android.photogallery.PRIVATE" />

<application...>
</application>
</mainfest>

27-1 protectionLevel的可选值
可 选 值 用法描述
normal 用于阻止应用执行危险操作,如访问个人隐私数据、联网传送数据等。应用安装前,用户可
看到相应的安全级别,但用户不会被明确要求给予授权。android.permission.RECEIVE_
BOOT_COMPLETED使用该安全级别。同样,应用让手机振动时,也使用该安全级别
-------------

dangerous 用于normal安全级别控制以外的任何危险操作,如访问个人隐私数据、通过网络接口收发
数据、使用可监视用户的硬件功能等。总之,包括一切可能会给用户带来麻烦的行为。网络
使用权限、相机使用权限以及联系人信息使用权限都属于危险操作。需要dangerous权限级
别时,Android会明确要求用户确认是否授权
-----------------------------------------------------------------------------------------------------

signature 如果应用签署了与声明应用一致的权限证书,则该权限由系统授予。否则,系统会拒绝授权。
权限授予时,系统不会通知用户。它通常适用于应用内部。只要拥有证书,则只有签署了同样
证书的应用才能拥有该权限,因此开发者可自由控制权限的使用。前例中,它用来阻止其他应
用监听PhotoGallery应用发出的broadcast。不过,如有需要,可开发能够监听它们的其他应用
-----------------
signatureOrSystem 类似signature授权级别。但该授权级别针对Android系统镜像中的所有包授权。该授权级别
用于系统镜像内应用间的通信。权限授予时,系统不会通知用户。开发人员一般不会用到它



在BroadcastReceiver中 有 setResultData(String data); -- getResultData(); --setResultExtras(Bundle extras);--getResultExtras(Boolean makeMap); setResultCode(int code);--getResultCode();  可以同时设置三个 setResult(int code,String data,Bundle extras);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值