本示例允许用户动态加载手机通讯录中的电话号码,勾选某些号码为黑名单,一旦将某些号码设为黑名单,当该号码呼入时,系统将会自动挂断该号码。

Android 没有对外公开挂断电话的 API,下面的示例中使用将使用反射机制来调用 ITelephony 的内部接口 silenceRinger 和 endCall。

本文参考文献:《疯狂Android讲义 : 第2版 》
本文参考文章: 《Android 6.0 - 动态权限管理的解决方案》
本文的反射方法参考链接:How to import com.android.internal.telephony.ITelephony to the Android application

检测权限工具类

检测权限工具类,我们可以将其在多个应用中复用:

package com.toby.personal.testlistview;import android.content.Context;import android.content.pm.PackageManager;import android.support.v4.content.ContextCompat;import android.util.Log;/** * Created by toby on 2017/4/29. */class PermissionsChecker {    private final Context mContext;    PermissionsChecker(Context context) {        mContext = context.getApplicationContext();    }    // 判断权限集合    boolean lacksPermissions(String... permissions) {        for (String permission : permissions) {            if (lacksPermission(permission)) {                Log.d("","jkdfksahdfkhsadkjghdfskg: " + permission);                return true;            }        }        return false;    }    // 判断是否缺少权限    private boolean lacksPermission(String permission) {        return ContextCompat.checkSelfPermission(mContext, permission) ==                PackageManager.PERMISSION_DENIED;    }}

授权页

授权页, 首先使用系统默认的授权页, 当用户拒绝时, 指导用户手动设置, 当用户再次操作失败后, 返回继续提示。用户手动退出授权页时, 给使用页发送授权失败的通知。我们可以保存这个授权页并将其在多个应用中复用。

package com.toby.personal.testlistview;import android.app.Activity;import android.content.DialogInterface;import android.content.Intent;import android.content.pm.PackageManager;import android.net.Uri;import android.os.Bundle;import android.provider.Settings;import android.support.annotation.NonNull;import android.support.annotation.Nullable;import android.support.v4.app.ActivityCompat;import android.support.v7.app.AlertDialog;import android.support.v7.app.AppCompatActivity;/** * Created by toby on 2017/4/29. */public class PermissionsActivity extends AppCompatActivity {    public static final int PERMISSIONS_GRANTED = 0; // 权限授权    public static final int PERMISSIONS_DENIED = 1; // 权限拒绝    private static final int PERMISSION_REQUEST_CODE = 0; // 系统权限管理页面的参数    private static final String EXTRA_PERMISSIONS =            "com.toby.personal.permission.extra_permission"; // 权限参数    private static final String PACKAGE_URL_SCHEME = "package:"; // 方案    private PermissionsChecker mChecker; // 权限检测器    private boolean isRequireCheck; // 是否需要系统权限检测, 防止和系统提示框重叠    // 启动当前权限页面的公开接口    public static void startActivityForResult(Activity activity, int requestCode, String... permissions) {        Intent intent = new Intent(activity, PermissionsActivity.class);        intent.putExtra(EXTRA_PERMISSIONS, permissions);        ActivityCompat.startActivityForResult(activity, intent, requestCode, null);    }    @Override protected void onCreate(@Nullable Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        if (getIntent() == null || !getIntent().hasExtra(EXTRA_PERMISSIONS)) {            throw new RuntimeException("PermissionsActivity需要使用静态startActivityForResult方法启动!");        }        setContentView(R.layout.activity_permissions);        mChecker = new PermissionsChecker(this);        isRequireCheck = true;    }    @Override protected void onResume() {        super.onResume();        if (isRequireCheck) {            String[] permissions = getPermissions();            if (mChecker.lacksPermissions(permissions)) {                requestPermissions(permissions); // 请求权限            } else {                allPermissionsGranted(); // 全部权限都已获取            }        } else {            isRequireCheck = true;        }    }    // 返回传递的权限参数    private String[] getPermissions() {        return getIntent().getStringArrayExtra(EXTRA_PERMISSIONS);    }    // 请求权限兼容低版本    private void requestPermissions(String... permissions) {        ActivityCompat.requestPermissions(this, permissions, PERMISSION_REQUEST_CODE);    }    // 全部权限均已获取    private void allPermissionsGranted() {        setResult(PERMISSIONS_GRANTED);        finish();    }    /**     * 用户权限处理,     * 如果全部获取, 则直接过.     * 如果权限缺失, 则提示Dialog.     *     * @param requestCode  请求码     * @param permissions  权限     * @param grantResults 结果     */    @Override    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {        if (requestCode == PERMISSION_REQUEST_CODE && hasAllPermissionsGranted(grantResults)) {            isRequireCheck = true;            allPermissionsGranted();        } else {            isRequireCheck = false;            showMissingPermissionDialog();        }    }    // 含有全部的权限    private boolean hasAllPermissionsGranted(@NonNull int[] grantResults) {        for (int grantResult : grantResults) {            if (grantResult == PackageManager.PERMISSION_DENIED) {                return false;            }        }        return true;    }    // 显示缺失权限提示    private void showMissingPermissionDialog() {        AlertDialog.Builder builder = new AlertDialog.Builder(PermissionsActivity.this);        builder.setTitle(R.string.help);        builder.setMessage(R.string.string_help_text);        // 拒绝, 退出应用        builder.setNegativeButton(R.string.quit, new DialogInterface.OnClickListener() {            @Override public void onClick(DialogInterface dialog, int which) {                setResult(PERMISSIONS_DENIED);                finish();            }        });        builder.setPositiveButton(R.string.settings, new DialogInterface.OnClickListener() {            @Override public void onClick(DialogInterface dialog, int which) {                startAppSettings();            }        });        builder.setCancelable(false);        builder.show();    }    // 启动应用的设置    private void startAppSettings() {        Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);        intent.setData(Uri.parse(PACKAGE_URL_SCHEME + getPackageName()));        startActivity(intent);    }}

需要在 AndroidManifest.xml 中加入权限的申请内容:

            

主布局文件的内容如下:

<?xml version="1.0" encoding="utf-8"?>    

my_list_view.xml 文件的代码如下:

<?xml version="1.0" encoding="utf-8"?>

主程序文件的代码如下:

package com.toby.personal.testlistview;import android.Manifest;import android.content.Context;import android.content.DialogInterface;import android.content.Intent;import android.database.Cursor;import android.os.Bundle;import android.provider.ContactsContract;import android.support.v7.app.AlertDialog;import android.support.v7.app.AppCompatActivity;import android.telephony.PhoneStateListener;import android.telephony.TelephonyManager;import android.util.Log;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.CheckBox;import android.widget.ListView;import android.widget.Toast;import java.io.FileNotFoundException;import java.io.OutputStream;import java.io.PrintStream;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.util.ArrayList;import java.util.Date;public class MainActivity extends AppCompatActivity {    final private static String TAG = "Toby_Test";    final private static int REQUEST_CODE = 29; // 请求码    ArrayList blockList = new ArrayList<>();    static final String[] PERMISSIONS = new String[]{            Manifest.permission.READ_PHONE_STATE            , Manifest.permission.READ_CONTACTS            , Manifest.permission.CALL_PHONE    };    private PermissionsChecker permissionsChecker;    @Override    protected void onCreate(Bundle savedInstanceState) {        Log.d(TAG, "=========== onCreate ===========");        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        permissionsChecker = new PermissionsChecker(this);    }    @Override    protected void onResume() {        super.onResume();        if (permissionsChecker.lacksPermissions(PERMISSIONS)) {            startPermissionsActivity();        }    }    private void startPermissionsActivity() {        PermissionsActivity.startActivityForResult(this, REQUEST_CODE, PERMISSIONS);    }    public void startListener() {        final TelephonyManager telephonyManager =                (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);        PhoneStateListener listener = new PhoneStateListener() {            @Override            public void onCallStateChanged(int state, String incomingNumber) {                switch (state) {                    case TelephonyManager.CALL_STATE_RINGING:                        if (isBlock(incomingNumber)) {                            try {                                Method m1 = telephonyManager.getClass().getDeclaredMethod("getITelephony");                                if (m1 != null) {                                    m1.setAccessible(true);                                    Object iTelephony = m1.invoke(telephonyManager);                                    if (iTelephony != null) {                                        Method m2 = iTelephony.getClass().getDeclaredMethod("silenceRinger");                                        if (m2 != null) {                                            m2.invoke(iTelephony);                                        }                                        Method m3 = iTelephony.getClass().getDeclaredMethod("endCall");                                        if (m3 != null) {                                            m3.invoke(iTelephony);                                        }                                    }                                }                            } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {                                e.printStackTrace();                            }                        }                        break;                    default:                        break;                }                super.onCallStateChanged(state, incomingNumber);            }        };        telephonyManager.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);    }    @Override    protected void onActivityResult(int requestCode, int resultCode, Intent data) {        super.onActivityResult(requestCode, resultCode, data);        // 拒绝时, 关闭页面, 缺少主要权限, 无法运行        if (requestCode == REQUEST_CODE && resultCode == PermissionsActivity.PERMISSIONS_DENIED) {            finish();        }    }    public void Settings(View view) {        final Cursor cursor =                getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,                        null, null, null, null);        BaseAdapter adapter = new BaseAdapter() {            @Override            public int getCount() {                return cursor != null ? cursor.getCount() : 0;            }            @Override            public Object getItem(int position) {                return position;            }            @Override            public long getItemId(int position) {                return position;            }            @Override            public View getView(int position, View convertView, ViewGroup parent) {                if (cursor != null) {                    cursor.moveToPosition(position);                    CheckBox rb = new CheckBox(MainActivity.this);                    String number = cursor.getString(cursor.getColumnIndex(                            ContactsContract.CommonDataKinds.Phone.NUMBER)).replace("-", "");                    rb.setText(number);                    if (isBlock(number)) {                        rb.setChecked(true);                    }                    return rb;                }                return null;            }        };        View selectView = getLayoutInflater().inflate(R.layout.my_list_view, null);        final ListView listView = (ListView) selectView.findViewById(R.id.listV);        listView.setAdapter(adapter);        new AlertDialog.Builder(this).setView(selectView)                .setPositiveButton("OK", new DialogInterface.OnClickListener() {                    @Override                    public void onClick(DialogInterface dialog, int which) {                        blockList.clear();                        for (int i = 0; i < listView.getCount(); ++i) {                            CheckBox checkBox = (CheckBox) listView.getChildAt(i);                            if (checkBox.isChecked()) {                                blockList.add(checkBox.getText().toString());                            }                        }                        Log.d(TAG, blockList.toString());                        startListener();                    }                }).show();    }    private boolean isBlock(String phone) {        Log.d(TAG, blockList.toString());        for (String s1 : blockList) {            if (s1.equals(phone)) {                return true;            }        }        return false;    }}

更多相关文章

  1. Nginx系列教程(六)| 手把手教你搭建 LNMP 架构并部署天空网络电影
  2. [Android问答] 如何实现“退出应用”功能?
  3. 收藏 Android系统 init 启动过程分析
  4. pc进入android手机shell的root权限(su: not found)
  5. Android(安卓)open failed: EBUSY (Device or resource busy)
  6. Android保活
  7. 获取Android设备唯一标识码
  8. Android版本差异适配方案(5.0-9.0)
  9. android 权限问题分析

随机推荐

  1. 【Android-Error】Android 4.4.4 java.la
  2. 深入解析_Android的自定义布局
  3. Android Google Map(create md5, create
  4. Android实现点击事件的三种方法
  5. Android(安卓)屏幕适配方案系列三
  6. 转:Android中shape的使用
  7. 【Android】Android(安卓)Input
  8. Android自定义实现圆形播放进度条
  9. Android框架模式之-MVP简单使用
  10. Android深入浅出之Audio第三部分Audio Po