1、监控RECEIVE_BOOT_COMPLETED,即开机自启动事件AndroidManifest.xml 设置开机启动权限以及相应的receiver
2、监控sd卡的mount事件,开机的时候一般都会扫描sd卡,监控sd卡事件也有类似开机启动效果,特别app安装在sd卡的情况下有些os是抓取不到RECEIVE_BOOT_COMPLETED所以设置android:installLocation=“internalOnly”,限制app的安装位置,使其能抓取到RECEIVE_BOOT_COMPLETED
3、Android 10 (API 级别 29) 及更高版本对后台应用可启动 Activity进行限制。Android10中, 当App的Activity不在前台时,其启动Activity会被系统拦截,导致无法启动。这导致使用静态注册开机广播后,实现开机自启的方式不能用了。
解决方案:向用户申请 SYSTEM_ALERT_WINDOW权限,系统就不会拦截该程序后台启动的Activity。
//检查是否已经授予权限
if (!Settings.canDrawOverlays(this)) {
//若未授权则请求权限
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
intent.setData(Uri.parse(“package:” + getPackageName()));
startActivityForResult(intent, 0);
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:installLocation="internalOnly"
package="com.arvin.playerautorun">
<application
android:name=".MyApplication"
android:allowBackup="true"
android:icon="@mipmap/logo"
tools:replace="android:icon"
android:label="@string/app_name"
android:requestLegacyExternalStorage="true"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.PlayerAutorun" >
<activity android:name=".MainActivity"
android:launchMode="singleTask"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".AppBroadcastReceiver">
<intent-filter android:priority="1000">
<!--开机自动启动-->
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<!--<!– 自动关机 –>-->
<action android:name="android.intent.action.ACTION_REQUEST_SHUTDOWN"/>
<!-- 监听sd卡挂载-->
<action android:name="android.intent.action.MEDIA_MOUNTED"/>
<action android:name="android.intent.action.MEDIA_UNMOUNTED"/>
<data android:scheme="file">
</data>
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.HOME"/>
</intent-filter>
</receiver>
</application>
</manifest>
receiver文件
package com.arvin.playerautorun;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class AppBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Intent ootStartIntent = new Intent(context, MainActivity.class);
ootStartIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent fullScreenPendingIntent = PendingIntent.getActivity(context, 0,
ootStartIntent, PendingIntent.FLAG_UPDATE_CURRENT);
context.startActivity(ootStartIntent);
}
}
package com.arvin.playerautorun;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.PersistableBundle;
import android.provider.Settings;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import com.shuyu.gsyvideoplayer.GSYVideoManager;
import com.shuyu.gsyvideoplayer.builder.GSYVideoOptionBuilder;
import com.shuyu.gsyvideoplayer.utils.OrientationUtils;
import com.shuyu.gsyvideoplayer.video.StandardGSYVideoPlayer;
import com.tencent.mmkv.MMKV;
import java.io.File;
import static android.Manifest.permission.CALL_PHONE;
import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
public class MainActivity extends AppCompatActivity {
private static final int REQUEST_PERMISSION_STORAGE = 914;
@RequiresApi(api = Build.VERSION_CODES.M)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//检查是否已经授予权限
if (!Settings.canDrawOverlays(this)) {
//若未授权则请求权限
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, 0);
}
}
private boolean checkPermission(String permission) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(this, READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
Log.e("checkPermission", "PERMISSION_GRANTED" + ContextCompat.checkSelfPermission(this, READ_EXTERNAL_STORAGE));
return true;
} else {
Log.e("checkPermission", "PERMISSION_DENIED" + ContextCompat.checkSelfPermission(this, READ_EXTERNAL_STORAGE));
return false;
}
} else {
Log.e("checkPermission", "M以下" + ContextCompat.checkSelfPermission(this, READ_EXTERNAL_STORAGE));
return true;
}
}
private void startRequestPermision(String permission) {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{READ_EXTERNAL_STORAGE}, REQUEST_PERMISSION_STORAGE);
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == REQUEST_PERMISSION_STORAGE) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
init();
} else {
//如果拒绝授予权限,且勾选了再也不提醒
if (!shouldShowRequestPermissionRationale(permissions[0])) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("说明")
.setMessage("需要使用电话权限,进行电话测试")
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
})
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
return;
}
})
.create()
.show();
} else {
}
}
}
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
启动失败常见问题:
1、手机没有设置应用开机自启动,找到手机设置,搜索启动
关键词 设置应用为自动启动,
2、可能被手机管家拦截
3、接收不到BOOT_COMPLETED广播
4、安装app后从来没有启动过
5、系统开启了Fast Boot模式,这种模式下系统启动并不会发送BOOT_COMPLETED广播
6、app没有ui显示 会启动失败
小米
打开「安全中心」-> 点击「应用管理」-> 点击「权限」-> 点击「自启动管理」-> 找到「触动精灵」启动开关
中兴/魅族
打开手机设置 -> 滑到底部找到「应用管理」-> 找到并点击「触动精灵」-> 点击「权限管理」-> 打开「自启动」开关
华为荣耀V8
方法一:点击「设置」-> 找到并点击「应用管理」-> 找到触动精灵点击「权限」-> 点击「设置单项权限」-> 点击开启「应用自动自动」
方法二:点击「手机管家」-> 点击「权限管理」-> 找到触动精灵点击「设置单项权限」-> 点击开启「应用自动启动」
三星(安装kingroot)
打开「kingroot」-> 点击「高级权限管理」-> 点击「自启行为管理」-> 找到触动精灵启动服务开关
Android3.1之后,系统为了加强了安全性控制,应用程序安装后或是(设置)应用管理中被强制关闭后处于stopped状态,在这种状态下接收不到任何广播。直到被启动过(用户打开或是其他应用调用)才会脱离这种状态,所以Android3.1之后
(1)、应用程序无法在安装后自己启动
(2)、没有ui的程序必须通过其他应用激活才能启动,如它的Activity、Service、Content Provider被其他应用调用。 存在一种例外,就是应用程序被adb push you.apk /system/app/下是会自动启动的,不处于stopped状态。