In the project, we need to force the app to be updated to the latest version when the user opens the app.The download source is not google play, but the website provided by the company.
Since we are not downloading from the google play store, we must have our own api to determine whether the current app version is the latest version.
For security, the code about the api will not be shown here.
AndroidManifest
The following permissions need to be enabled
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
The following properties need to be set in
android:requestLegacyExternalStorage="true"
After Android Nougat (API 24), file paths must be shared across apps through FileProvider. FileProvider will hide the actual path of the file, making file sharing more secure.
Declare androidx.core.content.FileProvider in AndroidManifest.xml
FileProvider
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${packageName}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_provider_paths" />
</provider>
xml/file_provider_paths is used to define which directories can be accessed by other apps.
<paths>
<external-path path="Android/data/${packageName}/" name="files_root" />
<external-path path="." name="external_storage_root" />
</paths>
AutoUpdateService
Create a service file and don't forget to declare it in AndroidManifest.xml
<service
android:name=".AutoUpdateService"
android:exported="false" />
When the service is started in the activity and the downloaded apk is detected, it will be automatically installed.
Implement AutoUpdateService.java
public class AutoUpdateService extends Service{
private DownloadCompleteReceiver mReceiver;
public static ServiceState serviceState = ServiceState.IDLE;
public static enum ServiceState {
RUNNING,
IDLE
}
private long downloadCompleteId;
public class DownloadCompleteReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
downloadCompleteId = intent.getLongExtra(DownloadManager.ACTION_DOWNLOAD_COMPLETE, -1);
serviceState = ServiceState.IDLE;
reInstallApp();
stopSelf();
}
}
@Override
public void onCreate() {
super.onCreate();
mReceiver = new DownloadCompleteReceiver();
registerReceiver(mReceiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
}
@Override
public void onDestroy() {
super.onDestroy();
serviceState = ServiceState.IDLE;
unregisterReceiver(mReceiver);
}
private void reInstallApp() {
Intent intent = new Intent(Intent.ACTION_VIEW);
String apkFilePath = Environment.getExternalStorageDirectory() + "/" + Environment.DIRECTORY_DOWNLOADS + "/" + APKConfig.APK_NAME;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Uri contentUri = FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID + ".fileProvider", new File(apkFilePath));
intent.setDataAndType(contentUri, APKConfig.INSTALL_APK_DATA_TYPE);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_GRANT_READ_URI_PERMISSION);
} else {
intent.setDataAndType(Uri.fromFile(new File(apkFilePath)), APKConfig.INSTALL_APK_DATA_TYPE);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
startActivity(intent);
}
}