我们一般代码调用安装apk会写下面的代码
Intent intent = new Intent(Intent.ACTION_VIEW); File apkFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/1.apk"); intent.setDataAndType(Uri.fromFile(apkFile),"application/vnd.android.package-archive"); startActivity(intent);
我们安装apk时系统会分析apk,然后弹出如下图的提示
当我们点击安装后,系统会进行安装
这里我们查看系统源码来看一下系统是怎么执行安装程序的
首先我们找到PackageInstallerActivity.java,一看命名规则就知道是apk安装的界面
既然是Activity 那么我们首先来看onCreate()方法
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
//get intent information 获取Intent信息
final Intent intent = getIntent();
mPackageURI = intent.getData();//apk的uri
mPm = getPackageManager();
mPkgInfo = PackageUtil.getPackageInfo(mPackageURI);
// Check for parse errors 检查apk是否有错误
if(mPkgInfo == null) {
Log.w(TAG, "Parse error when parsing manifest. Discontinuing installation");
showDialogInner(DLG_PACKAGE_ERROR);
return;
}
//set view
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.install_start); //这就是上面的界面
mInstallConfirm = findViewById(R.id.install_confirm_panel);
mInstallConfirm.setVisibility(View.INVISIBLE);
PackageUtil.AppSnippet as = PackageUtil.getAppSnippet(this,
mPkgInfo.applicationInfo, mPackageURI);
PackageUtil.initSnippetForNewApp(this, as, R.id.app_snippet);
//check setting //是否设置了 允许安装未知来源,就是设置那里的
if(!isInstallingUnknownAppsAllowed()) {
//ask user to enable setting first
showDialogInner(DLG_UNKNOWN_APPS);
return;
}
initiateInstall();
}
然后看initiateInstall()方法
private void initiateInstall() {
String pkgName = mPkgInfo.packageName;
// Check if there is already a package on the device with this name
// but it has been renamed to something else. //检查是否有相同包名的应用
String[] oldName = mPm.canonicalToCurrentPackageNames(new String[] { pkgName });
if (oldName != null && oldName.length > 0 && oldName[0] != null) {
pkgName = oldName[0];
mPkgInfo.setPackageName(pkgName);
}
// Check if package is already installed. display confirmation dialog if replacing pkg检查是否已经安装过了
try {
mAppInfo = mPm.getApplicationInfo(pkgName,
PackageManager.GET_UNINSTALLED_PACKAGES);
} catch (NameNotFoundException e) {
mAppInfo = null;
}
if (mAppInfo == null) {
startInstallConfirm();//安装
} else {
if(localLOGV) Log.i(TAG, "Replacing existing package:"+
mPkgInfo.applicationInfo.packageName);
showDialogInner(DLG_REPLACE_APP);
}
}
来到startInstallConfirm()
private void startInstallConfirm() {
LinearLayout permsSection = (LinearLayout) mInstallConfirm.findViewById(R.id.permissions_section);
LinearLayout securityList = (LinearLayout) permsSection.findViewById(
R.id.security_settings_list);
boolean permVisible = false;
if(mPkgInfo != null) {
AppSecurityPermissions asp = new AppSecurityPermissions(this, mPkgInfo);
if(asp.getPermissionCount() > 0) {
permVisible = true;
securityList.addView(asp.getPermissionsView());
}
}
if(!permVisible){
permsSection.setVisibility(View.INVISIBLE);
}
mInstallConfirm.setVisibility(View.VISIBLE);
mOk = (Button)findViewById(R.id.ok_button); //确认按钮
mCancel = (Button)findViewById(R.id.cancel_button);
mOk.setOnClickListener(this);
mCancel.setOnClickListener(this);
}
找点击事件 onClick()
public void onClick(View v) {
if(v == mOk) { //开始安装,弹出安装进度界面
// Start subactivity to actually install the application
Intent newIntent = new Intent();
newIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO,
mPkgInfo.applicationInfo);
newIntent.setData(mPackageURI);
newIntent.setClass(this, InstallAppProgress.class); //这里调到了InstallAppProgress.java
String installerPackageName = getIntent().getStringExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME);
if (installerPackageName != null) {
newIntent.putExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME, installerPackageName);
}
if(localLOGV) Log.i(TAG, "downloaded app uri="+mPackageURI);
startActivity(newIntent);
finish();
} else if(v == mCancel) {
// Cancel and finish
finish();
}
}继续跟踪 到InstallAppProgress.java 的onCreate()
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
Intent intent = getIntent();
mAppInfo = intent.getParcelableExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO);
mPackageURI = intent.getData();
initView();
}initView();
public void initView() {
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.op_progress);
int installFlags = 0; //设置錐lag
PackageManager pm = getPackageManager();
try {
PackageInfo pi = pm.getPackageInfo(mAppInfo.packageName,
PackageManager.GET_UNINSTALLED_PACKAGES);
if(pi != null) {
installFlags |= PackageManager.INSTALL_REPLACE_EXISTING; //替换已经存在的
}
} catch (NameNotFoundException e) {
}
if((installFlags & PackageManager.INSTALL_REPLACE_EXISTING )!= 0) {
Log.w(TAG, "Replacing package:" + mAppInfo.packageName);
}
PackageUtil.AppSnippet as = PackageUtil.getAppSnippet(this, mAppInfo,
mPackageURI);
mLabel = as.label;
PackageUtil.initSnippetForNewApp(this, as, R.id.app_snippet);
mStatusTextView = (TextView)findViewById(R.id.center_text);
mStatusTextView.setText(R.string.installing);
mProgressBar = (ProgressBar) findViewById(R.id.progress_bar);
mProgressBar.setIndeterminate(true);
// Hide button till progress is being displayed
mOkPanel = (View)findViewById(R.id.buttons_panel);
mDoneButton = (Button)findViewById(R.id.done_button);
mLaunchButton = (Button)findViewById(R.id.launch_button);
mOkPanel.setVisibility(View.INVISIBLE);
String installerPackageName = getIntent().getStringExtra(
Intent.EXTRA_INSTALLER_PACKAGE_NAME);
PackageInstallObserver observer = new PackageInstallObserver();
pm.installPackage(mPackageURI, observer, installFlags, installerPackageName);//安装的代码
}
几经周折,总算找到了。。。
下几句 关键的
int installFlags = 0; //设置Flag
PackageManager pm = getPackageManager();
try {
PackageInfo pi = pm.getPackageInfo(mAppInfo.packageName,
PackageManager.GET_UNINSTALLED_PACKAGES);
if(pi != null) {
installFlags |= PackageManager.INSTALL_REPLACE_EXISTING; //替换已经存在的
}
} catch (NameNotFoundException e) {
}
PackageUtil.AppSnippet as = PackageUtil.getAppSnippet(this, mAppInfo,
mPackageURI);
String installerPackageName = getIntent().getStringExtra(
Intent.EXTRA_INSTALLER_PACKAGE_NAME);
PackageInstallObserver observer = new PackageInstallObserver();
pm.installPackage(mPackageURI, observer, installFlags, installerPackageName);//安装的代
我们可以通过上面的代码直接进行安装,
不过我们需要android.Manifest.permission#INSTALL_PACKAGE,
此权限只有system应用才能使用.
所以此应用必须放入system/app下,
还有静默安装的一种方式是使用root权限 adb指令执行 install -r 进行安装