update:2020.10.21

fix:安装卸载功能兼容安卓10
add:
This commit is contained in:
2020-10-21 18:49:52 +08:00
parent 08d8c0bef4
commit 446de37ef5
13 changed files with 292 additions and 38 deletions

View File

@@ -17,8 +17,8 @@ android {
applicationId "com.appstore.uiui" applicationId "com.appstore.uiui"
minSdkVersion 23 minSdkVersion 23
targetSdkVersion 29 targetSdkVersion 29
versionCode 22 versionCode 24
versionName "1.2.2" versionName "1.2.4"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
//极光 //极光
ndk { ndk {

View File

@@ -71,7 +71,8 @@
<receiver <receiver
android:name=".receiver.AppManagerReceiver" android:name=".receiver.AppManagerReceiver"
android:enabled="true" android:enabled="true"
android:exported="true"> android:exported="true"
android:permission="com.example.broadcast.permission">
<intent-filter android:priority="1000"> <intent-filter android:priority="1000">
<action android:name="android.intent.action.PACKAGE_ADDED" /> <action android:name="android.intent.action.PACKAGE_ADDED" />
<action android:name="android.intent.action.PACKAGE_REPLACED" /> <action android:name="android.intent.action.PACKAGE_REPLACED" />
@@ -205,7 +206,10 @@
<category android:name="com.appstore.uiui" /> <category android:name="com.appstore.uiui" />
</intent-filter> </intent-filter>
</receiver> <!-- Required . Enable it you can get statistics data with channel --> </receiver>
<receiver android:name=".receiver.InstallResultReceiver"
android:enabled="true"
android:exported="true"/> <!-- Required . Enable it you can get statistics data with channel -->
<meta-data <meta-data
android:name="JPUSH_CHANNEL" android:name="JPUSH_CHANNEL"
android:value="developer-default" /> android:value="developer-default" />

View File

@@ -2,6 +2,8 @@ package com.appstore.uiui;
import android.app.Application; import android.app.Application;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.os.Handler; import android.os.Handler;
@@ -12,6 +14,7 @@ import androidx.annotation.NonNull;
import com.appstore.uiui.jpush.Logger; import com.appstore.uiui.jpush.Logger;
import com.appstore.uiui.network.OKGO; import com.appstore.uiui.network.OKGO;
import com.appstore.uiui.receiver.AppManagerReceiver;
import com.appstore.uiui.utils.ApkUtils; import com.appstore.uiui.utils.ApkUtils;
import com.appstore.uiui.utils.LogUtils; import com.appstore.uiui.utils.LogUtils;
import com.appstore.uiui.utils.SPUtils; import com.appstore.uiui.utils.SPUtils;
@@ -99,9 +102,23 @@ public class MyApplication extends Application {
// .setFontAttrId(R.attr.fontPath) // .setFontAttrId(R.attr.fontPath)
// .build() // .build()
// ); // );
registAppReceive();
} }
private AppManagerReceiver mAppManagerReceiver;
private void registAppReceive() {
mAppManagerReceiver = new AppManagerReceiver();
IntentFilter filter = new IntentFilter();
filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
filter.addAction(Intent.ACTION_PACKAGE_ADDED);
filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
filter.addDataScheme("package");
registerReceiver(mAppManagerReceiver, filter);
}
public boolean isDebug(Context context) { public boolean isDebug(Context context) {
boolean isDebug = context.getApplicationInfo() != null && boolean isDebug = context.getApplicationInfo() != null &&
(context.getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0; (context.getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
@@ -372,7 +389,7 @@ public class MyApplication extends Application {
new Thread(new Runnable() { new Thread(new Runnable() {
@Override @Override
public void run() { public void run() {
ApkUtils.installApkInSilence(app.getAppContext(), response.body().getAbsolutePath()); ApkUtils.installApp(app.getAppContext(), response.body().getAbsolutePath());
} }
}).start(); }).start();
LogUtils.e("onSuccess", "download file successful,now installing"); LogUtils.e("onSuccess", "download file successful,now installing");

View File

@@ -198,7 +198,7 @@ public class DetailsActivity extends BaseActivity {
new Thread(new Runnable() { new Thread(new Runnable() {
@Override @Override
public void run() { public void run() {
ApkUtils.installApkInSilence(DetailsActivity.this, file.getAbsolutePath()); ApkUtils.installApp(DetailsActivity.this, file.getAbsolutePath());
} }
}).start(); }).start();
} }

View File

@@ -416,7 +416,7 @@ public class MainActivity extends BaseActivity {
new Thread(new Runnable() { new Thread(new Runnable() {
@Override @Override
public void run() { public void run() {
ApkUtils.installApkInSilence(MainActivity.this, response.body().getAbsolutePath()); ApkUtils.installApp(MainActivity.this, response.body().getAbsolutePath());
} }
}).start(); }).start();
LogUtils.e("getFile", "download file successful,now installing"); LogUtils.e("getFile", "download file successful,now installing");

View File

@@ -267,7 +267,7 @@ public class AppAdapter extends RecyclerView.Adapter<AppAdapter.Holder> {
new Thread(new Runnable() { new Thread(new Runnable() {
@Override @Override
public void run() { public void run() {
ApkUtils.installApkInSilence(mContext, file.getAbsolutePath()); ApkUtils.installApp(mContext, file.getAbsolutePath());
} }
}).start(); }).start();
} }

View File

@@ -65,7 +65,7 @@ public class LocalAppAdapter extends RecyclerView.Adapter<LocalAppAdapter.LocalA
holder.btnDownLoad.setOnClickListener(new View.OnClickListener() { holder.btnDownLoad.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
ApkUtils.uninstall(context, localApp.getPackageName()); ApkUtils.uninstallApp(context, localApp.getPackageName());
} }
}); });
String totalLength = Formatter.formatFileSize(context, localApp.getSize()); String totalLength = Formatter.formatFileSize(context, localApp.getSize());

View File

@@ -186,7 +186,7 @@ public class UpdateAppAdapter extends RecyclerView.Adapter<UpdateAppAdapter.Upda
new Thread(new Runnable() { new Thread(new Runnable() {
@Override @Override
public void run() { public void run() {
ApkUtils.installApkInSilence(context,file.getAbsolutePath() ); ApkUtils.installApp(context,file.getAbsolutePath() );
} }
}).start(); }).start();
} }

View File

@@ -27,6 +27,8 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import okhttp3.internal.Util;
public class OKGO { public class OKGO {
private static final int GET_ALL_APPINFO = 0; private static final int GET_ALL_APPINFO = 0;
@@ -89,9 +91,48 @@ public class OKGO {
} }
}); });
} }
public static synchronized void checkDevicesInfo(final Context context) {
OkGo.<String>post(Url.GET_INFO_FROMESN)
.params("sn", Utils.getSerial())
.execute(new StringCallback() {
@Override
public void onSuccess(Response<String> response) {
Log.e("onSuccess", "checkDevicesInfo");
try {
JSONObject bodyObject = JSON.parseObject(response.body());
Integer code = (bodyObject.getInteger("code"));
String msg = bodyObject.getString("msg");
String data = bodyObject.getString("data");
UserInfo userInfo = JSON.parseObject(data, UserInfo.class);
if (code == 200) {
SPUtils.put(context, "isLogined", 1);
SPUtils.put(context, "member_id", userInfo.getMember_id());
SPUtils.put(context, "sn_id", userInfo.getId());
} else if (code == -200) {
SPUtils.put(context, "isLogined", 0);
} else if (code == -250) {
SPUtils.put(context, "isLogined", 2);
//设备验证
}
} catch (Exception ex) {
Log.e("checkDevicesInfo", ex.getMessage());
}
}
@Override
public void onError(Response<String> response) {
super.onError(response);
Log.e("onError", response.getException().toString());
}
});
}
synchronized public static void getAllAppPackageName(final Handler handler) { synchronized public static void getAllAppPackageName(final Handler handler) {
OkGo.<String>get(Url.GET_ALL_PACKAGENAME).execute(new StringCallback() { OkGo.<String>post(Url.GET_ALL_PACKAGENAME)
.params("sn", Utils.getSerial())
.execute(new StringCallback() {
@Override @Override
public void onSuccess(Response<String> response) { public void onSuccess(Response<String> response) {
String s = response.body(); String s = response.body();

View File

@@ -21,7 +21,7 @@ public class Url {
//根据包名获取更新 //根据包名获取更新
public final static String GET_BANNER_IMG = NETWORK_HOME_ADDRESS + "Slideshow/getImg"; public final static String GET_BANNER_IMG = NETWORK_HOME_ADDRESS + "Slideshow/getImg";
//获取banner图 //获取banner图
public final static String GET_ALL_PACKAGENAME = NETWORK_HOME_ADDRESS + "App/allPackage"; public final static String GET_ALL_PACKAGENAME = NETWORK_HOME_ADDRESS + "App/allPackageSn";
//获取所有应用包名 //获取所有应用包名
public final static String GET_SUBClASSFY = NETWORK_HOME_ADDRESS + "Application/getSubClassfy"; public final static String GET_SUBClASSFY = NETWORK_HOME_ADDRESS + "Application/getSubClassfy";
//获取应用分类 //获取应用分类

View File

@@ -0,0 +1,60 @@
package com.appstore.uiui.receiver;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInstaller;
import android.os.Build;
import android.util.Log;
import androidx.annotation.RequiresApi;
import com.appstore.uiui.utils.ToastUtil;
public class InstallResultReceiver extends BroadcastReceiver {
private static final String TAG = "InstallResultReceiver";
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public void onReceive(Context context, Intent intent) {
// TODO: This method is called when the BroadcastReceiver is receiving
// an Intent broadcast.
//throw new UnsupportedOperationException("Not yet implemented");
if (intent != null) {
final int status = intent.getIntExtra(PackageInstaller.EXTRA_STATUS,
PackageInstaller.STATUS_FAILURE);
if (status == PackageInstaller.STATUS_SUCCESS) {
// success
String PACKAGE_NAME = intent.getStringExtra("android.content.pm.extra.PACKAGE_NAME");
Log.e(TAG, "APP Install Success!");
} else {
String msg = intent.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE);
}
}
// String s = intent.getAction();
// Log.e("fht", s);
// Bundle extras = intent.getExtras();
// Set<String> ks = extras.keySet();
// Iterator<String> iterator = ks.iterator();
// while (iterator.hasNext()) {
// Log.d("KEY", iterator.next());
// }
String STATUS = intent.getStringExtra(PackageInstaller.EXTRA_STATUS);
String PACKAGE_NAME = intent.getStringExtra(PackageInstaller.EXTRA_PACKAGE_NAME);
String SESSION_ID = intent.getStringExtra(PackageInstaller.EXTRA_SESSION_ID);
String STATUS_MESSAGE = intent.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE);
String LEGACY_STATUS = intent.getStringExtra("android.content.pm.extra.LEGACY_STATUS");
// Log.e("fht", STATUS);
// Log.e("fht", PACKAGE_NAME);
// Log.e("fht", SESSION_ID);
// Log.e("fht", LEGACY_STATUS);
// Log.e("fht", STATUS_MESSAGE);
if (STATUS_MESSAGE != null && STATUS_MESSAGE.equals("INSTALL_SUCCEEDED")) {
ToastUtil.show(PACKAGE_NAME + "安装成功");
}
}
}

View File

@@ -119,7 +119,7 @@ public class GuardService extends Service {
case 201: case 201:
String apppackage = (String) msg.obj; String apppackage = (String) msg.obj;
Log.e("fht", Settings.System.getString(getContentResolver(), "qch_app_forbid") + "?"); Log.e("fht", Settings.System.getString(getContentResolver(), "qch_app_forbid") + "?");
if (Settings.System.putString(getContentResolver(), "qch_app_forbid", apppackage)) { if (Settings.System.putString(getContentResolver(), "qch_app_forbid", apppackage+ "com.info.sn,com.android.uiuios,com.appstore.uiui,com.uiuios.updatetools")) {
Log.e("fht", "app package write successful"); Log.e("fht", "app package write successful");
} }
break; break;
@@ -138,7 +138,7 @@ public class GuardService extends Service {
new Thread(new Runnable() { new Thread(new Runnable() {
@Override @Override
public void run() { public void run() {
ApkUtils.installApkInSilence(GuardService.this, response.body().getAbsolutePath()); ApkUtils.installApp(GuardService.this, response.body().getAbsolutePath());
} }
}).start(); }).start();
LogUtils.e("getFile", "download file successful,now installing"); LogUtils.e("getFile", "download file successful,now installing");
@@ -173,12 +173,12 @@ public class GuardService extends Service {
LogUtils.e("mjsheng", "downloadPath::" + downloadPath); LogUtils.e("mjsheng", "downloadPath::" + downloadPath);
LogUtils.e("mjsheng", "extendField::" + packageName); LogUtils.e("mjsheng", "extendField::" + packageName);
if (packageName.equalsIgnoreCase(this.getPackageName())) { if (packageName.equalsIgnoreCase(this.getPackageName())) {
ApkUtils.install(this, new File(downloadPath)); ApkUtils.installApp(this,downloadPath);
} else { } else {
new Thread(new Runnable() { new Thread(new Runnable() {
@Override @Override
public void run() { public void run() {
ApkUtils.installApkInSilence(GuardService.this, downloadPath); ApkUtils.installApp(GuardService.this, downloadPath);
} }
}).start(); }).start();
} }

View File

@@ -1,9 +1,11 @@
package com.appstore.uiui.utils; package com.appstore.uiui.utils;
import android.app.PendingIntent;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo; import android.content.pm.PackageInfo;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.net.Uri; import android.net.Uri;
import android.os.Binder; import android.os.Binder;
@@ -12,16 +14,20 @@ import android.util.Log;
import android.view.View; import android.view.View;
import android.widget.Toast; import android.widget.Toast;
import androidx.annotation.RequiresApi;
import androidx.core.content.FileProvider; import androidx.core.content.FileProvider;
import com.appstore.uiui.BuildConfig; import com.appstore.uiui.BuildConfig;
import com.appstore.uiui.R; import com.appstore.uiui.R;
import com.appstore.uiui.receiver.InstallResultReceiver;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
@@ -111,15 +117,17 @@ public class ApkUtils {
} }
/** /**
* 卸载一个app * 根据包名卸载应用
*
* @param packageName
*/ */
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public static void uninstall(Context context, String packageName) { public static void uninstall(Context context, String packageName) {
//通过程序的包名创建URI Intent broadcastIntent = new Intent(context, InstallResultReceiver.class);
Uri packageURI = Uri.parse("package:" + packageName); PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 1,
//创建Intent意图 broadcastIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Intent intent = new Intent(Intent.ACTION_DELETE, packageURI); PackageInstaller packageInstaller = context.getPackageManager().getPackageInstaller();
//执行卸载程序 packageInstaller.uninstall(packageName, pendingIntent.getIntentSender());
context.startActivity(intent);
} }
/** /**
@@ -294,20 +302,136 @@ public class ApkUtils {
}); });
} }
// public static void installApp(final String path, final String packageNames){ public static void installApp(Context context, String filePath) {
// File apkFile = new File(path); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
// try { installAppatPie(context, filePath);
// Class<?> clazz = Class.forName("android.os.ServiceManager"); } else {
// Method method_getService = clazz.getMethod("getService", String.class); installApps(filePath);
// IBinder bind = (IBinder) method_getService.invoke(null, "package"); }
// IPackageManager iPm = IPackageManager.Stub.asInterface(bind); }
// iPm.installPackage(Uri.fromFile(apkFile),null, 2, apkFile.getName());
// Log.e("fanhuitong", "安装成功");
// } catch (Exception e) { public static boolean installApps(String apkPath) {
// e.printStackTrace(); ToastUtil.show("正在安装应用...");
// Log.e("fanhuitong", "安装失败"); Process process = null;
// } BufferedReader successResult = null;
// } BufferedReader errorResult = null;
StringBuilder successMsg = new StringBuilder();
StringBuilder errorMsg = new StringBuilder();
try {
process = new ProcessBuilder("pm", "install", "-i", BuildConfig.APPLICATION_ID, "--user", "0", apkPath).start();
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 (Exception e) {
Log.e("installApps1", e.getMessage());
} finally {
try {
if (successResult != null) {
successResult.close();
}
if (errorResult != null) {
errorResult.close();
}
} catch (Exception e) {
Log.e("installApps2", e.getMessage());
}
if (process != null) {
process.destroy();
}
}
Log.e("result", "" + errorMsg.toString());
//如果含有“success”认为安装成功
Log.e("installApp", successMsg.toString());
// if (!successMsg.toString().equalsIgnoreCase("success")) {
// ApkUtils.install(context, new File(apkPath));
// }
return successMsg.toString().equalsIgnoreCase("success");
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public static void installAppatPie(Context context, String apkFilePath) {
File file = new File(apkFilePath);
PackageInstaller packageInstaller = context.getPackageManager().getPackageInstaller();
PackageInstaller.SessionParams sessionParams = new PackageInstaller.SessionParams(PackageInstaller
.SessionParams.MODE_FULL_INSTALL);
sessionParams.setSize(file.length());
int sessionId = createSession(packageInstaller, sessionParams);
if (sessionId != -1) {
boolean copySuccess = copyApkFile(packageInstaller, sessionId, apkFilePath);
if (copySuccess) {
ToastUtil.show("正在安装应用");
install(packageInstaller, sessionId, context);
}
}
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private static void install(PackageInstaller packageInstaller, int sessionId, Context context) {
try {
PackageInstaller.Session session = packageInstaller.openSession(sessionId);
Intent intent = new Intent(context, InstallResultReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
context,
1, intent,
PendingIntent.FLAG_UPDATE_CURRENT
);
session.commit(pendingIntent.getIntentSender());
} catch (IOException e) {
e.printStackTrace();
}
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private static int createSession(PackageInstaller packageInstaller, PackageInstaller.SessionParams sessionParams) {
int sessionId = -1;
try {
sessionId = packageInstaller.createSession(sessionParams);
} catch (IOException e) {
e.printStackTrace();
}
return sessionId;
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private static boolean copyApkFile(PackageInstaller pi, int sessionId, String apkFilePath) {
boolean success = false;
File apkFile = new File(apkFilePath);
PackageInstaller.Session session = null;
try {
session = pi.openSession(sessionId);
OutputStream out = session.openWrite("app.apk", 0, apkFile.length());
FileInputStream input = new FileInputStream(apkFile);
int read = 0;
byte[] buffer = new byte[65536];
// while (read != -1) {
// read = input.read(buffer);
// out.write(buffer, 0, read);
// }
while (true) {
read = input.read(buffer);
if (read == -1) {
session.fsync(out);
success = true;
out.close();
input.close();
break;
}
out.write(buffer, 0, read);
}
} catch (IOException e) {
e.printStackTrace();
Log.e("fht", "copyApkFile" + e.getMessage());
}
return success;
}
//使用系统签名 //使用系统签名
// public static void installApkInSilence(String installPath, String packageName) { // public static void installApkInSilence(String installPath, String packageName) {
@@ -378,6 +502,14 @@ public class ApkUtils {
return successMsg.toString().equalsIgnoreCase("success"); return successMsg.toString().equalsIgnoreCase("success");
} }
public static void uninstallApp(Context context, String packageName) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
ApkUtils.uninstall(context, packageName);
} else {
ApkUtils.deleteApkInSilence(packageName);
}
}
public static void deleteApkInSilence(String packageName) { public static void deleteApkInSilence(String packageName) {
Class<?> pmService; Class<?> pmService;
Class<?> activityTherad; Class<?> activityTherad;