Force update to latest version


Posted by Limon on 2022-04-11

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);
    }
}

#Android #force update







Related Posts

Nand2tetris第一週心得

Nand2tetris第一週心得

SSR vs CSR

SSR vs CSR

Object Recognition Kitchen 透明物體辨識(演算法概念)

Object Recognition Kitchen 透明物體辨識(演算法概念)


Comments