Android开发实战《手机安全卫士》——4.“手机防盗”模块拓展 & 手势移动

1.手机防盗——手势移动 & 抽取到父类中统一处理手势

我们基本上完成了手机防盗模块的功能,现在需要进行进一步优化——即在跳转页面的时候使用手势进行移动

手势移动的原理图如图所示:

在这里插入图片描述

  1. 修改SetupOneActivity,重写onTouchEvent()方法,并且定义一个GestureDetector类,用来完善跳转逻辑,代码如下:
package com.example.mobilesafe.activity;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;

import com.example.mobilesafe.R;

public class SetupOneActivity extends AppCompatActivity {

    /**
     * 手势管理对象
     */
    private GestureDetector mGestureDetector;

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

        // 创建手势管理的对象,用作管理在onTouchEvent(event)中传递过来的手势
        mGestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {
            @Override
            public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
                // 监听手势的移动
                if (e1.getX() - e2.getX() > 0) {
                    // 由右向左,移动到下一页
                    Intent intent = new Intent(getApplicationContext(), SetupTwoActivity.class);
                    startActivity(intent);
                    finish();
                    // 开启平移动画
                    overridePendingTransition(R.anim.next_in_anim,R.anim.next_out_anim);
                }
                if (e1.getX() - e2.getX() < 0) {
                    // 由左向右,移动到上一页

                }
                return super.onFling(e1, e2, velocityX, velocityY);
            }
        });
    }

    /**
     * 1.“下一页”按钮的点击方法
     * @param view
     */
    public void nextPage(View view){
        Intent intent = new Intent(getApplicationContext(), SetupTwoActivity.class);
        startActivity(intent);
        finish();
        // 开启平移动画
        overridePendingTransition(R.anim.next_in_anim,R.anim.next_out_anim);
    }

    /**
     * 2.监听屏幕上响应的事件类型(按下1次,移动多次,抬起1次)
     * @param event
     * @return
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // 通过手势处理类,接收多钟类型的事件,用作处理
        mGestureDetector.onTouchEvent(event);
        return super.onTouchEvent(event);
    }
}
  1. 为了体现代码的复用性,在activity包下新建BaseSetupActivity,作为SetupOneActivity,SetupTwoActivity,SetupThreeActivity,SetupFourActivity的父类,抽取公共方法,代码如下:
package com.example.mobilesafe.activity;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;

import com.example.mobilesafe.R;
import com.example.mobilesafe.constant.ConstantValue;
import com.example.mobilesafe.utils.SharedPreferencesUtil;
import com.example.mobilesafe.utils.ToastUtil;

public abstract class BaseSetupActivity extends AppCompatActivity {

    /**
     * 手势管理对象
     */
    private GestureDetector mGestureDetector;

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

        // 创建手势管理的对象,用作管理在onTouchEvent(event)中传递过来的手势
        mGestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {
            @Override
            public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
                // 监听手势的移动
                if (e1.getX() - e2.getX() > 0) {
                    // 由右向左,移动到下一页,直接调用子类的下一页方法
                    showNextPage();
                }
                if (e1.getX() - e2.getX() < 0) {
                    // 由左向右,移动到上一页,直接调用子类的上一页方法
                    showPrePage();
                }
                return super.onFling(e1, e2, velocityX, velocityY);
            }
        });
    }


    /**
     * 1.监听屏幕上响应的事件类型(按下1次,移动多次,抬起1次)
     * @param event
     * @return
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // 通过手势处理类,接收多钟类型的事件,用作处理
        mGestureDetector.onTouchEvent(event);
        return super.onTouchEvent(event);
    }

    /**
     * 2.展示下一页的方法,由子类决定具体跳转到哪个页面
     */
    protected abstract void showNextPage();

    /**
     * 3.展示上一页的方法,由子类决定具体跳转到哪个页面
     */
    protected abstract void showPrePage();

    /**
     * 4.“下一页”按钮的点击方法
     * @param view
     */
    public void nextPage(View view) {
        showNextPage();
    }

    /**
     * 5.“上一页”按钮的点击方法
     * @param view
     */
    public void prePage(View view) {
        showPrePage();
    }

}
  1. 修改SetupOneActivity,继承BaseSetupActivity,简化代码,代码如下:
package com.example.mobilesafe.activity;

import android.content.Intent;
import android.os.Bundle;

import com.example.mobilesafe.R;

public class SetupOneActivity extends BaseSetupActivity {

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

//    /**
//     * 1.“下一页”按钮的点击方法
//     * @param view
//     */
//    public void nextPage(View view){
//        Intent intent = new Intent(getApplicationContext(), SetupTwoActivity.class);
//        startActivity(intent);
//        finish();
//        // 开启平移动画
//        overridePendingTransition(R.anim.next_in_anim,R.anim.next_out_anim);
//    }
    

    @Override
    protected void showNextPage() {
        Intent intent = new Intent(getApplicationContext(), SetupTwoActivity.class);
        startActivity(intent);
        finish();
        // 开启平移动画
        overridePendingTransition(R.anim.next_in_anim,R.anim.next_out_anim);
    }

    @Override
    protected void showPrePage() {
        // 空实现
    }
}
  1. 其他三个界面同理,均继承父类,然后复制粘贴相关代码即可,以此来简化代码

2.手机防盗——功能列表界面布局编写

之前我们完成了4个导航界面的编写,现在来完成最后一个界面,即手机防盗功能列表界面的编写,如图所示:

  1. 修改activity_setup_over.xml,添加相应控件,代码如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".activity.SetupOverActivity">

    <TextView
        android:text="手机防盗"
        style="@style/TitleStyle"/>

    <RelativeLayout
        android:padding="5dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:text="安全号码"
            android:textSize="18sp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>

        <TextView
            android:id="@+id/tv_phone"
            android:textSize="18sp"
            android:text="0000"
            android:layout_alignParentRight="true"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>

        <ImageView
            android:background="@drawable/listview_divider"
            android:layout_below="@id/tv_phone"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
    </RelativeLayout>

    <RelativeLayout
        android:padding="5dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:text="防盗保护是否开启"
            android:textSize="18sp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>

        <ImageView
            android:id="@+id/iv_lock"
            android:background="@drawable/lock"
            android:layout_alignParentRight="true"
            android:layout_width="25dp"
            android:layout_height="25dp"/>

        <ImageView
            android:background="@drawable/listview_divider"
            android:layout_below="@id/iv_lock"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
    </RelativeLayout>

    <TextView
        android:background="@drawable/gradient_box"
        android:text="重新进入设置向导"
        android:textSize="18sp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</LinearLayout>
  1. 在res/drawable下新建gradient_box.xml,作为圆角图标的样式文件,代码如下:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">

    <gradient
        android:startColor="#ccc"
        android:endColor="#ccc"
        android:angle="45"/>

    <padding
        android:left="7dp"
        android:top="7dp"
        android:right="7dp"
        android:bottom="7dp"/>

    <corners android:radius="8dp"/>

</shape>

3.手机防盗——手机防盗界面逻辑编写

之前我们完成了4个导航界面的编写,现在来完成最后一个界面,即手机防盗界面的编写

  1. 新建selector_reset_setup_bg.xml,作为该布局的一个按钮中的状态选择器,代码如下:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" android:drawable="@drawable/gradient_box"/>
    <!-- 使用android提供的透明色   -->
    <item android:drawable="@android:color/transparent"/>
</selector>
  1. 修改activity_setup_over.xml,完善布局,代码如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".activity.SetupOverActivity">

    <TextView
        android:text="手机防盗"
        style="@style/TitleStyle"/>

    <RelativeLayout
        android:padding="5dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:text="安全号码"
            android:textSize="18sp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>

        <TextView
            android:id="@+id/tv_phone"
            android:textSize="18sp"
            android:text="0000"
            android:layout_alignParentRight="true"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>

        <ImageView
            android:background="@drawable/listview_divider"
            android:layout_below="@id/tv_phone"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
    </RelativeLayout>

    <RelativeLayout
        android:padding="5dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:text="防盗保护是否开启"
            android:textSize="18sp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>

        <ImageView
            android:id="@+id/iv_lock"
            android:background="@drawable/lock"
            android:layout_alignParentRight="true"
            android:layout_width="25dp"
            android:layout_height="25dp"/>

        <ImageView
            android:background="@drawable/listview_divider"
            android:layout_below="@id/iv_lock"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
    </RelativeLayout>

    <TextView
        android:id="@+id/tv_reset_setup"
        android:background="@drawable/selector_reset_setup_bg"
        android:text="重新进入设置向导"
        android:textSize="18sp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

    <TextView
        android:background="@android:color/darker_gray"
        android:text="功能简介"
        android:textSize="18sp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="#000"
        android:textSize="18sp"
        android:gravity="center_vertical"
        android:drawableLeft="@android:drawable/star_big_on"
        android:layout_margin="5dp"
        android:text="GPS追踪#*location*#"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="#000"
        android:textSize="18sp"
        android:gravity="center_vertical"
        android:drawableLeft="@android:drawable/star_big_on"
        android:layout_margin="5dp"
        android:text="播放报警音乐#*alarm*#"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="#000"
        android:textSize="18sp"
        android:gravity="center_vertical"
        android:drawableLeft="@android:drawable/star_big_on"
        android:layout_margin="5dp"
        android:text="数据销毁#*wipedata*#"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="#000"
        android:textSize="18sp"
        android:gravity="center_vertical"
        android:drawableLeft="@android:drawable/star_big_on"
        android:layout_margin="5dp"
        android:text="远程锁屏#*lockscreen*#"/>

</LinearLayout>
  1. 修改SetupOverActivity,给TextView注册点击事件,代码如下,
package com.example.mobilesafe.activity;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

import com.example.mobilesafe.R;
import com.example.mobilesafe.constant.ConstantValue;
import com.example.mobilesafe.utils.SharedPreferencesUtil;

public class SetupOverActivity extends AppCompatActivity {

    private TextView tv_phone;

    private TextView tv_reset_setup;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        boolean setup_over = SharedPreferencesUtil.getBoolean(this, ConstantValue.SETUP_OVER, false);
        if (setup_over){
            // 密码输入成功,并且四个导航界面均设置完成,才停留在设置完成后的功能列表
            setContentView(R.layout.activity_setupover);
            // 初始化UI
            initUI();
        }else {
            // 密码输入成功,若四个导航界面没有全部设置完成,则跳转到第一个导航界面
            Intent intent = new Intent(this, SetupOneActivity.class);
            startActivity(intent);
            finish();
        }
    }

    /**
     * 1.初始化UI
     */
    private void initUI() {
        tv_phone = findViewById(R.id.tv_phone);
        tv_reset_setup = findViewById(R.id.tv_reset_setup);
        tv_reset_setup.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

            }
        });
    }
}

4.手机防盗——功能列表界面业务逻辑

之前我们完善了功能列表界面,现在需要进一步完善其点击事件逻辑

修改SetupOverActivity,完善相应逻辑,代码如下:

package com.example.mobilesafe.activity;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

import com.example.mobilesafe.R;
import com.example.mobilesafe.constant.ConstantValue;
import com.example.mobilesafe.utils.SharedPreferencesUtil;

public class SetupOverActivity extends AppCompatActivity {

    private TextView tv_phone;

    private TextView tv_reset_setup;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        boolean setup_over = SharedPreferencesUtil.getBoolean(this, ConstantValue.SETUP_OVER, false);
        if (setup_over){
            // 密码输入成功,并且四个导航界面均设置完成,才停留在设置完成后的功能列表
            setContentView(R.layout.activity_setupover);
            // 初始化UI
            initUI();
        }else {
            // 密码输入成功,若四个导航界面没有全部设置完成,则跳转到第一个导航界面
            Intent intent = new Intent(this, SetupOneActivity.class);
            startActivity(intent);
            finish();
        }
    }

    /**
     * 1.初始化UI
     */
    private void initUI() {
        tv_phone = findViewById(R.id.tv_phone);
        // 1.设置联系人号码
        String phone = SharedPreferencesUtil.getString(this, ConstantValue.CONTACT_PHONE, "");
       tv_phone.setText(phone);
        // 2.重新设置条目被点击
        tv_reset_setup = findViewById(R.id.tv_reset_setup);
        tv_reset_setup.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(getApplicationContext(),SetupOneActivity.class);
                startActivity(intent);
                finish();
            }
        });
    }
}

5.手机防盗——监听重启手机广播

现在手机防盗的跳转逻辑我们已经完成了,现在需要逐步实现相应的功能,即第二个导航界面的功能——下次重启手机,如果发现SIM卡变化,就会发送报警短信

实现原理如下:

  • 重启手机发送重启广播,编写广播接受者,接收系统重启广告
  • 接收到了广播后,调用onReceiver(),获取重启后的sim卡的序列号和存储在sp中的序列号
    • 比对一致,电话卡没有替换
    • 比对不一致,发送报警短信
  1. 在包下新建一个receiver包,用来存储广播接收器,然后新建一个BootReceiver,作为广播接收器

  2. 修改清单文件,对BootReceiver进行过滤器配置,并添加相应权限,代码如下:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.mobilesafe"
    android:versionCode="1"
    android:versionName="1.0.0">

    <!-- android:versionCode 本地应用版本号是1,版本号是2,有必要提示用户更新 -->
    <!--
 android:versionName 本地应用版本名,假设版本名为1.0.0,它们所代表的意义如下:
                第一位:项目有重大更新(代码重构,大部分功能添加,界面整体添加)
                第二位:更新部分功能
                第三位:一般代表修复原有版本的bug
    -->
    <!-- 添加网络权限 -->
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_CONTACTS" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    <uses-permission android:name="android.permission.SEND_SMS"/>

    <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"
        android:usesCleartextTraffic="true">
        <receiver
            android:name=".receiver.BootReceiver"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
            </intent-filter>
        </receiver>

        <activity android:name=".activity.BaseSetupActivity" />
        <activity android:name=".activity.ContactListActivity" />
        <activity android:name=".activity.SetupFourActivity" />
        <activity android:name=".activity.SetupThreeActivity" />
        <activity android:name=".activity.SetupTwoActivity" />
        <activity android:name=".activity.SetupOneActivity" />
        <activity android:name=".activity.SetupOverActivity" />
        <activity android:name=".activity.SettingActivity" />
        <activity android:name=".activity.HomeActivity" />
        <activity android:name=".activity.SplashActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <uses-library
            android:name="org.apache.http.legacy"
            android:required="false" />
    </application>

</manifest>

6.手机防盗——sim卡变更报警

上一节里,我们新建了一个广播接收器。在这一节中,我们将完善这个逻辑

修改BootReveicer,重写onReceive()方法,完善相应逻辑,代码如下:

package com.example.mobilesafe.receiver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.SmsManager;
import android.telephony.TelephonyManager;

import com.example.mobilesafe.constant.ConstantValue;
import com.example.mobilesafe.utils.SharedPreferencesUtil;

public class BootReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        // 1.获取开启后手机的sim卡的序列号
        TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        //String simSerialNumber = tm.getSimSerialNumber();
        String simSerialNumber = "SIM卡序列号变化";
        // 2.sp中存储的序列卡号
        String sim_number = SharedPreferencesUtil.getString(context, ConstantValue.SIM_NUMBER, "");
        // 3.比对
        if (!simSerialNumber.equals(sim_number)){
            // 4.发送短信给选中联系人号码
            SmsManager sms = SmsManager.getDefault();
            sms.sendTextMessage("5556",null,"sim Change!!",null,null);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

赈川

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

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

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

打赏作者

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

抵扣说明:

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

余额充值