您的位置:首页 > 移动开发 > Android开发

Android中软件的静默安装,安装完成后再自动打开新安装软件(需Root)

2017-08-22 22:41 741 查看
编写不易,如有转载,请声明出处: 梦回河口:http://blog.csdn.net/zxc514257857/article/details/77488832

前言

  需要获取Root权限,安装过程完全静默实现,注册安装、卸载、升级的广播,安装完成后自动打开新安装的软件

全部代码

// AndroidManifest中权限配置
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.RESTART_PACKAGES" />
<uses-permission android:name="android.permission.INSTALL_PACKAGES"
tools:ignore="ProtectedPermissions" />
----------------------------------------------------------------------------------------
// AndroidManifest中静态注册广播
<receiver android:name=".SilenceInstallReceiver">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_REPLACED"/>
<action android:name="android.intent.action.PACKAGE_ADDED" />
<action android:name="android.intent.action.PACKAGE_REMOVED" />
<data android:scheme="package"/>
</intent-filter>
</receiver>
----------------------------------------------------------------------------------------
// MainActivity
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.net.Uri;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class MainActivity extends AppCompatActivity {

private static final String TAG = "MainActivity";
private String tempPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/temp.apk";
private PackageInfo mPackageInfo;
private Context mContext = MainActivity.this;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(RootUtils.isRooted()) {
// 从assets目录中获取apk并安装
installFromAssets();
}
}

/**
* 从assets目录中获取并安装
*/
public void installFromAssets(){
try {
// 根据包名判断是否安装 如果未找到包名说明包名输入错误或未安装
// 想要安装的apk的名字是testapk,其包名为com.testapk.apk
mPackageInfo = getPackageManager().getPackageInfo("com.test.testapk", 0);
} catch (Exception e) {
mPackageInfo = null;
e.printStackTrace();
}

if (mPackageInfo == null) {
// 启用安装新线程
new Thread(new Runnable() {
@Override
public void run() {
Log.i(TAG , "未安装进行安装");
// 静默安装(安装其他软件或自己的升级版 无界面显示) 并启动
slientInstall();
}
}).start();
} else {
Log.i(TAG , "已经安装");
}
}

/**
* 静默安装 并启动
*
* @return
*/
public boolean slientInstall() {
// 进行资源的转移 将assets下的文件转移到可读写文件目录下
createFile();

File file = new File(tempPath);
boolean result = false;
Process process = null;
OutputStream out = null;
Log.i(TAG , "file.getPath():" + file.getPath());
if (file.exists()) {
System.out.println(file.getPath() + "==");
try {
process = Runtime.getRuntime().exec("su");
out = process.getOutputStream();
DataOutputStream dataOutputStream = new DataOutputStream(out);
// 获取文件所有权限
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) {
Log.i(TAG , "安装成功!");
result = true;
// 失败
} else if (value == 1) {
Log.i(TAG , "安装失败!");
result = false;
// 未知情况
} else {
Log.i(TAG , "未知情况!");
result = false;
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
if (!result) {
Log.i(TAG , "root权限获取失败,将进行普通安装");
normalInstall(mContext);
result = true;
}
}
return result;
}

/**
* 进行资源的转移 将assets下的文件转移到可读写文件目录下
*/
public void createFile() {
InputStream is = null;
FileOutputStream fos = null;
try {
// 从assets文件夹中获取testapk.apk文件
is = getAssets().open("testapk.apk");
File file = new File(tempPath);
file.createNewFile();
fos = new FileOutputStream(file);
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();
}
}
}
}

/**
* 传统安装
*
* @param context
*/
public void normalInstall(Context context) {
// 进行资源的转移 将assets下的文件转移到可读写文件目录下
createFile();
File file = new File(tempPath);
Intent intent = new Intent();
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setAction(android.content.Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
context.startActivity(intent);
startApp(mContext);
}

/**
* 安装后自启动apk
*
* @param context
*/
private static void startApp(Context context) {
execRootShellCmd("am start -S  " + context.getPackageName() + "/"
+ MainActivity.class.getCanonicalName() + " \n");
}

/**
* 执行shell命令
*
* @param cmds
* @return
*/
private static boolean execRootShellCmd(String... cmds) {
if (cmds == null || cmds.length == 0) {
return false;
}
DataOutputStream dos = null;
InputStream dis = null;
Process p = null;
try {
p = Runtime.getRuntime().exec("su");// 经过Root处理的android系统即有su命令
dos = new DataOutputStream(p.getOutputStream());

for (int i = 0; i < cmds.length; i++) {
dos.writeBytes(cmds[i] + " \n");
}
dos.writeBytes("exit \n");

int code = p.waitFor();

return code == 0;
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (dos != null) {
dos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (dis != null) {
dis.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
try {
if (p != null) {
p.destroy();
p = null;
}
} catch (Exception e3) {
e3.printStackTrace();
}
}
return false;
}
}
----------------------------------------------------------------------------------------
// SilenceInstallReceiver
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class SilenceInstallReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("android.intent.action.PACKAGE_REPLACED")){
String packageName = intent.getDataString();
System.out.println("升级了:" + packageName + "包名的程序");
//            startApp(context);
}

// 接收安装广播
if (intent.getAction().equals("android.intent.action.PACKAGE_ADDED")) {
String packageName = intent.getDataString();
System.out.println("安装了:" +packageName + "包名的程序");
// 监测到升级后执行app的启动 只能启动自身 一般用于软件更新
startApp(context);
}

//接收卸载广播
if (intent.getAction().equals("android.intent.action.PACKAGE_REMOVED")) {
String packageName = intent.getDataString();
System.out.println("卸载了:"  + packageName + "包名的程序");
}
}

/**
* 监测到升级后执行app的启动
*/
public void startApp(Context context){
// 根据包名打开安装的apk
Intent resolveIntent = context.getPackageManager().getLaunchIntentForPackage("com.test.testapk");
context.startActivity(resolveIntent);

// 打开自身 一般用于软件升级
//        Intent intent = new Intent(context, MainActivity.class);
//        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//        context.startActivity(intent);
}
}
----------------------------------------------------------------------------------------
// RootUtil
import android.util.Log;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;

public class RootUtils {

public static final String TAG = "RootUtils";

@Deprecated
public static boolean isRooted() {
Process process = null;
try {
process = Runtime.getRuntime().exec("su");
OutputStream outputStream = process.getOutputStream();
InputStream inputStream = process.getInputStream();
outputStream.write("id\n".getBytes());
outputStream.flush();
outputStream.write("exit\n".getBytes());
outputStream.flush();
process.waitFor();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String s = bufferedReader.readLine();
if (s.contains("uid=0")) return true;
} catch (IOException e) {
Log.e(TAG, "没有root权限");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if (process != null)
process.destroy();
}
return false;
}

public static boolean checkRooted() {
boolean result = false;
try {
result = new File("/system/bin/su").exists() || new File("/system/xbin/su").exists();
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
}


Demo下载请移步:http://download.csdn.net/download/zxc514257857/9945636

因本人才疏学浅,如博客或Demo中有错误的地方请大家随意指出,与大家一起讨论,共同进步,谢谢!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息