Android项目:手机安全卫士(6)—— 手机防盗设置向导(二)

Android项目:手机安全卫士(6)—— 手机防盗设置向导(二)

1 介绍

前面的文章介绍了设置向导的界面与切换逻辑,今天来看看每个界面后面涉及到的代码逻辑,主要知识点有:

  • 读取手机 sim 卡序列号
  • 监听手机重启完成的广播
  • 读取手机通讯录

关于项目相关文章,请访问:

项目源码地址(实时更新):https://github.com/xwdoor/MobileSafe

2 读取手机 SIM 卡序列号

读取 sim 卡序列号,然后通过 SharedPreferences 保存,下面是代码:


    //获取系统服务
    TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
    //获取 sim 卡序列号
    String simSerialNumber = tm.getSimSerialNumber();

仅仅只是这样,系统会报错的:
java.lang.SecurityException: Requires READ_PHONE_STATE: Neither user 10053 nor current process has android.permission.READ_PHONE_STATE.
这是因为没有添加权限的结果,需要添加读取手机状态的权限:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />

3 监听手机重启完成的 Receiver 广播

绑定 sim 卡后,接下来需要做的就是在手机每次启动完成后,检测手机 sim 卡是否发生变化,创建广播接收器 BootCompleteReceiver,继承自 BroadcastReceiver:


    public class BootCompleteReceiver extends BroadcastReceiver {
        public BootCompleteReceiver() {
        }

        @Override
        public void onReceive(Context context, Intent intent) {
            String serialNumber = PrefUtils.getString(BaseActivity.PREF_BIND_SIM,"",context);

            if(!TextUtils.isEmpty(serialNumber)){
                TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
                String simSerialNumber = tm.getSimSerialNumber();

                if(serialNumber.equals(simSerialNumber)){
                    Log.i(BaseActivity.TAG_LOG,"手机安全");
                }else {
                    Log.i(BaseActivity.TAG_LOG,"SIM卡发生变化,危险");

                }
            }
        }
    }

当然,这个时候还没有添加代码的处理逻辑,只是输出日志。注意,接收该广播还需要添加权限:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
创建完成后,需要注册该广播接收器,且它的 action 是:BOOT_COMPLETED,代码如下:


    <receiver
        android:name=".receiver.BootCompleteReceiver"
        android:enabled="true"
        android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED"/>
        </intent-filter>
    </receiver>

4 读取手机通讯录

通过访问系统的 ContentProvider 来读取通讯录,系统有三张表,分别是 raw_contacts, data, mimetypes,我们的大概思路是:

  1. 读取 raw_contacts, 获取 contact_id
  2. 根据 contact_id, 从 data 中读取具体信息(姓名/电话 ) data1, mimetype_id
  3. 根据 mimetype_id, 从 mimetypes 中查到具体类型

    /**
     * 读取联系人
     */
    private ArrayList<HashMap<String, String>> readContacts() {
        // raw_contacts, data, mimetypes
        // 1. 读取raw_contacts, 获取contact_id
        // 2. 根据contact_id, 从data中读取具体信息(姓名/电话 ) data1, mimetype_id
        // 3. 根据mimetype_id, 从mimetypes中查到具体类型

        // 1. 读取raw_contacts, 获取contact_id
        Cursor rawCursor = getContentResolver().query(Uri.parse("content://com.android.contacts/raw_contacts"),
                new String[]{"contact_id"}, null, null, null);

        ArrayList<HashMap<String, String>> listContacts = new ArrayList<>();
        if (rawCursor != null) {
            while (rawCursor.moveToNext()) {
                String contactId = rawCursor.getString(rawCursor.getColumnIndex("contact_id"));

                // 2. 根据contact_id, 从data中读取具体信息(姓名/电话 ) data1, mimetype_id
                // 系统在查询data表时, 实际上查询的时view_data这个视图, 视图将data和mimetypes两个表的信息整合在了一起
                Cursor cursor = getContentResolver().query(Uri.parse("content://com.android.contacts/data"),
                        new String[]{"data1", "mimetype"}, "raw_contact_id=?", new String[]{contactId}, null);

                HashMap<String, String> map = new HashMap<>();
                if (cursor != null) {
                    while (cursor.moveToNext()) {
                        String data = cursor.getString(cursor.getColumnIndex("data1"));
                        String mimetype = cursor.getString(cursor.getColumnIndex("mimetype"));

                        if ("vnd.android.cursor.item/name".equals(mimetype)) {
                            //姓名
                            map.put("name", data);
                        } else if ("vnd.android.cursor.item/phone_v2".equals(mimetype)) {
                            //电话
                            map.put("phone", data);
                        }
                    }
                    cursor.close();

                    if (!TextUtils.isEmpty(map.get("name")) && !TextUtils.isEmpty(map.get("phone"))) {// 过滤掉脏数据
                        listContacts.add(map);
                    }
                }

            }
            rawCursor.close();
        }
        return listContacts;
    }

仅仅只是这样,系统会报错的:
java.lang.SecurityException: Permission Denial: reading com.android.providers.contacts.ContactsProvider2 requires android.permission.READ_CONTACTS, or grantUriPermission().
需要添加权限:
<uses-permission android:name="android.permission.READ_CONTACTS"/>

5 总结

我觉得今天的知识点很有用,使用了系统提供的一些服务,这些服务一般都需要访问权限,所以不要忘了加权限,我也是忘了好几次,谨记。

关于项目相关文章,请访问:

项目源码地址(实时更新):https://github.com/xwdoor/MobileSafe

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值