Android 静默方式实现批量安装卸载应用程序的深入分析
程序员文章站
2023-10-19 13:36:18
前段时间做了一个批量安装卸载应用程序的小应用,由于安装卸载应用程序的部分api是隐藏的,所以必须在ubuntu下下载android系统源码,并编译之后使用mm命令编译生成a...
前段时间做了一个批量安装卸载应用程序的小应用,由于安装卸载应用程序的部分api是隐藏的,所以必须在ubuntu下下载android系统源码,并编译之后使用mm命令编译生成apk文件,其实也难。
思路是这样的,在xx/packages/apps目录下有一个packageinstaller的应用程序,android机器中安装卸载都是由这个应用程序完成的。但是它没有批量安装和卸载的功能,如果要在自己的应用程序中添加批量安装和卸载的功能,其实很简单,只需要参考pakcageinstaller里面的安装卸载代码加个循环就可以了。但值得注意的是在编译的过程中必须复制packageinstaller里面的android.mk文件,修改文件为工程目录名。
好了,废话不再多说,下面是关键代码
1、 android.mk文件
local_path:= $(call my-dir)
include $(clear_vars)
local_module_tags := optional
local_src_files := $(call all-subdir-java-files)
local_package_name := packageinstaller
local_certificate := platform
include $(build_package)
local_path:= $(call my-dir)
include $(clear_vars)
local_module_tags := optional
local_src_files := $(call all-subdir-java-files)
local_package_name := packageinstaller
local_certificate := platform
include $(build_package)
2、pakcageinstaller.java文件(关键代码)
package cn.ceadic.apkmgr;
import java.io.file;
import java.io.filenotfoundexception;
import java.io.fileoutputstream;
import java.io.ioexception;
import android.content.context;
import android.content.intent;
import android.content.pm.packageinfo;
import android.content.pm.packagemanager;
import android.content.pm.packagemanager.namenotfoundexception;
import android.net.uri;
import android.util.log;
import android.content.pm.ipackageinstallobserver;
import android.content.pm.ipackagedeleteobserver;
import android.os.fileutils;
public class packageinstaller {
private file mtmpfile;
private final string tmp_file_name = "tmpcopy.apk";
private final static string tag = "packinstaller";
private context mcontext;
public packageinstaller(context context) {
mcontext = context;
}
public void install(string path,string packagename){
intent intent = new intent(intent.action_view);
intent.setdataandtype(uri.fromfile(new file(path)),
"application/vnd.android.package-archive");
mcontext.startactivity(intent);
}
public void instatllbatch(string path, string packagename) {
log.i(tag, "path=" + path);
int installflags = 0;
packagemanager pm = mcontext.getpackagemanager();
try {
packageinfo pi = pm.getpackageinfo(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:" + packagename);
}
// create temp file before invoking install api
mtmpfile = createtemppackagefile(path);
if (mtmpfile == null) {
// message msg = mhandler.obtainmessage(install_complete);
// msg.arg1 = packagemanager.install_failed_insufficient_storage;
// mhandler.sendmessage(msg);
return;
}
uri mpackageuri = uri.parse("file://" + mtmpfile.getpath());
string installerpackagename = mcontext.getintent().getstringextra(
intent.extra_installer_package_name);
packageinstallobserver observer = new packageinstallobserver();
pm.installpackage(mpackageuri, observer, installflags,
installerpackagename);
}
private file createtemppackagefile(string filepath) {
file tmppackagefile = mcontext.getfilestreampath(tmp_file_name);
if (tmppackagefile == null) {
log.w(tag, "failed to create temp file");
return null;
}
if (tmppackagefile.exists()) {
tmppackagefile.delete();
}
// open file to make it world readable
fileoutputstream fos;
try {
fos = openfileoutput(tmp_file_name, mode_world_readable);
} catch (filenotfoundexception e1) {
log.e(tag, "error opening file " + tmp_file_name);
return null;
}
try {
fos.close();
} catch (ioexception e) {
log.e(tag, "error opening file " + tmp_file_name);
return null;
}
file srcpackagefile = new file(filepath);
if (!fileutils.copyfile(srcpackagefile, tmppackagefile)) {
log.w(tag, "failed to make copy of file: " + srcpackagefile);
return null;
}
return tmppackagefile;
}
private class packageinstallobserver extends ipackageinstallobserver.stub {
public void packageinstalled(string packagename, int returncode) {
// message msg = mhandler.obtainmessage(install_complete);
// msg.arg1 = returncode;
// mhandler.sendmessage(msg);
log.i(tag, "====install_complete");
}
}
private class packagedeleteobserver extends ipackagedeleteobserver.stub {
public void packagedeleted(boolean succeeded) {
// message msg = mhandler.obtainmessage(uninstall_complete);
// msg.arg1 = succeeded?succeeded:failed;
// mhandler.sendmessage(msg);
log.i(tag, "====uninstall_complete");
}
}
public void uninstall(string packagename){
uri packageuri = uri.parse("package:" + packagename);
intent uninstallintent = new intent(intent.action_delete,
packageuri);
mcontext.startactivity(uninstallintent);
}
public void uninstallbatch(string packagename) {
packagedeleteobserver observer = new packagedeleteobserver();
mcontext.getpackagemanager().deletepackage(packagename, observer, 0);
}
}
package cn.ceadic.apkmgr;
import java.io.file;
import java.io.filenotfoundexception;
import java.io.fileoutputstream;
import java.io.ioexception;
import android.content.context;
import android.content.intent;
import android.content.pm.packageinfo;
import android.content.pm.packagemanager;
import android.content.pm.packagemanager.namenotfoundexception;
import android.net.uri;
import android.util.log;
import android.content.pm.ipackageinstallobserver;
import android.content.pm.ipackagedeleteobserver;
import android.os.fileutils;
public class packageinstaller {
private file mtmpfile;
private final string tmp_file_name = "tmpcopy.apk";
private final static string tag = "packinstaller";
private context mcontext;
public packageinstaller(context context) {
mcontext = context;
}
public void install(string path,string packagename){
intent intent = new intent(intent.action_view);
intent.setdataandtype(uri.fromfile(new file(path)),
"application/vnd.android.package-archive");
mcontext.startactivity(intent);
}
public void instatllbatch(string path, string packagename) {
log.i(tag, "path=" + path);
int installflags = 0;
packagemanager pm = mcontext.getpackagemanager();
try {
packageinfo pi = pm.getpackageinfo(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:" + packagename);
}
// create temp file before invoking install api
mtmpfile = createtemppackagefile(path);
if (mtmpfile == null) {
// message msg = mhandler.obtainmessage(install_complete);
// msg.arg1 = packagemanager.install_failed_insufficient_storage;
// mhandler.sendmessage(msg);
return;
}
uri mpackageuri = uri.parse("file://" + mtmpfile.getpath());
string installerpackagename = mcontext.getintent().getstringextra(
intent.extra_installer_package_name);
packageinstallobserver observer = new packageinstallobserver();
pm.installpackage(mpackageuri, observer, installflags,
installerpackagename);
}
private file createtemppackagefile(string filepath) {
file tmppackagefile = mcontext.getfilestreampath(tmp_file_name);
if (tmppackagefile == null) {
log.w(tag, "failed to create temp file");
return null;
}
if (tmppackagefile.exists()) {
tmppackagefile.delete();
}
// open file to make it world readable
fileoutputstream fos;
try {
fos = openfileoutput(tmp_file_name, mode_world_readable);
} catch (filenotfoundexception e1) {
log.e(tag, "error opening file " + tmp_file_name);
return null;
}
try {
fos.close();
} catch (ioexception e) {
log.e(tag, "error opening file " + tmp_file_name);
return null;
}
file srcpackagefile = new file(filepath);
if (!fileutils.copyfile(srcpackagefile, tmppackagefile)) {
log.w(tag, "failed to make copy of file: " + srcpackagefile);
return null;
}
return tmppackagefile;
}
private class packageinstallobserver extends ipackageinstallobserver.stub {
public void packageinstalled(string packagename, int returncode) {
// message msg = mhandler.obtainmessage(install_complete);
// msg.arg1 = returncode;
// mhandler.sendmessage(msg);
log.i(tag, "====install_complete");
}
}
private class packagedeleteobserver extends ipackagedeleteobserver.stub {
public void packagedeleted(boolean succeeded) {
// message msg = mhandler.obtainmessage(uninstall_complete);
// msg.arg1 = succeeded?succeeded:failed;
// mhandler.sendmessage(msg);
log.i(tag, "====uninstall_complete");
}
}
public void uninstall(string packagename){
uri packageuri = uri.parse("package:" + packagename);
intent uninstallintent = new intent(intent.action_delete,
packageuri);
mcontext.startactivity(uninstallintent);
}
public void uninstallbatch(string packagename) {
packagedeleteobserver observer = new packagedeleteobserver();
mcontext.getpackagemanager().deletepackage(packagename, observer, 0);
}
}
3、别忘记添加权限
<uses-permission android:name="android.permission.write_external_storage"/>
<uses-permission android:name="android.permission.install_packages" />
<uses-permission android:name="android.permission.delete_packages" />
<uses-permission android:name="android.permission.clear_app_cache" />
<uses-permission android:name="android.permission.read_phone_state" />
<uses-permission android:name="android.permission.clear_app_user_data" />
<uses-permission android:name="android.permission.write_external_storage"/>
<uses-permission android:name="android.permission.install_packages" />
<uses-permission android:name="android.permission.delete_packages" />
<uses-permission android:name="android.permission.clear_app_cache" />
<uses-permission android:name="android.permission.read_phone_state" />
<uses-permission android:name="android.permission.clear_app_user_data" />
以上代码在android2.1的sdk中编译通过,并正确批量安装卸载应用程序
思路是这样的,在xx/packages/apps目录下有一个packageinstaller的应用程序,android机器中安装卸载都是由这个应用程序完成的。但是它没有批量安装和卸载的功能,如果要在自己的应用程序中添加批量安装和卸载的功能,其实很简单,只需要参考pakcageinstaller里面的安装卸载代码加个循环就可以了。但值得注意的是在编译的过程中必须复制packageinstaller里面的android.mk文件,修改文件为工程目录名。
好了,废话不再多说,下面是关键代码
1、 android.mk文件
复制代码 代码如下:
local_path:= $(call my-dir)
include $(clear_vars)
local_module_tags := optional
local_src_files := $(call all-subdir-java-files)
local_package_name := packageinstaller
local_certificate := platform
include $(build_package)
复制代码 代码如下:
local_path:= $(call my-dir)
include $(clear_vars)
local_module_tags := optional
local_src_files := $(call all-subdir-java-files)
local_package_name := packageinstaller
local_certificate := platform
include $(build_package)
2、pakcageinstaller.java文件(关键代码)
复制代码 代码如下:
package cn.ceadic.apkmgr;
import java.io.file;
import java.io.filenotfoundexception;
import java.io.fileoutputstream;
import java.io.ioexception;
import android.content.context;
import android.content.intent;
import android.content.pm.packageinfo;
import android.content.pm.packagemanager;
import android.content.pm.packagemanager.namenotfoundexception;
import android.net.uri;
import android.util.log;
import android.content.pm.ipackageinstallobserver;
import android.content.pm.ipackagedeleteobserver;
import android.os.fileutils;
public class packageinstaller {
private file mtmpfile;
private final string tmp_file_name = "tmpcopy.apk";
private final static string tag = "packinstaller";
private context mcontext;
public packageinstaller(context context) {
mcontext = context;
}
public void install(string path,string packagename){
intent intent = new intent(intent.action_view);
intent.setdataandtype(uri.fromfile(new file(path)),
"application/vnd.android.package-archive");
mcontext.startactivity(intent);
}
public void instatllbatch(string path, string packagename) {
log.i(tag, "path=" + path);
int installflags = 0;
packagemanager pm = mcontext.getpackagemanager();
try {
packageinfo pi = pm.getpackageinfo(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:" + packagename);
}
// create temp file before invoking install api
mtmpfile = createtemppackagefile(path);
if (mtmpfile == null) {
// message msg = mhandler.obtainmessage(install_complete);
// msg.arg1 = packagemanager.install_failed_insufficient_storage;
// mhandler.sendmessage(msg);
return;
}
uri mpackageuri = uri.parse("file://" + mtmpfile.getpath());
string installerpackagename = mcontext.getintent().getstringextra(
intent.extra_installer_package_name);
packageinstallobserver observer = new packageinstallobserver();
pm.installpackage(mpackageuri, observer, installflags,
installerpackagename);
}
private file createtemppackagefile(string filepath) {
file tmppackagefile = mcontext.getfilestreampath(tmp_file_name);
if (tmppackagefile == null) {
log.w(tag, "failed to create temp file");
return null;
}
if (tmppackagefile.exists()) {
tmppackagefile.delete();
}
// open file to make it world readable
fileoutputstream fos;
try {
fos = openfileoutput(tmp_file_name, mode_world_readable);
} catch (filenotfoundexception e1) {
log.e(tag, "error opening file " + tmp_file_name);
return null;
}
try {
fos.close();
} catch (ioexception e) {
log.e(tag, "error opening file " + tmp_file_name);
return null;
}
file srcpackagefile = new file(filepath);
if (!fileutils.copyfile(srcpackagefile, tmppackagefile)) {
log.w(tag, "failed to make copy of file: " + srcpackagefile);
return null;
}
return tmppackagefile;
}
private class packageinstallobserver extends ipackageinstallobserver.stub {
public void packageinstalled(string packagename, int returncode) {
// message msg = mhandler.obtainmessage(install_complete);
// msg.arg1 = returncode;
// mhandler.sendmessage(msg);
log.i(tag, "====install_complete");
}
}
private class packagedeleteobserver extends ipackagedeleteobserver.stub {
public void packagedeleted(boolean succeeded) {
// message msg = mhandler.obtainmessage(uninstall_complete);
// msg.arg1 = succeeded?succeeded:failed;
// mhandler.sendmessage(msg);
log.i(tag, "====uninstall_complete");
}
}
public void uninstall(string packagename){
uri packageuri = uri.parse("package:" + packagename);
intent uninstallintent = new intent(intent.action_delete,
packageuri);
mcontext.startactivity(uninstallintent);
}
public void uninstallbatch(string packagename) {
packagedeleteobserver observer = new packagedeleteobserver();
mcontext.getpackagemanager().deletepackage(packagename, observer, 0);
}
}
复制代码 代码如下:
package cn.ceadic.apkmgr;
import java.io.file;
import java.io.filenotfoundexception;
import java.io.fileoutputstream;
import java.io.ioexception;
import android.content.context;
import android.content.intent;
import android.content.pm.packageinfo;
import android.content.pm.packagemanager;
import android.content.pm.packagemanager.namenotfoundexception;
import android.net.uri;
import android.util.log;
import android.content.pm.ipackageinstallobserver;
import android.content.pm.ipackagedeleteobserver;
import android.os.fileutils;
public class packageinstaller {
private file mtmpfile;
private final string tmp_file_name = "tmpcopy.apk";
private final static string tag = "packinstaller";
private context mcontext;
public packageinstaller(context context) {
mcontext = context;
}
public void install(string path,string packagename){
intent intent = new intent(intent.action_view);
intent.setdataandtype(uri.fromfile(new file(path)),
"application/vnd.android.package-archive");
mcontext.startactivity(intent);
}
public void instatllbatch(string path, string packagename) {
log.i(tag, "path=" + path);
int installflags = 0;
packagemanager pm = mcontext.getpackagemanager();
try {
packageinfo pi = pm.getpackageinfo(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:" + packagename);
}
// create temp file before invoking install api
mtmpfile = createtemppackagefile(path);
if (mtmpfile == null) {
// message msg = mhandler.obtainmessage(install_complete);
// msg.arg1 = packagemanager.install_failed_insufficient_storage;
// mhandler.sendmessage(msg);
return;
}
uri mpackageuri = uri.parse("file://" + mtmpfile.getpath());
string installerpackagename = mcontext.getintent().getstringextra(
intent.extra_installer_package_name);
packageinstallobserver observer = new packageinstallobserver();
pm.installpackage(mpackageuri, observer, installflags,
installerpackagename);
}
private file createtemppackagefile(string filepath) {
file tmppackagefile = mcontext.getfilestreampath(tmp_file_name);
if (tmppackagefile == null) {
log.w(tag, "failed to create temp file");
return null;
}
if (tmppackagefile.exists()) {
tmppackagefile.delete();
}
// open file to make it world readable
fileoutputstream fos;
try {
fos = openfileoutput(tmp_file_name, mode_world_readable);
} catch (filenotfoundexception e1) {
log.e(tag, "error opening file " + tmp_file_name);
return null;
}
try {
fos.close();
} catch (ioexception e) {
log.e(tag, "error opening file " + tmp_file_name);
return null;
}
file srcpackagefile = new file(filepath);
if (!fileutils.copyfile(srcpackagefile, tmppackagefile)) {
log.w(tag, "failed to make copy of file: " + srcpackagefile);
return null;
}
return tmppackagefile;
}
private class packageinstallobserver extends ipackageinstallobserver.stub {
public void packageinstalled(string packagename, int returncode) {
// message msg = mhandler.obtainmessage(install_complete);
// msg.arg1 = returncode;
// mhandler.sendmessage(msg);
log.i(tag, "====install_complete");
}
}
private class packagedeleteobserver extends ipackagedeleteobserver.stub {
public void packagedeleted(boolean succeeded) {
// message msg = mhandler.obtainmessage(uninstall_complete);
// msg.arg1 = succeeded?succeeded:failed;
// mhandler.sendmessage(msg);
log.i(tag, "====uninstall_complete");
}
}
public void uninstall(string packagename){
uri packageuri = uri.parse("package:" + packagename);
intent uninstallintent = new intent(intent.action_delete,
packageuri);
mcontext.startactivity(uninstallintent);
}
public void uninstallbatch(string packagename) {
packagedeleteobserver observer = new packagedeleteobserver();
mcontext.getpackagemanager().deletepackage(packagename, observer, 0);
}
}
3、别忘记添加权限
复制代码 代码如下:
<uses-permission android:name="android.permission.write_external_storage"/>
<uses-permission android:name="android.permission.install_packages" />
<uses-permission android:name="android.permission.delete_packages" />
<uses-permission android:name="android.permission.clear_app_cache" />
<uses-permission android:name="android.permission.read_phone_state" />
<uses-permission android:name="android.permission.clear_app_user_data" />
复制代码 代码如下:
<uses-permission android:name="android.permission.write_external_storage"/>
<uses-permission android:name="android.permission.install_packages" />
<uses-permission android:name="android.permission.delete_packages" />
<uses-permission android:name="android.permission.clear_app_cache" />
<uses-permission android:name="android.permission.read_phone_state" />
<uses-permission android:name="android.permission.clear_app_user_data" />
以上代码在android2.1的sdk中编译通过,并正确批量安装卸载应用程序