標籤:自啟 sdi trace 好的 inter [] evel 存取權限 資料
寫在前面
【apk靜默安裝】是android應用的一個重要功能,一般用在app自動更新等方面。靜默安裝在android裡面是指不需要介面或使用者參與的app安裝動作,且需要系統已獲root許可權。安裝完成後一般通過接收廣播的方式啟動App服務。
【app自啟動】是常用功能,一般通過接收系統啟動廣播實現。
本文1、被執行安裝 app:
a. 自訂許可權
<permission android:name="app.permission.install" android:protectionLevel="normal"></permission>
其中android:name是自訂許可權名稱,android:protectionLevel是表示許可權等級。
自訂許可權android:protectionLevel有四個設定選項分別是:normal、dangerous、signature、signatureOrSystem,依次指明預設的低風險許可權等級、涉及使用者私人資料或系統層級組件的高風險許可權等級、統一簽名許可權等級、系統級簽名許可權等級。此處用預設許可權。
b. service標籤加入許可權限制(執行端必須擁有該許可權才能訪問)
<service android:name=".×××Service" android:enabled="true" android:exported="true" android:permission="app.permission.install"> <intent-filter> <action android:name="×××.×××"/> </intent-filter></service>
2、執行靜默安裝 app:a. 加入被安裝app的自訂許可權(獲得存取權限)
<uses-permission android:name="app.permission.install"/>
b. 建立自動啟動的廣播接收器
<receiver android:name=".Broadcast.SilenceInstallReceiver" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="android.intent.action.PACKAGE_ADDED"/> <data android:scheme="package"/> </intent-filter></receiver>
廣播接收器:
public class SilenceInstallReceiver2 extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // 接收安裝廣播 if (intent.getAction().equals("android.intent.action.PACKAGE_ADDED")) { startApp(context); } } /** * 啟動app */ public void startApp(Context context) { /** * 啟動service */ Intent intent1 = new Intent(); intent1.setPackage("×××.×××"); //設定被執行啟動操作app包名 intent1.setAction("×××.×××"); //設定被執行啟動操作app中service的自訂intent context.startService(intent1); /** * 啟動activity */ Intent intent2= new Intent(); ComponentName componentName = new ComponentName( "×××.×××", //被執行啟動操作app的包名 "×××.×××"); //被執行啟動操作app的activity包路徑 intent2.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);// intent2.setComponent(componentName); context.startActivity(intent2); }}
c.拷貝需安裝的apk檔案到本地
項目中apk儲存位置:
具體代碼:
/** * 將assets下的需要安裝的apk檔案複製到本地可讀寫目錄 */public List<String> extractApkToLocal() { List<String> apkListLocal = new ArrayList<>(); InputStream is = null; FileOutputStream fos = null; String[] files; String assetsDir = "apks"; String localPath; try { File file = new File(apkPath); FileUtils.createOrExistsDir(file); files = mContext.getAssets().list(assetsDir); for (String f : files) { is = getAssets().open(assetsDir + "/" + f); localPath = apkPath + "/" + f; apkListLocal.add(localPath); fos = new FileOutputStream(new File(localPath)); byte[] temp = new byte[1024]; int i = 0; while ((i = is.read(temp)) > 0) { fos.write(temp, 0, i); } } } catch (IOException e) { e.printStackTrace(); } finally { if (is != null) { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } if (fos != null) { try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } } return apkListLocal;}
d.安裝apk
具體代碼:
public boolean slientInstall() { List<String> apkList; apkList = extractApkToLocal(); //擷取apk本地路徑 boolean result = false; for (String path : apkList) { File file = new File(path); Process process = null; OutputStream out = null; if (file.exists()) { try { process = Runtime.getRuntime().exec("su"); out = process.getOutputStream(); DataOutputStream dataOutputStream = new DataOutputStream(out); // 更改本地apk檔案許可權,方便執行安裝操作 dataOutputStream.writeBytes("chmod 777 " + file.getPath() + "\n"); // 進行安裝 dataOutputStream.writeBytes("LD_LIBRARY_PATH=/vendor/lib:/system/lib pm install -r " + file.getPath()); dataOutputStream.flush(); dataOutputStream.close(); out.close(); int value = process.waitFor(); // 成功 if (value == 0) { result = true; // 失敗 } else if (value == 1) { result = false; // 未知情況 } else { result = false; } } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } if (!result) { result = true; } } return result;}
3、app自啟動:a. 添加接收【系統啟動完成】廣播的許可權
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
b. 建立接收器
<receiver android:name=".Broadcast.BootReceiver" android:enabled="true"> <intent-filter> <!-- 這是開機啟動發送的廣播意圖--> <action android:name="android.intent.action.BOOT_COMPLETED"/> </intent-filter></receiver>
廣播接收器:
public class BootReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Log.e("BootReceiver:", "收到開機廣播"); //開啟服務 Intent startVoiceService = new Intent(context, ×××.class); context.startService(startVoiceService); }}
小結
靜默安裝有它的局限性,需要通過系統的超級使用者(root)進行操作任務,所以對系統安全性不高的情況有較強的實用性。此文是在查詢各方面資料基礎上實現的,旨在拋磚引玉,希望集思廣益後有更好的實現方案!
Android靜默安裝及開機自啟的簡單實現