广播接收者android,电话拦截广播,电话接收者demo

55 篇文章 1 订阅

一、Android广播机制介绍

广播机制最大的特点就是发送方并不关心接收方是否接到数据,也不关心接收方是如何处理数据的。

Android中广播的是操作系统中产生的各种各样的事件。例如,收到一条短信就会产生一个收到短信息的事件。而Android操作系统一旦内部产生了这些事件,就会向所有的广播接收器对象来广播这些事件。

BraodcastReceiver(广播接收器)是为了实现系统广播而提供的一种组件,并且广播事件处理机制是系统级别的。比如,我们可以发出一种广播来测试是否收到短信,这时候就可以定义一个BraodcastReceiver来接受广播,当收到短信时提示用户。我们既可以用Intent来启动一个组件,也可以用sendBroadcast()方法发起一个系统级别的事件广播来传递消息。

我们也可以在自己的应用程序中开发BroadcastReceiver,然后把广播接收器这个类或者对象注册到Android操作系统上去,让操作系统知道现在有这样一个广播接收器正在等待接收Android操作系统的广播,即在自己的应用程序中实现BroadcastReceiver来监听和响应广播的Intent。

当有广播事件产生时,Android操作系统首先告诉注册到其上面的广播接收器产生了一个怎么样的事件,每个接收器首先判断是不是我这个接收器需要的事件,如果是它所需要的事件,再进行相应的处理。

例子,我们把骚扰电话的黑名单放到数据库中去,当接到电话时会产生一个接电话事件,事先在Android操作系统中注册一个BroadcastReceiver的对象,当产生事件的时候,会通知我们的广播接收器对象,接收器对象接收到消息之后,就会到数据库里面去取所有黑名单电话和接到的这个电话号码进行比较,如果匹配就直接挂掉。

二、注册BroadcastReceiver的方法

BroadcastReceiver用于监听被广播的事件(Intent),为了达到这个目的,BroadcastReceiver必须进行注册,注册的方法有以下两种:

1.静态注册

静态注册方式是在AndroidManifest.xml的application里面定义receiver并设置要接收的action。

静态注册方式的特点:不管改应用程序是否处于活动状态,都会进行监听。

[html] view plain copy

  1. <receiver android:name="MyReceiver">  
  2.     <intent-filter>  
  3.         <action android:name="MyReceiver_Action"/>  
  4.     </intent-filter>  
  5. </receiver>  

其中,MyReceiver为继承BroadcastReceiver的类,重写了onReceiver方法,并在onReceiver方法中对广播进行处理。<intent-filter>标签设置过滤器,接收指定action广播。
 

2.动态注册

动态注册方式在activity里面调用函数来注册,和静态的内容差不多。一个形参是receiver,另一个是IntentFilter,其中里面是要接收的action。

动态注册方式特点:在代码中进行注册后,当应用程序关闭后,就不再进行监听。

[java] view plain copy

  1. MyReceiver receiver = new MyReceiver();  
  2. //创建过滤器,并指定action,使之用于接收同action的广播  
  3. IntentFilter filter = new IntentFilter("MyReceiver_Action");  
  4. //注册广播接收器  
  5. registerReceiver(receiver, filter);  

三、发送广播

[java] view plain copy

  1. // 指定广播目标Action  
  2. Intent intent = new Intent("MyReceiver_Action");  
  3. // 可通过Intent携带消息  
  4. intent.putExtra("msg""发送广播");  
  5. // 发送广播消息  
  6. sendBroadcast(intent);  

四、注销BroadcastReceiver

[java] view plain copy

  1. //注销广播接收器  
  2. unregisterReceiver(receiver);  

 

注:

1.一般在onStart中注册BroadcastReceiver,在onStop中取消BroadcastReceiver。

2.一个BroadcastReceiver 对象只有在被调用onReceive(Context, Intent)时才有效,当从该函数返回后,该对象就无效的了,结束生命周期。

注意事项:

谷歌修改了8.0的广播机制之后,那么静态注册的自定义有序广播相当于功能是废掉了,因为它不会按照优先级继续向下传递,
而是在第一次发送有序广播的时候就需要指定组件名,并且之后不会自动的向下传递,只能在之后的广播接收者当中
再次使用发送有序广播的方式,相当于是废掉了

=========================================

demo

广播者: app

package com.glsite.myapplication;

import android.content.ComponentName;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

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

    public void click(View vaiew) {
        Toast.makeText(this,"被点击了", Toast.LENGTH_SHORT).show();
        Intent intent = new Intent();
        intent.setAction("com.alsite.ccav.XXMLZY");
        intent.putExtra("money","wumao");
        //要兼容8.0以上的手机系统需要多这么一步
        intent.setComponent(new ComponentName("com.glsite.wumaodae","com.glsite.wumaodae.MyReceiver"));
        sendBroadcast(intent);
    }
}

接收者:app

新建:BroadcastReceiver

package com.glsite.wumaodae;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;

public class MyReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
      Toast.makeText(context,"wozaixuex", Toast.LENGTH_SHORT).show();
        String money = intent.getStringExtra("money");
        System.out.println("wo li dao le :"+money);
    }
}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.glsite.wumaodae">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <receiver
            android:name=".MyReceiver"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="com.alsite.ccav.XXMLZY"/>
            </intent-filter>
        </receiver>

        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

 

===================================================

拨打电话拦截app

在APP中保存区号,拨打电话时在电话前加上区号;

1.运行时权限

BaseActivity.java

package com.glsite.ipcall;

import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.widget.Toast;

/**
 * @author Admin
 * @version $Rev$
 * @des ${TODO}
 * @updateAuthor $Author$
 * @updateDes ${TODO}
 */
public class BaseActivity extends AppCompatActivity {
    //**************** Android M Permission (Android 6.0权限控制代码封装)
    private int permissionRequestCode = 88;
    private PermissionCallback permissionRunnable;

    public interface PermissionCallback {
        void hasPermission();

        void noPermission();
    }

    /**
     * Android M运行时权限请求封装
     *
     * @param permissionDes 权限描述
     * @param runnable      请求权限回调
     * @param permissions   请求的权限(数组类型),直接从Manifest中读取相应的值,比如Manifest.permission.WRITE_CONTACTS
     */
    public void performCodeWithPermission(@NonNull String permissionDes, PermissionCallback runnable, @NonNull String... permissions) {
        if (permissions == null || permissions.length == 0)
            return;
        //        this.permissionrequestCode = requestCode;
        this.permissionRunnable = runnable;
        if ((Build.VERSION.SDK_INT < Build.VERSION_CODES.M) || checkPermissionGranted(permissions)) {
            if (permissionRunnable != null) {
                permissionRunnable.hasPermission();
                permissionRunnable = null;
            }
        } else {
            //permission has not been granted.
            requestPermission(permissionDes, permissionRequestCode, permissions);
        }

    }

    private boolean checkPermissionGranted(String[] permissions) {
        boolean flag = true;
        for (String p : permissions) {
            if (ActivityCompat.checkSelfPermission(this, p) != PackageManager.PERMISSION_GRANTED) {
                flag = false;
                break;
            }
        }
        return flag;
    }

    private void requestPermission(String permissionDes, final int requestCode, final String[] permissions) {
        if (shouldShowRequestPermissionRationale(permissions)) {
            /*1. 第一次请求权限时,用户拒绝了,下一次:shouldShowRequestPermissionRationale()  返回 true,应该显示一些为什么需要这个权限的说明
            2.第二次请求权限时,用户拒绝了,并选择了“不在提醒”的选项时:shouldShowRequestPermissionRationale()  返回 false
            3. 设备的策略禁止当前应用获取这个权限的授权:shouldShowRequestPermissionRationale()  返回 false*/
            // Provide an additional rationale to the user if the permission was not granted
            // and the user would benefit from additional context for the use of the permission.
            // For example, if the request has been denied previously.

            //            Snackbar.make(getWindow().getDecorView(), requestName,
            //                    Snackbar.LENGTH_INDEFINITE)
            //                    .setAction(R.string.common_ok, new View.OnClickListener() {
            //                        @Override
            //                        public void onClick(View view) {
            //                            ActivityCompat.requestPermissions(BaseAppCompatActivity.this,
            //                                    permissions,
            //                                    requestCode);
            //                        }
            //                    })
            //                    .show();
            //如果用户之前拒绝过此权限,再提示一次准备授权相关权限
            new AlertDialog.Builder(this)
                    .setTitle("提示")
                    .setMessage(permissionDes)
                    .setPositiveButton("授权", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            ActivityCompat.requestPermissions(BaseActivity.this, permissions, requestCode);
                        }
                    }).show();

        } else {
            // Contact permissions have not been granted yet. Request them directly.
            ActivityCompat.requestPermissions(BaseActivity.this, permissions, requestCode);
        }
    }

    private boolean shouldShowRequestPermissionRationale(String[] permissions) {
        boolean flag = false;
        for (String p : permissions) {
            if (ActivityCompat.shouldShowRequestPermissionRationale(this, p)) {
                flag = true;
                break;
            }
        }
        return flag;
    }

    /**
     * Callback received when a permissions request has been completed.
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        if (requestCode == permissionRequestCode) {
            if (verifyPermissions(grantResults)) {
                if (permissionRunnable != null) {
                    permissionRunnable.hasPermission();
                    permissionRunnable = null;
                }
            } else {
                Toast.makeText(this, "暂无权限执行相关操作!", Toast.LENGTH_SHORT).show();
                if (permissionRunnable != null) {
                    permissionRunnable.noPermission();
                    permissionRunnable = null;
                }
            }
        } else {
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        }

    }

    public boolean verifyPermissions(int[] grantResults) {
        // At least one result must be checked.
        if (grantResults.length < 1) {
            return false;
        }

        // Verify that each required permission has been granted, otherwise return false.
        for (int result : grantResults) {
            if (result != PackageManager.PERMISSION_GRANTED) {
                return false;
            }
        }
        return true;
    }
    //********************** END Android M Permission ****************************************
}

2.OutCallReceiver.java

接收广播,将区号与手机号拼接后重新写入

package com.glsite.ipcall;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;

public class OutCallReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        String number = getResultData();// 获取当前的结果数据,数据就是外拨的电话号码
        SharedPreferences sp = context.getSharedPreferences("config", Context.MODE_PRIVATE);
        setResultData(sp.getString("ipnumber", "") + number);
    }
}

 

3.MainActivity

保存区号

package com.glsite.ipcall;

import android.Manifest;
import android.content.SharedPreferences;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends BaseActivity {

    private EditText mEtIpNumber;
    private SharedPreferences mSp;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        performCodeWithPermission("往外拨打电话获取权限", new PermissionCallback() {
            @Override
            public void hasPermission() {
             mEtIpNumber = findViewById(R.id.et_ipnumber);
             mSp = getSharedPreferences("config", MODE_PRIVATE);

            String ipnumber = mSp.getString("ipnumber", "");
            mEtIpNumber.setText(ipnumber);
            }

            @Override
            public void noPermission() {

            }
        }, Manifest.permission.PROCESS_OUTGOING_CALLS);
       
    }

    public void save(View view) {
        String ipnumber =  mEtIpNumber.getText().toString().trim();
        SharedPreferences.Editor editor = mSp.edit();
        editor.putString("ipnumber", ipnumber);
        editor.commit();
        Toast.makeText(this,"保存成功", Toast.LENGTH_SHORT).show();
    }
}

 

 

AndroidManifest.xml

 拨打电话的运行时权限: <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />

拦截拨打电话的action: <action android:name="android.intent.action.NEW_OUTGOING_CALL"/>

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.glsite.ipcall">

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

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <receiver
            android:name=".OutCallReceiver"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
               <action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
            </intent-filter>
        </receiver>

        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_无往而不胜_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值