安卓案例分析——实现简单的手机防盗软件

本文详细介绍了一款手机防盗软件的设计与实现过程,包括SIM状态监听、短信监听、远程锁屏与解锁等功能,以及项目调试中遇到的问题和解决方案。

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

一周前老师布置了一个任务,要求实现一个简单的手机防盗软件,这东西在好些年前非常流行,几乎每个XX管家都搞了一个这个功能,当然现在也是

时过境迁,其实好多功能已经不太能够实现了。

最近开始试着去画思维导图,其实这篇文章是来展现我高超的思维导图技巧的~

实际上就是把实验报告全部贴上来了,又水了一篇文章,真开心~

项目心得就不贴了,害羞


项目简介与功能说明

   (主要介绍本项目的应用意义与要完成的所有功能)

 

 

项目分析与设计

(主要描述针项目的分析与设计过程,如:项目的总的结构框图,项目功能模块、项目的技术难点以及解决这些难点的方法)

 项目实现与关键代码

(以流程图和关键代码来说明各功能模块的实现)

备注:

(1)流程图有点复杂,所以不方便用直线+实线,只好用虚线+曲线的形式给出。

(2)部分逻辑并未体现在图内,实际上设置信息及安全号码通过sharepreferences保存,所有功能模块执行前需要判断一次sharepreferences里的对应设置内容,只有当对应设置开关打开时才允许该功能模块执行。

(3)判断短信内容新添加了根据短信内容设置锁屏密码的机制,如发送lock88888,即将手机密码设置为88888。

关键代码:

实际上项目的重中之重就是SIM状态监听和短信监听了,核心功能的实现基本在这两部分,其余部分如开机启动监听,实际上是为了让项目整体更符合“手机防盗软件”定位的辅助部分。

SIM卡状态监听器(SIM卡状态监听广播)

public class SimReceiver extends BroadcastReceiver {
    private final static String ACTION_SIM_STATE_CHANGED = "android.intent.action.SIM_STATE_CHANGED";
    static String old_phonen_umber = null;
    static String new_phonen_umber = null;

    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(ACTION_SIM_STATE_CHANGED)) {
            //SharedPreferences
            SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
            Boolean checkbox_core = sp.getBoolean("checkbox_core", false);
            Boolean checkbox_sim = sp.getBoolean("checkbox_sim", false);
            //Log.i("Theft_phone_number", "**访问onReceive开始,初始号码为:" + old_phonen_umber);
            TelephonyManager tm = (TelephonyManager) context.getSystemService(Service.TELEPHONY_SERVICE);
            if (ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_SMS) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_NUMBERS) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
                Log.i("Theft_phone_number", "没有给予对应的权限而退出");
                return;
            }
            new_phonen_umber = tm.getLine1Number();
            if (new_phonen_umber != null) {
                if (!new_phonen_umber.isEmpty()) {
                    if (checkbox_core) {
                        Log.i("Theft_setting", "核心服务已启动");
                        if (checkbox_sim) {
                            Log.i("Theft_setting", "SIM监控服务已启动,一切准备就绪");
                            Log.i("Theft_phone_number", "执行了一次有效的电话号赋值:" + new_phonen_umber + "拟将新旧SIM信息进行替换");

                            if (old_phonen_umber == new_phonen_umber) {
                                Log.i("Theft_phone_number", "新旧SIM信息相同,不执行操作");
                            } else {
                                old_phonen_umber = new_phonen_umber;
                                Log.i("Theft_phone_number", "SIM卡发生变化,现在的SIM号码信息已经替换为:" + old_phonen_umber);
                                //读取...
                                String edittext_num = sp.getString("edittext_num", "");
                                if (!edittext_num.equals("")) {
                                    SmsManager.getDefault().sendTextMessage(edittext_num, null, "请当心SIM卡状态发生变化,SIM卡号目前为:" + old_phonen_umber, null, null);
                                }
                            }
                            Log.i("Theft_phone_number", "---------------------onReceive执行结束---------------------");

                        } else {
                             Log.i("Theft_setting", "SIM监控服务未启动,终止");
                        }
                    } else {
                        Log.i("Theft_setting", "核心服务未启动,终止");
                    }
                }
            }
        }
    }
}

短信监听器(短信监听广播) 

public class SmsReceiver extends BroadcastReceiver {
    private DevicePolicyManager mDPM;
    private PowerManager.WakeLock wakeLock;
    private PowerManager pm;
    KeyguardManager km;
    KeyguardManager.KeyguardLock keyguradLock;
    @SuppressLint("InvalidWakeLockTag")
    @Override
    public void onReceive(Context context, Intent intent) {
        mDPM = (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
        pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        Bundle bundle=intent.getExtras();
        if (bundle!=null){
            SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
            Boolean checkbox_unlock = sp.getBoolean("checkbox_unlock", false);
            Boolean checkbox_lock = sp.getBoolean("checkbox_lock", false);
            String edittext_num = sp.getString("edittext_num", "");
            Object[] objs= (Object[]) bundle.get("pdus");
            SmsMessage[] smsMessages=new SmsMessage[objs.length];
            for (int i=0;i<objs.length;i++){
                smsMessages[i]=SmsMessage.createFromPdu((byte[])objs[i]);
                //发送方的号码
                String number=smsMessages[i].getDisplayOriginatingAddress();
                Log.i("Theft_message","监听到的号码:"+number);
                //获取短信的内容
                String content = smsMessages[i].getDisplayMessageBody();
                String pre_four = "nodata";
                String tel = "123456";
                Log.i("Theft_message","监听到的内容:"+content);
                if (!TextUtils.isEmpty(content) && content.length()>=4){
                    pre_four = (content.substring(0,4));
                    Log.i("Theft_message","赋值pre_four为"+pre_four);
                }
                if(number.equals("+"+edittext_num)){
                    Log.i("Theft_message","监听到安全号码发送的消息,进行服务启动情况判断");
                    if(pre_four.equals("lock")){
                        if (checkbox_lock) {
                            Log.i("Theft_message", "远程锁屏服务已启动");
                            Log.i("Theft_message","执行锁定操作");
                            //mDPM.wipeData(DevicePolicyManager.WIPE_EXTERNAL_STORAGE);清除数据
                            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
                                km = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
                                if(km.isKeyguardSecure()){
                                    Log.i("Theft_message","已经锁定");
                                    mDPM.lockNow();
                                }else{
                                    Log.i("Theft_message","没有锁定,进行锁定");
                                    //锁屏设置密码
                                    if (!TextUtils.isEmpty(content) && content.length()>=4){
                                        tel=(content.substring(4,content.length()));
                                        Log.i("Theft_message","赋值tel为"+tel);
                                    }

                                    mDPM.resetPassword(tel, 0);
                                    mDPM.lockNow();
                                }
                            }else{
                                Log.i("Theft_message","试图去进行判断锁屏情况,但是API等级不够");
                            }
                        }else{
                            Log.i("Theft_message", "远程锁屏服务未启动");
                        }
                    }else if(content.equals("unlock")){
                        if (checkbox_unlock) {
                            Log.i("Theft_message", "远程解锁服务已启动");
                            Log.i("Theft_message","执行解锁操作");
                            wakeLock = pm.newWakeLock(PowerManager.ACQUIRE_CAUSES_WAKEUP
                                    | PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "unLock");
                            wakeLock.acquire();

                            // 键盘锁管理器对象
                            keyguradLock = km.newKeyguardLock("unLock");
                            keyguradLock.disableKeyguard();

                        }else{
                            Log.i("Theft_message", "远程解锁服务未启动");
                        }
                    }
                }
            }
            //黑名单...
            abortBroadcast();
        }
    }

项目调试与结果

(主要介绍项目调试中发现的问题和解决方法以及整个项目正常运行的结果截图)

1)项目UI逻辑(优先级:核心组件>是否打开SIM监控>安全号码>远程锁屏&远程解锁)

只有核心组件被启动,才能开启后续功能模块。

只有SIM监控被启动,才能进行安全号码输入及保存。

只有SIM监控被启动,安全号码被设置完毕,才能启动远程锁屏和解锁,否则弹出如下提示。

2)“钥匙”机制(项目实际为2APP,一个为防盗软件本体,另一个为“钥匙”,防盗软件本体安装后无法在桌面看到图标)

如下图,无法看到本体的图标(本体名为手机防盗助手),但它确实其实已经安装了,可以看到的是Key的图标,打开Key会自动唤醒本体的UI界面,用户只需要在第一次进行配置和需要对配置进行修改的时候下载安装Key即可,平时完全可以把Key卸载,不会影响本体的运行。

上述机制很好的解决了,手机丢失情况下,防盗软件可能被有意卸载,通过隐藏图标的形式保障了本体的安全,而且由于获取了设备管理器权限,实际上在设置界面也是不能直接卸载应用的。

3)动态权限申请(一般情况下,项目首次启动会进行权限申请,会直接跳到对应的申请界面)

这里其实权限要多了…

  

  

 

 

 

(4)远程锁定,格式lock+密码,可以将手机密码远程设置为指定内容。

点击发送,同时配置了完整的日志系统

 


 

 

(5)远程解锁,格式unlock,可以将手机远程唤醒

同样也配置了完整的日志系统

6)为了适应API机制,加入了锁定检查,已经锁定的手机无法再次进行锁定,避免了异常的发生,已经锁定的手机收到锁定命令只会执行熄屏。

 

(7)开机自启动测试

可以看到,并未载入项目UI界面,但是项目已经在后台启动了,在控制台也又有对应的日志文件,同时输出了设备的配置信息。

(8)接上测试,SIM卡状态变化自动发送当前SIM卡号

由于系统重启时重新加载了SIM卡服务,等价于一次SIM卡插拔操作,项目后台自动发送了一条警告信息给安全号码,如下图。左为测试机,右为安全号码机(也已经成功收到短信)

 

http://blog.youkuaiyun.com/xiaoxiao108/archive/2011/05/01/6381414.aspx 前段时间母亲手机遭贼了,以防万一,如果自己手机丢了,肯定会更郁闷,记得很多手机防盗功能,如果更换了sim卡就会,手机就会自动把新的 sim卡手机号,gps坐标,什么的发送到绑定的手机上。网上查了下资料,这类这类软件也挺多的。看了看功能也不是很复杂,就自己写了个玩玩 。 开发环境 vs2008 wm6 .net cf 3.5 编译运行代码时,电脑必须安装 Windows Mobile 6 Professional SDK Refresh.msi 实现方法很简单 1.每一个sim都有唯一的一个IMSI编号,可以根据IMSI编号来判断手机是否更换sim卡 2.如果检测到IMSI不是自己的sim卡的,可以确定其他人可能在用你的手机。 3.每次开机程序自动运行,检测到别人如果使用你的手机,自动把他的通话记录,跟gps坐标发送到绑定好的手机号上。 4.知道用你手机人的手机号,最近通话记录,gps坐标后,再自己想办法找到这人吧。 具体代码 1.取sim卡IMSI编号 使用 TapiLib.dll类库中的ControlTapi.GetIMSINumber()取到sim卡imsi编号 2.判断是不是自己的sim卡 string simStr=ControlTapi.GetIMSINumber(); if (simStr.Length != 0) { if (simStr != SIM) { 其中SIM为事先取好的自己手机卡的IMSI编号 3.取最近通话记录代码 [StructLayout(LayoutKind.Sequential)] public struct CALLLOGENTRY { public UInt32 cbSize; public UInt64 ftStartTime; public UInt64 ftEndTime; public short iom; public bool fOutgoing; public bool fConnected; public bool fEnded; public bool fRoam; public short cidt; public IntPtr pszNumber; public IntPtr pszName; public IntPtr pszNameType; public IntPtr pszNote; }; [DllImport("phone.dll", EntryPoint = "PhoneOpenCallLog", SetLastError = true)] //首先要PhoneOpenCallLog打开通话记录句柄 private static extern int PhoneOpenCallLog(ref IntPtr pHandle); [DllImport("phone.dll", EntryPoint = "PhoneCloseCallLog", SetLastError = true)] //要调用PhoneCloseCallLog关闭句柄 private static extern int PhoneCloseCallLog(IntPtr pHandle); [DllImport("phone.dll", EntryPoint = "PhoneGetCallLogEntry", SetLastError = true)] private static extern int PhoneGetCallLogEntry(IntPtr pHandke, ref CALLLOGENTRY pEntry); //用PhoneGetCallLogEntry方法会返回一个通话记录结构,在该结构中,包含号码、姓名、通话开始时间、通话结束时间等信息。 private string GetLog() { string CallInfo = ""; try { IntPtr handle = IntPtr.Zero; //句柄 CALLLOGENTRY entry = new CALLLOGENTRY(); PhoneOpenCallLog(ref handle); //首先要PhoneOpenCallLog打开通话记录句柄 entry.cbSize = (uint)Marshal.SizeOf(entry); //返回类的非托管大小 if (handle != IntPtr.Zero) { while (PhoneGetCallLogEntry(handle, ref entry) == 0) //获取通话记录 { //Marshal.PtrToStringUni 复制指定数目的字符 string phoneNumber = Marshal.PtrToStringUni(entry.pszNumber); //号码 string name = Marshal.PtrToStringUni(entry.pszName); //姓名 if (phoneNumber == null) { phoneNumber = string.Empty; } if (name == null) { name = string.Empty; } string temp = (phoneNumber.Trim() + name.Trim()); CallInfo = CallInfo + temp; } PhoneCloseCallLog(handle); if (CallInfo.Length < 140) { return CallInfo; } else { return CallInfo.Substring(0,140); } } else { int error = Marshal.GetLastWin32Error(); return ""; } } catch (Exception ep) { //MessageBox.Show(ep.ToString()); return ""; } finally { } } 4.取gps坐标代码 GpsDeviceState device = null; GpsPosition position = null; Gps gps = new Gps(); void gps_DeviceStateChanged(object sender, DeviceStateChangedEventArgs args) { device = args.DeviceState; } protected void gps_LocationChanged(object sender, LocationChangedEventArgs args) { position = args.Position; str = ""; if (position != null) { //维度 if (position.LatitudeValid) { str += position.Latitude; } //经度 if (position.LongitudeValid) { str += " " + position.Longitude; 5.发送短信代码 SmsMessage msg = new SmsMessage(PHONE, str); msg.Send(); 6.打包为开机启动程序 打包cab文件时,只需把快捷方式添加到Startup文件夹下面就ok。 不足之处。 1.gps代码根据sdk中修改的,只是卫星定位的,根据基站定位的代码不知如何实现,只有当使用手机的人走到卫星信号好的地方时才能把坐标发 出去 2.发送的gps坐标 ,只是一个大体的位置,几百米以内的范围,有些浮动 3.如果手机被恢复出厂设置,或者被刷机,程序肯定不能运行了 即使gps信号不好的情况下只是得到使用手机人的电话号码,跟通话记录,用处也是挺大的。代码只是写着玩的,提供下参考思路代码 如果你发现有什么不合理的,需要改进的地方,或者你有什么更好的实现方法联系328452421@qq.com 朱晓 (泰山学院)。相互交流 谢谢 http://blog.youkuaiyun.com/xiaoxiao108/archive/2011/05/01/6381414.aspx
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

云无心鸟知还

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

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

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

打赏作者

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

抵扣说明:

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

余额充值