" 须知少时凌云志,曾许人间第一流 "
在《风犬少年的天空》中刘闻钦下线时,嘴里念叨的就是这句,我们何尝不是这样的人呢,年轻时的凌云大志,曾决心要做人间第一流的人物,干出人间第一流的成绩,但岁月蹉跎,依旧名利双无收。

前言

本文重点讲述如何实现Android设备重启,这里的Android设备可不是我们用的手机哦,毕竟现在的手机越来越高级,好像除了苹果系列的手机没有定时开关机,Android手机都是有这个功能的,有的人喜欢睡前关机,早上四五点就定时开机,觉得这样手机用起来才不会卡,当然这只是一小部分人的做法,好多人都是直接通宵玩手机的,玩到没电就充电睡觉去。
好了,再说就跑题了,哈哈 ~~
进入正题,为什么需要重启Android设备呢?因为现在好多生产安卓板的厂家用的Android系统大部分是阉割版的,自身硬件和服务需要用到什么功能就放进去,没用到的就切掉,但是有些厂家对于这一块处理得不够好,导致系统长时间运行时,会出现不稳定情况,例如Android板长时间运行一款app的,比如广告投放机、自动售卖机等,如果本身配置不够高,系统做的又不好,就会出现卡死,黑屏或者卡屏闪屏问题出现,只要硬件没坏,只需要重启下Android系统就可以解决上述问题的。

一、利用系统广播ACTION_REBOOT

这种方式非常简单,只需要发送一个系统广播ACTION_REBOOT,代码如下:

mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent reboot = new Intent(Intent.ACTION_REBOOT);
                reboot.putExtra("nowait", 1);
                reboot.putExtra("interval", 1);
                reboot.putExtra("window", 0);
                sendBroadcast(reboot);
            }
        });

但是这样是不会重启的,程序还会因此闪退,直接报错:

com.xz.android72test E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.xz.android72test, PID: 3180
    java.lang.SecurityException: Permission Denial: not allowed to send broadcast android.intent.action.REBOOT from pid=3180, uid=10046
        at android.os.Parcel.readException(Parcel.java:1546)
        at android.os.Parcel.readException(Parcel.java:1499)
        at android.app.ActivityManagerProxy.broadcastIntent(ActivityManagerNative.java:2831)
        at android.app.ContextImpl.sendBroadcast(ContextImpl.java:1331)
        at android.content.ContextWrapper.sendBroadcast(ContextWrapper.java:377)
        at com.xz.android72test.MainActivity$2.onClick(MainActivity.java:115)
        at android.view.View.performClick(View.java:4780)
        at android.view.View$PerformClick.run(View.java:19866)
        at android.os.Handler.handleCallback(Handler.java:739)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:135)
        at android.app.ActivityThread.main(ActivityThread.java:5293)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)

最主要的错误是SecurityException: Permission Denial,权限不够,默认的SDK并没有提供应用开发者直接的Android系统关机或重启的API接口,一般来讲,实现Android系统的关机或重启,需要较高的权限(系统权限甚至Root权限),在此,我们需要将app的权限提高至系统权限,找到AndroidManifest.xml,添加下面的代码:

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

但是做到这里也是不会重启的,程序还会安装失败,直接报错:

Installation did not succeed.
The application could not be installed: INSTALL_FAILED_SHARED_USER_INCOMPATIBLE
Installation failed due to: 'null'

这是为什么呢? 因为这个apk没有这个系统的签名。如何签名呢?

有三种方式:

第一种,这种方式比较经典传统:

  • 联系安卓板厂家技术获取主板系统的签名文件platform.pk8platform.x509.pem,每家安卓板厂家签名文件都不一样,还需要signapk.jar这个文件,一般厂家也会将这个文件一起发送过来,网上也是可以下载的,jar包里面带有签名的程序。
  • 在windows下,启动cmd.exe,进入命令行模式,通过cd C:\Users\Administrator\Desktop\signapkApp进到带有platform.pk8platform.x509.pemsignapk.jar文件的文件夹。
  • 最后输入下面命令进行签名:
java -jar signapk.jar  platform.x509.pem platform.pk8 C:\Users\Administrator\Desktop\signapkApp\app-release.apk signed_app-release.apk

其中C:\Users\Administrator\Desktop\signapk.jar\app-release.apk为需要签名的apk路径,signed_app-release.apk是签名之后的apk,跟未签名的apk在同一个目录下。

最后直接通过adb push或者adb install把这个signed_app-release.apk安装完即可实现重启了。

第二种,这种方式跟第一种比较,更加简单,也可以在debug版本或者release版本进行签名:
只需要问安卓板厂家技术要一个文件,或者自己根据主板系统的签名文件platform.pk8platform.x509.pem做一个出来,这个文件就是platform.keystore签名文件。

然后在app\build.gradle文件下添加下面代码:

android {

    ......
    
    signingConfigs {
        debug {
            storeFile file('platform.keystore文件路径')
            storePassword 'keystore的密码'
            keyAlias '密钥别名'
            keyPassword '密钥密码'
        }
        release {
            storeFile file('platform.keystore文件路径')
            storePassword 'keystore的密码'
            keyAlias '密钥别名'
            keyPassword '密钥密码'
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.release
        }
        debug {
            signingConfig signingConfigs.debug
        }
    }
}

至此,Build出来的apk无论是debug还是release版本都带有系统签名的。

第三种,这种方式基本算是白嫖了,利用厂家提供的签名网站,只需要将未签名的apk上传到他们服务器,过一会签完名之后会自动下载下来,而这个文件就是已经签完名了。

android echo 设备重启 安卓设备重启_Android设备重启


对比这三种方式,是不是最后这一种最省事呢?但是呐,人还是不可以太懒的,建议用第二种方式啦。

二、利用Linux-shell发送reboot指令

这种方式非常简单,利用Runtime这个Java类可以直接调用并执行shell命令,直接贴代码:

mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                exec("reboot");
            }
        });

如果Android设备没有root过,需要在AndroidManifest.xml下添加一下权限,从而使下面代码获取管理员权限:

<uses-permission android:name="android.permission.ACCESS_SUPERUSER" />

exec方法:

private String exec(String command) {

        Process process = null;
        BufferedReader reader = null;
        InputStreamReader is = null;
        DataOutputStream os = null;

        try {
            process = Runtime.getRuntime().exec("su");
            is = new InputStreamReader(process.getInputStream());
            reader = new BufferedReader(is);
            os = new DataOutputStream(process.getOutputStream());
            os.writeBytes(command + "\n");
            os.writeBytes("exit\n");
            os.flush();
            int read;
            char[] buffer = new char[4096];
            StringBuilder output = new StringBuilder();
            while ((read = reader.read(buffer)) > 0) {
                output.append(buffer, 0, read);
            }
            process.waitFor();
            return output.toString();
        } catch (IOException | InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                if (os != null) {
                    os.close();
                }

                if (is != null) {
                    is.close();
                }

                if (reader != null) {
                    reader.close();
                }

                if (process != null) {
                    process.destroy();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

普通用户是没有权限执行reboot,所以使用的Android设备最好是root过的,不然会在获取su管理员权限时,出现一个弹窗询问你是否允许请求超级用户访问权限,非常影响用户体验。

android echo 设备重启 安卓设备重启_Android设备重启_02

非常感谢你能看到这里,如果能够帮助到你是我的荣幸!