package com.ht.gate; import android.annotation.SuppressLint; import android.app.AlertDialog; import android.app.PendingIntent; import android.app.ProgressDialog; import android.content.ComponentName; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentSender; import android.content.ServiceConnection; import android.content.SharedPreferences; import android.content.pm.PackageInstaller; import android.net.Uri; import android.os.Bundle; import android.os.IBinder; import android.provider.Settings; import android.text.TextUtils; import android.util.Log; import android.view.View; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; import com.blankj.utilcode.constant.PermissionConstants; import com.blankj.utilcode.util.AppUtils; import com.blankj.utilcode.util.PathUtils; import com.blankj.utilcode.util.PermissionUtils; import com.blankj.utilcode.util.ToastUtils; import com.ht.gate.domain.QueryUpdate; import com.ht.gate.domain.Room; import com.ht.gate.domain.UpdateInfo; import com.liulishuo.okdownload.DownloadListener; import com.liulishuo.okdownload.DownloadTask; import com.liulishuo.okdownload.SpeedCalculator; import com.liulishuo.okdownload.StatusUtil; import com.liulishuo.okdownload.core.Util; import com.liulishuo.okdownload.core.breakpoint.BlockInfo; import com.liulishuo.okdownload.core.breakpoint.BreakpointInfo; import com.liulishuo.okdownload.core.cause.EndCause; import com.liulishuo.okdownload.core.cause.ResumeFailedCause; import com.liulishuo.okdownload.core.listener.DownloadListener4WithSpeed; import com.liulishuo.okdownload.core.listener.assist.Listener4SpeedAssistExtend; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.List; import java.util.Map; import butterknife.BindView; import butterknife.ButterKnife; import butterknife.OnClick; import es.dmoral.toasty.Toasty; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; @SuppressLint("SetTextI18n") public class SettingsActivity extends AppCompatActivity { private static final String TAG = "SettingsActivity"; @BindView(R.id.tv_title) TextView tvTitle; @BindView(R.id.tv_space_id) TextView tvSpaceId; @BindView(R.id.tv_address) TextView tvAddress; @BindView(R.id.tv_site_name) TextView tvSiteName; @BindView(R.id.tv_version) TextView tvVersion; public static final String PREF_NAME_SETTINGS = "settings"; public static final String PREF_KEY_ADDRESS = "address"; private SharedPreferences sharedPreferences; private DoorService.DoorBinder mDoorBinder; private ProgressDialog progressDialog; private ProgressDialog loadingDialog; private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { Log.d(TAG, "onServiceConnected"); mDoorBinder = (DoorService.DoorBinder) service; } @Override public void onServiceDisconnected(ComponentName name) { Log.d(TAG, "onServiceDisconnected"); mDoorBinder = null; } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_settings); ButterKnife.bind(this); sharedPreferences = getSharedPreferences(PREF_NAME_SETTINGS, MODE_PRIVATE); bindService(new Intent(this, DoorService.class), connection, BIND_AUTO_CREATE); progressDialog = new ProgressDialog(this, AlertDialog.THEME_DEVICE_DEFAULT_DARK); progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); progressDialog.setCanceledOnTouchOutside(false); progressDialog.setCancelable(false); progressDialog.setMessage("下载中"); progressDialog.setProgress(0); loadingDialog = new ProgressDialog(this, AlertDialog.THEME_DEVICE_DEFAULT_DARK); loadingDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); loadingDialog.setCanceledOnTouchOutside(false); loadingDialog.setCancelable(false); loadingDialog.setMessage("加载中"); } @Override protected void onResume() { super.onResume(); View decorView = getWindow().getDecorView(); int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_IMMERSIVE; decorView.setSystemUiVisibility(uiOptions); Room room = Room.fromBase64(sharedPreferences.getString(Constants.PREF_ROOM_INFO, null)); if (room != null) { tvTitle.setText(room.getRoomName() + room.getRoomBizNum()); tvSpaceId.setText(room.getDeviceCode()); if (!TextUtils.isEmpty(room.getSiteName())) { tvSiteName.setText(room.getSiteName()); tvSiteName.setVisibility(View.VISIBLE); } else { tvSiteName.setVisibility(View.GONE); } } tvAddress.setText(sharedPreferences.getString(PREF_KEY_ADDRESS, "")); tvVersion.setText(AppUtils.getAppVersionName() + " (" + AppUtils.getAppVersionCode() + ")"); } @Override protected void onDestroy() { super.onDestroy(); if (connection != null) { unbindService(connection); } } @OnClick(R.id.btn_back) void back() { finish(); } @OnClick(R.id.btn_change_space_id) void changeSpaceId() { Intent intent = new Intent(this, LoginActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); startActivity(intent); finish(); } @OnClick(R.id.btn_change_address) void changeAddress() { new PromptBuilder(this) .setTitle("输入空间门禁地址") .setValue(tvAddress.getText().toString()) .setPositiveButton("确定") .setNegativeButton("取消") .setPromptListener(new PromptBuilder.PromptListener() { @Override public void onCancel(DialogInterface dialog) { dialog.dismiss(); } @Override public void onConfirm(DialogInterface dialog, String value) { dialog.dismiss(); tvAddress.setText(value); sharedPreferences.edit() .putString(PREF_KEY_ADDRESS, value) .apply(); if (mDoorBinder != null) { mDoorBinder.getService().restartSocket(); } } }) .show(); } @OnClick(R.id.btn_update) void checkUpdate() { try { Room room = Room.fromBase64(sharedPreferences.getString(Constants.PREF_ROOM_INFO, null)); RetrofitManager.getInstance().getRetrofit().create(ApiService.class) .checkUpdate(new QueryUpdate(room.getSiteCode(), "02", AppUtils.getAppVersionCode() + "")) .enqueue(new Callback() { @Override public void onResponse(Call call, Response response) { loadingDialog.dismiss(); if (response.code() == 200) { if (response.body() == null) { Toasty.info(SettingsActivity.this, "暂无更新").show(); return; } if (response.body().getResultData().isNeedUpdate()) { new AlertDialog.Builder(SettingsActivity.this, AlertDialog.THEME_DEVICE_DEFAULT_DARK) .setTitle("新版本") .setMessage("检测到新版本" + response.body().getResultData().getNewestVersion() + ",是否立即下载更新?") .setNegativeButton("取消", (dialog0, which0) -> { dialog0.dismiss(); }) .setPositiveButton("下载", (dialog0, which0) -> { dialog0.dismiss(); PermissionUtils.permission(PermissionConstants.STORAGE) .rationale((activity, shouldRequest) -> new AlertDialog.Builder(activity, AlertDialog.THEME_DEVICE_DEFAULT_DARK) .setTitle("无写入权限") .setMessage("请前往设置打开存储权限") .setNegativeButton("取消", (dialog, which) -> { dialog.dismiss(); activity.finish(); }) .setPositiveButton("打开设置", (dialog, which) -> { dialog.dismiss(); Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); Uri uri = Uri.fromParts("package", getPackageName(), null); intent.setData(uri); intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); intent.addCategory(Intent.CATEGORY_DEFAULT); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); activity.startActivity(intent); activity.finish(); }).show()) .callback(new PermissionUtils.SimpleCallback() { @Override public void onGranted() { String url; if (response.body().getResultData().getSoftwareUrl().startsWith("http")) { url = response.body().getResultData().getSoftwareUrl(); } else { url = RetrofitManager.BASE_URL.replaceAll("/$", "") + response.body().getResultData().getSoftwareUrl(); } Log.d(TAG, "download Url: " + url); startDownload2(url); } @Override public void onDenied() { } }).request(); }).show(); } else { Toasty.info(SettingsActivity.this, "暂无更新").show(); } } } @Override public void onFailure(Call call, Throwable t) { loadingDialog.dismiss(); Toasty.info(SettingsActivity.this, "暂无更新").show(); } }); } catch (Exception e) { e.printStackTrace(); Toasty.info(SettingsActivity.this, e.getMessage()).show(); } // PermissionUtils.permission(PermissionConstants.STORAGE) // .rationale((activity, shouldRequest) -> new AlertDialog.Builder(activity, AlertDialog.THEME_DEVICE_DEFAULT_DARK) // .setTitle("无写入权限") // .setMessage("请前往设置打开存储权限") // .setNegativeButton("取消", (dialog, which) -> { // dialog.dismiss(); // activity.finish(); // }) // .setPositiveButton("打开设置", (dialog, which) -> { // dialog.dismiss(); // Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); // Uri uri = Uri.fromParts("package", getPackageName(), null); // intent.setData(uri); // intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); // intent.addCategory(Intent.CATEGORY_DEFAULT); // intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); // intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); // activity.startActivity(intent); // activity.finish(); // }).show()) // .callback(new PermissionUtils.SimpleCallback() { // @Override // public void onGranted() { // startDownload("https://beautiful-nanjing.oss-cn-hangzhou.aliyuncs.com/Coolapk-v10.2-2005181-coolapk-app-release.apk"); // } // // @Override // public void onDenied() { // // } // }).request(); } // private void startDownload(String url) { // FileDownloader.setup(SettingsActivity.this); // String ext = FilenameUtils.getExtension(url); // String fileName = System.currentTimeMillis() + ".apk"; // String path = PathUtils.getExternalAppDownloadPath() + "/" + fileName; // BaseDownloadTask downloadTask = FileDownloader.getImpl().create(url).setPath(path).setListener(new FileDownloadListener() { // @Override // protected void pending(BaseDownloadTask task, int soFarBytes, int totalBytes) { // // } // // @Override // protected void progress(BaseDownloadTask task, int soFarBytes, int totalBytes) { // Log.d(TAG, "download progress: " + soFarBytes + " / " + totalBytes); // progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); // progressDialog.setProgress((int) (soFarBytes * 100L / totalBytes)); // } // // @Override // protected void completed(BaseDownloadTask task) { // progressDialog.dismiss(); // ToastUtils.showShort("下载完成"); // installApk(new File(task.getPath())); // } // // @Override // protected void paused(BaseDownloadTask task, int soFarBytes, int totalBytes) { // } // // @Override // protected void error(BaseDownloadTask task, Throwable e) { // progressDialog.dismiss(); // ToastUtils.showShort(e.getMessage()); // } // // @Override // protected void warn(BaseDownloadTask task) { // // } // }); // progressDialog.setButton(ProgressDialog.BUTTON_NEGATIVE, "取消下载", (dialog, which) -> { // downloadTask.pause(); // progressDialog.dismiss(); // }); // progressDialog.setProgress(0); // progressDialog.show(); // downloadTask.start(); // } private void startDownload2(String url) { String fileName = System.currentTimeMillis() + ".apk"; DownloadTask task = new DownloadTask.Builder(url, PathUtils.getExternalAppDownloadPath(), fileName) .setMinIntervalMillisCallbackProcess(16) .setConnectionCount(1) // ignore the same task has already completed in the past. .setPassIfAlreadyCompleted(false) .build(); Util.enableConsoleLog(); // task.enqueue(new DownloadListener() { // @Override // public void taskStart(@NonNull DownloadTask task) { // Log.d(TAG, "taskStart"); // } // // @Override // public void connectTrialStart(@NonNull DownloadTask task, @NonNull Map> requestHeaderFields) { // Log.d(TAG, "connectTrialStart"); // } // // @Override // public void connectTrialEnd(@NonNull DownloadTask task, int responseCode, @NonNull Map> responseHeaderFields) { // Log.d(TAG, "connectTrialEnd"); // } // // @Override // public void downloadFromBeginning(@NonNull DownloadTask task, @NonNull BreakpointInfo info, @NonNull ResumeFailedCause cause) { // Log.d(TAG, "downloadFromBeginning"); // } // // @Override // public void downloadFromBreakpoint(@NonNull DownloadTask task, @NonNull BreakpointInfo info) { // Log.d(TAG, "downloadFromBreakpoint"); // } // // @Override // public void connectStart(@NonNull DownloadTask task, int blockIndex, @NonNull Map> requestHeaderFields) { // Log.d(TAG, "connectStart"); // } // // @Override // public void connectEnd(@NonNull DownloadTask task, int blockIndex, int responseCode, @NonNull Map> responseHeaderFields) { // Log.d(TAG, "connectEnd"); // } // // @Override // public void fetchStart(@NonNull DownloadTask task, int blockIndex, long contentLength) { // // Log.d(TAG, String.format("fetchStart blockIndex %s contentLength %s", blockIndex, contentLength)); // } // // @Override // public void fetchProgress(@NonNull DownloadTask task, int blockIndex, long increaseBytes) { // Log.d(TAG, String.format("fetchProgress blockIndex %s increaseBytes %s", blockIndex, increaseBytes)); // } // // @Override // public void fetchEnd(@NonNull DownloadTask task, int blockIndex, long contentLength) { // Log.d(TAG, "fetchEnd"); // } // // @Override // public void taskEnd(@NonNull DownloadTask task, @NonNull EndCause cause, @Nullable Exception realCause) { // Log.d(TAG, "taskEnd"); // } // }); progressDialog.setButton(ProgressDialog.BUTTON_NEGATIVE, "取消下载", (dialog, which) -> { task.cancel(); progressDialog.dismiss(); }); progressDialog.setProgress(0); progressDialog.show(); final long[] totalLength = {0}; task.enqueue(new DownloadListener4WithSpeed() { @Override public void taskStart(@NonNull DownloadTask task) { Log.d(TAG, "taskStart"); } @Override public void connectStart(@NonNull DownloadTask task, int blockIndex, @NonNull Map> requestHeaderFields) { Log.d(TAG, "connectStart"); } @Override public void connectEnd(@NonNull DownloadTask task, int blockIndex, int responseCode, @NonNull Map> responseHeaderFields) { Log.d(TAG, "connectEnd"); } @Override public void infoReady(@NonNull DownloadTask task, @NonNull BreakpointInfo info, boolean fromBreakpoint, @NonNull Listener4SpeedAssistExtend.Listener4SpeedModel model) { totalLength[0] = info.getTotalLength(); Log.d(TAG, "infoReady"); } @Override public void progressBlock(@NonNull DownloadTask task, int blockIndex, long currentBlockOffset, @NonNull SpeedCalculator blockSpeed) { Log.d(TAG, "progressBlock"); } @Override public void progress(@NonNull DownloadTask task, long currentOffset, @NonNull SpeedCalculator taskSpeed) { Log.d(TAG, String.format("progress currentOffset %s ", currentOffset)); progressDialog.setProgress((int) (currentOffset * 100 / totalLength[0])); } @Override public void blockEnd(@NonNull DownloadTask task, int blockIndex, BlockInfo info, @NonNull SpeedCalculator blockSpeed) { Log.d(TAG, "blockEnd"); } @Override public void taskEnd(@NonNull DownloadTask task, @NonNull EndCause cause, @Nullable Exception realCause, @NonNull SpeedCalculator taskSpeed) { Log.d(TAG, "taskEnd"); progressDialog.dismiss(); if (cause == EndCause.COMPLETED) { installApk(task.getFile()); } else { Toasty.info(SettingsActivity.this, cause.name()).show(); } } }); } private void installApk(File apkFile) { // Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE); // intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); // intent.setDataAndType(FileProvider.getUriForFile(SettingsActivity.this, // "com.ht.gate.fileProvider", apkFile), "application/vnd.android.package-archive"); // startActivity(intent); AppUtils.installApp(apkFile); // try { // installPackage(apkFile.getPath()); // } catch (IOException e) { // e.printStackTrace(); // } } public void installPackage(String filename) throws IOException { PackageInstaller packageInstaller = getApplicationContext().getPackageManager().getPackageInstaller(); Log.i(TAG, "JIntentActionInstallApk - got packageInstaller"); PackageInstaller.SessionParams params = new PackageInstaller.SessionParams( PackageInstaller.SessionParams.MODE_FULL_INSTALL); Log.i(TAG, "JIntentActionInstallApk - set SessionParams"); int sessionId = packageInstaller.createSession(params); PackageInstaller.Session session = packageInstaller.openSession(sessionId); Log.i(TAG, "JIntentActionInstallApk - session opened"); // Create an install status receiver. Context context = getApplicationContext(); addApkToInstallSession(context, filename, session); Log.i(TAG, "JIntentActionInstallApk - apk added to session"); Intent intent = new Intent(context, MainActivity.class); intent.setAction("PACKAGE_INSTALLED_ACTION"); PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0); IntentSender statusReceiver = pendingIntent.getIntentSender(); // Commit the session (this will start the installation workflow). session.commit(statusReceiver); Log.i(TAG, "JIntentActionInstallApk - commited"); } private static void addApkToInstallSession(Context context, String filename, PackageInstaller.Session session) { Log.i(TAG, "addApkToInstallSession " + filename); // It's recommended to pass the file size to openWrite(). Otherwise installation may fail // if the disk is almost full. try { OutputStream packageInSession = session.openWrite("package", 0, -1); InputStream input; Uri uri = Uri.parse(filename); input = context.getContentResolver().openInputStream(uri); if (input != null) { Log.i(TAG, "input.available: " + input.available()); byte[] buffer = new byte[16384]; int n; while ((n = input.read(buffer)) >= 0) { packageInSession.write(buffer, 0, n); } } else { Log.i(TAG, "addApkToInstallSession failed"); throw new IOException("addApkToInstallSession"); } packageInSession.close(); //need to close this stream input.close(); //need to close this stream } catch (Exception e) { Log.i(TAG, "addApkToInstallSession failed2 " + e.toString()); } } }