Android 广播&服务

BroadCastReceiver

  • 广播接收者,Android四大组件之一
  • 用于接收广播Intent的,广播Intent的发送是通过调用sendBroadCast/sendOrderBroadCast来实现的,通常一个广播Intent可以被订阅了此Intent的多个广播接收者所接收。

广播

  • Android中系统通过广播发布信息,只需要注册广播接受者
  • Android系统运行过程中可能产生很多事件,当这些事件发生时,系统希望通知到其他应用知道这个事件,所以会发出广播。
  • 如:开机、电量改变、收发短信、拨打电话、屏幕开关。

定义广播接收者

  • 必须在清单文件中配置
  • 通过<intent-filter>设置接收什么广播
  • 广播中包含一个intent,当广播发出时,系统会遍历
  • 如果广播接收者被用户手动停止,那么再也不会启动了。知道用户下一次手动启动该进程,广播接收者才会生效。

广播分类

无序广播:

  • 所有与广播中的Intent匹配的广播接收者都能收到这条广播,并且接收顺序不分先后
  • 无序广播不可以被拦截,如果拦截的话会报错
  • 无序广播使用sendBroadcast方法来发送

有序广播:

  • 所有与广播中的Intent匹配的广播接收者都能收到这条广播,但是要按照广播接收者的优先级
  • 有序广播可以被拦截,且优先级高的接收者可以拦截优先级低的
  • 广播接收者的优先级取值范围-1000(最低)~1000(最高)
  • 相同优先级下,接收的顺序要看在清单文件中声明的顺序,先声明的接收者比后声明的要先接收到广播。
  • 无序广播使用sendOrderedBroadcast方法来发送,使用abortBroadcast方法拦截
  • 广播接收者的优先级在清单文件中声明接收者时,在<intent-filter>标签下通过设置"android:property"属性来设置。

注册一个广播接收者有两种方式

静态注册

  • 在清单文件中添加如下配置

    <!-- 配置广播接收者 -->
    <receiver android:name="com.istarry.ipbohao.IpCallReceiver" >
        <intent-filter>
    
            <!-- 指定接收那个广播 -->
            <action android:name="android.intent.action.NEW_OUTGOING_CALL" />
            <!-- <data android:scheme=" " /> -->
        </intent-filter>
    </receiver>
    

动态注册:在java代码中注册

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        IntentFilter intentFilter = new IntentFilter("android.intent.action.MEDIA_UNMOUNTED");
        intentFilter.addDataScheme("file");
        registerReceiver(new IpCallReceiver(), intentFilter);
    }
}

注意:

  • java代码注册的广播接收者优先级要比清单文件的要高,但是当前的广播接收者的声明周期的期限和Activity是相关联的,Activity销毁,广播接收者也就不再起作用。
  • 通过清单文件注册的广播接收者在系统中运行一次后就会被注册到系统中,以后无需运行此广播接收者,但是也可以收的到广播。
  • 接收广播时要注意在清单文件中添加对应的权限。

IP拨号器

  • 需求:

    • 监听用户拨打电话,在用户拨打电话号码前加上17951
  • 1.拦截广播

            <!-- 指定接收(拦截)那个广播 -->
            <action android:name="android.intent.action.NEW_OUTGOING_CALL" />           
    
  • 2.需要的权限

    <uses-permission android:name="android.permission.PROCESSOUTGOINGCALLS" />

  • 3.创建一个类IpCallReceiver继承BroadCastReceiver

    public class IpCallReceiver extends BroadcastReceiver {
        //当收到广播时,此方法调用
        @Override
        public void onReceive(Context arg0, Intent arg1) {
            //添加17951线路
            //1.拿到用户拨打的号码
            //广播会发送一个Intent,携带数据
            String number = getResultData();
            //在号码前加上17951,并返回数据
            setResultData("17951"+number);
        }
    }
    
  • 4.在清单文件中注册广播接收者

       <application
        …… >
        …………
        <!-- 配置广播接收者 -->
            <receiver android:name="com.istarry.ipbohao.IpCallReceiver" >
             <!-- android:priority="1000"代表着给当前接收者设置优先级,优先级越高就越先接收到广播,取值-1000~1000 -->
                <intent-filter android:priority="1000">
    
                <!-- 指定接收那个广播 -->
                <action android:name="android.intent.action.NEW_OUTGOING_CALL" />
                <!-- <data android:scheme=" " /> -->
              </intent-filter>
            </receiver>
        …………
    

 


Service

  • Service在Android中是一种长生命周期的组件,它不识闲任何用户界面,是一个没有界面的Activity。
  • Service长期在后台运行,执行不关乎界面的一些操作。比如:网易新闻服务,每隔一分钟去服务查看是否有最新新闻。
  • Service和Thread有点相似,但是使用Thread不安全,不严谨。
  • Service和其他组件一样,都是运行在主线程中,因此不能用它来做好事的操作

Android中的进程

Android中的进程种类

进程优先级由高到低,依次为:

  • 1. Foreground process 前台进程(拥有一个正在用户交互的Activity进程,即onResume()方法被调用)
  • 2. Visible process 可视进程,可以看见,但是不可以交互。(拥有一个不在前台但是依然可见的Activity,即onPause()方法被调用)
  • 3. Service process 服务进程(正在运行一个通过starService()方法启动的服务进程)
  • 4. Background process 后台进程(进Activity的onStop方法被调用)
  • 5. Empty process 空进程(当程序退出时,进程没有被销毁,而是变成了空进程)。即没有任何组件活动的进程(进程中没有服务也没有Activity)

进程的回收机制

Android

电话录音机

电话状态

TelephonyManager,设置PhoneStateListener监听状态

  • 空闲
  • 响铃
  • 摘机状态(接听)

权限

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

配置清单文件

<service android:name="com.istarry.luyinji.LuyinjiService" />

创建一个类LuyinjiService继承Service

public class LuyinjiService extends Service {
    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        return null;
    }
    @Override
    public void onCreate() {
        // TODO Auto-generated method stub
        super.onCreate();
        // 获取电话管理器
        TelephonyManager tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
        // 设置侦听
        // 参数2:设置监听器只监听什么数据
        tm.listen(new MyListener(), PhoneStateListener.LISTEN_CALL_STATE);
    }
    private MediaRecorder recorder;
    class MyListener 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:
                System.out.println("空闲");
                if (recorder != null) {
                    // 停止录音
                    recorder.stop();
                    // 释放占用的资源
                    recorder.release();
                    recorder = null;
                }
                break;
            case TelephonyManager.CALL_STATE_RINGING:
                System.out.println("响铃");
                if (recorder == null) {
                    recorder = new MediaRecorder();
                    // 设置录音源
                    recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
                    // 设置录音格式3gp格式
                    recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
                    // 设置录音文件保存位置
                    recorder.setOutputFile("sdcard/voice.3gp");
                    // 设置音频编码(一种格式可能有多重种编码方式)
                    recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
                    try {
                        // 准备完毕,随时可以录音
                        recorder.prepare();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                break;
            case TelephonyManager.CALL_STATE_OFFHOOK:
                System.out.println("摘机");

                if (recorder != null) {
                    recorder.start();
                }
                break;
            }
        }
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // TODO Auto-generated method stub
        return super.onStartCommand(intent, flags, startId);
    }
}

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。