APP内升级功能

This commit is contained in:
tongchao 2025-06-23 17:18:23 +08:00
parent c90376ab01
commit 989ff635c6
10 changed files with 327 additions and 21 deletions

View File

@ -139,5 +139,4 @@ dependencies {
implementation 'xyz.doikki.android.dkplayer:dkplayer-ui:3.3.7' implementation 'xyz.doikki.android.dkplayer:dkplayer-ui:3.3.7'
//使ijkplayer进行解码 //使ijkplayer进行解码
implementation 'xyz.doikki.android.dkplayer:player-ijk:3.3.7' implementation 'xyz.doikki.android.dkplayer:player-ijk:3.3.7'
} }

View File

@ -1,20 +0,0 @@
{
"version": 3,
"artifactType": {
"type": "APK",
"kind": "Directory"
},
"applicationId": "com.tairui.industrial_operation",
"variantName": "release",
"elements": [
{
"type": "SINGLE",
"filters": [],
"attributes": [],
"versionCode": 1,
"versionName": "1.0",
"outputFile": "IndustrialOperation_app_v1.0_20250610153115.apk"
}
],
"elementType": "File"
}

View File

@ -144,6 +144,16 @@
android:exported="false" android:exported="false"
android:screenOrientation="portrait" /> android:screenOrientation="portrait" />
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
</application> </application>
</manifest> </manifest>

View File

@ -30,6 +30,8 @@ public class Api {
public static final String REGISTER = BASE_HOST + "/auth/registerApp"; public static final String REGISTER = BASE_HOST + "/auth/registerApp";
public static final String LOGIN = BASE_HOST + "/auth/login"; public static final String LOGIN = BASE_HOST + "/auth/login";
public static final String UPDATE_APP = BASE_HOST + "/checkUpdate";
public static final String HOME_GOODS_LIST = BASE_HOST + "/goods/goodInfoManage/transactionGoodInfo"; public static final String HOME_GOODS_LIST = BASE_HOST + "/goods/goodInfoManage/transactionGoodInfo";
} }

View File

@ -1,23 +1,41 @@
package com.tairui.industrial_operation.ui; package com.tairui.industrial_operation.ui;
import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import com.flyco.tablayout.listener.CustomTabEntity; import com.flyco.tablayout.listener.CustomTabEntity;
import com.flyco.tablayout.listener.OnTabSelectListener; import com.flyco.tablayout.listener.OnTabSelectListener;
import com.gyf.immersionbar.ImmersionBar; import com.gyf.immersionbar.ImmersionBar;
import com.rxjava.rxlife.RxLife;
import com.tairui.industrial_operation.BuildConfig;
import com.tairui.industrial_operation.R; import com.tairui.industrial_operation.R;
import com.tairui.industrial_operation.base.BaseActivity; import com.tairui.industrial_operation.base.BaseActivity;
import com.tairui.industrial_operation.base.BaseFragment; import com.tairui.industrial_operation.base.BaseFragment;
import com.tairui.industrial_operation.base.adapter.TabFragmentPagerAdapter; import com.tairui.industrial_operation.base.adapter.TabFragmentPagerAdapter;
import com.tairui.industrial_operation.databinding.ActivityMainBinding; import com.tairui.industrial_operation.databinding.ActivityMainBinding;
import com.tairui.industrial_operation.entity.Api;
import com.tairui.industrial_operation.entity.TabEntity; import com.tairui.industrial_operation.entity.TabEntity;
import com.tairui.industrial_operation.http.OnError;
import com.tairui.industrial_operation.ui.home.HomeFragment; import com.tairui.industrial_operation.ui.home.HomeFragment;
import com.tairui.industrial_operation.ui.my.MyFragment; import com.tairui.industrial_operation.ui.my.MyFragment;
import com.tairui.industrial_operation.ui.service.ServiceFragment; import com.tairui.industrial_operation.ui.service.ServiceFragment;
import com.tairui.industrial_operation.ui.shopping.ShoppingFragment; import com.tairui.industrial_operation.ui.shopping.ShoppingFragment;
import com.tairui.industrial_operation.util.DownloadUtil;
import com.tairui.industrial_operation.util.LogUtil;
import com.tairui.industrial_operation.util.NetUtil;
import com.tairui.industrial_operation.util.ToastUtil;
import com.tairui.industrial_operation.widget.CustomProgressDialog;
import android.app.AlertDialog;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.text.TextUtils;
import androidx.core.content.FileProvider;
import androidx.viewpager.widget.ViewPager; import androidx.viewpager.widget.ViewPager;
import io.reactivex.android.schedulers.AndroidSchedulers;
import rxhttp.RxHttp;
public class MainActivity extends BaseActivity<ActivityMainBinding> { public class MainActivity extends BaseActivity<ActivityMainBinding> {
@ -28,6 +46,8 @@ public class MainActivity extends BaseActivity<ActivityMainBinding> {
private ArrayList<CustomTabEntity> mTabEntities = new ArrayList<>(); private ArrayList<CustomTabEntity> mTabEntities = new ArrayList<>();
private TabFragmentPagerAdapter mPagerAdapter; private TabFragmentPagerAdapter mPagerAdapter;
private CustomProgressDialog downloadDialog;
@Override @Override
protected void initStatusBar() { protected void initStatusBar() {
ImmersionBar.with(this).fitsSystemWindows(false).transparentStatusBar() ImmersionBar.with(this).fitsSystemWindows(false).transparentStatusBar()
@ -111,4 +131,124 @@ public class MainActivity extends BaseActivity<ActivityMainBinding> {
}); });
} }
@Override
protected void onApplyData() {
// getAppVersionInfo();
}
/**
* 获取线上APP的版本信息
*/
private void getAppVersionInfo() {
RxHttp.get(Api.UPDATE_APP)
.asResponse(Object.class)
.as(RxLife.asOnMain(this))
.subscribe(data -> {
//TODO
}, (OnError) error -> {
LogUtil.e("getAppVersionInfo", error.getErrorMsg());
});
}
/**
* @param grade app 的下载级别
* @param appDownloadUrl app 的下载地址
* @param remark 描述
*/
private void showUpdateDialog(int grade, final String appDownloadUrl, String remark) {
if (grade == 1) { // 强制更新
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(getString(R.string.str_hint_update));
builder.setMessage(remark);
builder.setPositiveButton(getString(R.string.str_confirm), (dialog, which) -> {
if (!isFinishing()) {
doAppDownload(appDownloadUrl);
}
dialog.dismiss();
});
builder.setCancelable(false);
builder.create().show();
} else { // 非强制更新
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(getString(R.string.str_hint_update));
builder.setMessage(remark);
builder.setPositiveButton(getString(R.string.str_confirm), (dialog, which) -> {
if (!isFinishing()) {
doAppDownload(appDownloadUrl);
}
dialog.dismiss();
});
builder.setNegativeButton(getString(R.string.str_cancel), (dialog, which) -> {
});
builder.create().show();
}
}
/**
* 下载新版本的apk
*/
private void doAppDownload(String appUrl) {
if (NetUtil.isNetworkConnected(this)) {
if (downloadDialog == null) {
downloadDialog = new CustomProgressDialog(this, getString(R.string.str_download_app));
downloadDialog.setCancelable(false);
}
downloadDialog.show();
//文件存储路径
String dir = DownloadUtil.getDownloadDir(mContext);
String fileName = System.currentTimeMillis() + ".apk";
String destPath = dir + "/" + fileName;
RxHttp.get(appUrl)
.asAppendDownload(destPath, AndroidSchedulers.mainThread(), progress -> {
//下载进度回调,0-100仅在进度有更新时才会回调
int currentProgress = progress.getProgress(); //当前进度 0-100
long currentSize = progress.getCurrentSize(); //当前已下载的字节大小
long totalSize = progress.getTotalSize(); //要下载的总字节大小
if (null != downloadDialog) {
downloadDialog.setProgress(currentProgress);
}
}) //指定主线程回调
.doFinally(() -> {
if (null != downloadDialog) {
downloadDialog.dismiss();
}
})
.subscribe(s -> { //s为String类型
// 下载成功进行安装
if (!TextUtils.isEmpty(s)) {
installApk(new File(s));
}
}, throwable -> {
if (null != downloadDialog) {
downloadDialog.dismiss();
}
});
} else {
ToastUtil.showShortToast(getString(R.string.network_error));
}
}
/**
* 安装 APK
*/
private void installApk(File file) {
try {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Uri data;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
data = FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID + ".fileprovider", file);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
} else {
data = Uri.fromFile(file);
}
intent.setDataAndType(data, "application/vnd.android.package-archive");
startActivity(intent);
} catch (Exception e) {
e.printStackTrace();
}
}
} }

View File

@ -0,0 +1,36 @@
package com.tairui.industrial_operation.util;
import android.content.Context;
import android.os.Environment;
public class DownloadUtil {
public static String getPictureDir(Context context) {
return context.getExternalFilesDir(Environment.DIRECTORY_PICTURES).getAbsolutePath();
}
public static String getMovieDir(Context context) {
return context.getExternalFilesDir(Environment.DIRECTORY_MOVIES).getAbsolutePath();
}
public static String getMusicDir(Context context) {
return context.getExternalFilesDir(Environment.DIRECTORY_MUSIC).getAbsolutePath();
}
public static String getDcimDir(Context context) {
return context.getExternalFilesDir(Environment.DIRECTORY_DCIM).getAbsolutePath();
}
public static String getDownloadDir(Context context) {
return context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath();
}
public static String getDocumentsDir(Context context) {
return context.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS).getAbsolutePath();
}
public static String getDbDir(Context context) {
return context.getExternalFilesDir("Databases").getAbsolutePath();
}
}

View File

@ -0,0 +1,89 @@
package com.tairui.industrial_operation.util;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
/**
* 网络工具类
* 判断是否有网络
* 网络的状态
*/
public class NetUtil {
/**
* 判断网络连接状态
*
* @param context 上下文对象
* @return 网络是否连接
*/
public static boolean isNetworkConnected(Context context) {
if (context != null) {
ConnectivityManager connectivityManager = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connectivityManager
.getActiveNetworkInfo();
if (networkInfo != null) {
return networkInfo.isAvailable();
}
}
return false;
}
/**
* 网络状态是否为 WIFI
*
* @param context 上下文对象
* @return 是否 WIFI 网络
*/
public static boolean isWifiConnected(Context context) {
if (context != null) {
ConnectivityManager mConnectivityManager = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo mWiFiNetworkInfo = mConnectivityManager
.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
if (mWiFiNetworkInfo != null) {
return mWiFiNetworkInfo.isAvailable();
}
}
return false;
}
/**
* 网络状态是否为数据流量
*
* @param context 上下文对象
* @return 是否为数据流量
*/
public static boolean isMobileConnected(Context context) {
if (context != null) {
ConnectivityManager mConnectivityManager = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo mMobileNetworkInfo = mConnectivityManager
.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
if (mMobileNetworkInfo != null) {
return mMobileNetworkInfo.isAvailable();
}
}
return false;
}
/**
* 获取网络连接类型
*
* @param context 上下文对象
* @return 网络连接状态
*/
public static int getConnectedType(Context context) {
if (context != null) {
ConnectivityManager mConnectivityManager = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo mNetworkInfo = mConnectivityManager
.getActiveNetworkInfo();
if (mNetworkInfo != null && mNetworkInfo.isAvailable()) {
return mNetworkInfo.getType();
}
}
return -1;
}
}

View File

@ -0,0 +1,37 @@
package com.tairui.industrial_operation.widget;
import android.app.ProgressDialog;
import android.content.Context;
public class CustomProgressDialog extends ProgressDialog {
public CustomProgressDialog(Context context) {
super(context);
setMessage("loading...");
setMax(100);
setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
setCanceledOnTouchOutside(false);
setCancelable(true);
}
public CustomProgressDialog(Context context, String title) {
super(context);
setMessage(title);
setMax(100);
setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
setCanceledOnTouchOutside(false);
setCancelable(true);
}
@Override
public void dismiss() {
super.dismiss();
setProgress(0);
}
@Override
public void cancel() {
super.cancel();
setProgress(0);
}
}

View File

@ -7,4 +7,10 @@
<string name="time_out_please_try_again_later">网络连接超时,请稍后再试</string> <string name="time_out_please_try_again_later">网络连接超时,请稍后再试</string>
<string name="str_no_content">空空如也~</string> <string name="str_no_content">空空如也~</string>
<string name="str_download_app">软件下载中...</string>
<string name="str_hint_update">更新提示</string>
<string name="str_confirm">确定</string>
<string name="str_cancel">取消</string>
</resources> </resources>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<paths>
<!--所有路径-->
<external-path
name="external_storage_root"
path="." />
</paths>