为了解决项目中应用程序开机自启动问题,搭建了一个小demo,用于学习这个开机自启动的问题;
参考博客:
https://blog.csdn.net/qq_34897442/article/details/52263384
Caused by: java.lang.SecurityException: Permission Denial: not allowed to send broadcast android.int的问题可以参考:https://blog.csdn.net/chengfu116/article/details/74636977
有大牛写了个AutoStart的库:https://github.com/csq20081052/AutoStarter
demo工程各部分代码如下:
AndroidMainfest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.ciky.bootstartup">
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"></uses-permission>
<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">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".BootBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</receiver>
</application>
</manifest>
新建一个广播接收器取名为BootBroadcastReceiver.java,其代码如下:
BootBroadcastReceiver.java
package com.ciky.bootstartup;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class BootBroadcastReceiver extends BroadcastReceiver {
static final String ACTION="android.intent.action.BOOT_COMPLETED";
@Override
public void onReceive(Context context, Intent intent) {
// TODO: This method is called when the BroadcastReceiver is receiving
// an Intent broadcast.
if(intent.getAction().equals(ACTION)){
Log.d("ciky","接收器接受到开启完成广播!"+intent.getAction());
System.out.println("自启动程序即将执行!");
Intent mainActivityIntent=new Intent(context,MainActivity.class);
mainActivityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(mainActivityIntent);
}
}
}
MainActivity.java
package com.ciky.bootstartup;
import android.support.v4.widget.TextViewCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView tv=new TextView(this);
tv.setText("Hello,Main");
setContentView(tv);
}
}
会产生如下结果——
接收器接受到开启完成广播!android.intent.action.BOOT_COMPLETED
自启动程序即将执行!
如果想要让你的apk获取系统权限的话(参考:https://www.cnblogs.com/cyqx/p/5829650.html)我没有尝试过~~摘录过来的
第一个方法简单点,不过需要在Android系统源码的环境下用make来编译:
1. 在应用程序的AndroidManifest.xml中的manifest节点中加入
android:sharedUserId="android.uid.system"这个属性。
2. 修改Android.mk文件,加入LOCAL_CERTIFICATE := platform这一行
3. 使用mm命令来编译,生成的apk就有修改系统时间的权限了。
第二个办法麻烦点,不过不用开虚拟机跑到源码环境下用make来编译:
1. 同上,加入android:sharedUserId="android.uid.system"这个属性。
2. 使用eclipse编译出apk文件,但是这个apk文件是不能用的。
3. 用压缩软件打开apk文件,删掉META-INF目录下的CERT.SF和CERT.RSA两个文件。
4. 使用目标系统的platform密钥来重新给apk文件签名。这步比较麻烦,
首先找到密钥文件,在我的Android源码目录中的位置
是"build argetproductsecurity",下面的platform.pk8和platform.x509.pem两个文件。
然后用Android提供的Signapk工具来签名,signapk的源代码是
在"build oolssignapk"下,用法为"signapk platform.x509.pem platform.pk8 input.apk output.apk",
文件名最好使用绝对路径防止找不到,也可以修改源代码直接使用。
这样最后得到的apk和第一个方法是一样的。
最后解释一下原理,首先加入android:sharedUserId="android.uid.system"这个属性。
通过Shared User id,拥有同一个User id的多个APK可以配置成运行在同一个进程中。那么把程序的UID配成android.uid.system,也就是要让程序运行在系统进程中,这样就 有权限来修改系统时间了。