• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
紫檀未灭,我亦未去
读书可以养气,做技术需要的是不断的学习,要努力,要奋斗!
博客园    首页    新随笔    联系   管理    订阅  订阅

安装模式及安装自启动

1:下载apk

 InputStream in=null;

 FileOutputStream out = null;

try {
URL url = new URL(urlStr);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setDoOutput(false);
urlConnection.setConnectTimeout(10 * 1000);
urlConnection.setReadTimeout(30 * 1000);
urlConnection.setRequestProperty("Connection", "Keep-Alive");
urlConnection.setRequestProperty("Charset", "UTF-8");
urlConnection.setRequestProperty("Accept-Encoding", "gzip, deflate");

urlConnection.connect();
long bytetotal = urlConnection.getContentLength();
long bytesum = 0;
int byteread = 0;
in = urlConnection.getInputStream();

//保存 apk
File apkFile = StorageUtils.getCacheFile(this,appName,apkVersion);

out = new FileOutputStream(apkFile);
byte[] buffer = new byte[BUFFER_SIZE];

int oldProgress = 0;

while ((byteread = in.read(buffer)) != -1) {
bytesum += byteread;
out.write(buffer, 0, byteread);

int progress = (int) (bytesum * 100L / bytetotal);
// 如果进度与之前进度相等,则不更新,如果更新太频繁,否则会造成界面卡顿
if (progress != oldProgress) {
updateProgress(progress);
}
oldProgress = progress;
}
2:一般user安装  
/**
* 点击系统通知栏安装
* @param apkFile
* @throws IOException
*/
public static void installByNotification (Context context,File apkFile) throws IOException {

NotificationManager mNotifyManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context);

String appName=context.getString(context.getApplicationInfo().labelRes);
int icon=context.getApplicationInfo().icon;
mBuilder.setContentTitle(appName).setSmallIcon(icon);

mBuilder.setContentText("下载成功").setProgress(0, 0, false);
Intent installAPKIntent = new Intent(Intent.ACTION_VIEW);
//如果没有设置SDCard写权限,或者没有sdcard,apk文件保存在内存中,需要授予权限才能安装
String[] command = {"chmod","777",apkFile.toString()};
ProcessBuilder builder = new ProcessBuilder(command);
builder.start();
installAPKIntent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive");
//installAPKIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//installAPKIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
//installAPKIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, installAPKIntent, PendingIntent.FLAG_UPDATE_CURRENT);

mBuilder.setContentIntent(pendingIntent);
Notification noti = mBuilder.build();
noti.flags = Notification.FLAG_AUTO_CANCEL;
mNotifyManager.notify(0, noti);
}

3:取得root权限静默安装
   /**

* 取得root权限实现静默安装
     * @param apkPath
* @return
*/
private static boolean rootClientInstall(String apkPath){
PrintWriter PrintWriter = null;
Process process = null;
try {
process = Runtime.getRuntime().exec("su");
// Log.v("apkPath--",apkPath);
PrintWriter = new PrintWriter(process.getOutputStream());
PrintWriter.println("chmod 777 "+apkPath);
PrintWriter.println("export LD_LIBRARY_PATH=/vendor/lib:/system/lib");
PrintWriter.println("pm install -r " + apkPath);
// PrintWriter.println("exit");
PrintWriter.flush();
PrintWriter.close();
int value = process.waitFor();
return returnResult(value);
} catch (Exception e) {
e.printStackTrace();
}finally{
if(process!=null){
process.destroy();
}
}
return false;
}

  
/**
* 判断手机是否有root权限
*/
private static boolean hasRootPermission(){
PrintWriter PrintWriter = null;
Process process = null;
try {
process = Runtime.getRuntime().exec("su");//执行su是向系统请求root权限,赋给当前进程
PrintWriter = new PrintWriter(process.getOutputStream());
PrintWriter.flush();
PrintWriter.close();
int value = process.waitFor();
return returnResult(value);
} catch (Exception e) {
e.printStackTrace();
}finally{
if(process!=null){
process.destroy();
}
}
return false;
}
 
4:获取系统权限静默安装||root权限安装
/**
* 系统内置rom静默安装或root权限安装
* @param apkPath
* @return
*/

   我用的是方法二,方法一没有用过。
  注:两种方法都不一定适用于所有android系统。

  方法一:需要在Android系统源码的环境下用make来编译:
  在应用程序的 AndroidManifest.xml 中的 manifest 节点中加入 android:sharedUserId="android.uid.system" 这个属性
  修改Android.mk文件,加入LOCAL_CERTIFICATE := platform这一行
  使用mm命令来编译,生成的apk就有修改系统时间的权限了。

 方法二:使用目标系统的platform密钥来重新给apk文件签名。这步比较麻烦,首先找到密钥文件,在Android源码目录中的位置 是"build\target\product\security",下面的platform.pk8和platform.x509.pem两个文件。然 后用And     roid提供的Signapk工具来签名,signapk的源代码是在"build\tools\signapk"下,用法为"signapk platform.x509.pem platform.pk8 input.apk output.apk",文件名最好使用绝对路径防止找不到,也可以修改源代码直接使用。

public static String installSilent(Context context, String filePath,boolean isRoot) {
return installSilent(context, filePath, " -r " + "-f", isRoot);
}//isRoot = true (root权限) isRoot=false(系统权限)

public static String installSilent(Context context, String filePath, String pmParams,boolean isRoot){

StringBuilder command = new StringBuilder().append("LD_LIBRARY_PATH=/vendor/lib:/system/lib pm install ")
.append(pmParams == null ? "" : pmParams).append(" ").append(filePath.replace(" ", "\\ "));

CommandResult commandResult = execCommand(command.toString(), isRoot, true);

if (commandResult.successMsg != null
&& (commandResult.successMsg.contains("Success") || commandResult.successMsg.contains("success"))) {
Toast.makeText(context,"更新成功,正在重启!",Toast.LENGTH_SHORT).show();
return "INSTALL_SUCCEEDED";
}
return "INSTALL_FAILED_OTHER";
}

public static CommandResult execCommand(String command, boolean isRoot, boolean isNeedResultMsg) {
return execCommand(new String[] {command}, isRoot, isNeedResultMsg);
}

public static CommandResult execCommand(String[] commands, boolean isRoot, boolean isNeedResultMsg) {
int result = -1;
if (commands == null || commands.length == 0) {
return new CommandResult(result, null, null);
}
Process process = null;
BufferedReader successResult = null;
BufferedReader errorResult = null;
StringBuilder successMsg = null;
StringBuilder errorMsg = null;

DataOutputStream os = null;
try {
process = Runtime.getRuntime().exec(isRoot ? "su" : "sh");
os = new DataOutputStream(process.getOutputStream());
for (String command : commands) {
if (command == null) {
continue;
}
// donnot use os.writeBytes(commmand), avoid chinese charset error
os.write(command.getBytes());
os.writeBytes("\n");
os.flush();
}
os.writeBytes("exit\n");
os.flush();

result = process.waitFor();
// get command result
if (isNeedResultMsg) {
successMsg = new StringBuilder();
errorMsg = new StringBuilder();
successResult = new BufferedReader(new InputStreamReader(process.getInputStream()));
errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream()));
String s;
while ((s = successResult.readLine()) != null) {
successMsg.append(s);
}
while ((s = errorResult.readLine()) != null) {
errorMsg.append(s);
}
}
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (os != null) {
os.close();
}
if (successResult != null) {
successResult.close();
}
if (errorResult != null) {
errorResult.close();
}
} catch (IOException e) {
e.printStackTrace();
}

if (process != null) {
process.destroy();
}
}
return new CommandResult(result, successMsg == null ? null : successMsg.toString(), errorMsg == null ? null
: errorMsg.toString());
}

public static class CommandResult {

/** result of command **/
public int result;
/** success message of command result **/
public String successMsg;
/** error message of command result **/
public String errorMsg;

public CommandResult(int result) {
this.result = result;
}

public CommandResult(int result, String successMsg, String errorMsg) {
this.result = result;
this.successMsg = successMsg;
this.errorMsg = errorMsg;
}
}


5:判断软件类型
  
/**
* 是否为系统软件
* @param pInfo
* @return
*/
private static boolean isSystemApp(PackageInfo pInfo) {
if(pInfo == null ) return false ;
return ((pInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
}

/**
* 是否为系统更新软件
* @param pInfo
* @return
*/
private static boolean isSystemUpdateApp(PackageInfo pInfo) {
if(pInfo == null ) return false ;
return ((pInfo.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0);
}

/**
* 是否为用户软件
* @param pInfo
* @return
*/
private static boolean isUserApp(PackageInfo pInfo) {
if(pInfo == null ) return false ;
return (!isSystemApp(pInfo) && !isSystemUpdateApp(pInfo));
}

6:安装完毕广播自启动

if(intent.getAction().equals(Intent.ACTION_PACKAGE_REPLACED)){
String packageName = intent.getDataString().substring(8);
Log.v("install app----", packageName);
Intent newIntent = new Intent();
newIntent.setClassName("com.example.********","com.example.*******"+ ".ui.activity.SplashActivity");
newIntent.setAction("android.intent.action.MAIN");
newIntent.addCategory("android.intent.category.LAUNCHER");
newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(newIntent);
checkDownloadApk(context);
}

广播注册
<receiver android:name=".ui.java.AppBroadcastServer">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_REPLACED" />
<data android:scheme="package" />
<!-- 注意!! 这句必须要加,否则接收不到BroadCast -->
</intent-filter>
</receiver>

安装权限添加
<uses-permission android:name="android.permission.INSTALL_PACKAGES" />
 
posted @ 2016-03-01 11:46  紫檀未灭,我亦未去  阅读(469)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3