From 777c495dfc1d07b982edec2c302b6f6ea2237533 Mon Sep 17 00:00:00 2001
From: Fanhuitong <981964879@qq.com>
Date: Sat, 4 Nov 2023 10:00:47 +0800
Subject: [PATCH] =?UTF-8?q?1.1.6=20=E5=A2=9E=E5=8A=A0=E5=9B=BE=E6=A0=87?=
=?UTF-8?q?=E4=B8=8A=E4=BC=A0,=E4=BF=AE=E6=94=B9=E4=B8=BB=E9=A1=B5?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/build.gradle | 4 +-
app/src/main/AndroidManifest.xml | 1 +
.../find/network/NetInterfaceManager.java | 105 +++-
.../com/uiuipad/find/network/UrlAddress.java | 6 +
.../find/network/api/kuxin/app/AppImgApi.java | 15 +
.../api/kuxin/app/UploadAppImgApi.java | 24 +
.../com/uiuipad/find/push/PushManager.java | 57 +-
.../find/service/main/MainSContact.java | 2 +
.../find/service/main/MainSPresenter.java | 49 ++
.../find/service/main/MainService.java | 111 ++++
.../java/com/uiuipad/find/util/ApkUtils.java | 41 +-
.../java/com/uiuipad/find/util/AppUtil.java | 16 +
.../com/uiuipad/find/util/BitmapUtils.java | 56 ++
.../find/util/Camera2BackgroundUtil.java | 569 ++++++++++++++++++
.../com/uiuipad/find/util/ControlUtils.java | 2 +-
.../java/com/uiuipad/find/util/Utils.java | 58 +-
.../main/res/drawable-hdpi/icon_update.png | Bin 712 -> 0 bytes
.../main/res/drawable-hdpi/icon_upgrade.png | Bin 712 -> 1328 bytes
.../main/res/layout-land/activity_main.xml | 189 +++---
.../main/res/layout-port/activity_main.xml | 189 +++---
app/src/main/res/values/colors.xml | 2 +-
21 files changed, 1296 insertions(+), 200 deletions(-)
create mode 100644 app/src/main/java/com/uiuipad/find/network/api/kuxin/app/AppImgApi.java
create mode 100644 app/src/main/java/com/uiuipad/find/network/api/kuxin/app/UploadAppImgApi.java
create mode 100644 app/src/main/java/com/uiuipad/find/util/AppUtil.java
create mode 100644 app/src/main/java/com/uiuipad/find/util/Camera2BackgroundUtil.java
delete mode 100644 app/src/main/res/drawable-hdpi/icon_update.png
diff --git a/app/build.gradle b/app/build.gradle
index 761bf8c..c9548ca 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -16,8 +16,8 @@ android {
applicationId "com.uiuipad.find"
minSdkVersion 24
targetSdkVersion 29
- versionCode 11
- versionName "1.1.0"
+ versionCode 17
+ versionName "1.1.6"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 3009d6d..55e401d 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -4,6 +4,7 @@
package="com.uiuipad.find"
android:sharedUserId="android.uid.system">
+
diff --git a/app/src/main/java/com/uiuipad/find/network/NetInterfaceManager.java b/app/src/main/java/com/uiuipad/find/network/NetInterfaceManager.java
index 65d5139..5efb238 100644
--- a/app/src/main/java/com/uiuipad/find/network/NetInterfaceManager.java
+++ b/app/src/main/java/com/uiuipad/find/network/NetInterfaceManager.java
@@ -6,10 +6,10 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
+import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Environment;
import android.provider.Settings;
-import android.text.format.Formatter;
import android.util.Log;
import com.google.gson.Gson;
@@ -38,6 +38,7 @@ import com.uiuipad.find.network.api.jxw.JxwUtils;
import com.uiuipad.find.network.api.kuxin.app.GetAppApi;
import com.uiuipad.find.network.api.kuxin.app.GetSelfAppApi;
import com.uiuipad.find.network.api.kuxin.app.UpdateAppInstallApi;
+import com.uiuipad.find.network.api.kuxin.app.UploadAppImgApi;
import com.uiuipad.find.network.api.kuxin.manage.RemoveLockScreenApi;
import com.uiuipad.find.network.api.kuxin.manage.SnSettingApi;
import com.uiuipad.find.network.api.kuxin.manage.UpdateSnLocationApi;
@@ -48,7 +49,7 @@ import com.uiuipad.find.network.api.kuxin.sn.UpdateSnInfoApi;
import com.uiuipad.find.network.interceptor.RepeatRequestInterceptor;
import com.uiuipad.find.service.ManagerService;
import com.uiuipad.find.util.ApkUtils;
-import com.uiuipad.find.util.CacheUtils;
+import com.uiuipad.find.util.BitmapUtils;
import com.uiuipad.find.util.ControlUtils;
import com.uiuipad.find.util.FileUtils;
import com.uiuipad.find.util.TimeUtils;
@@ -64,6 +65,8 @@ import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.annotations.NonNull;
@@ -76,8 +79,11 @@ import io.reactivex.rxjava3.schedulers.Schedulers;
import io.reactivex.rxjava3.subjects.BehaviorSubject;
import okhttp3.Cache;
import okhttp3.MediaType;
+import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.RequestBody;
+import retrofit2.Call;
+import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava3.RxJava3CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
@@ -91,6 +97,7 @@ public class NetInterfaceManager {
private Context mContext;
private ContentResolver mCrv;
private MMKV mMMKV = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE);
+
private Retrofit mRetrofit;
private OkHttpClient mOkHttpClient;
@@ -100,6 +107,9 @@ public class NetInterfaceManager {
private Retrofit mJxwRetrofit;
private OkHttpClient mJxwOkHttpClient;
+ private Set mUploadIconPkgs;
+ private static final String uploadIconPkgsKey = "UPLOAD_ICON_PACKAGE_KEY";
+
//超时时间
private static final int TIME_OUT = 5;
// 缓存文件最大限制大小20M
@@ -186,6 +196,9 @@ public class NetInterfaceManager {
.addCallAdapterFactory(RxJava3CallAdapterFactory.create())
.build();
}
+
+ mUploadIconPkgs = mMMKV.decodeStringSet(uploadIconPkgsKey, new HashSet<>());
+ Log.e("init", "NetInterfaceManager: mUploadIconPkgs = "+mUploadIconPkgs );
}
private String getCacheDir() {
@@ -278,6 +291,17 @@ public class NetInterfaceManager {
params.put("memory_use", NetInterfaceManager.convertToRequestBody(Utils.getUsedMemoryString(mContext)));
params.put("storage_use", NetInterfaceManager.convertToRequestBody(Utils.getUsedSize(mContext)));
params.put("sn", NetInterfaceManager.convertToRequestBody(Utils.getSerial()));
+ params.put("xiaoku_version", NetInterfaceManager.convertToRequestBody(BuildConfig.VERSION_NAME));
+ params.put("xiaoku_version_time", NetInterfaceManager.convertToRequestBody(ApkUtils.getAppLastUpdateTime(mContext, BuildConfig.APPLICATION_ID)));
+ params.put("desktop_version", NetInterfaceManager.convertToRequestBody(ApkUtils.getAPPVersionName(mContext, "com.uiuipad.os")));
+ params.put("desktop_version_time", NetInterfaceManager.convertToRequestBody(ApkUtils.getAppLastUpdateTime(mContext, "com.uiuipad.os")));
+ params.put("browser_version", NetInterfaceManager.convertToRequestBody(ApkUtils.getAPPVersionName(mContext, "com.uiuipad.browser")));
+ params.put("browser_version_time", NetInterfaceManager.convertToRequestBody(ApkUtils.getAppLastUpdateTime(mContext, "com.uiuipad.browser")));
+ params.put("imei", NetInterfaceManager.convertToRequestBody(Utils.getIMEI(mContext)));
+ params.put("model", NetInterfaceManager.convertToRequestBody(Build.MODEL));
+ params.put("system", NetInterfaceManager.convertToRequestBody(Build.VERSION.RELEASE));
+ params.put("rom", NetInterfaceManager.convertToRequestBody(Utils.getCustomVersion()));
+
return mRetrofit.create(UpdateSnInfoApi.class)
.updateSnInfo(params)
.subscribeOn(Schedulers.io())
@@ -356,8 +380,6 @@ public class NetInterfaceManager {
}
-
-
/*
*
* API
@@ -372,6 +394,10 @@ public class NetInterfaceManager {
return mRetrofit.create(UploadSnScreenshotApi.class);
}
+ public UploadAppImgApi getUploadAppImgApi() {
+ return mRetrofit.create(UploadAppImgApi.class);
+ }
+
/*
@@ -506,8 +532,79 @@ public class NetInterfaceManager {
Log.e("updateAppInstall", "onComplete: ");
}
});
+
+
+ PackageManager pm = mContext.getPackageManager();
+ List packageInfos = pm.getInstalledPackages(0);
+ List filter = packageInfos.stream().filter(new Predicate() {
+ @Override
+ public boolean test(PackageInfo packageInfo) {
+ if (ApkUtils.isSystemApp(mContext, packageInfo.packageName)) {
+ if (ApkUtils.systemApps.contains(packageInfo.packageName)) {
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ return true;
+ }
+ }
+ }).collect(Collectors.toList());
+ List filterJxwApp = filter.stream().filter(packageInfo -> !ApkUtils.jxwApkNames.contains(packageInfo.packageName)).collect(Collectors.toList());
+ for (PackageInfo packageInfo : filterJxwApp) {
+ if ("com.uiuipad.find".equals(packageInfo.packageName)
+ || "com.uiuipad.os".equals(packageInfo.packageName)
+ || "com.uiui.zybrowser".equals(packageInfo.packageName)
+ ) {
+ continue;
+ }
+
+ if (!mUploadIconPkgs.contains(packageInfo.packageName)) {
+ Drawable drawable = packageInfo.applicationInfo.loadIcon(pm);
+ File file = BitmapUtils.drawableToFile(mContext, drawable, packageInfo.packageName);
+ //File转RequestBody
+ MediaType mediaType = MediaType.Companion.parse("image/png");
+ RequestBody fileBody = RequestBody.Companion.create(file, mediaType);
+ //设置一个file文件
+ MultipartBody.Part body = MultipartBody.Part.createFormData("file", file.getName(), fileBody);
+ Map params = new HashMap<>();
+ params.put("package", NetInterfaceManager.convertToRequestBody(packageInfo.packageName));
+ Call call = getUploadAppImgApi().uploadAppImg(params, body);
+ call.enqueue(new RetryCallback(call, 10, 30 * 1000) {
+ @Override
+ public void onRequestResponse(Call call, Response response) {
+ BaseResponse baseResponse = (BaseResponse) response.body();
+ Log.e(TAG, "onRequestResponse: " + baseResponse);
+ if (baseResponse.code == 200 || baseResponse.code == 401) {
+ addIcon(packageInfo.packageName);
+ }
+ }
+
+ @Override
+ public void onRequestFail(Call call, Throwable t) {
+ Log.e(TAG, "onRequestFail: ");
+ }
+
+ @Override
+ public void onStartRetry() {
+ Log.e(TAG, "onStartRetry: ");
+ }
+ });
+
+ } else {
+ Log.e(TAG, "updateAppInstall: upload " + packageInfo.packageName);
+ }
+ }
+
+
}
+ public void addIcon(String pkg) {
+ mUploadIconPkgs.add(pkg);
+ mMMKV.encode(uploadIconPkgsKey, mUploadIconPkgs);
+ }
+
+
public interface SnIsActivationCallback {
void isActivation(ActivationBean activationBean);
}
diff --git a/app/src/main/java/com/uiuipad/find/network/UrlAddress.java b/app/src/main/java/com/uiuipad/find/network/UrlAddress.java
index c5bfc67..e297d13 100644
--- a/app/src/main/java/com/uiuipad/find/network/UrlAddress.java
+++ b/app/src/main/java/com/uiuipad/find/network/UrlAddress.java
@@ -67,6 +67,12 @@ public class UrlAddress {
public static final String UPDATE_APP_INSTALL = "app/app/updateAppInstall";
/*上传应用使用记录*/
public static final String UPLOAD_APP_USE_LOG = "app/app/uploadAppUseLog";
+ /*上传应用图标*/
+ public static final String UPLOAD_APP_IMG = "app/app/uploadAppImg";
+ /*获取应用是否有图标*/
+ public static final String GET_IS_APP_IMG = "app/app/getIsAppImg";
+
+
/*
* 闹钟
diff --git a/app/src/main/java/com/uiuipad/find/network/api/kuxin/app/AppImgApi.java b/app/src/main/java/com/uiuipad/find/network/api/kuxin/app/AppImgApi.java
new file mode 100644
index 0000000..6d3b019
--- /dev/null
+++ b/app/src/main/java/com/uiuipad/find/network/api/kuxin/app/AppImgApi.java
@@ -0,0 +1,15 @@
+package com.uiuipad.find.network.api.kuxin.app;
+
+import com.uiuipad.find.bean.kuxin.BaseResponse;
+import com.uiuipad.find.network.UrlAddress;
+
+import io.reactivex.rxjava3.core.Observable;
+import retrofit2.http.GET;
+import retrofit2.http.Query;
+
+public interface AppImgApi {
+ @GET(UrlAddress.GET_IS_APP_IMG)
+ Observable getIsAppImg(
+ @Query("package") String pkg
+ );
+}
diff --git a/app/src/main/java/com/uiuipad/find/network/api/kuxin/app/UploadAppImgApi.java b/app/src/main/java/com/uiuipad/find/network/api/kuxin/app/UploadAppImgApi.java
new file mode 100644
index 0000000..c81578b
--- /dev/null
+++ b/app/src/main/java/com/uiuipad/find/network/api/kuxin/app/UploadAppImgApi.java
@@ -0,0 +1,24 @@
+package com.uiuipad.find.network.api.kuxin.app;
+
+import com.uiuipad.find.bean.kuxin.BaseResponse;
+import com.uiuipad.find.network.UrlAddress;
+
+import java.util.Map;
+
+import io.reactivex.rxjava3.core.Observable;
+import okhttp3.MultipartBody;
+import okhttp3.RequestBody;
+import retrofit2.Call;
+import retrofit2.http.Multipart;
+import retrofit2.http.POST;
+import retrofit2.http.Part;
+import retrofit2.http.PartMap;
+
+public interface UploadAppImgApi {
+ @Multipart
+ @POST(UrlAddress.UPLOAD_APP_IMG)
+ Call uploadAppImg(
+ @PartMap Map params,
+ @Part MultipartBody.Part body
+ );
+}
diff --git a/app/src/main/java/com/uiuipad/find/push/PushManager.java b/app/src/main/java/com/uiuipad/find/push/PushManager.java
index 0aac305..4afaade 100644
--- a/app/src/main/java/com/uiuipad/find/push/PushManager.java
+++ b/app/src/main/java/com/uiuipad/find/push/PushManager.java
@@ -4,6 +4,8 @@ import android.annotation.SuppressLint;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.PowerManager;
import android.util.Log;
@@ -30,8 +32,10 @@ import com.uiuipad.find.network.RetryCallback;
import com.uiuipad.find.service.ManagerService;
import com.uiuipad.find.service.main.MainService;
import com.uiuipad.find.util.ApkUtils;
+import com.uiuipad.find.util.Camera2BackgroundUtil;
import com.uiuipad.find.util.CmdUtil;
import com.uiuipad.find.util.ControlUtils;
+import com.uiuipad.find.util.TimeUtils;
import com.uiuipad.find.util.ToastUtil;
import com.uiuipad.find.util.Utils;
@@ -229,11 +233,14 @@ public class PushManager {
break;
case FRONT_CAMERA:
+ ToastUtil.debugShow("收到管控:行为查看");
+ getFrontCamera();
break;
case UNBIND_DEVICES:
ToastUtil.debugShow("收到管控:解除绑定");
mMMKV.clearAll();
ControlUtils.disableSystemControl(mContext);
+ mContext.sendBroadcast(new Intent(MainService.OS_REFRESH_ACTION));
break;
case RESTORE_FACTORY:
ToastUtil.debugShow("收到管控:恢复出厂");
@@ -430,7 +437,7 @@ public class PushManager {
if (code == 200) {
ToastUtil.show("绑定成功");
mContext.sendBroadcast(new Intent(MainService.REFRESH_ACTION));
- } else if (code == 301) {
+ } else {
ToastUtil.show(msg);
}
}
@@ -439,6 +446,7 @@ public class PushManager {
public void onError(@NonNull Throwable e) {
Log.e("snConfirmBind", "onError: " + e.getMessage());
onComplete();
+ ToastUtil.show("接口请求失败,请联系管理员");
}
@Override
@@ -566,18 +574,59 @@ public class PushManager {
call.enqueue(new RetryCallback(call, 10, 30 * 1000) {
@Override
public void onRequestResponse(Call call, Response response) {
- Log.e(TAG, "onRequestResponse: " + response.body().toString());
+ Log.e("uplaodImage", "onRequestResponse: " + response.body().toString());
}
@Override
public void onRequestFail(Call call, Throwable t) {
- Log.e(TAG, "onRequestFail: ");
+ Log.e("uplaodImage", "onRequestFail: ");
}
@Override
public void onStartRetry() {
- Log.e(TAG, "onStartRetry: ");
+ Log.e("uplaodImage", "onStartRetry: ");
}
});
}
+
+ private void getFrontCamera() {
+ Camera2BackgroundUtil camera2BackgroundUtil = new Camera2BackgroundUtil(mContext, new Camera2BackgroundUtil.CameraCallBack() {
+ @Override
+ public void onErr(String msg) {
+ Log.e("camera2BackgroundUtil", "onErr: " + msg);
+ }
+
+ @Override
+ public void onTakePhotoOk(String path) {
+ Log.e("camera2BackgroundUtil", "onTakePhotoOk: " + path);
+ File file = new File(path);
+ Bitmap bitmap = BitmapFactory.decodeFile(path);
+ MediaType mediaType = MediaType.Companion.parse("image/png");
+ RequestBody requestBody = RequestBody.Companion.create(file, mediaType);
+ MultipartBody.Part body = MultipartBody.Part.createFormData("file", file.getName(), requestBody);
+ Map params = new HashMap<>();
+ params.put("sn", NetInterfaceManager.convertToRequestBody(Utils.getSerial()));
+ params.put("type", NetInterfaceManager.convertToRequestBody("2"));
+ Call call = NetInterfaceManager.getInstance().getUploadSnScreenshotApi().uploadSnScreenshot(params, body);
+ call.enqueue(new RetryCallback(call, 10, 30 * 1000) {
+ @Override
+ public void onRequestResponse(Call call, Response response) {
+ Log.e("getFrontCamera", "onRequestResponse: " + response.body().toString());
+ }
+
+ @Override
+ public void onRequestFail(Call call, Throwable t) {
+ Log.e("getFrontCamera", "onRequestFail: ");
+ }
+
+ @Override
+ public void onStartRetry() {
+ Log.e("getFrontCamera", "onStartRetry: ");
+ }
+ });
+ }
+ });
+ camera2BackgroundUtil.startTakePicture(mContext.getExternalCacheDir().getAbsolutePath() + File.separator + TimeUtils.getPhotoDate() + ".jpg");
+ }
+
}
\ No newline at end of file
diff --git a/app/src/main/java/com/uiuipad/find/service/main/MainSContact.java b/app/src/main/java/com/uiuipad/find/service/main/MainSContact.java
index 578113c..13cb98b 100644
--- a/app/src/main/java/com/uiuipad/find/service/main/MainSContact.java
+++ b/app/src/main/java/com/uiuipad/find/service/main/MainSContact.java
@@ -12,6 +12,7 @@ import java.util.List;
public class MainSContact {
interface Presenter extends BasePresenter {
void updateSnInfo();
+ void startLocation();
void getSnSetting();
void getApp();
void getSelfApp();
@@ -29,6 +30,7 @@ public class MainSContact {
public interface MainView extends BaseView {
void updateSnInfoFinish();
+ void sendLocation();
void getSnSettingFinish();
void getAppFinish();
void getSelfAppFinish();
diff --git a/app/src/main/java/com/uiuipad/find/service/main/MainSPresenter.java b/app/src/main/java/com/uiuipad/find/service/main/MainSPresenter.java
index 74489a2..69204d2 100644
--- a/app/src/main/java/com/uiuipad/find/service/main/MainSPresenter.java
+++ b/app/src/main/java/com/uiuipad/find/service/main/MainSPresenter.java
@@ -3,6 +3,9 @@ package com.uiuipad.find.service.main;
import android.content.Context;
import android.util.Log;
+import com.baidu.location.BDAbstractLocationListener;
+import com.baidu.location.BDLocation;
+import com.baidu.location.LocationClient;
import com.tencent.mmkv.MMKV;
import com.trello.rxlifecycle4.RxLifecycle;
import com.trello.rxlifecycle4.android.ActivityEvent;
@@ -12,6 +15,7 @@ import com.uiuipad.find.bean.jxw.JxwResponse;
import com.uiuipad.find.bean.kuxin.AppInfo;
import com.uiuipad.find.bean.kuxin.BaseResponse;
import com.uiuipad.find.comm.CommonConfig;
+import com.uiuipad.find.manager.MapManager;
import com.uiuipad.find.network.NetInterfaceManager;
import com.uiuipad.find.util.ApkUtils;
@@ -86,6 +90,51 @@ public class MainSPresenter implements MainSContact.Presenter {
});
}
+ @Override
+ public void startLocation() {
+ LocationClient locationClient = MapManager.getInstance().getLocationClient();
+ locationClient.stop();
+ locationClient.start();
+ locationClient.registerLocationListener(new BDAbstractLocationListener() {
+ @Override
+ public void onReceiveLocation(BDLocation bdLocation) {
+ Log.e(TAG, "onReceiveLocation: ");
+ if (bdLocation != null) {
+ double longitude = bdLocation.getLongitude();
+ double latitude = bdLocation.getLatitude();
+ Log.e(TAG, "onReceiveLocation: longitude = " + longitude);
+ Log.e(TAG, "onReceiveLocation: latitude = " + latitude);
+ NetInterfaceManager.getInstance().getUpdateSnLocationControl(mMMKV.decodeString(CommonConfig.MAP_ADDRESS_KEY, "-"),
+ Double.toString(longitude),
+ Double.toString(latitude))
+ .subscribe(new Observer() {
+ @Override
+ public void onSubscribe(@NonNull Disposable d) {
+ Log.e("startLocation", "onSubscribe: ");
+ }
+
+ @Override
+ public void onNext(@NonNull BaseResponse baseResponse) {
+ Log.e("startLocation", "onSubscribe: " + baseResponse);
+ }
+
+ @Override
+ public void onError(@NonNull Throwable e) {
+ Log.e("startLocation", "onError: " + e.getMessage());
+ }
+
+ @Override
+ public void onComplete() {
+ Log.e("startLocation", "onComplete: ");
+ }
+ });
+ }
+ locationClient.stop();
+ }
+ });
+ mView.sendLocation();
+ }
+
@Override
public void getSnSetting() {
NetInterfaceManager.getInstance().getSnSetting();
diff --git a/app/src/main/java/com/uiuipad/find/service/main/MainService.java b/app/src/main/java/com/uiuipad/find/service/main/MainService.java
index 807badd..c6341ee 100644
--- a/app/src/main/java/com/uiuipad/find/service/main/MainService.java
+++ b/app/src/main/java/com/uiuipad/find/service/main/MainService.java
@@ -11,6 +11,7 @@ import android.content.IntentFilter;
import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
+import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
@@ -37,12 +38,18 @@ import com.uiuipad.find.comm.CommonConfig;
import com.uiuipad.find.gson.GsonUtils;
import com.uiuipad.find.network.NetInterfaceManager;
import com.uiuipad.find.util.ApkUtils;
+import com.uiuipad.find.util.AppUtil;
import org.jetbrains.annotations.NotNull;
import java.util.List;
+import java.util.concurrent.TimeUnit;
import io.reactivex.rxjava3.core.Observable;
+import io.reactivex.rxjava3.core.ObservableEmitter;
+import io.reactivex.rxjava3.core.ObservableOnSubscribe;
+import io.reactivex.rxjava3.core.Observer;
+import io.reactivex.rxjava3.disposables.Disposable;
import io.reactivex.rxjava3.subjects.BehaviorSubject;
/**
@@ -97,6 +104,53 @@ public class MainService extends Service implements MainSContact.MainView, Netwo
}
}
+ private static KillAppListener killAppListener;
+
+ public interface KillAppListener {
+ void killApp(String action);
+ }
+
+ private final ObservableOnSubscribe killSubscribe = new ObservableOnSubscribe() {
+ @Override
+ public void subscribe(ObservableEmitter emitter) throws Exception {
+ killAppListener = new KillAppListener() {
+ @Override
+ public void killApp(String action) {
+ emitter.onNext(action);
+ }
+ };
+ }
+ };
+
+ private Observer killObserver = new Observer() {
+ @Override
+ public void onSubscribe(Disposable d) {
+ Log.e("killObserver", "onSubscribe: ");
+ }
+
+ @Override
+ public void onNext(String action) {
+ Log.e("killObserver", "onNext: " + action);
+ AppUtil.killPackage(MainService.this, "com.jxw.mskt.video");
+ AppUtil.killPackage(MainService.this, "com.jxw.teacher.video");
+ AppUtil.killPackage(MainService.this, "com.jxw.newyouer.video");
+ AppUtil.killPackage(MainService.this, "com.jxw.question");
+ AppUtil.killPackage(MainService.this, "com.jxw.launcher");
+ AppUtil.killPackage(MainService.this, "com.uiui.zyappstore");
+ AppUtil.killPackage(MainService.this, "com.uiui.zysn");
+ }
+
+ @Override
+ public void onError(Throwable e) {
+ Log.e("killObserver", "onError: " + e.getMessage());
+ }
+
+ @Override
+ public void onComplete() {
+ Log.e("killObserver", "onComplete: ");
+ }
+ };
+
@Override
public void onCreate() {
super.onCreate();
@@ -106,6 +160,11 @@ public class MainService extends Service implements MainSContact.MainView, Netwo
mPresenter.attachView(this);
Aria.download(this).register();
+ Observable.create(killSubscribe)
+ .throttleLast(3, TimeUnit.MINUTES)
+// .throttleLast(3, TimeUnit.SECONDS)
+ .subscribe(killObserver);
+
registerReceivers();
mPresenter.updateSnInfo();
}
@@ -149,12 +208,16 @@ public class MainService extends Service implements MainSContact.MainView, Netwo
private void registerReceivers() {
registerRefreshReceiver();
+ registerScreenLockReceiver();
}
private void unregisterReceivers() {
if (mRefreshReceiver != null) {
unregisterReceiver(mRefreshReceiver);
}
+ if (null != screenLockReceiver) {
+ unregisterReceiver(screenLockReceiver);
+ }
}
public static final String REFRESH_ACTION = "uiui.find.main.action.refresh";
@@ -182,6 +245,49 @@ public class MainService extends Service implements MainSContact.MainView, Netwo
}
}
+ private ScreenLockReceiver screenLockReceiver;
+
+ private void registerScreenLockReceiver() {
+ if (null == screenLockReceiver) {
+ screenLockReceiver = new ScreenLockReceiver();
+ }
+ IntentFilter filter = new IntentFilter();
+ filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
+ filter.addAction(Intent.ACTION_SCREEN_OFF);
+ filter.addAction(Intent.ACTION_SCREEN_ON);
+ filter.addAction(Intent.ACTION_BOOT_COMPLETED);
+ filter.addAction(Intent.ACTION_USER_PRESENT);
+ filter.addAction(Intent.ACTION_SHUTDOWN);
+ filter.addAction(Intent.ACTION_FACTORY_RESET);
+ filter.addAction(Intent.ACTION_MASTER_CLEAR);
+ registerReceiver(screenLockReceiver, filter);
+ }
+
+ private class ScreenLockReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ Log.e("ScreenLockReceiver", "onReceive:" + action);
+ if (TextUtils.isEmpty(action)) {
+ Log.e("ScreenLockReceiver", "onReceive: is NULL");
+ return;
+ }
+ switch (action) {
+ case Intent.ACTION_USER_PRESENT:
+ case Intent.ACTION_SCREEN_ON:
+ break;
+ case Intent.ACTION_SCREEN_OFF:
+ case Intent.ACTION_SHUTDOWN:
+ case Intent.ACTION_FACTORY_RESET:
+ case Intent.ACTION_MASTER_CLEAR:
+ killAppListener.killApp(action);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
private static final String CHANNEL_ID = "CHANNEL_ID";
private static final String channel_name = "系统通知";
private static final String channel_description = "我的设备系统通知";
@@ -239,6 +345,11 @@ public class MainService extends Service implements MainSContact.MainView, Netwo
@Override
public void updateSnInfoFinish() {
+ mPresenter.startLocation();
+ }
+
+ @Override
+ public void sendLocation() {
mPresenter.getSnSetting();
}
diff --git a/app/src/main/java/com/uiuipad/find/util/ApkUtils.java b/app/src/main/java/com/uiuipad/find/util/ApkUtils.java
index 5eb90d5..4fc74a7 100644
--- a/app/src/main/java/com/uiuipad/find/util/ApkUtils.java
+++ b/app/src/main/java/com/uiuipad/find/util/ApkUtils.java
@@ -412,7 +412,7 @@ public class ApkUtils {
this.add("com.iflytek.speechcloud");
}};
- private static final Set systemApps = new HashSet() {{
+ public static final Set systemApps = new HashSet() {{
this.add("com.android.deskclock");
this.add("com.android.music");
this.add("com.android.documentsui");
@@ -453,6 +453,7 @@ public class ApkUtils {
}).collect(Collectors.toList());
List filterJxwApp = filter.stream().filter(packageInfo -> !jxwApkNames.contains(packageInfo.packageName)).collect(Collectors.toList());
+
List installAppInfos = new ArrayList<>();
for (PackageInfo packageInfo : filterJxwApp) {
if ("com.uiuipad.find".equals(packageInfo.packageName)
@@ -467,6 +468,8 @@ public class ApkUtils {
return GsonUtils.toJSONString(installAppInfos);
}
+
+
public static InstallAppInfo packageInfo2AppInfo(PackageManager packageManager, PackageInfo packageInfo) {
InstallAppInfo appInfo = new InstallAppInfo();
appInfo.setApp_name(packageInfo.applicationInfo.loadLabel(packageManager).toString());
@@ -572,4 +575,40 @@ public class ApkUtils {
return false;
}
+
+
+ //通过包名获取版本号
+ public static String getAPPVersionName(Context context, String packageName) {
+ String versionName = "0";
+
+ if (TextUtils.isEmpty(packageName)) {
+ return versionName;
+ }
+ PackageManager pm = context.getPackageManager();
+ try {
+ PackageInfo packageInfo = pm.getPackageInfo(packageName, 0);
+ versionName = packageInfo.versionName;
+ } catch (PackageManager.NameNotFoundException e) {
+ e.printStackTrace();
+ }
+ return versionName;
+ }
+
+ public static long getAppLastUpdateTime(Context context, String pkg) {
+ if (TextUtils.isEmpty(pkg)) {
+ return 0;
+ }
+ PackageManager pm = context.getPackageManager();
+ PackageInfo packageInfo = null;
+ try {
+ packageInfo = pm.getPackageInfo(pkg, 0);
+ } catch (PackageManager.NameNotFoundException e) {
+ e.printStackTrace();
+ }
+ if (packageInfo == null) {
+ return 0;
+ } else {
+ return packageInfo.lastUpdateTime / 1000;
+ }
+ }
}
diff --git a/app/src/main/java/com/uiuipad/find/util/AppUtil.java b/app/src/main/java/com/uiuipad/find/util/AppUtil.java
new file mode 100644
index 0000000..d42f459
--- /dev/null
+++ b/app/src/main/java/com/uiuipad/find/util/AppUtil.java
@@ -0,0 +1,16 @@
+package com.uiuipad.find.util;
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.util.Log;
+
+public class AppUtil {
+ private static final String TAG = AppUtil.class.getSimpleName();
+
+ public static void killPackage(Context context,String pkg) {
+ Log.e(TAG, "killPackage: " + pkg);
+ ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+ manager.killBackgroundProcesses(pkg);
+ CmdUtil.execute("am force-stop " + pkg);
+ }
+}
diff --git a/app/src/main/java/com/uiuipad/find/util/BitmapUtils.java b/app/src/main/java/com/uiuipad/find/util/BitmapUtils.java
index feac0cc..ebddef4 100644
--- a/app/src/main/java/com/uiuipad/find/util/BitmapUtils.java
+++ b/app/src/main/java/com/uiuipad/find/util/BitmapUtils.java
@@ -1,6 +1,11 @@
package com.uiuipad.find.util;
+import android.content.Context;
import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.PixelFormat;
+import android.graphics.drawable.Drawable;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
@@ -9,6 +14,9 @@ import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
@@ -65,4 +73,52 @@ public class BitmapUtils {
}
return null;
}
+
+ /**
+ * Drawable转换成一个Bitmap
+ *
+ * @param drawable drawable对象
+ * @return
+ */
+ public static final Bitmap drawableToBitmap(Drawable drawable) {
+ Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(),
+ drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565);
+ Canvas canvas = new Canvas(bitmap);
+ drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
+ drawable.draw(canvas);
+ return bitmap;
+ }
+
+
+ /**
+ * drawable转为file
+ *
+ * @param mContext
+ * @param drawable drawable
+ * @param fileName 转换后的文件名
+ * @return
+ */
+ public static File drawableToFile(Context mContext, Drawable drawable, String fileName) {
+// InputStream is = view.getContext().getResources().openRawResource(R.drawable.logo);
+ Bitmap bitmap = drawableToBitmap(drawable);
+// Bitmap bitmap = BitmapFactory.decodeStream(is);
+ String defaultPath = Utils.getCacheDir(mContext) + "/iconCache";
+ File file = new File(defaultPath);
+ if (!file.exists()) {
+ file.mkdirs();
+ }
+ String defaultImgPath = defaultPath + "/" + fileName;
+ File iconFile = new File(defaultImgPath);
+ try {
+ iconFile.createNewFile();
+ FileOutputStream fOut = new FileOutputStream(iconFile);
+ bitmap.compress(Bitmap.CompressFormat.PNG, 20, fOut);
+// is.close();
+ fOut.flush();
+ fOut.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return iconFile;
+ }
}
diff --git a/app/src/main/java/com/uiuipad/find/util/Camera2BackgroundUtil.java b/app/src/main/java/com/uiuipad/find/util/Camera2BackgroundUtil.java
new file mode 100644
index 0000000..109d120
--- /dev/null
+++ b/app/src/main/java/com/uiuipad/find/util/Camera2BackgroundUtil.java
@@ -0,0 +1,569 @@
+package com.uiuipad.find.util;
+
+import android.Manifest;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.graphics.ImageFormat;
+import android.graphics.SurfaceTexture;
+import android.hardware.Camera;
+import android.hardware.camera2.CameraAccessException;
+import android.hardware.camera2.CameraCaptureSession;
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraDevice;
+import android.hardware.camera2.CameraManager;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.TotalCaptureResult;
+import android.hardware.camera2.params.StreamConfigurationMap;
+import android.media.Image;
+import android.media.ImageReader;
+import android.media.MediaRecorder;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.util.Size;
+
+import androidx.annotation.NonNull;
+import androidx.core.app.ActivityCompat;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.stream.Collectors;
+
+/**
+ * @作者 Liushihua
+ * @创建时间 2021-2-3 10:54
+ * @描述
+ */
+public class Camera2BackgroundUtil {
+ private static final String TAG = Camera2BackgroundUtil.class.getSimpleName();
+
+ private Context context;
+ private CameraCallBack cameraCallBack;
+ private CameraManager cameraManager;
+ // 默认相机id是0 LENS_FACING_FRONT,LENS_FACING_BACK
+ private int cameraId = CameraCharacteristics.LENS_FACING_FRONT;
+ private CameraDevice mCameraDevice;
+ private String savePath;
+
+ private CaptureRequest.Builder mPreviewRequestBuilder;
+ private CameraCaptureSession mCameraCaptureSession;
+ private CaptureRequest request;
+ private ExecutorService service;
+ private boolean isTakedPicture = false;//是否已经拍照
+
+ private int needSetOrientation = 0;// 设置默认的拍照方向
+ private boolean isInitOk = false;// 是否初始化成功
+ private boolean isSessionClosed = true;// captureSession是否被关闭
+ private boolean isCameraDoing = false;// 是否正在使用相机
+ private final long CAPTURE_DELAY_TIME_LONG = 1200;// 延时拍照——聚焦需要时间
+
+ private final int HANDLER_ERR = 3;// 拍照失败
+ private final int HANDLER_TAKE_PHOTO_SUCCESS = 5;// 拍照成功
+ private List enableCameraList;//可用摄像头列表
+ private boolean mFlashSupported = false;//是否支持闪光灯
+ private List recordSizeList;// 录制尺寸
+ private Size mPreviewOutputSize;// 预览尺寸
+ private List imgOutputSizes;// 拍照尺寸
+
+ private final int PREVIEW_TYPE_NORMAL = 0;// 默认预览
+ private final int PREVIEW_TYPE_RECORD = 1;// 录屏预览
+ private final int PREVIEW_TYPE_TAKE_PHOTO = 2;// 拍照预览
+ private int previewType = 0;//默认预览
+
+ private boolean mTakePictureFinish = false;
+
+ private long lastSaveFileTime = 0;
+
+ public interface CameraCallBack {
+ void onErr(String msg);
+
+ void onTakePhotoOk(String path);
+ }
+
+ /**
+ * 处理静态图片的输出
+ */
+ private ImageReader imageReader;
+
+ private Handler handler = new Handler(Looper.getMainLooper()) {
+ @Override
+ public void handleMessage(Message msg) {
+ super.handleMessage(msg);
+ switch (msg.what) {
+ case HANDLER_ERR:
+ cameraCallBack.onErr("" + msg.obj);
+ isCameraDoing = false;
+ break;
+ case HANDLER_TAKE_PHOTO_SUCCESS:
+ if (!mTakePictureFinish) {
+ cameraCallBack.onTakePhotoOk(savePath);
+ mTakePictureFinish = true;
+ }
+ break;
+ default:
+ }
+ }
+ };
+
+ /**
+ * 当相机设备的状态发生改变的时候,将会回调。
+ */
+ protected final CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
+ /**
+ * 当相机打开的时候,调用
+ * @param cameraDevice
+ */
+ @Override
+ public void onOpened(@NonNull CameraDevice cameraDevice) {
+ Log.e(TAG, "onOpened");
+ mCameraDevice = cameraDevice;
+ startPreview();
+ }
+
+ @Override
+ public void onDisconnected(@NonNull CameraDevice cameraDevice) {
+ Log.e(TAG, "onDisconnected");
+ cameraDevice.close();
+ mCameraDevice = null;
+ Message message = new Message();
+ message.what = HANDLER_ERR;
+ message.obj = "后台相机断开连接";
+ handler.sendMessage(message);
+ }
+
+ /**
+ * 发生异常的时候调用
+ *
+ * 这里释放资源,然后关闭界面
+ * @param cameraDevice
+ * @param error
+ */
+ @Override
+ public void onError(@NonNull CameraDevice cameraDevice, int error) {
+ Log.e(TAG, "onError 相机设备异常,请重启!");
+ cameraDevice.close();
+ mCameraDevice = null;
+ Message messagef = new Message();
+ messagef.what = HANDLER_ERR;
+ messagef.obj = "相机设备异常,请重启!";
+ handler.sendMessage(messagef);
+ }
+
+ /**
+ *当相机被关闭的时候
+ */
+ @Override
+ public void onClosed(@NonNull CameraDevice camera) {
+ super.onClosed(camera);
+ Log.e(TAG, "onClosed");
+ mCameraDevice = null;
+ isCameraDoing = false;
+ }
+ };
+
+ /**
+ * 相机状态回调
+ */
+ private CameraManager.AvailabilityCallback callback = new CameraManager.AvailabilityCallback() {
+ @Override
+ public void onCameraAvailable(@NonNull String cameraId) {// 相机可用
+ super.onCameraAvailable(cameraId);
+ Log.e(TAG, "相机可用");
+ }
+
+ @Override
+ public void onCameraUnavailable(@NonNull String cameraId) {// 相机不可用
+ super.onCameraUnavailable(cameraId);
+ Log.e(TAG, "相机不可用");
+ }
+ };
+
+
+ /**
+ * 初始化
+ *
+ * @param activity
+ * @param cameraCallBack 回调
+ */
+ public Camera2BackgroundUtil(Context activity, @NonNull CameraCallBack cameraCallBack) {
+ this.context = activity;
+ this.cameraCallBack = cameraCallBack;
+ cameraManager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
+ // 对于静态图片,使用可用的最大值来拍摄。
+ if (cameraManager != null) {
+ isInitOk = true;
+ cameraManager.registerAvailabilityCallback(callback, null);
+ getCameraInfo();
+ setupImageReader();
+ service = Executors.newSingleThreadExecutor();
+ }
+ }
+
+ private void setupImageReader() {
+// Size size = getOutputSize(imgOutputSizes);
+ //前三个参数分别是需要的尺寸和格式,最后一个参数代表每次最多获取几帧数据,本例的3代表ImageReader中最多可以获取2帧图像流
+ imageReader = ImageReader.newInstance(1600, 1200, ImageFormat.JPEG, 1);
+ //监听ImageReader的事件,当有图像流数据可用时会回调onImageAvailable方法,它的参数就是预览帧数据,可以对这帧数据进行处理
+ imageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
+ @Override
+ public void onImageAvailable(ImageReader reader) {
+ Image image = reader.acquireLatestImage();
+ if (image == null) return;
+ //我们可以将这帧数据转成字节数组,类似于Camera1的PreviewCallback回调的预览帧数据
+ ByteBuffer buffer = image.getPlanes()[0].getBuffer();
+ byte[] data = new byte[buffer.remaining()];
+ buffer.get(data);
+ image.close();
+ saveFile(data, savePath);
+ }
+ }, null);
+ }
+
+ /**
+ * 打开相机
+ */
+ private void openCamera() {
+ cameraId = getFrontCameraId();
+ Log.e(TAG, "openCamera: getFrontCameraId = " + getFrontCameraId());
+ Log.e(TAG, "openCamera:" + cameraId);
+ isCameraDoing = true;
+ // 设置TextureView的缓冲区大小
+ // 获取Surface显示预览数据
+ if (ActivityCompat.checkSelfPermission(context, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
+ Message message = new Message();
+ message.what = HANDLER_ERR;
+ message.obj = "权限不足";
+ handler.sendMessage(message);
+ return;
+ }
+ try {
+ cameraManager.openCamera(Integer.toString(cameraId), stateCallback, null);
+ Log.e(TAG, "打开相机成功!");
+ } catch (Exception e) {
+ Log.e(TAG, "打开相机失败-Exception:" + e.getMessage());
+ e.printStackTrace();
+ Message messagef = new Message();
+ messagef.what = HANDLER_ERR;
+ messagef.obj = "打开相机失败";
+ handler.sendMessage(messagef);
+ }
+ }
+
+ private int getFrontCameraId() {
+ int numberOfCameras = Camera.getNumberOfCameras();
+ for (int i = 0; i < numberOfCameras; i++) {
+ Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
+ Camera.getCameraInfo(i, cameraInfo);
+ if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
+ return i;
+ }
+ }
+ return 0;
+ }
+
+ /**
+ * 开始视频录制预览
+ */
+ private void startPreview() {
+ Log.e(TAG, "startPreview");
+ // CaptureRequest添加imageReaderSurface,不加的话就会导致ImageReader的onImageAvailable()方法不会回调
+ // 创建CaptureSession时加上imageReaderSurface,如下,这样预览数据就会同时输出到previewSurface和imageReaderSurface了
+ try {
+ // 创建CaptureRequestBuilder,TEMPLATE_PREVIEW比表示预览请求
+ mPreviewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
+ mPreviewRequestBuilder.addTarget(imageReader.getSurface());// 设置Surface作为预览数据的显示界面
+ // 创建相机捕获会话,第一个参数是捕获数据的输出Surface列表,第二个参数是CameraCaptureSession的状态回调接口,当它创建好后会回调onConfigured方法,第三个参数用来确定Callback在哪个线程执行,为null的话就在当前线程执行
+ mCameraDevice.createCaptureSession(Arrays.asList(imageReader.getSurface()), captureSessionStateCallBack, null);
+ } catch (CameraAccessException e) {
+ e.printStackTrace();
+ Message messagef = new Message();
+ messagef.what = HANDLER_ERR;
+ messagef.obj = "捕获帧失败";
+ handler.sendMessage(messagef);
+ Log.e(TAG, "Camera获取成功,创建录制请求或捕获Session失败" + e.getMessage());
+ }
+ }
+
+ /**
+ * 捕获图片数据
+ */
+ private CameraCaptureSession.StateCallback captureSessionStateCallBack = new CameraCaptureSession.StateCallback() {
+ @Override
+ public void onConfigured(CameraCaptureSession session) {
+ try {
+ mCameraCaptureSession = session;
+ isSessionClosed = false;
+ request = mPreviewRequestBuilder.build();
+ // 设置反复捕获数据的请求,这样预览界面就会一直有数据显示
+ mCameraCaptureSession.setRepeatingRequest(request, null, null);
+ } catch (Exception e) {
+ e.printStackTrace();
+ Message messagef = new Message();
+ messagef.what = HANDLER_ERR;
+ messagef.obj = "开启图像预览失败";
+ handler.sendMessage(messagef);
+ }
+ if (!isTakedPicture) {
+ isTakedPicture = true;
+ handler.postDelayed(() -> takePicture(), CAPTURE_DELAY_TIME_LONG);
+ }
+ }
+
+ @Override
+ public void onConfigureFailed(CameraCaptureSession session) {
+ Log.e(TAG, "onConfigureFailed");
+ }
+ };
+
+
+ public void startTakePicture(String savePath) {
+ Log.e(TAG, "拍照:" + savePath);
+ this.savePath = savePath;
+ if (isCameraDoing) {
+ Log.e(TAG, "相机使用中...");
+ } else {
+ isTakedPicture = false;
+ openCamera();
+ }
+ }
+
+ /**
+ * 拍照
+ */
+ private void takePicture() {
+ Log.e(TAG, "takePicture");
+ try {
+ if (mCameraDevice == null || mPreviewRequestBuilder == null) return;
+ mPreviewRequestBuilder.addTarget(imageReader.getSurface());
+ //设置拍照方向
+ mPreviewRequestBuilder.set(CaptureRequest.JPEG_ORIENTATION, this.needSetOrientation);
+ //这个回调接口用于拍照结束时重启预览,因为拍照会导致预览停止
+ CameraCaptureSession.CaptureCallback mImageSavedCallback = new CameraCaptureSession.CaptureCallback() {
+ @Override
+ public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
+ Log.e(TAG, "拍照完成");
+ onStop();
+ }
+ };
+ //开始拍照,然后回调上面的接口重启预览,因为mCaptureBuilder设置ImageReader作为target,所以会自动回调ImageReader的onImageAvailable()方法保存图片
+ mCameraCaptureSession.capture(mPreviewRequestBuilder.build(), mImageSavedCallback, null);
+ } catch (CameraAccessException e) {
+ Log.e(TAG, "takePhoto CameraAccessException:" + e.getMessage());
+ e.printStackTrace();
+ Message messagef = new Message();
+ messagef.what = HANDLER_ERR;
+ messagef.obj = "拍照失败";
+ handler.sendMessage(messagef);
+ }
+ }
+
+ /**
+ * 停止预览,释放资源
+ */
+ public void stopRecord() {
+ Log.e(TAG, "停止预览,释放资源");
+ try {
+ if (mCameraCaptureSession != null && !isSessionClosed) {
+ mCameraCaptureSession.stopRepeating();
+ mCameraCaptureSession.abortCaptures();
+ mCameraCaptureSession.close();
+ isSessionClosed = true;
+ imageReader.close();
+ imageReader = null;
+ }
+ if (mCameraDevice != null)
+ mCameraDevice.close();
+ isCameraDoing = false;
+ } catch (Exception e) {
+ e.printStackTrace();
+ Log.e(TAG, "stopRecord-Exception:" + e.getMessage());
+ }
+ }
+
+ /**
+ * 重置后,开始预览
+ */
+ public void reset() {
+ previewType = PREVIEW_TYPE_NORMAL;
+ stopRecord();
+ openCamera();
+ }
+
+ /**
+ * 在 activity,fragment的onStop中调用
+ */
+ public void onStop() {
+ stopRecord();
+ }
+
+ /**
+ * 注销 回调
+ */
+ public void onDestroy() {
+ this.cameraCallBack = null;
+ if (cameraManager != null)
+ cameraManager.unregisterAvailabilityCallback(callback);
+ }
+
+ /**
+ * 获得可用的摄像头
+ *
+ * @return SparseArray of available cameras ids。key为摄像头方位,见CameraCharacteristics#LENS_FACING,value为对应的摄像头id
+ */
+ public void getCameras() {
+ if (cameraManager == null) return;
+ enableCameraList = new ArrayList<>();
+ try {
+ String[] camerasAvailable = cameraManager.getCameraIdList();
+ CameraCharacteristics cam;
+ Integer characteristic;
+ Log.e(TAG, "-------------------------------------");
+ for (String id : camerasAvailable) {
+ Log.e(TAG, "getCameras:" + id);
+ try {
+ enableCameraList.add(Integer.parseInt(id));
+ } catch (NumberFormatException e) {
+ e.printStackTrace();
+ }
+ }
+ Log.e(TAG, "-------------------------------------");
+ } catch (CameraAccessException e) {
+ Log.e(TAG, "getCameras CameraAccessException:" + e.getMessage());
+ }
+ }
+
+ /**
+ * 设置输出数据尺寸选择器,在selectCamera之前设置有效
+ * (一般手机支持多种输出尺寸,请用户根据自身需要选择最合适的一种)
+ * 举例:
+ * SizeSelector maxPreview = SizeSelectors.and(SizeSelectors.maxWidth(720), SizeSelectors.maxHeight(480));
+ * SizeSelector minPreview = SizeSelectors.and(SizeSelectors.minWidth(320), SizeSelectors.minHeight(240));
+ * camera.setmOutputSizeSelector(SizeSelectors.or(
+ * SizeSelectors.and(maxPreview, minPreview)//先在最大和最小中寻找
+ * , SizeSelectors.and(maxPreview, SizeSelectors.biggest())//找不到则按不超过最大尺寸的那个选择
+ * ));
+ */
+ public void getOutputSizeSelector() {
+
+ }
+
+
+ /**
+ * 获取摄像头信息
+ */
+ public void getCameraInfo() {
+ if (enableCameraList == null) {
+ getCameras();
+ }
+ try {
+ CameraCharacteristics mCameraCharacteristics = cameraManager.getCameraCharacteristics(String.valueOf(cameraId));
+ // 设置是否支持闪光灯
+ Boolean available = mCameraCharacteristics.get(CameraCharacteristics.FLASH_INFO_AVAILABLE);
+ mFlashSupported = available == null ? false : available;
+ StreamConfigurationMap map = mCameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
+ if (map == null) {
+ Log.e(TAG, "Could not get configuration map.");
+ return;
+ }
+ int mSensorOrientation = mCameraCharacteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);//这个方法来获取CameraSensor的方向。
+ Log.e(TAG, "camera sensor orientation:" + mSensorOrientation + ",display rotation=" + context.getDisplay().getRotation());
+
+ int[] formats = map.getOutputFormats();//获得手机支持的输出格式,其中jpeg是一定会支持的,yuv_420_888是api21才开始支持的
+ for (int format : formats) {
+ Log.e(TAG, "手机格式支持: " + format);
+ }
+ Size[] yuvOutputSizes = map.getOutputSizes(ImageFormat.YUV_420_888);
+ Size[] mediaOutputSizes = map.getOutputSizes(MediaRecorder.class);
+ Size[] previewOutputSizes = map.getOutputSizes(SurfaceTexture.class);
+ Size[] jpegOutputSizes = map.getOutputSizes(ImageFormat.JPEG);
+
+ recordSizeList = new ArrayList<>();
+ imgOutputSizes = new ArrayList<>();
+
+ Log.e(TAG, "---------------------------------------------------");
+ for (Size size : mediaOutputSizes) {
+ recordSizeList.add(new Size(size.getWidth(), size.getHeight()));
+ Log.e(TAG, "mediaOutputSizes: " + size.toString());
+ }
+ for (Size size : jpegOutputSizes) {
+ imgOutputSizes.add(new Size(size.getWidth(), size.getHeight()));
+ Log.e(TAG, "jpegOutputSizes: " + size.toString());
+ }
+ for (Size size : previewOutputSizes) {
+ Log.e(TAG, "previewOutputSizes: " + size.toString());
+ }
+ for (Size size : yuvOutputSizes) {
+ Log.e(TAG, "yuvOutputSizes: " + size.toString());
+ }
+ Log.e(TAG, "---------------------------------------------------");
+ } catch (Exception e) {
+ Log.e(TAG, "selectCamera Exception:" + e.getMessage());
+ }
+ }
+
+ private Size getOutputSize(List sizes) {
+ DisplayMetrics dm = context.getResources().getDisplayMetrics();
+ int screenWidth = dm.widthPixels;
+ int screenHeight = dm.heightPixels;
+ Log.e(TAG, "getOutputSize: screenWidth = " + screenWidth);
+ Log.e(TAG, "getOutputSize: screenHeight = " + screenHeight);
+ List sorted = sizes.stream().sorted(new Comparator() {
+ @Override
+ public int compare(Size o1, Size o2) {
+ return Long.compare(o1.getHeight() * o1.getWidth(), o2.getHeight() * o2.getWidth());
+ }
+ }).collect(Collectors.toList());
+ for (Size size : sorted) {
+ if (size.getWidth() > screenHeight && size.getHeight() > screenWidth) {
+ return size;
+ }
+ }
+ return new Size(1600, 1200);
+ }
+
+ //覆盖性保存
+ private void saveFile(final byte[] data, final String savePath) {
+ if (data == null || data.length == 0) return;
+ if (System.currentTimeMillis() - lastSaveFileTime > 1000)
+ service.execute(() -> {
+ File file = new File(savePath);
+ File parent = file.getParentFile();
+ if (parent != null && !parent.exists()) {
+ parent.mkdirs();
+ }
+ if (file.exists()) {
+ file.delete();
+ }
+ try {
+ file.createNewFile();
+ FileOutputStream fos = new FileOutputStream(file);
+ fos.write(data);
+ fos.flush();
+ fos.close();
+ lastSaveFileTime = System.currentTimeMillis();
+ Message message = new Message();
+ message.what = HANDLER_TAKE_PHOTO_SUCCESS;
+ message.obj = savePath;
+ handler.sendMessage(message);
+ } catch (IOException e) {
+ e.printStackTrace();
+ Log.e(TAG, "图片保存-IOException:" + e.getMessage());
+ Message messagef = new Message();
+ messagef.what = HANDLER_ERR;
+ messagef.obj = "图片保存失败";
+ handler.sendMessage(messagef);
+ }
+ });
+ }
+}
+
diff --git a/app/src/main/java/com/uiuipad/find/util/ControlUtils.java b/app/src/main/java/com/uiuipad/find/util/ControlUtils.java
index da2357a..5f1bbd1 100644
--- a/app/src/main/java/com/uiuipad/find/util/ControlUtils.java
+++ b/app/src/main/java/com/uiuipad/find/util/ControlUtils.java
@@ -152,7 +152,7 @@ public class ControlUtils {
setActionBar(context, 1);
// setNavigationBar(context, 0);
setStatusBar(context);
- setTF(context, 0);
+ setTF(context, 1);
} else {
int is_storeinstall = snSetting.getIs_storeinstall();
int is_usb = snSetting.getIs_usb();
diff --git a/app/src/main/java/com/uiuipad/find/util/Utils.java b/app/src/main/java/com/uiuipad/find/util/Utils.java
index 60e9f54..ec0a00c 100644
--- a/app/src/main/java/com/uiuipad/find/util/Utils.java
+++ b/app/src/main/java/com/uiuipad/find/util/Utils.java
@@ -9,7 +9,11 @@ import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.BatteryManager;
import android.os.Build;
+import android.os.Environment;
+import android.os.PowerManager;
import android.os.StatFs;
+import android.provider.Settings;
+import android.telephony.TelephonyManager;
import android.text.format.Formatter;
import android.util.Log;
@@ -31,7 +35,6 @@ public class Utils {
*/
@SuppressLint({"MissingPermission", "NewApi"})
public static String getSerial() {
-// return JGYUtils.getInstance().getIMEI();
String serial = "unknown";
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {//9.0+
@@ -50,6 +53,36 @@ public class Utils {
return serial;
}
+
+ public static String getIMEI(Context context) {
+ String IMEI = "unknown";
+ String IMEI1, IMEI2, IMEI3;
+ //获取手机设备号
+ TelephonyManager TelephonyMgr = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+ //8.0及以后版本获取
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ IMEI = TelephonyMgr.getDeviceId();
+ } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+// try {
+// Method method = TelephonyMgr.getClass().getMethod("getImei");
+// IMEI = (String) method.invoke(TelephonyMgr);
+// } catch (Exception e) {
+// e.printStackTrace();
+// Log.e("getIMEI", e.getMessage());
+// }
+// IMEI = TelephonyMgr.getDeviceId();
+
+// } else {//9.0到10.0获取
+ IMEI = Settings.System.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
+ }
+// Log.e("IMEI:", "IMEI: " + IMEI);
+ if (null == IMEI) {
+ return "-";
+ } else {
+ return IMEI.toUpperCase();
+ }
+ }
+
/**
* @param context
* @return 获取WiFi名
@@ -254,4 +287,27 @@ public class Utils {
return getProperty("ro.build.display.id", "获取失败");
// return Utils.getProperty("ro.custom.build.version", "获取失败");
}
+
+ public static String getCacheDir(Context context) {
+ String cachePath;
+ if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())
+ || !Environment.isExternalStorageRemovable()) {
+ if (context.getExternalCacheDir() != null) {
+ cachePath = context.getExternalCacheDir().getPath();
+ } else if (context.getExternalFilesDir("cache") != null) {
+ cachePath = context.getExternalFilesDir("cache").getPath();
+ } else {
+ cachePath = context.getCacheDir().getPath();
+ }
+ } else {
+ cachePath = context.getCacheDir().getPath();
+ }
+ return cachePath;
+ }
+
+ public static boolean isScreenOn(Context context) {
+ PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+ //true为打开,false为关闭
+ return powerManager.isInteractive();
+ }
}
diff --git a/app/src/main/res/drawable-hdpi/icon_update.png b/app/src/main/res/drawable-hdpi/icon_update.png
deleted file mode 100644
index a18747f61b0c5aa2d228e7ad980e588947811bb6..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 712
zcmV;(0yq7MP)Px%f=NU{RA@u(ne9;nArOX_N;H*tsU%4WSAkl=m0+wyti)K!IWGf95(po=oKEJL
zar}{k+lP0*;1u1-P->
zq#^XEQ0&OA+X7Rh${C1oeLy`h5NlK6m43Q5~6XmaP6Eh=dv;1ZvJskIDr5FwJOb-d*rA+$;)XK!nt|gg{`UJr6;UwR|RG
z!uYkp;6PC9IGrq7aOXB*^^bwzy&(+86a0G}2xl=EW>RFNg-L;U7^XM)^`$^k)%zBR
z%R=1N$GEfu>D89!K(ZCP-~r=a4g?vcwtXmgM>N<==G8o7n#+4o#Hj8-T5myeJGX>u
zp>5eXkX{F-B|uCnm#QNvWtIgAS_tWY4?*UfA2$B}n|>`wFZV+G{nYEItVdavaR
zm4+KPJ3Gy{I$ti3=^+c^_Q#&)pb}E)5(Agn-}Z(+`yr?pWC_bT
u?^r=NyVqmxsz{Gr<*d0X!r8qZbAJFB??^)268kp*0000MU*6jO-+2woYowOwoxnS-BL`W_pkjY1%0X
z$uUMvgmQ1LB^hI?M?@iyBsn^DoIm0G@V=ktegA;Z6@TA-dT=v11Om~cdQ$?{$^I`e
z?e&hH$O~Kt5EHPE45{q5_yB=uexy?N23`oBmjF3~IE3f;O_>cQAtx;Bg%QL?v2lc;
zJGC|X8t&jC(y}m_-z+KlpRLnq`KtIjkU~+Y3LGjhdIIHsN
zlaVF$Eyj2_kE=~$uq*_G^|EN;`%ml&8>99
zA`d~%%_LKdK>>#EfJQVD=5q&wI$A?K3_D0jA^4--EmZGmM6kThg;GXzJlul>4!5VPQGso0$Yr1h#T$cmjT$1>1GAy<%K
zr+UD!MpmFi(fb%oJ9L5l>mywzAM)pGeWPFcy3Z<0tY@6r^qLKP^wDwo<6V9
z%L^qv>=~bA!OdCKE%M$s4@Z|~b1r(L`fBQ{FPdG8aK~4ojAeRX_vtsvnc@?Xc>Nkz{IO|
z$-D=kkj#y&A&
z8hEcvKS6Z=OWzJ`KapvL4CO}Mk5s8Q5^-+%Q$~$~$^gxzH;!<+CkgSJYvyTj!$0h7
zGGmp^ms8~{`oxV#bbfE#M6eCgY|q`|#c0Z+A=vWpcE{%B_(Y#M-IQIMrZP%Ja-wS2
zVyj=0`3-l2k4RxzTXMx`c=tr%^`FKWbrpSfb=%n;#B)P$#}bHylRe={&zATLB~-Wb
z*+LDKZp2=vv0(}GbdrI=*)8sY?l0`>%Y;C7Vtv!}Yp6DVt`djV=J!I`?{AR*zhKDk
g0p}PW44ZTb8i6ps964N3zpg+C)zgPx%f=NU{RA@u(ne9;nArOX_N;H*tsU%4WSAkl=m0+wyti)K!IWGf95(po=oKEJL
zar}{k+lP0*;1u1-P->
zq#^XEQ0&OA+X7Rh${C1oeLy`h5NlK6m43Q5~6XmaP6Eh=dv;1ZvJskIDr5FwJOb-d*rA+$;)XK!nt|gg{`UJr6;UwR|RG
z!uYkp;6PC9IGrq7aOXB*^^bwzy&(+86a0G}2xl=EW>RFNg-L;U7^XM)^`$^k)%zBR
z%R=1N$GEfu>D89!K(ZCP-~r=a4g?vcwtXmgM>N<==G8o7n#+4o#Hj8-T5myeJGX>u
zp>5eXkX{F-B|uCnm#QNvWtIgAS_tWY4?*UfA2$B}n|>`wFZV+G{nYEItVdavaR
zm4+KPJ3Gy{I$ti3=^+c^_Q#&)pb}E)5(Agn-}Z(+`yr?pWC_bT
u?^r=NyVqmxsz{Gr<*d0X!r8qZbAJFB??^)268kp*0000
@@ -160,13 +160,13 @@
@@ -194,90 +195,11 @@
android:singleLine="true"
android:text="@string/unknown"
android:textColor="@color/text_gray"
- android:textSize="@dimen/sp_10"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintTop_toTopOf="parent" />
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -325,8 +248,8 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -374,11 +377,11 @@
android:id="@+id/tv_bind_statu"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginStart="@dimen/dp_8"
+ android:layout_marginStart="@dimen/dp_12"
android:layout_marginTop="@dimen/dp_8"
android:text="设备绑定"
android:textColor="@color/black"
- android:textSize="@dimen/sp_10"
+ android:textSize="@dimen/sp_9"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
diff --git a/app/src/main/res/layout-port/activity_main.xml b/app/src/main/res/layout-port/activity_main.xml
index 75aa9c7..d48deff 100644
--- a/app/src/main/res/layout-port/activity_main.xml
+++ b/app/src/main/res/layout-port/activity_main.xml
@@ -128,10 +128,10 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/dp_20"
- android:layout_marginBottom="@dimen/dp_16"
+ android:layout_marginBottom="@dimen/dp_12"
android:maxLines="1"
android:textColor="@color/text_gray"
- android:textSize="@dimen/sp_8"
+ android:textSize="@dimen/sp_6"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
tools:text="绑定时间" />
@@ -160,13 +160,13 @@
@@ -194,90 +195,11 @@
android:singleLine="true"
android:text="@string/unknown"
android:textColor="@color/text_gray"
- android:textSize="@dimen/sp_10"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintTop_toTopOf="parent" />
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -325,8 +248,8 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -374,11 +377,11 @@
android:id="@+id/tv_bind_statu"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginStart="@dimen/dp_8"
+ android:layout_marginStart="@dimen/dp_12"
android:layout_marginTop="@dimen/dp_8"
android:text="设备绑定"
android:textColor="@color/black"
- android:textSize="@dimen/sp_10"
+ android:textSize="@dimen/sp_9"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index 489ce24..f337725 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -1,6 +1,6 @@
- #efefef
+ #f3f3f3
#303F9F
#0480FF