android 代码实现软件的静默安装,卸载功能
研究这个问题有一段时间,不过一直没有测试,就是需要在系统源码下进行编译,嫌麻烦就一直没动手。不过这次项目有这种需求,就必须要实现了。
android源码目录下关于安装卸载类是在,源码\packages\apps\PackageInstaller\src\com\android\packageinstaller目录下。在这几个类中主要都是各种提示框的处理
(安装,替换,卸载,成功,失败等)操作,真正执行安装,卸载逻辑只有两行代码。
好了说一下工作准备:
1,下好系统源码,在Ubantu下搭建好编译环境
2,将要编译的项目工程放入[源码目录]/packages/apps/
创建PackageInstallObserver .java安装监听(安装是否成功)
[java] view plaincopy
class PackageInstallObserver extends IPackageInstallObserver.Stub {
private Context mcontext;
public PackageInstallObserver(Context context){
this.mcontext=context;
}
public void packageInstalled(String packageName, int returnCode) {
Looper.prepare();
if (returnCode == 1) {
Toast.makeText(mcontext, "install Success!", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(mcontext, "install fail!", Toast.LENGTH_LONG).show();
}
Looper.loop();
}
}
IPackageInstallObserver.Stub为系统隐藏类,需要引入import android.content.pm.IPackageInstallObserver;
静默安装方法:
[java] view plaincopy
public void SilentInstall(Context mContext,String packageName, String path) {
Uri uri = Uri.fromFile(new File(path));
int installFlags = 0;
PackageManager pm = mContext.getPackageManager();
try {
PackageInfo packageInfo = pm.getPackageInfo(packageName,
PackageManager.GET_UNINSTALLED_PACKAGES);
if (packageInfo != null) {
installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
}
} catch (NameNotFoundException e) {
//Log.e(TAG, "NameNotFoundException = " + e.getMessage());
}
PackageInstallObserver observer = new PackageInstallObserver(mContext);
pm.installPackage(uri, observer, installFlags, packageName);
}
静默卸载与安装类似:
卸载监听:
[java] view plaincopy
class PackageDeleteObserver extends IPackageDeleteObserver.Stub {
private Context mcontext;
public PackageDeleteObserver(Context context){
this.mcontext=context;
}
public void packageDeleted(String packageName, int returnCode) {
Looper.prepare();
if (returnCode == 1) {
Toast.makeText(mcontext, "unstall Success!", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(mcontext, "unstall fail!", Toast.LENGTH_LONG).show();
}
Looper.loop();
}
}
需要引入import android.content.pm.IPackageDeleteObserver;
卸载方法:
[java] view plaincopy
public void SilentUnstall(Context mContext,String packageName){
PackageDeleteObserver observer = new PackageDeleteObserver(mContext);
mContext.getPackageManager().deletePackage(packageName, observer, 0);
}
完整代码:
[java] view plaincopy
package com.pioneersoft.pacakgeapp;
import java.io.File;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageDeleteObserver;
import android.content.pm.IPackageInstallObserver;
import android.content.pm.PackageManager;
import android.content.pm.PackageInfo;
import android.content.pm.ResolveInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.Uri;
import android.os.Looper;
import android.widget.Toast;
public class PackageMag {
public void SilentUnstall(Context mContext,String packageName){
PackageDeleteObserver observer = new PackageDeleteObserver(mContext);
mContext.getPackageManager().deletePackage(packageName, observer, 0);
}
public void SilentInstall(Context mContext,String packageName, String path) {
Uri uri = Uri.fromFile(new File(path));
int installFlags = 0;
PackageManager pm = mContext.getPackageManager();
try {
PackageInfo packageInfo = pm.getPackageInfo(packageName,
PackageManager.GET_UNINSTALLED_PACKAGES);
if (packageInfo != null) {
installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
}
} catch (NameNotFoundException e) {
//Log.e(TAG, "NameNotFoundException = " + e.getMessage());
}
PackageInstallObserver observer = new PackageInstallObserver(mContext);
pm.installPackage(uri, observer, installFlags, packageName);
}
class PackageInstallObserver extends IPackageInstallObserver.Stub {
private Context mcontext;
public PackageInstallObserver(Context context){
this.mcontext=context;
}
public void packageInstalled(String packageName, int returnCode) {
Looper.prepare();
if (returnCode == 1) {
Toast.makeText(mcontext, "install Success!", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(mcontext, "install fail!", Toast.LENGTH_LONG).show();
}
Looper.loop();
}
}
class PackageDeleteObserver extends IPackageDeleteObserver.Stub {
private Context mcontext;
public PackageDeleteObserver(Context context){
this.mcontext=context;
}
public void packageDeleted(String packageName, int returnCode) {
Looper.prepare();
if (returnCode == 1) {
Toast.makeText(mcontext, "unstall Success!", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(mcontext, "unstall fail!", Toast.LENGTH_LONG).show();
}
Looper.loop();
}
}
}
添加权限:
[java] view plaincopy
<uses-permission android:name="android.permission.INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.DELETE_PACKAGES" />
最好再加上系统签名,以获取更高权限 android:sharedUserId="android.uid.system"
[java] view plaincopy
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.pioneersoft.pacakgeapp"
android:sharedUserId="android.uid.system"
android:versionCode="1"
android:versionName="1.0" >
在根目录下创建编写Android.mk文件,这里Android.mk我是从 源码package/APP/PackageInstaller中的Android.mk拷贝过来,
然后修改LOCAL_PACKAGE_NAME := //你的项目名称
完整文件如下:
[java] view plaincopy
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_PACKAGE_NAME := PackageApp
LOCAL_CERTIFICATE := platform
include $(BUILD_PACKAGE)
做完上述所有步骤之后,就可以将这个项目放在源码环境下编译了,在源码编译前需要删除gen,bin目录,然后进行编译
编译成成功后会在out\target\product\leader75_6628_ics2\system\app生成改项目的apk,然后push到system/app或者编译在升级包里面就可以使用了