Android-手机防盗

SMS机制收发短信

发送短信

发短信比较简单,我们可以定义一个类,通过传参(包括号码与内容)的方式进行进一步操作。

import android.telephony.SmsManager;
import java.util.ArrayList;

public class SendMsg {
    String message;
    String phone;

    public SendMsg(String message, String phone) {
        this.message = message;
        this.phone = phone;
        SmsManager smsManager = SmsManager.getDefault();
        ArrayList<String> list = smsManager.divideMessage(message);
        for (String text:list) {
            smsManager.sendTextMessage(phone, null, text, null, null);
        }
    }
}

在manifest清单文件中加入权限声明:

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

以上权限属于危险权限,需要在程序运行时动态申请。在主MainActivity中加入运行权限:

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

        if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.SEND_SMS) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.SEND_SMS}, 1);
        }
    }

    //接着就是重写onRequestPermissionsResult
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        switch (requestCode) {
            case 1:
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    //这里写操作 如send(); send函数中New SendMsg (号码,内容);
                } else {
                    Toast.makeText(this, "你没启动权限", Toast.LENGTH_SHORT).show();
                }
                break;
        default:
    }

接收短信

广播需要创建一个Receiver进行监听短信的查收。如下:

public class SMSReceiver extends BroadcastReceiver {

     @Override
     public void onReceive(Context context, Intent intent) {
          String phone = "10086";
          String num, con;
          //读取data中存入的安全号码
          Bundle bundle = intent.getExtras();
          if (bundle != null) {
              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]);
                  num = smsMessages[i].getDisplayOriginatingAddress(); //短信的号码
                  con = smsMessages[i].getDisplayMessageBody(); //短信的内容
                  Toast.makeText(context, num + "----" + con, Toast.LENGTH_SHORT).show();
                  System.out.println("号码:" + num + "内容:" + con);
                  SendMsg sendMsg = new SendMsg("号码:" + num + "内容:" + con, phone);
                  if (num.equals(phone)) {
                     //这里是对短信进行拦截但是并不能实现(Android4.4以上已不适用)
                      abortBroadcast();  
                 }
             }
        }
    }
}

写完receiver之后就可以进行注册(静态与动态),这里就写静态了如下:

<!--广播接收器静态注册,可以在手机未启动该应用的情况下也监听相应的系统广播--!>
<receiver
    android:name=".SMSReceiver"
    android:enabled="true"
    android:exported="true">
     <!--设置有序广播的最高优先权1000,该短信广播接收器这么设置便于拦截阻断垃圾短信--!>
     <intent-filter android:priority="1000"> 
        <action android:name="android.provider.Telephony.SMS_RECEIVED"/>
     </intent-filter>
</receiver>

上面的intent-filter便是静态注册了,打开APP便进行短信监听。

还有就是权限问题:

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

动态权限申请:

  if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.RECEIVE_SMS)!= PackageManager.PERMISSION_GRANTED){
      ActivityCompat.requestPermissions(MainActivity.this,new String[]{Manifest.permission.RECEIVE_SMS},2);
  }

  //onRequestPermissionsResult方法如上
  ……

手机被盗应急措施

市面上流行了很多安全卫士软件,它们在手机被盗之后,都拥有远程操控手机的功能,如播放报警铃声、获取手机位置、远程锁屏、恢复出厂设置等等,这次我们就来看看怎么实现这些功能。

报警铃声的实现

说起所有的远程操控的功能中,就属于报警铃声最容易实现了,所以我们先实现这个。

首先建立一个Android project,然后建立一个SmsReceive广播接收者,没错,就是这个,我们的目的就是使用广播接收者接收到短信,然后通过解析短信的内容来远程操控手机。

SmsReceive代码:

public class SmsReceive extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        
    }
}

那么如何才能解析短信呢?这其实非常简单,只要用以下几行代码就行了:

Object[] objs = (Object[]) intent.getExtras().get("pdus");
    for (Object obj : objs) {
        // 获得短信内容
        SmsMessage sms = SmsMessage.createFromPdu((byte[]) obj); // 此方法已过时
        String smsbody = sms.getMessageBody();
        String sender = sms.getOriginatingAddress();
        System.out.println("发件人:" + sender + "  内容:" + smsbody);
}

我们将这段解析短信的代码加入SmsReceive广播接收者的onReceive()方法之中,这时我们就可以监听到短信的信息了!

但是且慢,我们还必须在mainfest中注册广播接收者才能生效,要时刻牢记Android四大组件都是必须要注册才能生效的。

<receiver android:name="com.example.controldevice.SmsReceive" >
        <intent-filter android:priority="1000" >
            <!-- 获取短信接收事件 -->
            <action android:name="android.provider.Telephony.SMS_RECEIVED" />
        </intent-filter>
 </receiver>

另外,接收短信是属于用户的隐私,所以还需要添加权限,如下:

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

OK,这时候我们就已经成功的监听到了短信了,够简单吧!现在就打开模拟器尝试着发一条短信看看有没有输出吧!

前期准备工作已经完成,那么我们就来操控报警短信吧。在SmsReceive广播接收者的onReceive()方法中添加以下代码:

public void onReceive(Context context, Intent intent) {

    Object[] objs = (Object[]) intent.getExtras().get("pdus");
    ······
        System.out.println("发件人:" + sender + "  内容:" + smsbody);
        
        if ("#*music*#".equals(smsbody)){
            System.out.println("快点播放音乐");
            // 播放音乐(需要在res目录下的raw文件夹添加bestfriend的歌曲)
            MediaPlayer mediaPlayer = MediaPlayer.create(context, R.raw.bestfriend); 
            mediaPlayer.start();
        } 
        }
    }
}

妥妥的,现在当你发送"#music#到你的模拟器时,广播接收者就会解析短信,然后播放报警铃声。
真的是很简单的一个项目呀~~~哎,不要吐槽,我们只是先来一点简单的东西但开胃菜,剩下的就稍微有些难度了。

远程锁屏与恢复出厂设置

响起报警铃声是如此的简单,那么擦除手机数据(恢复出厂设置)和远程锁屏呢?擦除手机信息和远程锁屏属于手机的危险操作,所以一般情况下是无法使用手机应用直接使用这些功能的。

这些高危操作都属于手机管理员的操作,所以我们必须要获得手机的超级管理员权限才能够操作。需要注意的是手机超级管理员与root是不同的,手机超级管理员指的是获得手机最高的权限,而root则是获得手机的所有权限

如何获得手机超级管理员权限呢?

手机超级管理员权限是在Android2.3的时候提出来的,它可以设置开屏密码,禁用摄像头,锁屏等等,具体可以查看Android官网:https://developer.android.com/guide/topics/admin/device-admin.html

获取超级管理员,首先要创建一个Admin类继承自DeviceAdminReceiver,当然了,里面可以重写很多方法,但是我们现在先不理。代码如下:

 public class Admin extends DeviceAdminReceiver {

 }

然后我们要在res资源目录下创建一个xml目录,在里面创建device_admin_sample.xml。这个文件是用来说明开启超级管理员后用户所拥有的权限,代码如下:

 <device-admin
  xmlns:android="http://schemas.android.com/apk/res/android">
   <uses-policies>
       <limit-password />
       <watch-login />
       <reset-password />
       <force-lock />
       <wipe-data />
       <expire-password />
       <encrypted-storage />
       <disable-camera />
   </uses-policies>
 </device-admin>

在manifest中注册DeviceAdminReceiver,添加代码如下:

  <receiver
      android:name="com.example.controldevice.Admin"
      android:description="@string/sample_device_admin_description"
      android:label="@string/sample_device_admin"
      android:permission="android.permission.BIND_DEVICE_ADMIN" >
      <meta-data
          android:name="android.app.device_admin"
          android:resource="@xml/device_admin_sample" />

      <intent-filter>
          <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
      </intent-filter>
  </receiver>

前置工作已经完成了,我们就来正式获取管理员权限吧。我们在MainActivity中添加两个按钮,一个register按钮,点击打开激活超级管理员权限,另一个unregister按钮,点击取消激活超级管理员权限。

要注意的是如果激活了超级管理员权限,那么以后是不能够直接卸载这个app的,必须要取消激活超级管理员权限之后才能正常卸载(在华为真机中测试,是可以直接卸载的),但是在模拟器中确实是无法卸载的。

在这里插入图片描述
MainActivity代码如下:

public class MainActivity extends Activity {

  private DevicePolicyManager devicePolicyManager;
  private ComponentName componentName;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      devicePolicyManager = (DevicePolicyManager) getSystemService(DEVICE_POLICY_SERVICE);
      componentName = new ComponentName(this, Admin.class);
      Button register = (Button) findViewById(R.id.register);
       // Launch the activity to have the user enable our admin.
      register.setOnClickListener(new OnClickListener() {
          @Override
          public void onClick(View v) {
              Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
              intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, componentName);
              intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION,
                      "激活超级管理员中");
              startActivity(intent);
          }
      });
    
      Button unregister = (Button) findViewById(R.id.unregister);
      // 取消激活超级管理员
      unregister.setOnClickListener(new OnClickListener() {
          @Override
          public void onClick(View v) {
              if (devicePolicyManager.isAdminActive(componentName)){
                  devicePolicyManager.removeActiveAdmin(componentName);
              }
          }
      });
    }
}

在这里我们遇到两个陌生的API,一个是DevicePolicyManager,这个是设备权限管理器,使用它才能够管理锁屏、擦出手机数据等等功能。另一个是ComponentName,它用于打开其他应用程序中的Activity或服务的,因为启动超级管理员权限是要启动Android内置Activity才能激活的,所以需要使用ComponentName

但我们点击register按钮的时候,app会直接打开另一个活动,不要慌,这是正常现象,点击Activate激活即可激活超级管理员,界面如下:

在这里插入图片描述在这里插入图片描述
当然了,这是用代码的方法来激活超级管理员,你也可以直接在设置中激活,方法是:Settings-security-Device administrators-我们的app。要注意的是只有继承了DeviceAdminReceiver,以及在manifest注册过之后才会出现我们创建的app。

现在我们终于可以远程擦除手机信息和远程锁屏了!回到我们的SmsReceive,继续在onReceive()中添加代码:

 public class SmsReceive extends BroadcastReceiver {
 
    private DevicePolicyManager mDevicePolicyManager;
    private ComponentName mComponentName;
   
    @Override
    public void onReceive(Context context, Intent intent) {
        
        mDevicePolicyManager = (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
        mComponentName = new ComponentName(context, Admin.class);
    
        Object[] objs = (Object[]) intent.getExtras().get("pdus");
        for (Object obj : objs) {
            // 获得短信内容
            SmsMessage sms = SmsMessage.createFromPdu((byte[]) obj);
            String smsbody = sms.getMessageBody();
            String sender = sms.getOriginatingAddress();
            System.out.println("发件人:" + sender + "  内容:" + smsbody);
        
            if ("#*music*#".equals(smsbody)){               
                // 播放音乐
                MediaPlayer mediaPlayer = MediaPlayer.create(context, R.raw.bestfriend);
                mediaPlayer.start();
            } else if ("#*wipedata*#".equals(smsbody)){
                // 擦出手机数据
                if(mDevicePolicyManager.isAdminActive(mComponentName)) {
                mDevicePolicyManager.wipeData(0);
                }
            } else if ("#*lock*#".equals(smsbody)){
                // 锁屏
                if (mDevicePolicyManager.isAdminActive(mComponentName)){
                    mDevicePolicyManager.lockNow();
                }
            } 
        }
    }
}

这时候你发送短信#wipedata#或者#lock#就能实现远程擦除数据和锁屏了。不过需要提示的是擦出数据在模拟器中不太好用,有可能会导致模拟器卡死,还有小心在真机测试,这可真是会恢复出厂设置的。

GPS位置反馈

/**
* FileName: LocationService <br>
* Description: 用于防盗模块向安全号码发送位置信息的服务 <br>
* Author: 沈滨伟-13042299081 <br>
* Date: 2019/4/23 19:19
*/
public class LocationService extends Service {
    public LocationService() {

    }

    @Override
    public void onCreate() {
        super.onCreate();
        LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        // 最优的获取位置信息的方式
        Criteria criteria = new Criteria();
        criteria.setCostAllowed(true);
        criteria.setAccuracy(Criteria.ACCURACY_FINE);
        String bestProvider = locationManager.getBestProvider(criteria, true);
        // 权限检测
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
                && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return;
        }
        //设置当手机所处位置变动超过100米,自动向安全手机再发送一次地理位置变更信息短信
        locationManager.requestLocationUpdates(bestProvider, 0, 100, new LocationListener() {
            @Override
            public void onLocationChanged(Location location) {
                // 获取当前的经纬度信息
                double latitude = location.getLatitude();
                double longitude = location.getLongitude();
                // 读取手机安全联系人号码
                String selectedSecurityNum = SharePreferenceUtil.getStringFromSharePreference(getApplicationContext(),
                        ConstantValues.CONTACT_PHONE, "");
                // 发送当前的经纬度信息到绑定的安全号码上(需要手机打开GPS定位)
                SmsManager smsManager = SmsManager.getDefault();
                smsManager.sendTextMessage(selectedSecurityNum, null, "您被盗的手机目前所在的纬度为:" + latitude + ",经度为:" + longitude, null, null);
                //停止位置短信发送服务
                stopService(new Intent(MyMobileApplication.getContext(),LocationService.class));
            }

            @Override
            public void onStatusChanged(String provider, int status, Bundle extras) {
            }

            @Override
            public void onProviderEnabled(String provider) {
            }

            @Override
            public void onProviderDisabled(String provider) {
            }
        });
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }
}

指令短信接收器

/**
* FileName: SmsReceiver <br>
* Description: 用于接收安全号码发来的短信并做出安全响应的广播接收器 <br>
* Author: 沈滨伟-13042299081 <br>
* Date: 2019/4/23 19:58
*/
public class SmsReceiver extends BroadcastReceiver {

    private DevicePolicyManager mDPM;

    @Override
    public void onReceive(Context context, Intent intent) {
        ComponentName mDeviceAdminSample = new ComponentName(context, DeviceAdmin.class);
        // 获取设备的管理者对象
        mDPM = (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
        // 判断是否开启防盗保护
        boolean isOpenedSecurity = SharePreferenceUtil.getBooleanFromSharePreference(context, ConstantValues.OPEN_SECURITY, false);
        if (isOpenedSecurity) {
            // 获取接收短信的内容
            Object[] messages = (Object[]) intent.getExtras().get("pdus");
            // 循环遍历获取到的短信内容
            for (Object object : messages) {
                // 获取短信对象
                SmsMessage sms = SmsMessage.createFromPdu((byte[]) object);
                // 获取短信对象的基本信息
                String messageAdress = sms.getOriginatingAddress();
                String messageBody = sms.getMessageBody();
                // 判断是否包含播放音乐的关键字
                if (messageBody.contains("#*alarm*#")) {
                    // 播放音乐
                    MediaPlayer mediaPlayer = MediaPlayer.create(context, R.raw.ylzs);
                    mediaPlayer.setLooping(true);
                    mediaPlayer.start();
                }
                // 判断是否包含发送位置信息的关键字
                if (messageBody.contains("#*location*#")) {
                    // 启动位置服务,发送位置信息
                    Intent intentService = new Intent(context, LocationService.class);
                    context.startService(intentService);
                }
                // 判断是否包含启动远程锁屏的关键字
                if (messageBody.contains("#*lockscreen*#")) {
                    if (mDPM.isAdminActive(mDeviceAdminSample)) {
                        // 远程锁屏
                        mDPM.lockNow();
                        //重置密码,已失效,在真机上只能锁屏,无法重置密码
                        mDPM.resetPassword("123456", 0);
                    }
                }
                // 判断是否包含启动数据销毁的关键字
                if (messageBody.contains("#*wipedata*#")) {
                    // 数据销毁,恢复出厂设置
                    mDPM.wipeData(0);
                }
            }
        }
    }
}

发布了117 篇原创文章 · 获赞 84 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/weixin_39190897/article/details/89645416