drew 5 tahun lalu
induk
melakukan
b6bb54d378

+ 8 - 0
.idea/compiler.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="CompilerConfiguration">
+    <annotationProcessing>
+      <profile default="true" name="Default" enabled="true" />
+    </annotationProcessing>
+  </component>
+</project>

+ 5 - 0
app/build.gradle

@@ -54,4 +54,9 @@ dependencies {
     implementation 'com.zy.mocknet:mocknet:1.0'
     implementation 'cat.ereza:customactivityoncrash:2.2.0'
     implementation 'org.xutils:xutils:3.8.3'
+    implementation 'com.blankj:utilcodex:1.28.4'
+    implementation 'com.liulishuo.filedownloader:library:1.7.7'
+    implementation group: 'org.apache.commons', name: 'commons-io', version: '1.3.2'
+    implementation 'com.liulishuo.okdownload:okdownload:1.0.7'
+    implementation 'com.liulishuo.okdownload:sqlite:1.0.7'
 }

+ 13 - 0
app/src/main/AndroidManifest.xml

@@ -6,6 +6,9 @@
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
     <uses-permission android:name="android.permission.INTERNET" />
     <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
 
     <application
         android:name=".MyApplication"
@@ -44,6 +47,16 @@
         <activity android:name=".WelcomeActivity" />
         <activity android:name=".MainActivity" />
         <activity android:name=".LoginActivity" />
+
+        <provider
+            android:name="androidx.core.content.FileProvider"
+            android:authorities="com.ht.gate.fileProvider"
+            android:exported="false"
+            android:grantUriPermissions="true">
+            <meta-data
+                android:name="android.support.FILE_PROVIDER_PATHS"
+                android:resource="@xml/file_provider" />
+        </provider>
     </application>
 
 </manifest>

+ 4 - 0
app/src/main/java/com/ht/gate/ApiService.java

@@ -1,7 +1,9 @@
 package com.ht.gate;
 
+import com.ht.gate.domain.QueryUpdate;
 import com.ht.gate.domain.Room;
 import com.ht.gate.domain.RoomMeetings;
+import com.ht.gate.domain.UpdateInfo;
 import com.ht.gate.domain.emp.EmpInfo;
 
 import java.util.List;
@@ -24,4 +26,6 @@ public interface ApiService {
     @GET("getEmpInfoData")
     Call<EmpInfo> getEmpInfo(@Query("empId") String empId);
 
+    @POST("api/software/getLatestVersion")
+    Call<UpdateInfo> checkUpdate(@Body QueryUpdate queryUpdate);
 }

+ 2 - 2
app/src/main/java/com/ht/gate/RetrofitManager.java

@@ -12,8 +12,8 @@ import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
 import retrofit2.converter.gson.GsonConverterFactory;
 
 public class RetrofitManager {
-    //    private final String BASE_URL = "http://localhost:8080/";
-    private final String BASE_URL = "http://screen.crm.htsc:30000/";
+    public static final String BASE_URL = "http://168.63.70.94:30000/";
+    //    public static final String BASE_URL = "http://screen.crm.htsc:30000/";
     private static RetrofitManager sInstance;
     private Retrofit mRetrofit;
 

+ 241 - 0
app/src/main/java/com/ht/gate/SettingsActivity.java

@@ -1,25 +1,69 @@
 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.Build;
 import android.os.Bundle;
+import android.os.Environment;
 import android.os.IBinder;
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.View;
 import android.widget.TextView;
+import android.widget.Toast;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.appcompat.app.AppCompatActivity;
+import androidx.core.content.FileProvider;
 
+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.UtilsTransActivity;
+import com.ht.gate.domain.QueryUpdate;
 import com.ht.gate.domain.Room;
+import com.ht.gate.domain.UpdateInfo;
+import com.liulishuo.filedownloader.BaseDownloadTask;
+import com.liulishuo.filedownloader.FileDownloadListener;
+import com.liulishuo.filedownloader.FileDownloader;
+import com.liulishuo.okdownload.DownloadListener;
+import com.liulishuo.okdownload.DownloadTask;
+import com.liulishuo.okdownload.StatusUtil;
+import com.liulishuo.okdownload.core.breakpoint.BreakpointInfo;
+import com.liulishuo.okdownload.core.cause.EndCause;
+import com.liulishuo.okdownload.core.cause.ResumeFailedCause;
+
+import org.apache.commons.io.FilenameUtils;
+import org.xutils.x;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.file.Paths;
+import java.util.List;
+import java.util.Map;
 
 import butterknife.BindView;
 import butterknife.ButterKnife;
 import butterknife.OnClick;
+import retrofit2.Call;
+import retrofit2.Callback;
+import retrofit2.Response;
 
 @SuppressLint("SetTextI18n")
 public class SettingsActivity extends AppCompatActivity {
@@ -33,6 +77,8 @@ public class SettingsActivity extends AppCompatActivity {
     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";
@@ -83,6 +129,7 @@ public class SettingsActivity extends AppCompatActivity {
             }
         }
         tvAddress.setText(sharedPreferences.getString(PREF_KEY_ADDRESS, ""));
+        tvVersion.setText(AppUtils.getAppVersionName() + " (" + AppUtils.getAppVersionCode() + ")");
     }
 
     @Override
@@ -135,4 +182,198 @@ public class SettingsActivity extends AppCompatActivity {
                 .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<UpdateInfo>() {
+//                        @Override
+//                        public void onResponse(Call<UpdateInfo> call, Response<UpdateInfo> response) {
+//                            if (response.code() == 200) {
+//                                if (response.body() == null) {
+//                                    return;
+//                                }
+//                                if (response.body().getResultData().isNeedUpdate()) {
+//                                    PermissionUtils.permission(PermissionConstants.STORAGE).rationale(new PermissionUtils.OnRationaleListener() {
+//                                        @Override
+//                                        public void rationale(UtilsTransActivity activity, ShouldRequest shouldRequest) {
+//                                        }
+//                                    }).callback(new PermissionUtils.SimpleCallback() {
+//                                        @Override
+//                                        public void onGranted() {
+//                                            startDownload(RetrofitManager.BASE_URL.replaceAll("/$", "") + response.body().getResultData().getSoftwareUrl());
+//                                        }
+//
+//                                        @Override
+//                                        public void onDenied() {
+//
+//                                        }
+//                                    }).request();
+//                                }
+//                            }
+//                        }
+//
+//                        @Override
+//                        public void onFailure(Call<UpdateInfo> call, Throwable t) {
+//
+//                        }
+//                    });
+//        } catch (Exception e) {
+//            e.printStackTrace();
+//        }
+//        startDownload("http://dl-cdn.coolapkmarket.com/down/apk_file/2020/0518/Coolapk-v10.2-2005181-coolapk-app-release.apk");
+        installApk(new File("file:///sdcard/Android/data/com.ht.gate/files/Download/1589872246972.apk"));
+    }
+
+    private void startDownload(String url) {
+        FileDownloader.setup(SettingsActivity.this);
+        ProgressDialog 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);
+        String ext = FilenameUtils.getExtension(url);
+        String fileName = System.currentTimeMillis() + "." + ext;
+        progressDialog.show();
+        new DownloadTask.Builder(url, new File(PathUtils.getExternalAppDownloadPath()))
+                .setFilename(fileName)
+                // the minimal interval millisecond for callback progress
+                .setMinIntervalMillisCallbackProcess(16)
+                // ignore the same task has already completed in the past.
+                .setPassIfAlreadyCompleted(false)
+                .build()
+                .enqueue(new DownloadListener() {
+                    @Override
+                    public void taskStart(@NonNull DownloadTask task) {
+
+                    }
+
+                    @Override
+                    public void connectTrialStart(@NonNull DownloadTask task, @NonNull Map<String, List<String>> requestHeaderFields) {
+
+                    }
+
+                    @Override
+                    public void connectTrialEnd(@NonNull DownloadTask task, int responseCode, @NonNull Map<String, List<String>> responseHeaderFields) {
+
+                    }
+
+                    @Override
+                    public void downloadFromBeginning(@NonNull DownloadTask task, @NonNull BreakpointInfo info, @NonNull ResumeFailedCause cause) {
+
+                    }
+
+                    @Override
+                    public void downloadFromBreakpoint(@NonNull DownloadTask task, @NonNull BreakpointInfo info) {
+
+                    }
+
+                    @Override
+                    public void connectStart(@NonNull DownloadTask task, int blockIndex, @NonNull Map<String, List<String>> requestHeaderFields) {
+
+                    }
+
+                    @Override
+                    public void connectEnd(@NonNull DownloadTask task, int blockIndex, int responseCode, @NonNull Map<String, List<String>> responseHeaderFields) {
+
+                    }
+
+                    @Override
+                    public void fetchStart(@NonNull DownloadTask task, int blockIndex, long contentLength) {
+
+                    }
+
+                    @Override
+                    public void fetchProgress(@NonNull DownloadTask task, int blockIndex, long increaseBytes) {
+                        long total = StatusUtil.getCurrentInfo(task).getTotalLength();
+                        long current = StatusUtil.getCurrentInfo(task).getTotalOffset();
+                        if (total != 0)
+                            progressDialog.setProgress((int) (current * 100 / total));
+                    }
+
+                    @Override
+                    public void fetchEnd(@NonNull DownloadTask task, int blockIndex, long contentLength) {
+                        progressDialog.dismiss();
+                        Log.d("xxxx", "fetchEnd");
+
+                        installApk(new File(PathUtils.getExternalAppDownloadPath() + fileName));
+                    }
+
+                    @Override
+                    public void taskEnd(@NonNull DownloadTask task, @NonNull EndCause cause, @Nullable Exception realCause) {
+                        progressDialog.dismiss();
+                        Log.d("xxxx", "taskEnd");
+                    }
+                });
+    }
+
+    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());
+        }
+    }
 }

+ 37 - 0
app/src/main/java/com/ht/gate/domain/QueryUpdate.java

@@ -0,0 +1,37 @@
+package com.ht.gate.domain;
+
+public class QueryUpdate {
+    private String hallId;
+    private String typeCode;
+    private String currentVersion;
+
+    public QueryUpdate(String hallId, String typeCode, String currentVersion) {
+        this.hallId = hallId;
+        this.typeCode = typeCode;
+        this.currentVersion = currentVersion;
+    }
+
+    public String getHallId() {
+        return hallId;
+    }
+
+    public void setHallId(String hallId) {
+        this.hallId = hallId;
+    }
+
+    public String getTypeCode() {
+        return typeCode;
+    }
+
+    public void setTypeCode(String type) {
+        this.typeCode = type;
+    }
+
+    public String getCurrentVersion() {
+        return currentVersion;
+    }
+
+    public void setCurrentVersion(String currentVersion) {
+        this.currentVersion = currentVersion;
+    }
+}

+ 10 - 0
app/src/main/java/com/ht/gate/domain/UpdateData.java

@@ -0,0 +1,10 @@
+package com.ht.gate.domain;
+
+import lombok.Data;
+
+@Data
+public class UpdateData {
+    private boolean needUpdate;
+    private String softwareUrl;
+    private Integer newestVersion;
+}

+ 10 - 0
app/src/main/java/com/ht/gate/domain/UpdateInfo.java

@@ -0,0 +1,10 @@
+package com.ht.gate.domain;
+
+import lombok.Data;
+
+@Data
+public class UpdateInfo {
+    private String msg;
+    private String code;
+    private UpdateData resultData;
+}

+ 2 - 1
app/src/main/res/layout/activity_settings.xml

@@ -193,15 +193,16 @@
                 android:textSize="18sp" />
 
             <TextView
+                android:id="@+id/tv_version"
                 android:layout_width="0dp"
                 android:layout_height="wrap_content"
                 android:layout_weight="1"
                 android:fontFamily="@font/source_han_sans_sc_medium"
-                android:text="V1.0.0"
                 android:textColor="@android:color/white"
                 android:textSize="18sp" />
 
             <Button
+                android:id="@+id/btn_update"
                 style="@style/Widget.AppCompat.Button.Borderless"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"

+ 56 - 0
app/src/main/res/xml/file_provider.xml

@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <paths>
+        <root-path
+            name="root_path"
+            path="" />
+
+        <files-path
+            name="files_path"
+            path="." />
+
+        <cache-path
+            name="cache_path"
+            path="." />
+
+        <external-path
+            name="external_path"
+            path="." />
+
+        <external-files-path
+            name="external_files_path"
+            path="." />
+
+        <external-cache-path
+            name="external_cache_path"
+            path="." />
+
+        <external-media-path
+            name="external_media_path"
+            path="." />
+
+        <files-path
+            name="files_path1"
+            path="Android/data/com.ht.gate/files/Download" />
+
+        <cache-path
+            name="cache_path1"
+            path="Android/data/com.ht.gate/files/Download" />
+
+        <external-path
+            name="external_path1"
+            path="Android/data/com.ht.gate/files/Download" />
+
+        <external-files-path
+            name="external_files_path1"
+            path="Android/data/com.ht.gate/files/Download" />
+
+        <external-cache-path
+            name="external_cache_path1"
+            path="Android/data/com.ht.gate/files/Download" />
+
+        <external-media-path
+            name="external_media_path1"
+            path="Android/data/com.ht.gate/files/Download" />
+    </paths>
+</resources>