一、前言:这个apk之前就做好了一直没发,今天看到也有一些朋友看到我之前的提问,就想着发出来,也许对你们会有帮助,新手上路,如有问题请多指教。
二、设计思路:
1.作为一个功能简单的apk界面设计不需要太复杂,一个悬浮窗口,三个按钮:start(开始重启);stop(停止重启);clear(清除计数),以及一个显示计数的文本框;
2.工作流程:点击开始按钮==>发送重启广播,设备重启==>接收到开机广播,设备自启,弹出界面==>计算重启次数==>倒计时10秒重启(自接收到开机广播开始)==>点击停止按钮,apk停止自启
三、设计难点:
整个apk码出来并不难,应用到的都是简单控件的用法,其中最难的就是签名问题。看过很多文章,他们的签名方法大都是Android10以前的对于,10之后的设备并不适用,在一番苦找之下终于找到了救命稻草,附上链接:
四、效果图:
五、工作流程:
1.布局文件
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<Button
android:id="@+id/btn_start"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="start"/>
<Button
android:id="@+id/btn_stop"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="stop"/>
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="20dp"
android:background="#999999" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="horizontal">
<TextView
android:id="@+id/tv_count"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_gravity="bottom"
android:layout_weight="2"
android:gravity="left|center"
android:text="RebootCount:0"
android:textSize="18sp" >
</TextView>
<Button
android:id="@+id/btn_clear"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="clear"/>
</LinearLayout>
- 代码逻辑:
ManActivity.java
2.设备设置:有些设备不适用,具体看型号
//开机解锁
getWindow().setFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD,
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
//屏幕常亮
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
3. 显示重启计数
SharedPreferences preferences = getSharedPreferences("rebootCount", MODE_PRIVATE);
//读取 SharedPreferences 保存的count数据
rebootCount = preferences.getInt("rebootCount", 0);
Toast.makeText(this,"重启了"+rebootCount+"次",Toast.LENGTH_SHORT).show();
tv_count = findViewById(R.id.tv_count);
tv_count.setText("RebootCount:"+ rebootCount);
4.按钮监听
@Override
public void onClick(View view) {
switch (view.getId()){
//点击开始
case R.id.btn_start :
// 点击按钮重启
Log.v( "Reboot" , "Reboot-->broadcast_reboot" );
Intent intent = new Intent(Intent.ACTION_REBOOT);
intent.putExtra( "nowait" , 1);
intent.putExtra( "interval" , 1);
intent.putExtra( "window" , 0);
sendBroadcast(intent);
break;
//点击结束
case R.id.btn_stop:
Intent stopIntent = new Intent(Intent.ACTION_MAIN);
stopIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
stopIntent.setFlags(Integer.parseInt(Intent.ACTION_REBOOT));
startActivity(stopIntent);
finish();
break;
case R.id.btn_clear:
SharedPreferences preferences = getSharedPreferences("rebootCount", MODE_PRIVATE);
//读取 SharedPreferences 保存的count数据
rebootCount = preferences.getInt("rebootCount", 0);
SharedPreferences.Editor editor = preferences.edit();
//设置为0
editor.putInt("rebootCount", 0);
//提交数据
editor.commit();
tv_count.setText("RebootCount:"+ rebootCount);
break;
}
}
5.MyReceiver 继承BroadcastReceiver接收开机广播,重启、计数
@Override
public void onReceive(Context context, Intent intent)
{
String action = intent.getAction();
int rebootCount;
switch (action){
case "android.intent.action.BOOT_COMPLETED":
Log.i("rebootzhu","接收到了开机广播");
//apk开机自启悬浮在锁屏界面之上
Intent mBootIntent = new Intent(context, MainActivity.class);
mBootIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP );
context.startActivity(mBootIntent);
//计算重启次数
SharedPreferences preferences = context.getSharedPreferences("rebootCount", MODE_PRIVATE);
//读取 SharedPreferences 保存的count数据
rebootCount = preferences.getInt("rebootCount", 0);
SharedPreferences.Editor editor = preferences.edit();
//计算重启次数,存入数据
editor.putInt("rebootCount", ++rebootCount);
//提交数据
editor.commit();
//重启
Intent rebootIntent=new Intent(Intent.ACTION_REBOOT);
rebootIntent.putExtra("nowait",1);
rebootIntent.putExtra("interval",1);
rebootIntent.putExtra("window",0);
timer.schedule(new TimerTask() {
@Override
public void run() {
// TODO Auto-generated method stub
context.sendBroadcast(rebootIntent);
}
}, 10000);
break;
}
}
6.配置文件
<uses-permission android:name="android.permission.DISABLE_KEYGUARD"/><!--解锁-->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.REBOOT"
tools:ignore="ProtectedPermissions" />
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.RebootCount"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true"
android:enabled="true"
android:theme="@android:style/Theme.Dialog"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
<intent-filter android:priority="1000">
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<!--接收启动完成的广播-->
<category android:name="android.intent.category.DEFAULT" />
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<!--选择开机界面-->
<!--<category android:name="android.intent.category.HOME"/>-->
<!--开机解锁-->
<action android:name="android.intent.action.USER_PRESENT" />
</intent-filter>
<meta-data
android:name="android.app.lib_name"
android:value="" />
</activity>
<receiver android:name=".MyReceiver"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.SCREEN_ON"/>
</intent-filter>
</receiver>
</application>
六、签名、安装
1.先配置adb环境:^v70^control,201^v4^add_ask&spm=1018.2226.3001.4187
2.签名参考设计难点中的链接;
3.安装:adb install D:\xxx\xxx\debug\app-debug.apk (apk签名成功后路径)
七、结语:
- 缺陷:apk有一个缺陷就是,因为apk的机制就是接收广播开始重启计数,当点击stop按钮后,虽然是可以停止重启,但是你手动重启后,依然会接收广播,继续循环。
- 解决方案,将两个按钮设置为二者选其一,单击start按钮则一直接收开机广播,点击stop按钮则停止接收.