现在很多公司都开始做智能硬件产品,主要是在Android开发板上面开发应用app,尤其这两年物联网越来越火,这方面的需求越来越多,目前公司也是做智能公交站台的,需要开发的app实现开机自启动,异常崩溃重新启动,版本升级静默安装并自动打开,定时开关机,感觉都要跟Android系统打交道,查了很多资料,开发的时候也遇到很多坑,终于整合完成了,现在连夜分享出去,希望能够帮到大家:

首先把实现这些功所要用到的权限全部加入清单文件中:

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

<uses-permission android:name="android.permission.READ_FRAME_BUFFER" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.REBOOT" />
<uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
<uses-permission android:name="android.permission.DEVICE_POWER" />
<uses-permission android:name="android.permission.SHUTDOWN" />
<uses-permission android:name="android.permission.READ_FRAME_BUFFER" />
<uses-permission android:name="android.permission.WRITE_MEDIA_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.SERIAL_PORT" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
<uses-permission android:name="android.permission.INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.INSTALL_LOCATION_PROVIDER" />
<uses-permission android:name="android.permission.DELETE_PACKAGES" />

1,开机自启动:开启一个广播监控就好了

<uses-permission  
android 
:name= 
"android.permission.READ_MEDIA_STORAGE"  
/> 
<uses-permission  
android 
:name= 
"android.permission.SET_TIME"  
/> 
<uses-permission  
android 
:name= 
"android.permission.STATUS_BAR"  
/> 
<uses-permission  
android 
:name= 
"android.permission.ACCESS_FINE_LOCATION"  
/> 
<uses-permission  
android 
:name= 
"android.permission.ACCESS_CACHE_FILESYSTEM"  
/> 
<uses-permission  
android 
:name= 
"android.permission.DELETE_CACHE_FILES"  
/> 
<uses-permission  
android 
:name= 
"android.permission.MODIFY_SOUND_SETTINGS"  
/> 
<uses-permission  
android 
:name= 
"android.permission.MODIFY_AUDIO_SETTINGS"  
/>
/**
 * 我们通过广播来启动Activity的时候如果不设置intent的FLAG_ACTIVITY_NEW_TASK属性,就会报这个异常:
 * android.util.AndroidRuntimeException:
 * Calling startActivity() from outside of an Activity  context requires the FLAG_ACTIVITY_NEW_TASK flag.
 * 就是说在activity上下文之外调用startActivity需要FLAG_ACTIVITY_NEW_TASK属性。
 *
 * @author Administrator
 */
public class BootCompletedReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        //UpdateActivity.class是程序启动的主Activity
        Intent intent1 = new Intent(context, UpdateActivity.class);
        intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(intent1);

    }
}

还要在清单文件中注册广播:
<!-- Android 开机自启动示例程序。使用广播方式接受,采用Android自带存储SharedPreferences存储开机自启动的设置。 -->
<!-- 开机自启动广播接受 -->
<receiver android:name=".receiver.BootCompletedReceiver">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />

        <category android:name="android.intent.category.HOME" />
    </intent-filter>
</receiver>



2,app崩溃自启动:在程序入口Application中实现。

不过有些异常崩溃,但是进程并没有杀死,这种请款就没效果了,可以参考兄弟博客(看门狗的实现):

public class BaseApplication extends Application {
    public static Context mContext;

    public static Context getContext() {
        return mContext;
    }

    @Override
    public void onCreate() {
        super.onCreate();

        //获取全局上下文
        mContext = getApplicationContext();

        //程序崩溃异常捕获并自动重启
        Thread.setDefaultUncaughtExceptionHandler(restartHandler);
    }

    private Thread.UncaughtExceptionHandler restartHandler = new Thread.UncaughtExceptionHandler() {
        @Override
        public void uncaughtException(Thread t, Throwable e) {
            
            Intent intent = new Intent(mContext, UpdateActivity.class);
            //重启应用,得使用PendingIntent
            PendingIntent restartIntent = PendingIntent.getActivity(mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
            
            AlarmManager mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
            mAlarmManager.set(AlarmManager.RTC, System.currentTimeMillis() + 2000,
                    restartIntent); // 2秒钟后重启应用
            //退出程序
            android.os.Process.killProcess(android.os.Process.myPid());  //结束当前进程
        }
    };
}

3,apk实现静默安装和自动打开,这个需要系统签名,不过做智能硬件开发都会有系统签名的,也很简单,这里就不说了:


<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    android:sharedUserId="android:sharedUserId="android.uid.system"">

需要的权限

<uses-permission android:name="android.permission.INSTALL_LOCATION_PROVIDER" />
    <uses-permission android:name="android.permission.INSTALL_PACKAGES" />
    <uses-permission android:name="android.permission.DELETE_PACKAGES" />
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

方法:

/**
 * 说明:
 *
 * android.os.Process.killProcess(android.os.Process.myPid());如果不加,最后不会提示完成、打开。
 *
 * intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);如果不加,最后安装完成,点打开,无法打开新版本应用。
 */
private void installAPK() {
    //apkPath是程序从服务器上面下载的安装包存储位置
     String apkPath = Environment.getExternalStorageDirectory().getPath().toString() + File.separator + "test.apk";
    Intent intent = new Intent(Intent.ACTION_VIEW);
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    intent.setDataAndType(Uri.fromFile(new File(apkPath)), "application/vnd.android.package-archive");
    startActivity(intent);
    android.os.Process.killProcess(android.os.Process.myPid());
}

4,实现自动开关机功能见博客:

只有关机功能,开机功能没有实现不过Android开发板可以通过电源管理实现自动开机。


总结:这几个功能基本都要用到系统签名,上面有很多权限都是需要系统签名才有效的,很多会报错,提示就是要系统签名才能使用,这个不影响程序的开发,不签名也可以运行程序,这种报错可以忽略。

有不当之处请给与提示。目前这些功能全部整合到公司项目中。