android9 apk自动安装功能,Android9.0 静默安装源码的实现

网上基本都停在8.0就没人开始分析Android9.0如何静默apk的代码,这是我自己之前研究9.0的framework整理出来的,真实源码整理

import android.content.BroadcastReceiver;

import android.content.Context;

import android.content.IIntentReceiver;

import android.content.IIntentSender;

import android.content.Intent;

import android.content.IntentFilter;

import android.content.IntentSender;

import android.content.pm.ApplicationInfo;

import android.content.pm.PackageInfo;

import android.content.pm.PackageInstaller;

import android.content.pm.PackageManager;

import android.net.Uri;

import android.os.Bundle;

import android.os.Environment;

import android.os.IBinder;

import android.os.RemoteException;

import android.util.Log;

import java.io.File;

import java.io.FileInputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.lang.reflect.Constructor;

import java.lang.reflect.Field;

import java.lang.reflect.InvocationTargetException;

import java.util.concurrent.SynchronousQueue;

import java.util.concurrent.TimeUnit;

/**

* 作者 :

* 邮箱 : 709847739#qq.com

* 时间 : 2019/2/21-9:21

* desc :

* version: 1.0

*/

public class PackageManagerCompatP {

private final static String TAG = PackageManagerCompatP.class.getSimpleName();

public static final long MAX_WAIT_TIME = 25 * 1000;

public static final long WAIT_TIME_INCR = 5 * 1000;

private static final String SECURE_CONTAINERS_PREFIX = "/mnt/asec";

private Context mContext;

public PackageManagerCompatQ(Context context) {

this.mContext = context;

}

private static class LocalIntentReceiver {

private final SynchronousQueue mResult = new SynchronousQueue<>();

private IIntentSender.Stub mLocalSender = new IIntentSender.Stub() {

@Override

public void send(int code, Intent intent, String resolvedType, IBinder whitelistToken,

IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {

try {

mResult.offer(intent, 5, TimeUnit.SECONDS);

} catch (InterruptedException e) {

throw new RuntimeException(e);

}

}

};

public IntentSender getIntentSender() {

Class> aClass = null;

try {

aClass = Class.forName("android.content.IntentSender");

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

if (aClass == null) {

return null;

}

try {

Constructor>[] declaredConstructors = aClass.getDeclaredConstructors();

for (Constructor> declaredConstructor : declaredConstructors) {

Log.i(TAG, "declaredConstructor.toString():" + declaredConstructor.toString());

Log.i(TAG, "declaredConstructor.getName():" + declaredConstructor.getName());

Class>[] parameterTypes = declaredConstructor.getParameterTypes();

for (Class> parameterType : parameterTypes) {

Class aClass1 = parameterType.getClass();

Log.i(TAG, "parameterTypes...aClass1:" + aClass1.getName());

}

}

} catch (Exception e) {

e.printStackTrace();

}

Constructor constructor = null;

try {

constructor = aClass.getDeclaredConstructor(IIntentSender.class);

} catch (NoSuchMethodException e) {

e.printStackTrace();

}

if (constructor == null) {

return null;

}

Object o = null;

try {

o = constructor.newInstance((IIntentSender) mLocalSender);

} catch (IllegalAccessException e) {

e.printStackTrace();

} catch (InstantiationException e) {

e.printStackTrace();

} catch (InvocationTargetException e) {

e.printStackTrace();

}

return (IntentSender) o;

// new IntentSender((IIntentSender) mLocalSender)

}

public Intent getResult() {

try {

return mResult.take();

} catch (InterruptedException e) {

throw new RuntimeException(e);

}

}

}

private PackageManager getPm() {

return mContext.getPackageManager();

}

private PackageInstaller getPi() {

return getPm().getPackageInstaller();

}

private void writeSplitToInstallSession(PackageInstaller.Session session, String inPath,

String splitName) throws RemoteException {

long sizeBytes = 0;

final File file = new File(inPath);

if (file.isFile()) {

sizeBytes = file.length();

} else {

return;

}

InputStream in = null;

OutputStream out = null;

try {

in = new FileInputStream(inPath);

out = session.openWrite(splitName, 0, sizeBytes);

int total = 0;

byte[] buffer = new byte[65536];

int c;

while ((c = in.read(buffer)) != -1) {

total += c;

out.write(buffer, 0, c);

}

session.fsync(out);

} catch (IOException e) {

e.printStackTrace();

} finally {

IoUtils.closeQuietly(out);

IoUtils.closeQuietly(in);

IoUtils.closeQuietly(session);

}

}

/**

* 入口方法

* String apkPackageName = ""; //填写安装的包名

* String apkPath = "";//填写安装的路径

**/

public void testReplaceFlagSdcardInternal(String apkPackageName, String apkPath) throws Exception {

// Do not run on devices with emulated external storage.

if (Environment.isExternalStorageEmulated()) {

return;

}

int iFlags = 0x00000008;// PackageManager.INSTALL_EXTERNAL 0x00000008

int rFlags = 0;

//这个暂时用不上

//InstallParams ip = sampleInstallFromRawResource(iFlags, false);

Uri uri = Uri.fromFile(new File(apkPath));

GenericReceiver receiver = new ReplaceReceiver(apkPackageName);

int replaceFlags = rFlags | 0x00000002;//PackageManager.INSTALL_REPLACE_EXISTING 0x00000002

try {

invokeInstallPackage(uri, replaceFlags, receiver, true);

//assertInstall(ip.pkg, iFlags, ip.pkg.installLocation);

} catch (Exception e) {

Log.e(TAG, "Failed with exception : " + e);

} finally {

// cleanUpInstall(ip);

}

}

// class InstallParams {

// Uri packageURI;

//

// PackageParser.Package pkg;

//

// InstallParams(String outFileName, int rawResId) throws PackageParserException {

// this.pkg = getParsedPackage(outFileName, rawResId);

// this.packageURI = Uri.fromFile(new File(pkg.codePath));

// }

//

// InstallParams(PackageParser.Package pkg) {

// this.packageURI = Uri.fromFile(new File(pkg.codePath));

// this.pkg = pkg;

// }

//

// long getApkSize() {

// File file = new File(pkg.codePath);

// return file.length();

// }

// }

//

// private InstallParams sampleInstallFromRawResource(int flags, boolean cleanUp)

// throws Exception {

// return installFromRawResource("install.apk", android.R.raw.install, flags, cleanUp, false, -1,

// PackageInfo.INSTALL_LOCATION_UNSPECIFIED);

// }

// private void cleanUpInstall(InstallParams ip) {

//

// }

private void cleanUpInstall(String pkgName) throws Exception {

if (pkgName == null) {

return;

}

Log.i(TAG, "Deleting package : " + pkgName);

try {

final ApplicationInfo info = getPm().getApplicationInfo(pkgName,

PackageManager.MATCH_UNINSTALLED_PACKAGES);

if (info != null) {

//PackageManager.DELETE_ALL_USERS

final LocalIntentReceiver localReceiver = new LocalIntentReceiver();

//这是卸载,不调用

// getPi().uninstall(pkgName,

// 0x00000002,

// localReceiver.getIntentSender());

localReceiver.getResult();

assertUninstalled(info);

}

} catch (IllegalArgumentException | PackageManager.NameNotFoundException e) {

e.printStackTrace();

}

}

private static void assertUninstalled(ApplicationInfo info) throws Exception {

File nativeLibraryFile = new File(info.nativeLibraryDir);

Log.e(TAG, "Native library directory " + info.nativeLibraryDir

+ " should be erased" + nativeLibraryFile.exists());

}

private void invokeInstallPackage(Uri packageUri, int flags, GenericReceiver receiver,

boolean shouldSucceed) {

mContext.registerReceiver(receiver, receiver.filter);

synchronized (receiver) {

final String inPath = packageUri.getPath();

PackageInstaller.Session session = null;

try {

final PackageInstaller.SessionParams sessionParams =

new PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL);

try {

//sessionParams.installFlags = flags;

Field installFlags = sessionParams.getClass().getDeclaredField("installFlags");

installFlags.set(sessionParams, flags);

} catch (NoSuchFieldException e) {

e.printStackTrace();

} catch (IllegalAccessException e) {

e.printStackTrace();

}

final int sessionId = getPi().createSession(sessionParams);

session = getPi().openSession(sessionId);

writeSplitToInstallSession(session, inPath, "base.apk");

final LocalIntentReceiver localReceiver = new LocalIntentReceiver();

session.commit(localReceiver.getIntentSender());

final Intent result = localReceiver.getResult();

final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,

PackageInstaller.STATUS_FAILURE);

if (shouldSucceed) {

if (status != PackageInstaller.STATUS_SUCCESS) {

Log.e(TAG, "Installation should have succeeded, but got code " + status);

}

} else {

if (status == PackageInstaller.STATUS_SUCCESS) {

Log.e(TAG, "Installation should have failed");

}

// We'll never get a broadcast since the package failed to install

return;

}

// Verify we received the broadcast

long waitTime = 0;

while ((!receiver.isDone()) && (waitTime < MAX_WAIT_TIME)) {

try {

receiver.wait(WAIT_TIME_INCR);

waitTime += WAIT_TIME_INCR;

} catch (InterruptedException e) {

Log.i(TAG, "Interrupted during sleep", e);

}

}

if (!receiver.isDone()) {

Log.e(TAG, "Timed out waiting for PACKAGE_ADDED notification");

}

} catch (IllegalArgumentException | IOException | RemoteException e) {

Log.e(TAG, "Failed to install package; path=" + inPath, e);

} finally {

IoUtils.closeQuietly(session);

mContext.unregisterReceiver(receiver);

}

}

}

private abstract static class GenericReceiver extends BroadcastReceiver {

private boolean doneFlag = false;

boolean received = false;

Intent intent;

IntentFilter filter;

abstract boolean notifyNow(Intent intent);

@Override

public void onReceive(Context context, Intent intent) {

if (notifyNow(intent)) {

synchronized (this) {

received = true;

doneFlag = true;

this.intent = intent;

notifyAll();

}

}

}

public boolean isDone() {

return doneFlag;

}

public void setFilter(IntentFilter filter) {

this.filter = filter;

}

}

class ReplaceReceiver extends GenericReceiver {

String pkgName;

final static int INVALID = -1;

final static int REMOVED = 1;

final static int ADDED = 2;

final static int REPLACED = 3;

int removed = INVALID;

// for updated system apps only

boolean update = false;

ReplaceReceiver(String pkgName) {

this.pkgName = pkgName;

filter = new IntentFilter(Intent.ACTION_PACKAGE_REMOVED);

filter.addAction(Intent.ACTION_PACKAGE_ADDED);

if (update) {

filter.addAction(Intent.ACTION_PACKAGE_REPLACED);

}

filter.addDataScheme("package");

super.setFilter(filter);

}

public boolean notifyNow(Intent intent) {

String action = intent.getAction();

Uri data = intent.getData();

String installedPkg = data.getEncodedSchemeSpecificPart();

if (pkgName == null || !pkgName.equals(installedPkg)) {

return false;

}

if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) {

removed = REMOVED;

} else if (Intent.ACTION_PACKAGE_ADDED.equals(action)) {

if (removed != REMOVED) {

return false;

}

boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);

if (!replacing) {

return false;

}

removed = ADDED;

if (!update) {

return true;

}

} else if (Intent.ACTION_PACKAGE_REPLACED.equals(action)) {

if (removed != ADDED) {

return false;

}

removed = REPLACED;

return true;

}

return false;

}

}

}

就这一个类的封装,我也是看framework扣出来的

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值