From 93f87d3b68fa779ac65d1d705c610cd255d79729 Mon Sep 17 00:00:00 2001 From: Fanhuitong <981964879@qq.com> Date: Mon, 6 Feb 2023 19:08:49 +0800 Subject: [PATCH] =?UTF-8?q?version:zhanrui=206.3.8,MTK=202.3.8=20fix:=20up?= =?UTF-8?q?date:=E6=8E=A5=E5=8F=A3=E4=BC=98=E5=8C=96=EF=BC=8C=E4=B8=BB?= =?UTF-8?q?=E9=A1=B5=E4=BC=98=E5=8C=96=EF=BC=8C=E5=BF=83=E8=B7=B3=E6=9C=BA?= =?UTF-8?q?=E5=88=B6=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 10 +- .../activity/checknet/CheckNetPresenter.java | 4 +- .../sn/activity/main/MainAContact.java | 18 +- .../sn/activity/main/MainAPresenter.java | 35 +- .../sn/activity/main/MainActivity.java | 417 ++++++-- .../com/aoleyun/sn/base/BaseApplication.java | 2 - .../com/aoleyun/sn/bean/AppUpdateInfo.java | 9 + .../com/aoleyun/sn/comm/CommonConfig.java | 2 +- .../com/aoleyun/sn/dialog/UpdateDialog.java | 197 ++++ .../sn/network/NetInterfaceManager.java | 244 ++--- .../com/aoleyun/sn/network/UrlAddress.java | 33 +- .../sn/network/api/GetPublicIPApi.java | 19 - .../network/api/post/NetworkConnectApi.java | 5 +- .../interceptor/RepeatRequestInterceptor.java | 10 +- .../aoleyun/sn/receiver/NewAppReceiver.java | 1 + .../com/aoleyun/sn/service/StepService.java | 31 +- .../aoleyun/sn/service/main/MainSContact.java | 77 +- .../sn/service/main/MainSPresenter.java | 232 +++-- .../aoleyun/sn/service/main/MainService.java | 289 +++--- .../sn/utils/AES/AesCbcWithIntegrity.java | 2 +- .../java/com/aoleyun/sn/utils/ApkUtils.java | 2 - .../java/com/aoleyun/sn/utils/JGYUtils.java | 45 +- .../com/aoleyun/sn/utils/StatusBarUtil.java | 2 +- .../main/java/com/aoleyun/sn/utils/Utils.java | 14 - app/src/main/res/drawable-hdpi/back.png | Bin 2040 -> 0 bytes app/src/main/res/drawable-hdpi/bt_return.png | Bin 0 -> 1897 bytes .../main/res/drawable-hdpi/default_head.png | Bin 0 -> 21399 bytes app/src/main/res/drawable-hdpi/delimiter.png | Bin 0 -> 3586 bytes app/src/main/res/drawable-hdpi/head.png | Bin 4950 -> 0 bytes .../main/res/drawable-hdpi/icon_battery.png | Bin 0 -> 2688 bytes .../main/res/drawable-hdpi/icon_ipaddress.png | Bin 0 -> 3448 bytes app/src/main/res/drawable-hdpi/icon_wifi.png | Bin 0 -> 3386 bytes app/src/main/res/drawable-hdpi/more.png | Bin 0 -> 476 bytes app/src/main/res/drawable/bg_dialog.xml | 9 + .../res/drawable/bt_activation_normnl.xml | 15 + .../res/drawable/bt_activation_pressed.xml | 15 + .../res/drawable/bt_activation_selector.xml | 13 + app/src/main/res/drawable/bt_trial.xml | 15 + app/src/main/res/drawable/bt_vip.xml | 15 + app/src/main/res/drawable/card_background.xml | 24 + app/src/main/res/drawable/join_background.xml | 13 + .../main/res/drawable/joined_background.xml | 13 + .../main/res/layout-land/activity_main.xml | 782 +++++++-------- .../res/layout-land/activity_request_log.xml | 2 +- .../main/res/layout-port/activity_main.xml | 943 ++++++++++++------ .../res/layout-port/activity_request_log.xml | 2 +- app/src/main/res/layout/update_dialog.xml | 90 ++ app/src/main/res/values/colors.xml | 13 +- app/src/main/res/values/strings.xml | 80 +- app/src/main/res/values/styles.xml | 13 + 50 files changed, 2399 insertions(+), 1358 deletions(-) create mode 100644 app/src/main/java/com/aoleyun/sn/dialog/UpdateDialog.java delete mode 100644 app/src/main/java/com/aoleyun/sn/network/api/GetPublicIPApi.java delete mode 100644 app/src/main/res/drawable-hdpi/back.png create mode 100644 app/src/main/res/drawable-hdpi/bt_return.png create mode 100644 app/src/main/res/drawable-hdpi/default_head.png create mode 100644 app/src/main/res/drawable-hdpi/delimiter.png delete mode 100644 app/src/main/res/drawable-hdpi/head.png create mode 100644 app/src/main/res/drawable-hdpi/icon_battery.png create mode 100644 app/src/main/res/drawable-hdpi/icon_ipaddress.png create mode 100644 app/src/main/res/drawable-hdpi/icon_wifi.png create mode 100644 app/src/main/res/drawable-hdpi/more.png create mode 100644 app/src/main/res/drawable/bg_dialog.xml create mode 100644 app/src/main/res/drawable/bt_activation_normnl.xml create mode 100644 app/src/main/res/drawable/bt_activation_pressed.xml create mode 100644 app/src/main/res/drawable/bt_activation_selector.xml create mode 100644 app/src/main/res/drawable/bt_trial.xml create mode 100644 app/src/main/res/drawable/bt_vip.xml create mode 100644 app/src/main/res/drawable/card_background.xml create mode 100644 app/src/main/res/drawable/join_background.xml create mode 100644 app/src/main/res/drawable/joined_background.xml create mode 100644 app/src/main/res/layout/update_dialog.xml diff --git a/app/build.gradle b/app/build.gradle index 970f35b..2ce8c91 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -82,16 +82,16 @@ android { //酷比魔方 cube { flavorDimensions "default" - versionCode 73 - versionName "6.3.3" + versionCode 78 + versionName "6.3.8" buildConfigField "String", "platform", '"ZhanRuiCube"' } //MTK MTKnewly { flavorDimensions "default" - versionCode 43 - versionName "2.3.3" + versionCode 48 + versionName "2.3.8" buildConfigField "String", "platform", '"MTK"' } } @@ -278,7 +278,7 @@ dependencies { implementation 'com.squareup.moshi:moshi:1.9.3' //OkHttp - implementation 'com.squareup.okhttp3:okhttp:4.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.8.0' //Retrofit implementation 'com.squareup.retrofit2:retrofit:2.9.0' implementation 'com.squareup.retrofit2:converter-gson:2.9.0' diff --git a/app/src/main/java/com/aoleyun/sn/activity/checknet/CheckNetPresenter.java b/app/src/main/java/com/aoleyun/sn/activity/checknet/CheckNetPresenter.java index c7e010e..ec3b0c2 100644 --- a/app/src/main/java/com/aoleyun/sn/activity/checknet/CheckNetPresenter.java +++ b/app/src/main/java/com/aoleyun/sn/activity/checknet/CheckNetPresenter.java @@ -154,9 +154,9 @@ public class CheckNetPresenter implements CheckNetContact.Presenter { @Override public void setPushTags() { - mNetInterfaceManager.setPushTags(true, getLifecycle(), new NetInterfaceManager.onCompleteCallback() { + mNetInterfaceManager.setPushTags(true, getLifecycle(), new NetInterfaceManager.PushTagCallback() { @Override - public void onComplete() { + public void setPushTag(String tag) { Log.e("setPushTags", "onComplete: "); mView.setTagsFinish(false); } diff --git a/app/src/main/java/com/aoleyun/sn/activity/main/MainAContact.java b/app/src/main/java/com/aoleyun/sn/activity/main/MainAContact.java index f894ccb..18ac20d 100644 --- a/app/src/main/java/com/aoleyun/sn/activity/main/MainAContact.java +++ b/app/src/main/java/com/aoleyun/sn/activity/main/MainAContact.java @@ -13,21 +13,33 @@ public class MainAContact { /*获取设备锁定状态*/ void getLockedState(); /*获取设备二维码*/ - void getQRCode(boolean loocked); + void getQrCode(boolean loocked); /*获取学生信息*/ - void getStudesInfo(boolean refresh); + void getStudesInfo(); + /*获取公网ip*/ + void getPublicIp(); /*手动获取设备信息更新*/ void buttonCheckUpdate(View view); + /*获取设备信息更新*/ + void checkAoleyunUpdate(); + /*获取测试应用更新*/ + void checkTestUpdate(); } public interface MainView extends BaseView { /*获取设备锁定状态*/ void setLockedState(boolean loocked); /*获取设备二维码*/ - void setQRCode(Bitmap qrcode); + void setQrCode(Bitmap qrcode); /*获取学生信息*/ void setStudesInfo(StudentsInfo studesInfo); + /*获取公网ip*/ + void setPublicIp(String ip); /*手动获取设备信息更新*/ void buttonCheckUpdateFinish(boolean update, JsonObject jsonObject); + /*获取设备信息更新*/ + void checkAoleyunUpdateFinish(); + /*获取测试应用更新*/ + void checkTestUpdateFinish(); } } diff --git a/app/src/main/java/com/aoleyun/sn/activity/main/MainAPresenter.java b/app/src/main/java/com/aoleyun/sn/activity/main/MainAPresenter.java index 44018d8..5c4cf86 100644 --- a/app/src/main/java/com/aoleyun/sn/activity/main/MainAPresenter.java +++ b/app/src/main/java/com/aoleyun/sn/activity/main/MainAPresenter.java @@ -84,18 +84,18 @@ public class MainAPresenter implements MainAContact.Presenter { } @Override - public void getQRCode(boolean loocked) { + public void getQrCode(boolean loocked) { String encryptString = CXAESUtil.encrypt(CommonConfig.AES_KEY, Utils.getSerial()); Log.e("getQRCode", "setImageAndText: " + encryptString); Bitmap bitmap = Utils.createQRImage(encryptString, 400, 400); - mView.setQRCode(bitmap); + mView.setQrCode(bitmap); } /** * 通过sn获取用户信息 */ @Override - public void getStudesInfo(boolean refresh) { + public void getStudesInfo() { NetInterfaceManager.getInstance().getStudesInfo(true, getLifecycle(), new NetInterfaceManager.StudesInfoListener() { @Override public void setStudentsInfo(StudentsInfo studentsInfo) { @@ -109,12 +109,41 @@ public class MainAPresenter implements MainAContact.Presenter { }); } + @Override + public void getPublicIp() { + NetInterfaceManager.getInstance().getPublicIp(lifecycle, ip -> mView.setPublicIp(ip)); + } + @Override public void buttonCheckUpdate(View view) { checkUpdateInfo(); } + @Override + public void checkAoleyunUpdate() { + checkUpdateInfo(); + NetInterfaceManager.getInstance() + .checkAoleyunUpdate(true, getLifecycle(), new NetInterfaceManager.onCompleteCallback() { + @Override + public void onComplete() { + mView.checkAoleyunUpdateFinish(); + } + }); +// mView.checkAoleyunUpdateFinish(); + } + + @Override + public void checkTestUpdate() { + NetInterfaceManager.getInstance() + .checkTestUpdate(true, getLifecycle(), new NetInterfaceManager.onCompleteCallback() { + @Override + public void onComplete() { + mView.checkTestUpdateFinish(); + } + }); + } + private void checkUpdateInfo() { NetInterfaceManager.getInstance() .getUpdateApi() diff --git a/app/src/main/java/com/aoleyun/sn/activity/main/MainActivity.java b/app/src/main/java/com/aoleyun/sn/activity/main/MainActivity.java index 2949227..3871e21 100644 --- a/app/src/main/java/com/aoleyun/sn/activity/main/MainActivity.java +++ b/app/src/main/java/com/aoleyun/sn/activity/main/MainActivity.java @@ -5,19 +5,25 @@ import android.app.AlertDialog; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; -import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.graphics.Bitmap; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; +import android.net.wifi.WifiInfo; +import android.net.wifi.WifiManager; +import android.os.Build; import android.os.IBinder; import android.os.SystemClock; import android.provider.Settings; import android.text.TextUtils; +import android.text.format.Formatter; import android.util.Log; +import android.view.Gravity; import android.view.KeyEvent; import android.view.View; -import android.widget.Button; +import android.view.WindowManager; import android.widget.ImageView; import android.widget.TextView; @@ -30,6 +36,7 @@ import com.aoleyun.sn.base.BaseActivity; import com.aoleyun.sn.bean.StudentsInfo; import com.aoleyun.sn.comm.CommonConfig; import com.aoleyun.sn.comm.JGYActions; +import com.aoleyun.sn.dialog.UpdateDialog; import com.aoleyun.sn.service.main.MainService; import com.aoleyun.sn.utils.JGYUtils; import com.aoleyun.sn.utils.SPUtils; @@ -53,57 +60,83 @@ import io.reactivex.rxjava3.core.ObservableOnSubscribe; import io.reactivex.rxjava3.core.Observer; import io.reactivex.rxjava3.disposables.Disposable; +import static android.os.BatteryManager.EXTRA_LEVEL; +import static android.os.BatteryManager.EXTRA_VOLTAGE; + public class MainActivity extends BaseActivity implements MainAContact.MainView, NetworkUtils.OnNetworkStatusChangedListener { private static final String TAG = MainActivity.class.getSimpleName(); public static final String UPDATE_LOCKED_STATUS = "UPDATE_LOCKED_STATUS"; - @BindView(R.id.iv_head) - ImageView head; - @BindView(R.id.tv_devsn) - TextView tv_devsn; - @BindView(R.id.tv_imei2) - TextView tv_imei2; - @BindView(R.id.tv_devmac) - TextView tv_devmac; - @BindView(R.id.version) - TextView tv_version; - @BindView(R.id.tv_batch) - TextView tv_batch; - @BindView(R.id.tv_class_name) - TextView tv_class_name; - @BindView(R.id.tv_class) - TextView tv_class; - @BindView(R.id.tv_number_name) - TextView tv_number_name; - @BindView(R.id.tv_number) - TextView tv_number; - @BindView(R.id.tv_name) - TextView tv_name; - @BindView(R.id.tv_wifi) - TextView tv_wifi; - @BindView(R.id.chkupd) - Button bt_checkupdate; - // @BindView(R.id.checkupdate) -// ConstraintLayout checkupdate; @BindView(R.id.iv_back) ImageView back; - @BindView(R.id.iv_locked) - ImageView iv_locked; - @BindView(R.id.layout_class) - ConstraintLayout layout_class; - @BindView(R.id.layout_number) - ConstraintLayout layout_number; - @BindView(R.id.layout_name) - ConstraintLayout layout_name; - @BindView(R.id.cl_imei) - ConstraintLayout cl_imei; - @BindView(R.id.tv_customversion) - TextView tv_customversion; + @BindView(R.id.tv_version) + TextView tv_version; + @BindView(R.id.iv_head) + ImageView iv_head; + @BindView(R.id.tv_name) + TextView tv_name; + @BindView(R.id.tv_batch) + TextView tv_batch; + @BindView(R.id.tv_number) + TextView tv_number; + @BindView(R.id.tv_class) + TextView tv_class; + @BindView(R.id.tv_model) + TextView tv_model; + @BindView(R.id.cl_ota) + ConstraintLayout cl_ota; + @BindView(R.id.tv_system_version) + TextView tv_system_version; + + @BindView(R.id.tv_battery) + TextView tv_battery; + @BindView(R.id.tv_voltage) + TextView tv_voltage; + @BindView(R.id.tv_wifi) + TextView tv_wifi; + @BindView(R.id.tv_signal) + TextView tv_signal; + @BindView(R.id.tv_ip) + TextView tv_ip; + @BindView(R.id.tv_public_ip) + TextView tv_public_ip; + + @BindView(R.id.tv_serial) + TextView tv_serial; + @BindView(R.id.tv_imei) + TextView tv_imei; + @BindView(R.id.tv_mac) + TextView tv_mac; + + @BindView(R.id.tv_bind_statu) + TextView tv_bind_statu; @BindView(R.id.iv_qrcode) ImageView iv_qrcode; + @BindView(R.id.tv_bind_time) + TextView tv_bind_time; - @OnClick({R.id.iv_back, R.id.tv_title, R.id.chkupd}) +// @BindView(R.id.tv_class_name) +// TextView tv_class_name; +// @BindView(R.id.tv_number_name) +// TextView tv_number_name; +// @BindView(R.id.chkupd) +// Button bt_checkupdate; + // @BindView(R.id.checkupdate) +// ConstraintLayout checkupdate; +// @BindView(R.id.iv_locked) +// ImageView iv_locked; +// @BindView(R.id.layout_class) +// ConstraintLayout layout_class; +// @BindView(R.id.layout_number) +// ConstraintLayout layout_number; +// @BindView(R.id.layout_name) +// ConstraintLayout layout_name; +// @BindView(R.id.cl_imei) +// ConstraintLayout cl_imei; + + + @OnClick({R.id.iv_back, R.id.tv_title}) public void onClick(View view) { switch (view.getId()) { case R.id.iv_back: @@ -144,7 +177,6 @@ public class MainActivity extends BaseActivity implements MainAContact.MainView, @Override public void onConnected(NetworkUtils.NetworkType networkType) { Log.e("OnNetworkStatusChanged", "onConnected: "); - Utils.getPublicIP(this); } @Override @@ -161,11 +193,12 @@ public class MainActivity extends BaseActivity implements MainAContact.MainView, JGYUtils.startServices(MainActivity.this); getDevicesInfo(); if (Utils.isWifiAvailable(MainActivity.this)) { - tv_wifi.setText(Utils.obtainWifiInfo(MainActivity.this) + "dbm"); - }else { - tv_wifi.setText("未连接"); + tv_signal.setText(Utils.obtainWifiInfo(MainActivity.this) + "dbm"); + } else { + tv_signal.setText("未连接"); } - setStoreUpdateListener(bt_checkupdate); +// setStoreUpdateListener(bt_checkupdate); + registerReceiver(); } private void setStoreUpdateListener(View view) { @@ -194,7 +227,7 @@ public class MainActivity extends BaseActivity implements MainAContact.MainView, public void onNext(@NonNull View view) { Log.e("mObserver", "onNext"); ToastUtil.show("正在检查更新"); - mMainAPresenter.buttonCheckUpdate(bt_checkupdate); +// mMainAPresenter.buttonCheckUpdate(bt_checkupdate); } @Override @@ -216,34 +249,39 @@ public class MainActivity extends BaseActivity implements MainAContact.MainView, } private void getDevicesInfo() { + tv_model.setText(Build.MODEL); String sn = Utils.getSerial(this); - tv_devsn.setText(sn); + tv_serial.setText(sn); getIMEI(); - checkSNError(sn); - String macaddr = Utils.getAndroid10MAC(this); - if (TextUtils.isEmpty(macaddr)) { - tv_devmac.setText("获取失败"); - } else { - tv_devmac.setText(macaddr); - } + setMac(); + checkSnError(sn); tv_version.setText(BuildConfig.VERSION_NAME); //获取自定义版本号 Log.e(TAG, "getDevicesInfo: CustomVersion: " + Utils.getCustomVersion()); Log.e(TAG, "getDevicesInfo: RomVersion: " + Utils.getRomVersion()); - tv_customversion.setText(Utils.getCustomVersion()); + tv_system_version.setText(Utils.getCustomVersion()); } private void getIMEI() { if (!Utils.NOSN.equalsIgnoreCase(Utils.getSerial())) { - tv_imei2.setText(Utils.getIMEI(this, 1)); + tv_imei.setText(Utils.getIMEI(this, 1)); } else { if (!TextUtils.isEmpty(Utils.getIMEI(this, 1))) { - tv_imei2.setText(Utils.getIMEI(this, 1)); + tv_imei.setText(Utils.getIMEI(this, 1)); } } } - private void checkSNError(String sn) { + private void setMac() { + String macaddr = Utils.getAndroid10MAC(this); + if (TextUtils.isEmpty(macaddr)) { + tv_mac.setText("获取失败"); + } else { + tv_mac.setText(macaddr); + } + } + + private void checkSnError(String sn) { //sn长度最长30位 if (sn.length() > 30) { showSNErrorDialog("设备SN号码格式错误!"); @@ -302,23 +340,23 @@ public class MainActivity extends BaseActivity implements MainAContact.MainView, public void setLockedState(boolean loocked) { Log.e(TAG, "setLockedState: " + loocked); if (loocked) { - iv_locked.setVisibility(View.VISIBLE); - iv_locked.setImageDrawable(getDrawable(R.drawable.locked)); - mMainAPresenter.getStudesInfo(false); +// iv_locked.setVisibility(View.VISIBLE); +// iv_locked.setImageDrawable(getDrawable(R.drawable.locked)); + mMainAPresenter.getStudesInfo(); } else { - iv_locked.setVisibility(View.VISIBLE); - iv_locked.setImageDrawable(getDrawable(R.drawable.unlock)); +// iv_locked.setVisibility(View.VISIBLE); +// iv_locked.setImageDrawable(getDrawable(R.drawable.unlock)); setNumberText("", View.GONE); setNameText("", View.GONE); setClassText("", View.GONE); setBatchText("", View.GONE); SysSettingUtils.setEnableSetting(this); } - mMainAPresenter.getQRCode(loocked); + mMainAPresenter.getQrCode(loocked); } @Override - public void setQRCode(Bitmap qrcode) { + public void setQrCode(Bitmap qrcode) { iv_qrcode.setImageBitmap(qrcode); } @@ -357,21 +395,28 @@ public class MainActivity extends BaseActivity implements MainAContact.MainView, setBatchText(batch, View.VISIBLE); } if (TextUtils.isEmpty(head_img)) { - setHead(""); + setIv_head(""); } else { - setHead(head_img); + setIv_head(head_img); } SPUtils.put(this, CommonConfig.ADMIN_ID, studesInfo.getAdmin_id()); } + @Override + public void setPublicIp(String ip) { + Log.e(TAG, "setPublicIp: " + ip); + tv_public_ip.setText(ip); + mMainAPresenter.checkAoleyunUpdate(); + } + public void settradeType(int tradeType) { - if (tradeType == 1) { - tv_class_name.setText("班级"); - tv_number_name.setText("学号"); - } else if (tradeType == 2) { - tv_class_name.setText("部门"); - tv_number_name.setText("工号"); - } +// if (tradeType == 1) { +// tv_class_name.setText("班级"); +// tv_number_name.setText("学号"); +// } else if (tradeType == 2) { +// tv_class_name.setText("部门"); +// tv_number_name.setText("工号"); +// } } public void setBatchText(String text, int visibility) { @@ -394,11 +439,11 @@ public class MainActivity extends BaseActivity implements MainAContact.MainView, // layout_name.setVisibility(visibility); } - public void setHead(String url) { + public void setIv_head(String url) { if (TextUtils.isEmpty(url)) { - Glide.with(head).load(getDrawable(R.drawable.head)).into(head); + Glide.with(iv_head).load(getDrawable(R.drawable.default_head)).into(iv_head); } else { - Glide.with(head).load(url).into(head); + Glide.with(iv_head).load(url).error(R.drawable.default_head).into(iv_head); } } @@ -407,7 +452,7 @@ public class MainActivity extends BaseActivity implements MainAContact.MainView, public void buttonCheckUpdateFinish(boolean update, JsonObject jsonObject) { this.updateApp = !update; if (update) { - showDialog(jsonObject); + showUpdateDialog(jsonObject); } else { Observable.timer(5000, TimeUnit.MILLISECONDS) .observeOn(AndroidSchedulers.mainThread()) @@ -415,30 +460,66 @@ public class MainActivity extends BaseActivity implements MainAContact.MainView, } } - private void showDialog(JsonObject jsonObject) { - AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setTitle("更新:"); - builder.setMessage("检测到有新版本,是否更新?"); - builder.setIcon(R.mipmap.ic_launcher); - builder.setCancelable(true); - //设置正面按钮 - builder.setPositiveButton("更新", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - JGYUtils.getInstance().installAPK(jsonObject); - dialog.dismiss(); - } - }); - //设置反面按钮 - builder.setNegativeButton("取消", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - dialog.dismiss(); - } - }); - builder.show(); + @Override + public void checkAoleyunUpdateFinish() { + mMainAPresenter.checkTestUpdate(); } + @Override + public void checkTestUpdateFinish() { + + } + + private void showUpdateDialog(JsonObject jsonObject) { + UpdateDialog dialog = new UpdateDialog(this); + dialog.setMessage(String.format(getString(R.string.upgrade_app), jsonObject.get("version_name").getAsString())) + .setTitle("版本更新") + .setPositive("确定") + .setSingle(true) + .setOnClickBottomListener(new UpdateDialog.OnClickBottomListener() { + @Override + public void onPositiveClick() { + JGYUtils.getInstance().installAPK(jsonObject); + dialog.dismiss(); + } + + @Override + public void onNegtiveClick() { + dialog.dismiss(); + } + }); + dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); + dialog.show(); + dialog.getWindow().setGravity(Gravity.CENTER); + dialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); + dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); + dialog.setCancelable(false); + } + +// private void showDialog(JsonObject jsonObject) { +// AlertDialog.Builder builder = new AlertDialog.Builder(this); +// builder.setTitle("版本更新"); +// builder.setMessage(String.format(getString(R.string.upgrade_app),jsonObject.get("version_code").getAsString())); +// builder.setIcon(R.mipmap.ic_launcher); +// builder.setCancelable(true); +// //设置正面按钮 +// builder.setPositiveButton("更新", new DialogInterface.OnClickListener() { +// @Override +// public void onClick(DialogInterface dialog, int which) { +// JGYUtils.getInstance().installAPK(jsonObject); +// dialog.dismiss(); +// } +// }); +// //设置反面按钮 +// builder.setNegativeButton("取消", new DialogInterface.OnClickListener() { +// @Override +// public void onClick(DialogInterface dialog, int which) { +// dialog.dismiss(); +// } +// }); +// builder.show(); +// } + @Override protected void onStop() { super.onStop(); @@ -465,6 +546,7 @@ public class MainActivity extends BaseActivity implements MainAContact.MainView, super.onDestroy(); mMainAPresenter.detachView(); mMainAPresenter = null; + unregister(); JGYUtils.startServices(MainActivity.this); } @@ -488,6 +570,20 @@ public class MainActivity extends BaseActivity implements MainAContact.MainView, } } + private void registerReceiver() { + registerWiFiReceiver(); + registerBatteryReceiver(); + } + + private void unregister() { + if (mWifiReceiver != null) { + unregisterReceiver(mWifiReceiver); + } + if (mBatteryReceiver != null) { + unregisterReceiver(mBatteryReceiver); + } + } + private UpdateReceiver mUpdateReceiver; private void registerUpdateReceiver() { @@ -505,19 +601,124 @@ public class MainActivity extends BaseActivity implements MainAContact.MainView, if (UPDATE_LOCKED_STATUS.equals(intent.getAction())) { int locked = Settings.System.getInt(getContentResolver(), JGYActions.ACTION_QCH_UNLOCK_IPAD, JGYActions.FRAME_CODE_LOCKED); if (locked == JGYActions.FRAME_CODE_LOCKED) { - iv_locked.setVisibility(View.VISIBLE); - iv_locked.setImageDrawable(getDrawable(R.drawable.locked)); +// iv_locked.setVisibility(View.VISIBLE); +// iv_locked.setImageDrawable(getDrawable(R.drawable.locked)); } else { - iv_locked.setVisibility(View.VISIBLE); - iv_locked.setImageDrawable(getDrawable(R.drawable.unlock)); +// iv_locked.setVisibility(View.VISIBLE); +// iv_locked.setImageDrawable(getDrawable(R.drawable.unlock)); setNumberText("", View.GONE); setNameText("", View.GONE); setClassText("", View.GONE); setBatchText("", View.GONE); - Glide.with(head).load(getDrawable(R.drawable.head)).into(head); + Glide.with(iv_head).load(getDrawable(R.drawable.default_head)).error(R.drawable.default_head).into(iv_head); SysSettingUtils.setEnableSetting(MainActivity.this); } } } } + + private WifiReceiver mWifiReceiver; + + private void registerWiFiReceiver() { + if (mWifiReceiver == null) { + mWifiReceiver = new WifiReceiver(); + } + IntentFilter filter = new IntentFilter(); + filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); + filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); + filter.addAction(WifiManager.RSSI_CHANGED_ACTION); + filter.addAction(WifiManager.NETWORK_IDS_CHANGED_ACTION); + filter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); + filter.addAction(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION); + filter.addAction(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION); + filter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION); + filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); + registerReceiver(mWifiReceiver, filter); + } + + public class WifiReceiver extends BroadcastReceiver { + private static final String TAG = "wifiReceiver"; + + @Override + public void onReceive(Context context, Intent intent) { + switch (intent.getAction()) { + case WifiManager.RSSI_CHANGED_ACTION: + int rssi = intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, -1); + tv_signal.setText(rssi + "dBm"); + //这函数可以计算出信号的等级 + int strength = WifiManager.calculateSignalLevel(rssi, 5); + Log.e(TAG, "wifi信号强度变化"); + break; + //wifi连接上与否 + case WifiManager.NETWORK_STATE_CHANGED_ACTION: + NetworkInfo info = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO); + if (info.getState().equals(NetworkInfo.State.DISCONNECTED)) { + Log.e(TAG, getString(R.string.wifi_disconnected)); + tv_wifi.setText(getString(R.string.wifi_disconnected)); + tv_signal.setText(""); + tv_ip.setText(getString(R.string.unknown)); + } else if (info.getState().equals(NetworkInfo.State.CONNECTED)) { + WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); + WifiInfo wifiInfo = wifiManager.getConnectionInfo(); + //获取当前wifi名称 + String newSSID = wifiInfo.getSSID(); + tv_wifi.setText(newSSID); + tv_ip.setText(Formatter.formatIpAddress(wifiInfo.getIpAddress())); + setMac(); + Log.e(TAG, "连接到网络 " + newSSID); + } + break; + //wifi打开与否 + case WifiManager.WIFI_STATE_CHANGED_ACTION: + int wifistate = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_DISABLED); + if (wifistate == WifiManager.WIFI_STATE_DISABLED) { +// tv_wifi.setText(getString(R.string.turn_off_wifi)); + Log.e(TAG, getString(R.string.turn_off_wifi)); + } else if (wifistate == WifiManager.WIFI_STATE_ENABLED) { +// tv_wifi.setText(getString(R.string.turn_on_wifi)); + Log.e(TAG, getString(R.string.turn_on_wifi)); + mMainAPresenter.getPublicIp(); + } + break; + default: + } + } + } + + private BatteryReceiver mBatteryReceiver; + + private void registerBatteryReceiver() { + if (mBatteryReceiver == null) { + mBatteryReceiver = new BatteryReceiver(); + } + IntentFilter filter = new IntentFilter(); + filter.addAction(Intent.ACTION_BATTERY_CHANGED); + registerReceiver(mBatteryReceiver, filter); + } + + private class BatteryReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + if (null == intent) { + return; + } + String action = intent.getAction(); + if (Intent.ACTION_BATTERY_CHANGED.equals(action)) { + int level = intent.getIntExtra(EXTRA_LEVEL, 0); + int batteryVolt = intent.getIntExtra(EXTRA_VOLTAGE, -1); + String levelStr = getLevel(level); + tv_battery.setText("电量:" + levelStr); + String batteryVoltStr = getBatteryVolt(batteryVolt); + tv_voltage.setText("电压:" + batteryVoltStr); + } + } + } + + private String getLevel(int level) { + return String.format("%d %%", level); + } + + private String getBatteryVolt(int batteryVolt) { + return String.format("%.3f V", batteryVolt / 1000.0); + } } diff --git a/app/src/main/java/com/aoleyun/sn/base/BaseApplication.java b/app/src/main/java/com/aoleyun/sn/base/BaseApplication.java index 178a5da..f619d55 100644 --- a/app/src/main/java/com/aoleyun/sn/base/BaseApplication.java +++ b/app/src/main/java/com/aoleyun/sn/base/BaseApplication.java @@ -9,8 +9,6 @@ import android.util.Log; import androidx.multidex.MultiDexApplication; -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; import com.aoleyun.sn.BuildConfig; import com.aoleyun.sn.bean.BaseResponse; import com.aoleyun.sn.manager.MapManager; diff --git a/app/src/main/java/com/aoleyun/sn/bean/AppUpdateInfo.java b/app/src/main/java/com/aoleyun/sn/bean/AppUpdateInfo.java index e64802f..4bfbd7e 100644 --- a/app/src/main/java/com/aoleyun/sn/bean/AppUpdateInfo.java +++ b/app/src/main/java/com/aoleyun/sn/bean/AppUpdateInfo.java @@ -12,6 +12,7 @@ public class AppUpdateInfo implements Serializable { int id; String url; long version_code; + String version_name; String app_name; @SerializedName("package") String packages; @@ -41,6 +42,14 @@ public class AppUpdateInfo implements Serializable { this.version_code = version_code; } + public String getVersion_name() { + return version_name; + } + + public void setVersion_name(String version_name) { + this.version_name = version_name; + } + public String getApp_name() { return app_name; } diff --git a/app/src/main/java/com/aoleyun/sn/comm/CommonConfig.java b/app/src/main/java/com/aoleyun/sn/comm/CommonConfig.java index 2dbddca..0f59d13 100644 --- a/app/src/main/java/com/aoleyun/sn/comm/CommonConfig.java +++ b/app/src/main/java/com/aoleyun/sn/comm/CommonConfig.java @@ -48,7 +48,7 @@ public class CommonConfig { /*上次检查更新时间*/ public final static String LAST_CHECK_ALL_UPDATE_TIME = "lastCheckAllUpdateTime"; /*获取设备的标签*/ - public final static String DEVICES_TAG = "Aoleyun_devices_tag"; + public final static String DEVICES_TAG = "Aoleyun_devices_tpush_tag"; /*上次获取标签的时间*/ public final static String GET_DEVICES_TAG_LASTTIME = "Aoleyun_devices_tag_last_time"; diff --git a/app/src/main/java/com/aoleyun/sn/dialog/UpdateDialog.java b/app/src/main/java/com/aoleyun/sn/dialog/UpdateDialog.java new file mode 100644 index 0000000..fa1b6a2 --- /dev/null +++ b/app/src/main/java/com/aoleyun/sn/dialog/UpdateDialog.java @@ -0,0 +1,197 @@ +package com.aoleyun.sn.dialog; + + +import android.content.Context; +import android.os.Bundle; +import android.text.TextUtils; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.appcompat.app.AlertDialog; + +import com.aoleyun.sn.R; + + +/** + * description:自定义dialog + */ + +public class UpdateDialog extends AlertDialog { + /** + * 显示的标题 + */ + private TextView titleTv; + + /** + * 显示的消息 + */ + private TextView messageTv; + + /** + * 确认和取消按钮 + */ + private TextView positiveBn; + + /** + * 按钮之间的分割线 + */ +// private View columnLineView; + + private Context mContext; + + public UpdateDialog(Context context) { + super(context, R.style.CustomDialog); + this.mContext = context; + } + + /** + * 都是内容数据 + */ + private String message; + private String title; + private String positive; + private int imageResId = -1; + + /** + * 底部是否只有一个按钮 + */ + private boolean isSingle = false; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.update_dialog); + //按空白处不能取消动画 + setCanceledOnTouchOutside(false); + //初始化界面控件 + initView(); + //初始化界面数据 + refreshView(); + //初始化界面控件的事件 + initEvent(); + } + + /** + * 初始化界面的确定和取消监听器 + */ + private void initEvent() { + //设置确定按钮被点击后,向外界提供监听 + positiveBn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (onClickBottomListener != null) { + onClickBottomListener.onPositiveClick(); + } + } + }); + } + + /** + * 初始化界面控件的显示数据 + */ + private void refreshView() { + //如果用户自定了title和message + if (!TextUtils.isEmpty(title)) { + titleTv.setText(title); + titleTv.setVisibility(View.VISIBLE); + } else { + titleTv.setVisibility(View.GONE); + } + if (!TextUtils.isEmpty(message)) { + messageTv.setText(message); + } + //如果设置按钮的文字 + if (!TextUtils.isEmpty(positive)) { + positiveBn.setText(positive); + } else { + positiveBn.setText("确定"); + } + } + + @Override + public void show() { + super.show(); + refreshView(); + } + + /** + * 初始化界面控件 + */ + private void initView() { + positiveBn = findViewById(R.id.positive); + titleTv = findViewById(R.id.title); + messageTv = findViewById(R.id.message); + } + + /** + * 设置确定取消按钮的回调 + */ + private OnClickBottomListener onClickBottomListener; + + public void setOnClickBottomListener(OnClickBottomListener onClickBottomListener) { + this.onClickBottomListener = onClickBottomListener; + } + + public interface OnClickBottomListener { + /** + * 点击确定按钮事件 + */ + void onPositiveClick(); + + /** + * 点击取消按钮事件 + */ + void onNegtiveClick(); + } + + public String getMessage() { + return message; + } + + public UpdateDialog setMessage(String message) { + this.message = message; + return this; + } + + public String getTitle() { + return title; + } + + public UpdateDialog setTitle(String title) { + this.title = title; + return this; + } + + public String getPositive() { + return positive; + } + + public UpdateDialog setPositive(String positive) { + this.positive = positive; + return this; + } + + public int getImageResId() { + return imageResId; + } + + public boolean isSingle() { + return isSingle; + } + + public UpdateDialog setSingle(boolean single) { + isSingle = single; + return this; + } + + public UpdateDialog setImageResId(int imageResId) { + this.imageResId = imageResId; + return this; + } + + @Override + public void dismiss() { + super.dismiss(); + } +} diff --git a/app/src/main/java/com/aoleyun/sn/network/NetInterfaceManager.java b/app/src/main/java/com/aoleyun/sn/network/NetInterfaceManager.java index 9aba943..334d860 100644 --- a/app/src/main/java/com/aoleyun/sn/network/NetInterfaceManager.java +++ b/app/src/main/java/com/aoleyun/sn/network/NetInterfaceManager.java @@ -49,7 +49,6 @@ import com.aoleyun.sn.gson.GsonUtils; import com.aoleyun.sn.gson.NullStringToEmptyAdapterFactory; import com.aoleyun.sn.manager.ConnectManager; import com.aoleyun.sn.manager.ConnectMode; -import com.aoleyun.sn.network.api.GetPublicIPApi; import com.aoleyun.sn.network.api.GetWhoisApi; import com.aoleyun.sn.network.api.get.CheckTestUpdateApi; import com.aoleyun.sn.network.api.get.DefaultAppApi; @@ -590,9 +589,9 @@ public class NetInterfaceManager { .observeOn(AndroidSchedulers.mainThread()); } - public Observable GetNetworkConnectControl() { + public Observable GetNetworkConnectControl(String time) { return mRetrofit.create(NetworkConnectApi.class) - .sendNetwork(Utils.getSerial(mContext)) + .sendNetwork(Utils.getSerial(mContext), time) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); } @@ -1594,6 +1593,9 @@ public class NetInterfaceManager { @Override public void onComplete() { Log.e("getSnAppAttr", "onComplete: "); + if (onCompleteCallback != null) { + onCompleteCallback.onComplete(); + } } }; } @@ -1826,9 +1828,9 @@ public class NetInterfaceManager { * @param studesInfoListener */ public void getStudesInfo(boolean refresh, BehaviorSubject lifecycle, StudesInfoListener studesInfoListener) { - ConnectMode connectMode = ConnectMode.FIFTEEN_MINUTES; + ConnectMode connectMode = ConnectMode.ONE_MINUTE; if (refresh) { - connectMode = ConnectMode.ONE_MINUTE; + connectMode = ConnectMode.DEFAULT; } if (ConnectManager.getInstance().isNeedConnect(UrlAddress.GET_STUDENTS_INFO, connectMode)) { getInfo(lifecycle, studesInfoListener); @@ -1903,23 +1905,23 @@ public class NetInterfaceManager { .subscribe(new Observer() { @Override public void onSubscribe(@NonNull Disposable d) { - Log.e(TAG + ":" + "getLockedState", "onSubscribe: "); + Log.e("getLockedState", "onSubscribe: "); } @Override public void onNext(@NonNull BaseResponse response) { - Log.e(TAG + ":" + "getLockedState", "onNext: " + response); + Log.e("getLockedState", "onNext: " + response); if (response.code == OK) { JsonObject jsonObject = JsonParser.parseString(new Gson().toJson(response.data)).getAsJsonObject(); int locked = jsonObject.get("lock").getAsInt(); - Log.e(TAG + ":" + "getLockedState", "locked: " + locked); + Log.e("getLockedState", "locked: " + locked); // int oldState = Settings.System.getInt(mContext.getContentResolver(), JGYActions.ACTION_QCH_UNLOCK_IPAD, JGYActions.FRAME_CODE_LOCKED); -// Log.e(TAG + ":" + "getLockedState", "qch_unlock_ipad: " + oldState); +// Log.e( "getLockedState", "qch_unlock_ipad: " + oldState); //后台1是锁定,底层0是锁定 SPUtils.put(mContext, CommonConfig.JGY_FIRST_CONNECT, 1); if (locked == JGYActions.NET_CODE_LOCKED) { // if (oldState == JGYActions.FRAME_CODE_UNLOCKED) { -// Log.e(TAG + ":" + "getLockedState", "onNext: " + "state changed , reset devices"); +// Log.e( "getLockedState", "onNext: " + "state changed , reset devices"); // Utils.doMasterClear(mContext); // } Settings.System.putInt(mContext.getContentResolver(), JGYActions.ACTION_QCH_UNLOCK_IPAD, JGYActions.FRAME_CODE_LOCKED); @@ -1929,19 +1931,19 @@ public class NetInterfaceManager { } } else if (response.code == NOTFOUND) { Settings.System.putInt(mContext.getContentResolver(), JGYActions.ACTION_QCH_UNLOCK_IPAD, JGYActions.FRAME_CODE_LOCKED); - Log.e(TAG + ":" + "getLockedState", "locked: " + false); + Log.e("getLockedState", "locked: " + false); } } @Override public void onError(@NonNull Throwable e) { - Log.e(TAG + ":" + "getLockedState", "onError: " + e.getMessage()); + Log.e("getLockedState", "onError: " + e.getMessage()); onComplete(); } @Override public void onComplete() { - Log.e(TAG + ":" + "getLockedState", "onComplete: "); + Log.e("getLockedState", "onComplete: "); callback.onComplete(); } }); @@ -2018,91 +2020,82 @@ public class NetInterfaceManager { }); } + public interface PushTagCallback { + void setPushTag(String tag); + } - synchronized public void setPushTags(boolean refresh, BehaviorSubject lifecycle, onCompleteCallback callback) { - ConnectMode connectMode = ConnectMode.ONCE; + public void setPushTags(boolean refresh, BehaviorSubject lifecycle, PushTagCallback callback) { + ConnectMode connectMode = ConnectMode.ONE_DAY; if (refresh) { - connectMode = ConnectMode.ONE_DAY; + connectMode = ConnectMode.SIX_HOUR; } if (ConnectManager.getInstance().isNeedConnect(UrlAddress.GET_DEVICES_TAGS, connectMode)) { setPushTags(lifecycle, callback); } else { - String jsonString = cacheHelper.getAsString(UrlAddress.GET_DEVICES_TAGS); + String batch = mMMKV.decodeString(CommonConfig.DEVICES_TAG, ""); //为 "" 是已经请求成功的 - if (jsonString == null) { + if (TextUtils.isEmpty(batch)) { setPushTags(lifecycle, callback); } else { - Set tagSets = mMMKV.decodeStringSet(CommonConfig.DEVICES_TAG + "pushset"); - Log.e("setPushTags", "tagSets: " + tagSets); - clearAndAppendTags(tagSets); - callback.onComplete(); + Log.e("setPushTags", "tagSets: " + batch); + callback.setPushTag(batch); } } } + /** * 设置推送的标签 * * @param lifecycle * @param callback */ - synchronized public void setPushTags(BehaviorSubject lifecycle, onCompleteCallback callback) { - Set set = new HashSet<>(); - JGYUtils.getInstance().getAppPlatform(new JGYUtils.GetAppPlatformCallback() { - @Override - public void AppPlatform(int platform) { - if (platform == JGYUtils.MTKPlatform) { - set.add(JGYUtils.MTKTag); - } else if (platform == JGYUtils.ZhanruiPlatform) { - set.add(JGYUtils.ZhanruiTag); - } else if (platform == JGYUtils.CubePlatform) { - set.add(JGYUtils.CubeTag); - } - } - }); + public void setPushTags(BehaviorSubject lifecycle, PushTagCallback callback) { getPushTagsObservable() .compose(RxLifecycle.bindUntilEvent(lifecycle, ActivityEvent.DESTROY)) .subscribe(new Observer>() { @Override public void onSubscribe(@NonNull Disposable d) { - Log.e(TAG + ":" + "setPushTags", "onSubscribe: "); + Log.e("setPushTags", "onSubscribe: "); } @Override public void onNext(@NonNull BaseResponse response) { if (response.code == OK) { - String batch = response.data.getBatch(); cacheHelper.put(UrlAddress.GET_DEVICES_TAGS, GsonUtils.toJSONString(response.data)); - Log.e(TAG + ":" + "setPushTags", "onNext: " + batch); - if (!TextUtils.isEmpty(batch)) { - set.add(batch); + String batch = response.data.getBatch(); + Log.e("setPushTags", "onNext: " + batch); + if (TextUtils.isEmpty(batch)) { + Log.e("setPushTags", "onNext: " + "batch empty"); + callback.setPushTag(""); } else { - Log.e(TAG + ":" + "setPushTags", "onNext: " + "batch empty"); + callback.setPushTag(batch); + mMMKV.encode(CommonConfig.DEVICES_TAG, batch); } } else { cacheHelper.put(UrlAddress.GET_DEVICES_TAGS, ""); - Log.e(TAG + ":" + "setPushTags", "onNext: " + response.toString()); + callback.setPushTag(""); + Log.e("setPushTags", "onNext: " + response.toString()); } - mMMKV.encode(CommonConfig.DEVICES_TAG + "pushset", set); } @Override public void onError(@NonNull Throwable e) { - Log.e(TAG + ":" + "setPushTags", "onError: " + e.getMessage()); + Log.e("setPushTags", "onError: " + e.getMessage()); + String batch = mMMKV.decodeString(CommonConfig.DEVICES_TAG, ""); + Log.e("setPushTags", "tagSets: " + batch); + callback.setPushTag(batch); onComplete(); } @Override public void onComplete() { - Log.e(TAG + ":" + "setPushTags", "onComplete: "); - Log.e("setPushTags", "tagSets: " + set); - clearAndAppendTags(set); - callback.onComplete(); + Log.e("setPushTags", "onComplete: "); } }); } - synchronized private void clearAndAppendTags(Set tagSets) { + public void clearAndAppendTags(Set tagSets) { XGPushManager.clearAndAppendTags(mContext, "clearAndAppendTags :" + System.currentTimeMillis(), tagSets, new XGIOperateCallback() { @Override public void onSuccess(Object o, int i) { @@ -2118,7 +2111,7 @@ public class NetInterfaceManager { public void updateDeviceInfo(boolean refresh, BehaviorSubject lifecycle, onCompleteCallback callback) { - ConnectMode connectMode = ConnectMode.SIX_HOUR; + ConnectMode connectMode = ConnectMode.ONE_MINUTE; if (refresh) { connectMode = ConnectMode.DEFAULT; } @@ -2328,7 +2321,7 @@ public class NetInterfaceManager { } public void getBookMarkBlackWhiteList(boolean refresh, BehaviorSubject lifecycle, onCompleteCallback callback) { - ConnectMode connectMode = ConnectMode.ONE_HOUR; + ConnectMode connectMode = ConnectMode.ONE_MINUTE; if (refresh) { connectMode = ConnectMode.DEFAULT; } @@ -2585,9 +2578,9 @@ public class NetInterfaceManager { listener.setScreenLockState(false, ""); return; } - ConnectMode connectMode = ConnectMode.SIX_HOUR; + ConnectMode connectMode = ConnectMode.ONE_MINUTE; if (refresh) { - connectMode = ConnectMode.ONE_HOUR; + connectMode = ConnectMode.DEFAULT; } if (ConnectManager.getInstance().isNeedConnect(UrlAddress.GET_LOCK_SCREEN_STATE, connectMode)) { getScreenLock(lifecycle, listener); @@ -2646,9 +2639,9 @@ public class NetInterfaceManager { } public void getAppLimit(boolean refresh, BehaviorSubject lifecycle, onCompleteCallback callback) { - ConnectMode connectMode = ConnectMode.HALF_DAY; + ConnectMode connectMode = ConnectMode.ONE_MINUTE; if (refresh) { - connectMode = ConnectMode.SIX_HOUR; + connectMode = ConnectMode.DEFAULT; } if (ConnectManager.getInstance().isNeedConnect(UrlAddress.SET_WHITE_PACKAGE_LIST, connectMode)) { getAppLimit(lifecycle, callback); @@ -2732,9 +2725,9 @@ public class NetInterfaceManager { * 获取所有app详细信息 */ public void getAllAppList(boolean refresh, BehaviorSubject lifecycle, onCompleteCallback callback) { - ConnectMode connectMode = ConnectMode.ONE_HOUR; + ConnectMode connectMode = ConnectMode.ONE_MINUTE; if (refresh) { - connectMode = ConnectMode.HALF_HOUR; + connectMode = ConnectMode.DEFAULT; } if (ConnectManager.getInstance().isNeedConnect(UrlAddress.GET_ALL_APP, connectMode)) { getAllAppList(lifecycle, callback); @@ -2807,9 +2800,9 @@ public class NetInterfaceManager { public void getSnTimeControl(boolean refresh, BehaviorSubject lifecycle, onCompleteCallback callback) { - ConnectMode connectMode = ConnectMode.SIX_HOUR; + ConnectMode connectMode = ConnectMode.ONE_MINUTE; if (refresh) { - connectMode = ConnectMode.ONE_HOUR; + connectMode = ConnectMode.DEFAULT; } if (ConnectManager.getInstance().isNeedConnect(UrlAddress.GET_SN_TIME_CONTROL, connectMode)) { getSnTimeControl(lifecycle, callback); @@ -2960,9 +2953,9 @@ public class NetInterfaceManager { } public void getTopApp(boolean refresh, BehaviorSubject lifecycle, onCompleteCallback callback) { - ConnectMode connectMode = ConnectMode.HALF_DAY; + ConnectMode connectMode = ConnectMode.ONE_MINUTE; if (refresh) { - connectMode = ConnectMode.SIX_HOUR; + connectMode = ConnectMode.DEFAULT; } if (ConnectManager.getInstance().isNeedConnect(UrlAddress.GET_TOP_APP_CONTROL, connectMode)) { getTopApp(lifecycle, callback); @@ -3099,7 +3092,7 @@ public class NetInterfaceManager { } public void getPoweroffTime(boolean refresh, BehaviorSubject lifecycle, onCompleteCallback callback) { - ConnectMode connectMode = ConnectMode.ONE_HOUR; + ConnectMode connectMode = ConnectMode.ONE_MINUTE; if (refresh) { connectMode = ConnectMode.DEFAULT; } @@ -3176,7 +3169,7 @@ public class NetInterfaceManager { public void getWiFiPasswd(boolean refresh, BehaviorSubject lifecycle, onCompleteCallback callback) { - ConnectMode connectMode = ConnectMode.ONE_HOUR; + ConnectMode connectMode = ConnectMode.ONE_MINUTE; if (refresh) { connectMode = ConnectMode.DEFAULT; } @@ -3198,21 +3191,18 @@ public class NetInterfaceManager { } public void getWiFiPasswd(BehaviorSubject lifecycle, onCompleteCallback callback) { - NetInterfaceManager.getInstance() - .getWiFiControl() + getWiFiControl() .compose(RxLifecycle.bindUntilEvent(lifecycle, ActivityEvent.DESTROY)) .subscribe(getWiFiPasswdObserver(callback)); } public void getWiFiPasswd(onCompleteCallback callback) { - NetInterfaceManager.getInstance() - .getWiFiControl() + getWiFiControl() .subscribe(getWiFiPasswdObserver(callback)); } public void getWiFiPasswd() { - NetInterfaceManager.getInstance() - .getWiFiControl() + getWiFiControl() .subscribe(getWiFiPasswdObserver(null)); } @@ -3308,73 +3298,8 @@ public class NetInterfaceManager { }); } - - public interface PublicIP { - void set(String ip); - } - public static final String PublicIP = "PublicIP"; - /** - * 获取设备公网IP - * - * @param publicIP - */ - private static String IpAddr = ""; - - public static void getPublicIP(PublicIP publicIP) { - Retrofit retrofit = new Retrofit.Builder() - .client(NetInterfaceManager.getInstance().getOkHttpClient()) - .baseUrl(UrlAddress.SHOUHU_CITYJSON) - .addConverterFactory(GsonConverterFactory.create()) - .addCallAdapterFactory(RxJava3CallAdapterFactory.create()) - .build(); - retrofit.create(GetPublicIPApi.class) - .getPublicIP() - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new Observer() { - @Override - public void onSubscribe(Disposable d) { - Log.e("getPublicIP", "onSubscribe: "); - } - - @Override - public void onNext(ResponseBody responseBody) { - try { - String s = responseBody.string(); - Log.e("getPublicIP", "onNext: " + s); - if (!TextUtils.isEmpty(s)) { - //var returnCitySN = {"cip": "183.11.74.141", "cid": "440300", "cname": "广东省深圳市"}; - if (s.contains("{")) { - String jsonString = s.substring(s.indexOf("{"), s.lastIndexOf("}") + 1); - JsonObject jsonObject = JsonParser.parseString(jsonString).getAsJsonObject(); - String ip = jsonObject.get("cip").getAsString(); - if (!TextUtils.isEmpty(ip)) { - IpAddr = ip; - } - } - } - } catch (IOException e) { - e.printStackTrace(); - Log.e("getPublicIP", "IOException: " + e.getMessage()); - } - } - - @Override - public void onError(Throwable e) { - Log.e("getPublicIP", "onError: " + e.getMessage()); - } - - @Override - public void onComplete() { - Log.e("getPublicIP", "onComplete: "); - MMKV.defaultMMKV().encode(NetInterfaceManager.PublicIP, IpAddr); - publicIP.set(IpAddr); - } - }); - } - public static final String WHOIS_ADDR = "whois_ip_addr"; public static void GetWhois() { @@ -3565,4 +3490,53 @@ public class NetInterfaceManager { } }); } + + public static final String WHOIS_IP = "whois_ip_addr"; + + public interface PublicIpCallbak { + void getPublicIp(String ip); + } + + public void getPublicIp(BehaviorSubject lifecycle, PublicIpCallbak callbak) { + Retrofit retrofit = new Retrofit.Builder() + .client(NetInterfaceManager.getInstance().getOkHttpClient()) + .baseUrl(UrlAddress.PCONLINE_WHOIS) + .addConverterFactory(GsonConverterFactory.create()) + .addCallAdapterFactory(RxJava3CallAdapterFactory.create()) + .build(); + retrofit.create(GetWhoisApi.class) + .getWhois(true) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .compose(RxLifecycle.bindUntilEvent(lifecycle, ActivityEvent.DESTROY)) + .subscribe(new Observer() { + @Override + public void onSubscribe(@NonNull Disposable d) { + Log.e("getPublicIp", "onSubscribe: "); + } + + @Override + public void onNext(@NonNull WhoisBean whoisBean) { + Log.e("getPublicIp", "onNext: " + whoisBean); + if (whoisBean != null && !TextUtils.isEmpty(whoisBean.getIp())) { + callbak.getPublicIp(whoisBean.getIp()); + MMKV.defaultMMKV().encode(NetInterfaceManager.WHOIS_IP, whoisBean.getIp()); + } else { + callbak.getPublicIp("unknown"); + } + } + + @Override + public void onError(@NonNull Throwable e) { + Log.e("getPublicIp", "onError: "); + callbak.getPublicIp("unknown"); + onComplete(); + } + + @Override + public void onComplete() { + Log.e("getPublicIp", "onComplete: "); + } + }); + } } diff --git a/app/src/main/java/com/aoleyun/sn/network/UrlAddress.java b/app/src/main/java/com/aoleyun/sn/network/UrlAddress.java index ad9b1be..c435a5b 100644 --- a/app/src/main/java/com/aoleyun/sn/network/UrlAddress.java +++ b/app/src/main/java/com/aoleyun/sn/network/UrlAddress.java @@ -4,6 +4,20 @@ package com.aoleyun.sn.network; * @author Administrator */ public class UrlAddress { + + /** + * 设备管控信息 + */ + + /*获取设备锁定状态*/ + public static final String GET_DEVICES_LOCKED = "lock/index"; + /*获取设备标签*/ + public static final String GET_DEVICES_TAGS = "Sn/getSnTag"; + + /*获取批次*/ + @Deprecated + public static final String GET_BATCH = "log/getBatch"; + /** * 应用策略相关 */ @@ -37,16 +51,8 @@ public class UrlAddress { /*下载接口 根据包名匹配 请求后更新下载次数*/ public static final String SEND_DOWNLOAD_TIMES = "count/index"; - /** - * 设备相关 - */ - /*获取设备锁定状态*/ - public static final String GET_DEVICES_LOCKED = "lock/index"; - /*获取设备标签*/ - public static final String GET_DEVICES_TAGS = "Sn/getSnTag"; - /*获取批次*/ - public static final String GET_BATCH = "log/getBatch"; + /*上传安装的应用信息*/ public static final String UPLOAD_APPINFO = "log/index"; @@ -70,6 +76,7 @@ public class UrlAddress { public static final String GET_LOCK_SCREEN_STATE = "Sn/getSnScreen"; /*上传电池信息*/ public static final String SEND_BATTERY_INFO = "And/sn/updateBatteryInfo"; + /*上传联网时间*/ public static final String NETWORK_CONNECT = "And/network"; @@ -115,6 +122,11 @@ public class UrlAddress { /*开发人员选项开关*/ public static final String GET_DEVELOPER = "Sn/getDeveloper"; + + /** + * log相关 + */ + /*获取log任务*/ public static final String GET_LOG_ORDER = "And/getSnRunLog"; /*上传log文件*/ @@ -123,8 +135,7 @@ public class UrlAddress { public static final String UPLOAD_IS_LOG_FILE = "And/sn/uploadIsLogFile"; - /*获取公网IP*/ - public static final String SHOUHU_CITYJSON = "http://pv.sohu.com/cityjson/"; + /*通过ip获取信息*/ public static final String PCONLINE_WHOIS = "http://whois.pconline.com.cn/"; public static final String WHOIS = "ipJson.jsp"; diff --git a/app/src/main/java/com/aoleyun/sn/network/api/GetPublicIPApi.java b/app/src/main/java/com/aoleyun/sn/network/api/GetPublicIPApi.java deleted file mode 100644 index 4d23ac3..0000000 --- a/app/src/main/java/com/aoleyun/sn/network/api/GetPublicIPApi.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.aoleyun.sn.network.api; - -import com.aoleyun.sn.network.UrlAddress; - -import io.reactivex.rxjava3.core.Observable; -import okhttp3.ResponseBody; -import retrofit2.http.GET; - -/** - * @author : fanhuitong - * e-mail : - * @date : 2021/10/1814:39 - * desc : - * version: 1.0 - */ -public interface GetPublicIPApi { - @GET(UrlAddress.SHOUHU_CITYJSON) - Observable getPublicIP(); -} diff --git a/app/src/main/java/com/aoleyun/sn/network/api/post/NetworkConnectApi.java b/app/src/main/java/com/aoleyun/sn/network/api/post/NetworkConnectApi.java index e59d020..a39d20a 100644 --- a/app/src/main/java/com/aoleyun/sn/network/api/post/NetworkConnectApi.java +++ b/app/src/main/java/com/aoleyun/sn/network/api/post/NetworkConnectApi.java @@ -3,6 +3,8 @@ package com.aoleyun.sn.network.api.post; import com.aoleyun.sn.bean.BaseResponse; import com.aoleyun.sn.network.UrlAddress; +import java.util.List; + import io.reactivex.rxjava3.core.Observable; import retrofit2.http.Field; import retrofit2.http.FormUrlEncoded; @@ -12,6 +14,7 @@ public interface NetworkConnectApi { @FormUrlEncoded @POST(UrlAddress.NETWORK_CONNECT) Observable sendNetwork( - @Field("sn") String sn + @Field("sn") String sn, + @Field("time") String time ); } diff --git a/app/src/main/java/com/aoleyun/sn/network/interceptor/RepeatRequestInterceptor.java b/app/src/main/java/com/aoleyun/sn/network/interceptor/RepeatRequestInterceptor.java index 76c919e..0b4a1af 100644 --- a/app/src/main/java/com/aoleyun/sn/network/interceptor/RepeatRequestInterceptor.java +++ b/app/src/main/java/com/aoleyun/sn/network/interceptor/RepeatRequestInterceptor.java @@ -39,7 +39,11 @@ public class RepeatRequestInterceptor implements Interceptor { // Response copy = response.newBuilder().body(responseBody).build(); ResponseBody copy = ResponseBody.create(responseBody.contentType(), content); if (BuildConfig.DEBUG) { - Log.e(TAG, "请求体返回:| Response: " + request.url().encodedPath() + "\t body: " + content); + if (content.length() < 1024) { + Log.e(TAG, "请求体返回:| Response: " + request.url() + "\t body: " + content); + }else { + Log.e(TAG, "请求体返回:| Response: " + request.url() + "\t body: too long" ); + } } //相同的请求 String requestKey = MD5Util.getUpperMD5Str(request.method() + request.url().toString() + requestBodyToString(request.body())); @@ -83,7 +87,7 @@ public class RepeatRequestInterceptor implements Interceptor { final Request copy = request.newBuilder().build(); final Buffer buffer = new Buffer(); copy.body().writeTo(buffer); - if (buffer.size() > 4096) { + if (buffer.size() > 1024) { return "-too long"; } return buffer.readUtf8(); @@ -96,7 +100,7 @@ public class RepeatRequestInterceptor implements Interceptor { try { final Buffer buffer = new Buffer(); body.writeTo(buffer); - if (buffer.size() > 4096) { + if (buffer.size() > 1024) { return "-too long"; } return buffer.readUtf8(); diff --git a/app/src/main/java/com/aoleyun/sn/receiver/NewAppReceiver.java b/app/src/main/java/com/aoleyun/sn/receiver/NewAppReceiver.java index 53d6df2..e6ba966 100644 --- a/app/src/main/java/com/aoleyun/sn/receiver/NewAppReceiver.java +++ b/app/src/main/java/com/aoleyun/sn/receiver/NewAppReceiver.java @@ -96,6 +96,7 @@ public class NewAppReceiver extends BroadcastReceiver { public void onNext(@NonNull String s) { Log.e(TAG, "sendAppInfo: onNext: " + s); JGYUtils.getInstance().checkForceDownload(); + NetInterfaceManager.getInstance().getAppLimit(); NetInterfaceManager.getInstance().getDefaultDesktop(); NetInterfaceManager.getInstance().sendInstalledAppInfo(new NetInterfaceManager.onCompleteCallback() { @Override diff --git a/app/src/main/java/com/aoleyun/sn/service/StepService.java b/app/src/main/java/com/aoleyun/sn/service/StepService.java index b79fe6f..53794e8 100644 --- a/app/src/main/java/com/aoleyun/sn/service/StepService.java +++ b/app/src/main/java/com/aoleyun/sn/service/StepService.java @@ -18,6 +18,7 @@ import androidx.annotation.Nullable; import com.alibaba.fastjson.JSONObject; import com.aoleyun.sn.BuildConfig; +import com.aoleyun.sn.utils.JGYUtils; import com.blankj.utilcode.util.NetworkUtils; import com.aoleyun.sn.KeepAliveConnection; import com.aoleyun.sn.utils.ServiceAliveUtils; @@ -46,7 +47,7 @@ public class StepService extends Service implements NetworkUtils.OnNetworkStatus @Override public void onConnected(NetworkUtils.NetworkType networkType) { - connect(); +// connect(); } //用于Activity和service通讯 @@ -134,6 +135,7 @@ public class StepService extends Service implements NetworkUtils.OnNetworkStatus case Intent.ACTION_BOOT_COMPLETED: case Intent.ACTION_USER_PRESENT: case Intent.ACTION_SCREEN_ON: + mHandler.post(heartBeatRunnable);//开启心跳检测 sendMsg(1); break; case Intent.ACTION_SCREEN_OFF: @@ -185,8 +187,9 @@ public class StepService extends Service implements NetworkUtils.OnNetworkStatus Log.i("JWebSocketClientService", "websocket连接关闭"); // client.close(); // initSocketClient(); - mHandler.postDelayed(heartBeatRunnable, HEART_BEAT_RATE);//开启心跳检测 - + if (JGYUtils.getInstance().isScreenOn()) { + mHandler.postDelayed(heartBeatRunnable, HEART_BEAT_RATE);//开启心跳检测 + } } @Override @@ -195,8 +198,11 @@ public class StepService extends Service implements NetworkUtils.OnNetworkStatus Log.i("JWebSocketClientService", "websocket连接错误:" + ex.getMessage()); // client.close(); // initSocketClient(); - mHandler.postDelayed(heartBeatRunnable, HEART_BEAT_RATE);//开启心跳检测 - + if (JGYUtils.getInstance().isScreenOn()) { + mHandler.postDelayed(heartBeatRunnable, HEART_BEAT_RATE);//开启心跳检测 + } else { + Log.i("JWebSocketClientService", "postDelayed off"); + } } }; connect(); @@ -219,7 +225,6 @@ public class StepService extends Service implements NetworkUtils.OnNetworkStatus } } }.start(); - } /** @@ -285,7 +290,11 @@ public class StepService extends Service implements NetworkUtils.OnNetworkStatus sendMsg(); } else if (client.isClosed()) { Log.i("JWebSocketClientService", "websocket重连中"); - reconnectWs(); + if (JGYUtils.getInstance().isScreenOn()) { + reconnectWs(); + } else { + Log.i("JWebSocketClientService", "reconnectWs off"); + } } } else { //如果client已为空,重新初始化连接 @@ -293,7 +302,11 @@ public class StepService extends Service implements NetworkUtils.OnNetworkStatus initSocketClient(); } //每隔一定的时间,对长连接进行一次心跳检测 - mHandler.postDelayed(this, HEART_BEAT_RATE); + if (JGYUtils.getInstance().isScreenOn()) { + mHandler.postDelayed(this, HEART_BEAT_RATE); + } else { + Log.i("JWebSocketClientService", "websocket息屏不重连"); + } } }; @@ -314,4 +327,4 @@ public class StepService extends Service implements NetworkUtils.OnNetworkStatus } }.start(); } -} +} \ No newline at end of file diff --git a/app/src/main/java/com/aoleyun/sn/service/main/MainSContact.java b/app/src/main/java/com/aoleyun/sn/service/main/MainSContact.java index de5299c..cb073af 100644 --- a/app/src/main/java/com/aoleyun/sn/service/main/MainSContact.java +++ b/app/src/main/java/com/aoleyun/sn/service/main/MainSContact.java @@ -3,37 +3,49 @@ package com.aoleyun.sn.service.main; import com.aoleyun.sn.base.BasePresenter; import com.aoleyun.sn.base.BaseView; +import java.util.List; + public class MainSContact { public interface Presenter extends BasePresenter { - void sendNetwork(); /*分支1*/ /*获取设备锁定状态*/ - void getLockedState(String key); + void getLockedState(); /*设置极光推送标签*/ void setPushTags(); - /*获取设备批次*/ - void getDeviceBatch(); /*分支2 基本信息*/ /*是否第一次联网*/ void getFirstConnect(); /*获取学生信息*/ - void getStudesInfo(boolean refresh); + void getStudesInfo(); /*分支3 上传信息*/ + /*上传联网时间*/ + void sendNetwork(List time); /*发送mac地址*/ - void sendMACAddress(); + void sendMacAddress(); /*更新设备信息*/ void updateDeviceInfo(); /*上传安装的应用列表*/ void sendInstalled(); - - /*分支4 获取应用*/ /*获取设备信息更新*/ void checkAoleyunUpdate(); /*获取测试应用更新*/ void checkTestUpdate(); + + /*分支4 根据SN获取*/ + /*获取开发者选项*/ + void getDeveloper(); + /*获取自定义内置app*/ + void getRomApp(); + /*获取屏幕锁状态*/ + void getScreenLockState(); + + + /*分支5 根据批次获取*/ + /*获取设备后台设置*/ + void getSystemSettingBegin(); /*获取可被写入的安装包名*/ void getAppLimit(); /*获取强制下载apk*/ @@ -42,16 +54,8 @@ public class MainSContact { void getDefaultDesktop(); /*设置开机动画*/ void setLogoImg(); - - /*分支5 获取管控*/ - /*获取开发者选项*/ - void getDeveloper(); - /*获取设备后台设置*/ - void getSystemSettingBegin(); /*获取所有app详细信息*/ void getAllAppList(); - /*获取自定义内置app*/ - void getROMApp(); /*获取浏览器书签设置管控*/ void getBrowserBookmarks(); /*设置白名单的url 单独*/ @@ -63,11 +67,11 @@ public class MainSContact { /*获取禁用app*/ void getSnAppAttr(); /*获取第三方应用子页面ID连网限制*/ - void getAppIDControl(); + void getAppIdControl(); /*获取第三方应用内部网页跳转屏蔽*/ void setAppinsideWeb(); /*获取系统其他管控设置*/ - void setSystemSetting(); + void getSystemSetting(); /*获取系统默认程序设置*/ void getDefaultApp(); /*应用霸屏*/ @@ -77,23 +81,16 @@ public class MainSContact { /*获取时间管控*/ void getSnTimeControl(); /*获取电子书包激活码*/ - void getEBagCode(); + void getEbagCode(); /*获取wifi密码*/ void getWiFiPasswd(); - - /*获取屏幕锁状态*/ - void getScreenLockState(); } public interface MainView extends BaseView { - void sendNetworkFinish(); - /*获取设备锁定状态*/ void setLockedState(boolean loocked); /*设置极光推送标签*/ void setTagsFinish(boolean noTag); - /*获取设备批次结束*/ - void getDeviceBatchFinish(); /*是否第一次联网*/ @@ -101,8 +98,10 @@ public class MainSContact { /*获取学生信息*/ void setStudesInfo(); + /*上传联网时间*/ + void sendNetworkFinish(); /*发送mac地址*/ - void sendMACFinish(); + void sendMacFinish(); /*更新设备信息*/ void updateDeviceInfoFinish(); /*上传安装的应用列表*/ @@ -112,6 +111,15 @@ public class MainSContact { void checkAoleyunUpdateFinish(); /*获取测试应用更新*/ void checkTestUpdateFinish(); + /*获取开发者选项结束*/ + void getDeveloperFinish(); + /*获取自定义内置app*/ + void getRomAppFinish(); + /*设置屏幕锁状态结束*/ + void setScreenLockStateFinish(boolean locked, String tips); + + /*设置设备后台设置*/ + void setSystemSetting(); /*获取可被写入的安装包名结束*/ void getAppLimitFinish(); /*获取强制下载apk结束*/ @@ -120,15 +128,8 @@ public class MainSContact { void getDefaultDesktopFinish(); /*设置开机动画*/ void setLogoImgFinish(); - - /*获取开发者选项结束*/ - void getDeveloperFinish(); - /*设置设备后台设置*/ - void setSystemSetting(); /*获取所有app详细信息*/ void getAllAppListFinish(); - /*获取自定义内置app*/ - void getROMAppFinish(); /*获取浏览器书签设置管控结束*/ void getBrowserBookmarksFinish(); /*设置白名单的url 单独*/ @@ -140,11 +141,11 @@ public class MainSContact { /*获取禁用app*/ void getSnAppAttrFinish(); /*获取第三方应用子页面ID连网限制结束*/ - void getAppIDControlFinish(); + void getAppIdControlFinish(); /*获取第三方应用内部网页跳转屏蔽结束*/ void setAppinsideWebFinish(); /*获取系统其他管控设置结束*/ - void setSystemSettingFinish(); + void getSystemSettingFinish(); /*获取系统默认程序设置*/ void setDefaultAppFinish(); /*获取应用霸屏结束*/ @@ -154,11 +155,9 @@ public class MainSContact { /*获取时间管控*/ void getSnTimeControlFinish(); /*获取电子书包激活码*/ - void getEBagCodeFinish(); + void getEbagCodeFinish(); /*获取wifi密码结束*/ void setWiFiPasswd(); - /*设置屏幕锁状态结束*/ - void setScreenLockStateFinish(boolean locked, String tips); } } diff --git a/app/src/main/java/com/aoleyun/sn/service/main/MainSPresenter.java b/app/src/main/java/com/aoleyun/sn/service/main/MainSPresenter.java index 6f591a6..fd63ab4 100644 --- a/app/src/main/java/com/aoleyun/sn/service/main/MainSPresenter.java +++ b/app/src/main/java/com/aoleyun/sn/service/main/MainSPresenter.java @@ -3,6 +3,7 @@ package com.aoleyun.sn.service.main; import android.content.ContentResolver; import android.content.Context; import android.provider.Settings; +import android.text.TextUtils; import android.util.Log; import com.aoleyun.sn.bean.BaseResponse; @@ -11,17 +12,17 @@ import com.aoleyun.sn.comm.CommonConfig; import com.aoleyun.sn.comm.JGYActions; import com.aoleyun.sn.disklrucache.CacheHelper; import com.aoleyun.sn.network.NetInterfaceManager; +import com.aoleyun.sn.network.UrlAddress; import com.aoleyun.sn.utils.JGYUtils; import com.aoleyun.sn.utils.SPUtils; import com.aoleyun.sn.utils.ToastUtil; import com.aoleyun.sn.utils.URLUtils; import com.aoleyun.sn.utils.Utils; -import com.arialyy.aria.orm.annotation.Ignore; import com.tencent.mmkv.MMKV; import com.trello.rxlifecycle4.RxLifecycle; import com.trello.rxlifecycle4.android.ActivityEvent; -import java.util.Set; +import java.util.List; import io.reactivex.rxjava3.annotations.NonNull; import io.reactivex.rxjava3.core.Observer; @@ -69,59 +70,18 @@ public class MainSPresenter implements MainSContact.Presenter { this.mView = null; } - private boolean requesting = false; - - public boolean isRequesting() { - return requesting; - } - - public void setRequesting(boolean requesting) { - this.requesting = requesting; - } - - public long responseTime; - - @Override - public void sendNetwork() { - NetInterfaceManager.getInstance().GetNetworkConnectControl() - .compose(RxLifecycle.bindUntilEvent(lifecycle, ActivityEvent.DESTROY)) - .subscribe(new Observer() { - @Override - public void onSubscribe(@NonNull Disposable d) { - Log.e("sendNetwork", "onSubscribe: "); - } - - @Override - public void onNext(@NonNull BaseResponse baseResponse) { - Log.e("sendNetwork", "onNext: " + baseResponse); - } - - @Override - public void onError(@NonNull Throwable e) { - Log.e("sendNetwork", "onError: "); - } - - @Override - public void onComplete() { - Log.e("sendNetwork", "onComplete: "); - } - }); - } - /** * 1 */ @Override - public void getLockedState(String key) { - Log.e(TAG, "getLockedState: " + key); + public void getLockedState() { + Log.e(TAG, "getLockedState: "); if (JGYUtils.getInstance().isAihuaFramwwork()) { int aihuaUnlock = Settings.System.getInt(mContext.getContentResolver(), CommonConfig.AIHUA_UNLOCK, 0); if (aihuaUnlock == 1) { return; } } - requesting = true; - responseTime = System.currentTimeMillis(); NetInterfaceManager.getInstance() .getLockedState(getLifecycle(), new NetInterfaceManager.onCompleteCallback() { @Override @@ -129,30 +89,31 @@ public class MainSPresenter implements MainSContact.Presenter { Log.e("getLockedState", "onComplete: "); int locked = Settings.System.getInt(crv, JGYActions.ACTION_QCH_UNLOCK_IPAD, JGYActions.FRAME_CODE_LOCKED); Log.e("getLockedState", "locked: " + locked); + if (locked == 0) { + JGYUtils.getInstance().deleteOtherApp(); + } mView.setLockedState(locked == JGYActions.FRAME_CODE_LOCKED); } }); } - @Override public void setPushTags() { - Set tagSets = mMMKV.decodeStringSet(CommonConfig.DEVICES_TAG + "pushset"); + NetInterfaceManager.getInstance().setPushTags(false, getLifecycle(), new NetInterfaceManager.PushTagCallback() { + @Override + public void setPushTag(String tag) { + mView.setTagsFinish(TextUtils.isEmpty(tag)); + } + }); + String tagSets = mMMKV.decodeString(CommonConfig.DEVICES_TAG); Log.e("setPushTags", "onComplete: tagSets =" + tagSets); - String tags = cacheHelper.getAsString(CommonConfig.DEVICES_TAG); + String tags = cacheHelper.getAsString(UrlAddress.GET_DEVICES_TAGS); Log.e("setPushTags", "onComplete: tags = " + tags); - mView.setTagsFinish(tagSets == null || tagSets.size() < 2); } - @Override - public void getDeviceBatch() { - int locked = Settings.System.getInt(mContext.getContentResolver(), JGYActions.ACTION_QCH_UNLOCK_IPAD, 0); - Log.e(TAG, "getDeviceBatch: " + locked); - if (locked == 0) { - JGYUtils.getInstance().deleteOtherApp(); - mView.getDeviceBatchFinish(); - } - } + /* + * 2 + */ /** * 第一次连接 @@ -164,15 +125,11 @@ public class MainSPresenter implements MainSContact.Presenter { mView.setFirstConnect(first == 0); } - /** - * 2 - */ - /** * 通过sn获取用户信息 */ @Override - public void getStudesInfo(boolean refresh) { + public void getStudesInfo() { NetInterfaceManager.getInstance().getStudesInfo(false, getLifecycle(), new NetInterfaceManager.StudesInfoListener() { @Override public void setStudentsInfo(StudentsInfo studentsInfo) { @@ -186,16 +143,54 @@ public class MainSPresenter implements MainSContact.Presenter { }); } + @Override + public void sendNetwork(List time) { + if (time == null || time.size() == 0) { + Log.e(TAG, "sendNetwork: " + "time empty"); + return; + } + NetInterfaceManager.getInstance().GetNetworkConnectControl(time.toString()) + .compose(RxLifecycle.bindUntilEvent(lifecycle, ActivityEvent.DESTROY)) + .subscribe(new Observer() { + @Override + public void onSubscribe(@NonNull Disposable d) { + Log.e("sendNetwork", "onSubscribe: "); + } + + @Override + public void onNext(@NonNull BaseResponse baseResponse) { + Log.e("sendNetwork", "onNext: " + baseResponse); + if (baseResponse.code == 200) { + JGYUtils.getInstance().removeNetworkConnectedTime(time); + } else { + + } + } + + @Override + public void onError(@NonNull Throwable e) { + Log.e("sendNetwork", "onError: "); + onComplete(); + } + + @Override + public void onComplete() { + Log.e("sendNetwork", "onComplete: "); + mView.sendNetworkFinish(); + } + }); + } + /** * 3 */ @Override - public void sendMACAddress() { + public void sendMacAddress() { NetInterfaceManager.getInstance().sendMACAddress(true, getLifecycle(), new NetInterfaceManager.onCompleteCallback() { @Override public void onComplete() { - mView.sendMACFinish(); + mView.sendMacFinish(); } }); } @@ -226,7 +221,6 @@ public class MainSPresenter implements MainSContact.Presenter { }); } - /** * 4 */ @@ -240,9 +234,9 @@ public class MainSPresenter implements MainSContact.Presenter { mView.checkAoleyunUpdateFinish(); } }); +// mView.checkAoleyunUpdateFinish(); } - @Override public void checkTestUpdate() { NetInterfaceManager.getInstance() @@ -254,6 +248,51 @@ public class MainSPresenter implements MainSContact.Presenter { }); } + /** + * 5 + */ + @Override + public void getDeveloper() { + NetInterfaceManager.getInstance() + .getDeveloper(true, getLifecycle(), new NetInterfaceManager.onCompleteCallback() { + @Override + public void onComplete() { + mView.getDeveloperFinish(); + } + }); + } + + @Override + public void getRomApp() { + String customVersion = Utils.getCustomVersion(); + Log.e(TAG, "getROMApp: " + customVersion); + NetInterfaceManager.getInstance() + .getCustomROMApp(true, getLifecycle(), new NetInterfaceManager.onCompleteCallback() { + @Override + public void onComplete() { + mView.getRomAppFinish(); + } + }); + } + + @Override + public void getScreenLockState() { + NetInterfaceManager.getInstance().getScreenLockState(true, getLifecycle(), new NetInterfaceManager.ScreenLockStateListener() { + @Override + public void setScreenLockState(boolean locked, String tips) { + mView.setScreenLockStateFinish(locked, tips); + } + }); + } + + @Override + public void getSystemSettingBegin() { + //重置设备 + JGYUtils.getInstance().resetDevice(); + ToastUtil.betaShow("开始获取管控"); + mView.setSystemSetting(); + } + @Override public void getAppLimit() { NetInterfaceManager.getInstance() @@ -312,29 +351,6 @@ public class MainSPresenter implements MainSContact.Presenter { } } - - /** - * 5 - */ - @Override - public void getDeveloper() { - NetInterfaceManager.getInstance() - .getDeveloper(true, getLifecycle(), new NetInterfaceManager.onCompleteCallback() { - @Override - public void onComplete() { - mView.getDeveloperFinish(); - } - }); - } - - @Override - public void getSystemSettingBegin() { - //重置设备 - JGYUtils.getInstance().resetDevice(); - ToastUtil.betaShow("开始获取管控"); - mView.setSystemSetting(); - } - @Override public void getAllAppList() { NetInterfaceManager.getInstance() @@ -346,19 +362,6 @@ public class MainSPresenter implements MainSContact.Presenter { }); } - @Override - public void getROMApp() { - String customVersion = Utils.getCustomVersion(); - Log.e(TAG, "getROMApp: " + customVersion); - NetInterfaceManager.getInstance() - .getCustomROMApp(true, getLifecycle(), new NetInterfaceManager.onCompleteCallback() { - @Override - public void onComplete() { - mView.getROMAppFinish(); - } - }); - } - @Override public void getBrowserBookmarks() { NetInterfaceManager.getInstance() @@ -411,12 +414,12 @@ public class MainSPresenter implements MainSContact.Presenter { } @Override - public void getAppIDControl() { + public void getAppIdControl() { NetInterfaceManager.getInstance() .getAppIDControl(true, getLifecycle(), new NetInterfaceManager.onCompleteCallback() { @Override public void onComplete() { - mView.getAppIDControlFinish(); + mView.getAppIdControlFinish(); } }); } @@ -436,12 +439,12 @@ public class MainSPresenter implements MainSContact.Presenter { } @Override - public void setSystemSetting() { + public void getSystemSetting() { NetInterfaceManager.getInstance() .setSystemSetting(true, getLifecycle(), new NetInterfaceManager.onCompleteCallback() { @Override public void onComplete() { - mView.setSystemSettingFinish(); + mView.getSystemSettingFinish(); } }); } @@ -499,17 +502,16 @@ public class MainSPresenter implements MainSContact.Presenter { } @Override - public void getEBagCode() { + public void getEbagCode() { NetInterfaceManager.getInstance() .getEBagCode(true, getLifecycle(), new NetInterfaceManager.onCompleteCallback() { @Override public void onComplete() { - mView.getEBagCodeFinish(); + mView.getEbagCodeFinish(); } }); } - @Override public void getWiFiPasswd() { NetInterfaceManager.getInstance() @@ -520,14 +522,4 @@ public class MainSPresenter implements MainSContact.Presenter { } }); } - - @Override - public void getScreenLockState() { - NetInterfaceManager.getInstance().getScreenLockState(true, getLifecycle(), new NetInterfaceManager.ScreenLockStateListener() { - @Override - public void setScreenLockState(boolean locked, String tips) { - mView.setScreenLockStateFinish(locked, tips); - } - }); - } } diff --git a/app/src/main/java/com/aoleyun/sn/service/main/MainService.java b/app/src/main/java/com/aoleyun/sn/service/main/MainService.java index 431859a..b026472 100644 --- a/app/src/main/java/com/aoleyun/sn/service/main/MainService.java +++ b/app/src/main/java/com/aoleyun/sn/service/main/MainService.java @@ -43,7 +43,6 @@ import com.aoleyun.sn.bean.PoweroffBean; import com.aoleyun.sn.comm.CommonConfig; import com.aoleyun.sn.comm.JGYActions; import com.aoleyun.sn.comm.PackageNames; -import com.aoleyun.sn.manager.ConnectManager; import com.aoleyun.sn.network.NetInterfaceManager; import com.aoleyun.sn.rlog.LogDBManager; import com.aoleyun.sn.utils.ApkUtils; @@ -76,6 +75,7 @@ import java.util.Arrays; import java.util.Date; import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.concurrent.TimeUnit; import io.reactivex.rxjava3.core.Observable; @@ -103,23 +103,15 @@ public class MainService extends Service implements MainSContact.MainView, Netwo Aria.download(this).resumeAllTask(); String WiFiAlias = Utils.getWifiAlias(this); Log.e("OnNetworkStatusChanged", "onConnected: " + WiFiAlias); - - if (!checkAoleyunApp()) { - mPresenter.checkAoleyunUpdate(); - } - Utils.getPublicIP(this); - TimeTask task = new TimeTask(); - task.execute("ntp.aliyun.com"); - mPresenter.sendNetwork(); + JGYUtils.getInstance().addNetworkConnectedTime(System.currentTimeMillis() / 1000); if (JGYUtils.getInstance().isScreenOn()) { - mPresenter.getLockedState("onConnected"); + TimeTask task = new TimeTask(); + task.execute("ntp.aliyun.com"); + if (!checkAoleyunApp()) { + mPresenter.checkAoleyunUpdate(); + } + mPresenter.getLockedState(); } -// if (mMMKV.decodeInt(CommonConfig.DEVICES_FRIST_START, 1) == 1) { -// Intent intent = new Intent(this, CheckNetActivity.class); -// intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); -// startActivity(intent); -// } - } private class TimeTask extends AsyncTask { @@ -150,18 +142,13 @@ public class MainService extends Service implements MainSContact.MainView, Netwo public void onSuccess(Object data, int flag) { //token在设备卸载重装的时候有可能会变 Log.e("TPush", "注册成功,设备token为:" + data); + List accountInfoList = new ArrayList<>(); accountInfoList.add(new XGPushManager.AccountInfo(XGPushManager.AccountType.CUSTOM.getValue(), Utils.getSerial(MainService.this))); XGPushManager.upsertAccounts(MainService.this, accountInfoList, new XGIOperateCallback() { @Override public void onSuccess(Object data, int flag) { Log.e("TPush", "onSuccess, data:" + data + ", flag:" + flag); - NetInterfaceManager.getInstance().setPushTags(false, lifecycleSubject, new NetInterfaceManager.onCompleteCallback() { - @Override - public void onComplete() { - Log.e("TimeTask", "onComplete: "); - } - }); } @Override @@ -169,6 +156,28 @@ public class MainService extends Service implements MainSContact.MainView, Netwo Log.e("TPush", "onFail, data:" + data + ", code:" + errCode + ", msg:" + msg); } }); + NetInterfaceManager.getInstance().setPushTags(false, lifecycleSubject, new NetInterfaceManager.PushTagCallback() { + @Override + public void setPushTag(String tag) { + Set tagSets = new HashSet<>(); + if (!TextUtils.isEmpty(tag)) { + tagSets.add(tag); + } + JGYUtils.getInstance().getAppPlatform(new JGYUtils.GetAppPlatformCallback() { + @Override + public void AppPlatform(int platform) { + if (platform == JGYUtils.MTKPlatform) { + tagSets.add(JGYUtils.MTKTag); + } else if (platform == JGYUtils.ZhanruiPlatform) { + tagSets.add(JGYUtils.ZhanruiTag); + } else if (platform == JGYUtils.CubePlatform) { + tagSets.add(JGYUtils.CubeTag); + } + } + }); + NetInterfaceManager.getInstance().clearAndAppendTags(tagSets); + } + }); } @Override @@ -282,7 +291,41 @@ public class MainService extends Service implements MainSContact.MainView, Netwo String action = intent.getAction(); Log.e("RefreshReceiver", "onReceive: " + action); if (!TextUtils.isEmpty(action)) { - mPresenter.getLockedState("refresh"); + mPresenter.getLockedState(); + } + } + } + + 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_ON); + filter.addAction(Intent.ACTION_SCREEN_OFF); + registerReceiver(screenLockReceiver, filter); + } + + private class ScreenLockReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + Log.e(TAG, "onReceive:" + action); + if (TextUtils.isEmpty(action)) { + Log.e(TAG, "onReceive: is NULL"); + return; + } + switch (action) { + case Intent.ACTION_SCREEN_ON: + mPresenter.sendNetwork(JGYUtils.getInstance().getNetworkConnectedTime()); + break; + case Intent.ACTION_SCREEN_OFF: + break; + default: + break; } } } @@ -312,10 +355,9 @@ public class MainService extends Service implements MainSContact.MainView, Netwo mPresenter = new MainSPresenter(this); mPresenter.attachView(this); mPresenter.setLifecycle(lifecycleSubject); - TimeTask task = new TimeTask(); task.execute("ntp.aliyun.com"); - mPresenter.getLockedState("onCreate"); + mPresenter.getLockedState(); //根据要求卸载这两个应用 if (!JGYUtils.getInstance().getDeviceIsLocked()) { @@ -454,6 +496,7 @@ public class MainService extends Service implements MainSContact.MainView, Netwo registerTimeReceiver(); registerInstallReceiver(); registerRefreshReceiver(); + registerScreenLockReceiver(); } private void unRegisterReceivers() { @@ -472,6 +515,9 @@ public class MainService extends Service implements MainSContact.MainView, Netwo if (null != mRefreshReceiver) { unregisterReceiver(mRefreshReceiver); } + if (null != screenLockReceiver) { + unregisterReceiver(screenLockReceiver); + } } private static WindowManager windowManager; @@ -506,7 +552,7 @@ public class MainService extends Service implements MainSContact.MainView, Netwo TextView textView = topView.findViewById(R.id.textView); textView.setText(name); } else { - if (topView.getTag().equals("added")) { + if ("added".equals(topView.getTag())) { TextView textView = topView.findViewById(R.id.textView); textView.setText(name); return; @@ -665,7 +711,7 @@ public class MainService extends Service implements MainSContact.MainView, Netwo setFloatingWindow(); } else if (ACTION_UPDATE.equals(intent.getAction())) { setFloatingWindow(); - mPresenter.getScreenLockState(); +// mPresenter.getScreenLockState(); Log.e("TimeChangedReceiver", "onReceive:" + "date update"); } timeChangedStart.onstar(System.currentTimeMillis()); @@ -712,6 +758,40 @@ public class MainService extends Service implements MainSContact.MainView, Netwo } } + synchronized private void setFloatingWindow() { + Log.e(TAG, "setFloatingWindow: "); + long nowTime = System.currentTimeMillis(); + mTopApp.open(nowTime); +// ForegroundAppUtil.openTopApp(MainService.this); + TimeUtils.ContralTime contralTime = TimeUtils.getDefaltContralTime(this); + Log.e(TAG, "setFloatingWindow: " + contralTime); + Log.e(TAG, "setFloatingWindow: screenlocked: " + screenlocked); + if (null != contralTime) { + if (contralTime.inControlTime(nowTime)) { + Log.e(TAG, "setFloatingWindow: " + "inControlTime is true"); + if (!screenlocked) { + showFloatingWindow("设备可用时间:" + contralTime.toString()); + } else { + TextView textView = topView.findViewById(R.id.textView); + textView.setText("设备可用时间:" + contralTime.toString()); + } + timelocked = true; + } else { + Log.e(TAG, "setFloatingWindow: " + "inControlTime is false"); + if (!screenlocked) { + hideFloatingWindow(); + } + timelocked = false; + } + } else { + Log.e(TAG, "setFloatingWindow: " + "inControlTime is null"); + if (!screenlocked) { + hideFloatingWindow(); + } + timelocked = false; + } + } + private interface TopApp { void open(Long time); } @@ -748,39 +828,6 @@ public class MainService extends Service implements MainSContact.MainView, Netwo } }; - synchronized private void setFloatingWindow() { - Log.e(TAG, "setFloatingWindow: "); - long nowTime = System.currentTimeMillis(); - mTopApp.open(nowTime); -// ForegroundAppUtil.openTopApp(MainService.this); - TimeUtils.ContralTime contralTime = TimeUtils.getDefaltContralTime(this); - Log.e(TAG, "setFloatingWindow: " + contralTime); - Log.e(TAG, "setFloatingWindow: screenlocked: " + screenlocked); - if (null != contralTime) { - if (contralTime.inControlTime(nowTime)) { - Log.e(TAG, "setFloatingWindow: " + "inControlTime is true"); - if (!screenlocked) { - showFloatingWindow("设备可用时间:" + contralTime.toString()); - } else { - TextView textView = topView.findViewById(R.id.textView); - textView.setText("设备可用时间:" + contralTime.toString()); - } - timelocked = true; - } else { - Log.e(TAG, "setFloatingWindow: " + "inControlTime is false"); - if (!screenlocked) { - hideFloatingWindow(); - } - timelocked = false; - } - } else { - Log.e(TAG, "setFloatingWindow: " + "inControlTime is null"); - if (!screenlocked) { - hideFloatingWindow(); - } - timelocked = false; - } - } private void registerInstallReceiver() { if (mInstallReceiver == null) { @@ -790,12 +837,13 @@ public class MainService extends Service implements MainSContact.MainView, Netwo registerReceiver(mInstallReceiver, intentFilter, INSTALLAPK_PREMISSIONS, null); } - private String INSTALLAPK_ACTION = "JGY_INSTALLAPK_ACTION"; - private String INSTALLAPK_PREMISSIONS = "com.aoleyun.sn.permissions.INSTALL_APK"; + private static final String INSTALLAPK_ACTION = "JGY_INSTALLAPK_ACTION"; + private static final String INSTALLAPK_PREMISSIONS = "com.aoleyun.sn.permissions.INSTALL_APK"; private InstallReceiver mInstallReceiver; /** + * 安装第三方的应用 * https://blog.csdn.net/jdsjlzx/article/details/82630113 */ class InstallReceiver extends BroadcastReceiver { @@ -843,11 +891,6 @@ public class MainService extends Service implements MainSContact.MainView, Netwo } } - @Override - public void sendNetworkFinish() { - - } - @Override public void setLockedState(boolean loocked) { Log.e(TAG, "setLockedState: " + loocked); @@ -855,15 +898,16 @@ public class MainService extends Service implements MainSContact.MainView, Netwo ToastUtil.betaShow("设备已上锁"); // sendSimpleNotification(); mPresenter.setPushTags(); - mPresenter.getDeveloper(); ApkUtils.UninstallAPP(this, "com.joytv.live"); ApkUtils.UninstallAPP(this, "com.tencent.android.qqdownloader"); } else { ToastUtil.betaShow("设备已解锁"); - notificationManager.cancel(NotificationID); +// notificationManager.cancel(NotificationID); SysSettingUtils.setEnableSetting(this); - mPresenter.checkAoleyunUpdate(); } + mPresenter.sendMacAddress(); + + //更新主页锁定状态 Intent intent = new Intent(MainActivity.UPDATE_LOCKED_STATUS); sendBroadcast(intent); } @@ -875,13 +919,10 @@ public class MainService extends Service implements MainSContact.MainView, Netwo Log.e(TAG, "setTagsFinish: " + "not set tag"); // mPresenter.getStudesInfo(true); } else { - mPresenter.getDeviceBatch(); + mPresenter.getFirstConnect(); } - } - - @Override - public void getDeviceBatchFinish() { - mPresenter.getFirstConnect(); + mPresenter.getStudesInfo(); + mPresenter.getDeveloper(); } /** @@ -896,20 +937,22 @@ public class MainService extends Service implements MainSContact.MainView, Netwo Log.e(TAG, "setDisableSetting: "); //设置系统管控 SysSettingUtils.setDisableSetting(this); - } else { - } - mPresenter.getStudesInfo(true); + mPresenter.getSystemSettingBegin(); } @Override public void setStudesInfo() { Log.e(TAG, "setStudesInfo: " + "基本信息获取完毕"); - mPresenter.sendMACAddress(); } @Override - public void sendMACFinish() { + public void sendNetworkFinish() { + Log.e(TAG, "sendNetworkFinish: " ); + } + + @Override + public void sendMacFinish() { mPresenter.updateDeviceInfo(); } @@ -931,6 +974,40 @@ public class MainService extends Service implements MainSContact.MainView, Netwo @Override public void checkTestUpdateFinish() { + Log.e(TAG, "checkTestUpdateFinish: "); + } + + @Override + public void getDeveloperFinish() { + mPresenter.getRomApp(); + } + + @Override + public void getRomAppFinish() { + mPresenter.getScreenLockState(); + } + + @Override + public void setScreenLockStateFinish(boolean locked, String tips) { + if (locked) { + if (!timelocked) { + showFloatingWindow(tips); + } + screenlocked = true; + SPUtils.put(this, "is_screen_lock", true); + SPUtils.put(this, "screen_tips", tips); + } else { + if (!timelocked) { + hideFloatingWindow(); + } + screenlocked = false; + SPUtils.put(this, "is_screen_lock", false); + SPUtils.put(this, "screen_tips", ""); + } + } + + @Override + public void setSystemSetting() { mPresenter.getAppLimit(); } @@ -951,28 +1028,11 @@ public class MainService extends Service implements MainSContact.MainView, Netwo @Override public void setLogoImgFinish() { - mPresenter.setRequesting(false); - Log.e(TAG, "setLogoImgFinish: "); - Log.e(TAG, "SettingFinish: " + (System.currentTimeMillis() - mPresenter.responseTime) + " ms"); - } - - @Override - public void getDeveloperFinish() { - mPresenter.getSystemSettingBegin(); - } - - @Override - public void setSystemSetting() { mPresenter.getAllAppList(); } @Override public void getAllAppListFinish() { - mPresenter.getROMApp(); - } - - @Override - public void getROMAppFinish() { mPresenter.getBrowserBookmarks(); } @@ -998,21 +1058,21 @@ public class MainService extends Service implements MainSContact.MainView, Netwo @Override public void getSnAppAttrFinish() { - mPresenter.getAppIDControl(); + mPresenter.getAppIdControl(); } @Override - public void getAppIDControlFinish() { + public void getAppIdControlFinish() { mPresenter.setAppinsideWeb(); } @Override public void setAppinsideWebFinish() { - mPresenter.setSystemSetting(); + mPresenter.getSystemSetting(); } @Override - public void setSystemSettingFinish() { + public void getSystemSettingFinish() { mPresenter.getDefaultApp(); } @@ -1033,37 +1093,16 @@ public class MainService extends Service implements MainSContact.MainView, Netwo @Override public void getSnTimeControlFinish() { - mPresenter.getEBagCode(); + mPresenter.getEbagCode(); } @Override - public void getEBagCodeFinish() { + public void getEbagCodeFinish() { mPresenter.getWiFiPasswd(); } @Override public void setWiFiPasswd() { - mPresenter.setRequesting(false); Log.e(TAG, "setWiFiPasswd: "); - Log.e(TAG, "SettingFinish: " + (System.currentTimeMillis() - mPresenter.responseTime) + " ms"); - } - - @Override - public void setScreenLockStateFinish(boolean locked, String tips) { - if (locked) { - if (!timelocked) { - showFloatingWindow(tips); - } - screenlocked = true; - SPUtils.put(this, "is_screen_lock", true); - SPUtils.put(this, "screen_tips", tips); - } else { - if (!timelocked) { - hideFloatingWindow(); - } - screenlocked = false; - SPUtils.put(this, "is_screen_lock", false); - SPUtils.put(this, "screen_tips", ""); - } } } diff --git a/app/src/main/java/com/aoleyun/sn/utils/AES/AesCbcWithIntegrity.java b/app/src/main/java/com/aoleyun/sn/utils/AES/AesCbcWithIntegrity.java index cf607b4..101adb1 100644 --- a/app/src/main/java/com/aoleyun/sn/utils/AES/AesCbcWithIntegrity.java +++ b/app/src/main/java/com/aoleyun/sn/utils/AES/AesCbcWithIntegrity.java @@ -282,7 +282,7 @@ public class AesCbcWithIntegrity { aesCipherForEncryption.init(Cipher.ENCRYPT_MODE, secretKeys.getConfidentialityKey(), new IvParameterSpec(iv)); /* - * Now we get back the IV that will actually be used. Some Android + * Now we get bt_return the IV that will actually be used. Some Android * versions do funny stuff w/ the IV, so this is to work around bugs: */ iv = aesCipherForEncryption.getIV(); diff --git a/app/src/main/java/com/aoleyun/sn/utils/ApkUtils.java b/app/src/main/java/com/aoleyun/sn/utils/ApkUtils.java index cadf5ba..23c4f51 100644 --- a/app/src/main/java/com/aoleyun/sn/utils/ApkUtils.java +++ b/app/src/main/java/com/aoleyun/sn/utils/ApkUtils.java @@ -427,7 +427,6 @@ public class ApkUtils { ToastUtil.show("正在安装应用"); install(packageInstaller, sessionId, context); } - } } @@ -447,7 +446,6 @@ public class ApkUtils { } } - @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) private static int createSession(PackageInstaller packageInstaller, PackageInstaller.SessionParams sessionParams) { int sessionId = -1; diff --git a/app/src/main/java/com/aoleyun/sn/utils/JGYUtils.java b/app/src/main/java/com/aoleyun/sn/utils/JGYUtils.java index faba1ca..8e6e349 100644 --- a/app/src/main/java/com/aoleyun/sn/utils/JGYUtils.java +++ b/app/src/main/java/com/aoleyun/sn/utils/JGYUtils.java @@ -51,6 +51,7 @@ import com.aoleyun.sn.comm.CommonConfig; import com.aoleyun.sn.comm.JGYActions; import com.aoleyun.sn.comm.PackageNames; import com.aoleyun.sn.disklrucache.CacheHelper; +import com.aoleyun.sn.gson.GsonUtils; import com.aoleyun.sn.network.NetInterfaceManager; import com.aoleyun.sn.network.UrlAddress; import com.aoleyun.sn.receiver.BootReceiver; @@ -94,6 +95,7 @@ import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.concurrent.Executor; import java.util.function.Consumer; import java.util.function.Predicate; @@ -107,6 +109,7 @@ public class JGYUtils { @SuppressLint("StaticFieldLeak") private static JGYUtils sInstance; + private MMKV mMMKV = MMKV.defaultMMKV(); private Context mContext; private ContentResolver crv; @@ -136,6 +139,7 @@ public class JGYUtils { this.mContext = context; this.crv = context.getContentResolver(); this.cacheHelper = new CacheHelper(context); + initConnectedTimeCache(); } public static void init(Context context) { @@ -2165,7 +2169,7 @@ public class JGYUtils { jsonObject.addProperty("desktop_version", Utils.getAPPVersionName("com.aoleyun.os", mContext)); jsonObject.addProperty("local_mac", Utils.getAndroid7MAC()); // jsonObject.addProperty("wifi_status", Utils.obtainWifiInfo(mContext)); - jsonObject.addProperty("PN_ip", MMKV.defaultMMKV().decodeString(NetInterfaceManager.PublicIP, "")); + jsonObject.addProperty("PN_ip", mMMKV.decodeString(NetInterfaceManager.PublicIP, "")); jsonObject.addProperty("LAN_ip", Utils.getIPAddress(mContext)); jsonObject.addProperty("bluetooth", Utils.getBluetoothList()); jsonObject.addProperty("wifi_name", Utils.getWifiAlias(mContext)); @@ -2370,4 +2374,43 @@ public class JGYUtils { //true为打开,false为关闭 return powerManager.isInteractive(); } + + private static final String CONNECTED_TIME_KEY = "connectedTimeKey"; + + private List connectedTime; + + private void initConnectedTimeCache() { + String jsonString = cacheHelper.getAsString(CONNECTED_TIME_KEY); + Gson gson = new Gson(); + Type listType = new TypeToken>() { + }.getType(); + List longList = gson.fromJson(jsonString, listType); + if (longList == null) { + connectedTime = new ArrayList<>(); + } else { + connectedTime = longList; + } + } + + public List getNetworkConnectedTime() { + Log.e(TAG, "getNetworkConnectedTime: " + connectedTime); + return connectedTime; + } + + public void addNetworkConnectedTime(Long time) { + Log.e(TAG, "addNetworkConnectedTime: " + time); + connectedTime.add(time); + cacheHelper.put(CONNECTED_TIME_KEY, GsonUtils.toJSONString(connectedTime)); + } + + public void removeNetworkConnectedTime(List time) { + if (time == null || time.size() == 0) { + return; + } + List copy = new ArrayList<>(time); + for (Long l : copy) { + connectedTime.remove(l); + } + cacheHelper.put(CONNECTED_TIME_KEY, GsonUtils.toJSONString(connectedTime)); + } } diff --git a/app/src/main/java/com/aoleyun/sn/utils/StatusBarUtil.java b/app/src/main/java/com/aoleyun/sn/utils/StatusBarUtil.java index 285acbb..75ac728 100644 --- a/app/src/main/java/com/aoleyun/sn/utils/StatusBarUtil.java +++ b/app/src/main/java/com/aoleyun/sn/utils/StatusBarUtil.java @@ -271,7 +271,7 @@ public class StatusBarUtil { decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR); } else { // We want to change tint color to white again. - // You can also record the flags in advance so that you can turn UI back completely if + // You can also record the flags in advance so that you can turn UI bt_return completely if // you have set other flags before, such as translucent or full screen. decor.setSystemUiVisibility(0); } diff --git a/app/src/main/java/com/aoleyun/sn/utils/Utils.java b/app/src/main/java/com/aoleyun/sn/utils/Utils.java index 3d3d3c0..e747ff3 100644 --- a/app/src/main/java/com/aoleyun/sn/utils/Utils.java +++ b/app/src/main/java/com/aoleyun/sn/utils/Utils.java @@ -1755,20 +1755,6 @@ public class Utils { return "获取失败"; } - /** - * 获取公网IP并保存 - * - * @param context - */ - public static void getPublicIP(Context context) { - NetInterfaceManager.getPublicIP(new NetInterfaceManager.PublicIP() { - @Override - public void set(String ip) { - Log.e("getPublicIP", "set: " + ip); - } - }); - } - /** * 获取WiFi信号强度 * diff --git a/app/src/main/res/drawable-hdpi/back.png b/app/src/main/res/drawable-hdpi/back.png deleted file mode 100644 index 3bb1c1044d15458c0c8e7d73f76948eeb32e981d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2040 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-hdpi/head.png b/app/src/main/res/drawable-hdpi/head.png deleted file mode 100644 index 3e60edefd78ac5a156bd911ef068791e6441840e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4950 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 bE&wtOOHlq{!ppz@bQ$WI>Q-I8b@zV&{qo6U diff --git a/app/src/main/res/drawable-hdpi/icon_battery.png b/app/src/main/res/drawable-hdpi/icon_battery.png new file mode 100644 index 0000000000000000000000000000000000000000..9817cfd2957f06f49c337328aeb1beae27f4f6d0 GIT binary patch literal 2688 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-hdpi/icon_ipaddress.png b/app/src/main/res/drawable-hdpi/icon_ipaddress.png new file mode 100644 index 0000000000000000000000000000000000000000..d21913b8a351f7b2883736d42c231e9cd026be83 GIT binary patch literal 3448 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 a`~Z7xp|q~zmaUz;kd1`{>Vdg;?EeAtZ3{{O literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-hdpi/icon_wifi.png b/app/src/main/res/drawable-hdpi/icon_wifi.png new file mode 100644 index 0000000000000000000000000000000000000000..f7cb889ec41864bd4ca17b597833266220ba5eac GIT binary patch literal 3386 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 NV`uA(uCfkc{s#jV-z)$C literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-hdpi/more.png b/app/src/main/res/drawable-hdpi/more.png new file mode 100644 index 0000000000000000000000000000000000000000..7174552ca18e97b8f1d4805bd1e107fab6e2c6d6 GIT binary patch literal 476 zcmV<20VDp2P)pn0)3W+6Pt$hc8<8S!0 zG3JDYkR4zchNIRx04y&wgzNyJdK|}>d7d9~AdmoX&KPXN$hBai?H(YX-F0OUd- z1&{-Q8~`=~NdQa)vH(~JqyaDx$OEKCU;&U4fek<^1Xchk5ZD34MqmjL6M-#2ECkj7 zF%Z}T>_rd(um?d5z*YoN09z2m0sMzBP19}LwqMJA$D#nV);CSle2WISbaPeI1Y8;) zCP56qmUuA$TjNCl?1^U&us5DHK#X{{0I}j(0>q4G2M{}+6+nu3HUO#OSpcMrCl8Q1 zo-_bPJXrv&c#;5^@#Fxo<4FPJh$jP(E1nF1we}4F?v|UC0Dy8{IQy1ZJuD3XMIVI6^#0000 + + + + + + diff --git a/app/src/main/res/drawable/bt_activation_normnl.xml b/app/src/main/res/drawable/bt_activation_normnl.xml new file mode 100644 index 0000000..9cfee8e --- /dev/null +++ b/app/src/main/res/drawable/bt_activation_normnl.xml @@ -0,0 +1,15 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bt_activation_pressed.xml b/app/src/main/res/drawable/bt_activation_pressed.xml new file mode 100644 index 0000000..8551266 --- /dev/null +++ b/app/src/main/res/drawable/bt_activation_pressed.xml @@ -0,0 +1,15 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bt_activation_selector.xml b/app/src/main/res/drawable/bt_activation_selector.xml new file mode 100644 index 0000000..3b50ee2 --- /dev/null +++ b/app/src/main/res/drawable/bt_activation_selector.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bt_trial.xml b/app/src/main/res/drawable/bt_trial.xml new file mode 100644 index 0000000..70d5bee --- /dev/null +++ b/app/src/main/res/drawable/bt_trial.xml @@ -0,0 +1,15 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bt_vip.xml b/app/src/main/res/drawable/bt_vip.xml new file mode 100644 index 0000000..c22d1db --- /dev/null +++ b/app/src/main/res/drawable/bt_vip.xml @@ -0,0 +1,15 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/card_background.xml b/app/src/main/res/drawable/card_background.xml new file mode 100644 index 0000000..039758e --- /dev/null +++ b/app/src/main/res/drawable/card_background.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/join_background.xml b/app/src/main/res/drawable/join_background.xml new file mode 100644 index 0000000..75ac08f --- /dev/null +++ b/app/src/main/res/drawable/join_background.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/joined_background.xml b/app/src/main/res/drawable/joined_background.xml new file mode 100644 index 0000000..5e209a7 --- /dev/null +++ b/app/src/main/res/drawable/joined_background.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout-land/activity_main.xml b/app/src/main/res/layout-land/activity_main.xml index 9525238..8e205fd 100644 --- a/app/src/main/res/layout-land/activity_main.xml +++ b/app/src/main/res/layout-land/activity_main.xml @@ -8,434 +8,434 @@ android:fitsSystemWindows="true" tools:context=".activity.main.MainActivity"> - + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + + + + - - + + + + + + + + + + + + + - + + + + + + + + - + + + + - - + + + + + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + + + + + - + + + - + + + + + + + + + + + - + + + + + + + + + + + - - + + + + + + + + + + + - + + + + - + + + + + + + + + + + - + + + + + + + + + + + - - + + + + + + + + + + + - + + + - + + + + + + + + + + + - + + + + + + + + + + + - - + + + + + + + + + + + - + + + + + - + + + + + + + + + + + - + + + + + + + + + + + - - + + + + + + + + + + + - + + + + + - + + + + + + + + + + + - + + + + + + + + + + + - - + + + + + + + + + + + - + + + + + - + + + + + + + + + + + - + + + + + + + + + + - - + + + + + + + + + + + - + + + + - + + + + + + + + + + + - + + + + + + + + + + - - + + + + + + + + + + + -