Search in sources :

Example 11 with Apk

use of org.fdroid.fdroid.data.Apk in project fdroidclient by f-droid.

the class AppDetailsActivity method uninstallApk.

/**
 * Uninstall the app from the current screen.  Since there are many ways
 * to uninstall an app, including from Google Play, {@code adb uninstall},
 * or Settings -> Apps, this method cannot ever be sure that the app isn't
 * already being uninstalled.  So it needs to check that we can actually
 * get info on the installed app, otherwise, just call it interrupted and
 * quit.
 *
 * @see <a href="https://gitlab.com/fdroid/fdroidclient/issues/1435">issue #1435</a>
 */
@Override
public void uninstallApk() {
    Apk apk = app.installedApk;
    if (apk == null) {
        apk = app.getMediaApkifInstalled(getApplicationContext());
        if (apk == null) {
            // When the app isn't a media file - the above workaround refers to this.
            apk = app.getInstalledApk(this);
            if (apk == null) {
                Log.d(TAG, "Couldn't find installed apk for " + app.packageName);
                Toast.makeText(this, R.string.uninstall_error_unknown, Toast.LENGTH_SHORT).show();
                uninstallReceiver.onReceive(this, new Intent(Installer.ACTION_UNINSTALL_INTERRUPTED));
                return;
            }
        }
        app.installedApk = apk;
    }
    Installer installer = InstallerFactory.create(this, apk);
    Intent intent = installer.getUninstallScreen();
    if (intent != null) {
        // uninstall screen required
        Utils.debugLog(TAG, "screen screen required");
        startActivityForResult(intent, REQUEST_UNINSTALL_DIALOG);
        return;
    }
    startUninstall();
}
Also used : Installer(org.fdroid.fdroid.installer.Installer) PendingIntent(android.app.PendingIntent) Intent(android.content.Intent) Apk(org.fdroid.fdroid.data.Apk)

Example 12 with Apk

use of org.fdroid.fdroid.data.Apk in project fdroidclient by f-droid.

the class AppDetailsActivity method onActivityResult.

/*
    private void shareApkBluetooth() {
        // If Bluetooth has not been enabled/turned on, then
        // enabling device discoverability will automatically enable Bluetooth
        Intent discoverBt = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
        discoverBt.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 121);
        startActivityForResult(discoverBt, REQUEST_ENABLE_BLUETOOTH);
        // if this is successful, the Bluetooth transfer is started
    }
     */
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    switch(requestCode) {
        case REQUEST_ENABLE_BLUETOOTH:
            fdroidApp.sendViaBluetooth(this, resultCode, app.packageName);
            break;
        case REQUEST_PERMISSION_DIALOG:
            if (resultCode == AppCompatActivity.RESULT_OK) {
                Uri uri = data.getData();
                Apk apk = ApkProvider.Helper.findByUri(this, uri, Schema.ApkTable.Cols.ALL);
                InstallManagerService.queue(this, app, apk);
            }
            break;
        case REQUEST_UNINSTALL_DIALOG:
            if (resultCode == AppCompatActivity.RESULT_OK) {
                startUninstall();
            }
            break;
    }
}
Also used : Uri(android.net.Uri) Apk(org.fdroid.fdroid.data.Apk)

Example 13 with Apk

use of org.fdroid.fdroid.data.Apk in project fdroidclient by f-droid.

the class InstallManagerService method registerInstallReceiver.

/**
 * Register a {@link BroadcastReceiver} for tracking install progress for a
 * give {@link Uri}.  There can be multiple of these registered at a time.
 */
private void registerInstallReceiver(String canonicalUrl) {
    BroadcastReceiver installReceiver = new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {
            if (!running) {
                localBroadcastManager.unregisterReceiver(this);
                return;
            }
            String canonicalUrl = intent.getDataString();
            Apk apk;
            switch(intent.getAction()) {
                case Installer.ACTION_INSTALL_STARTED:
                    appUpdateStatusManager.updateApk(canonicalUrl, AppUpdateStatusManager.Status.Installing, null);
                    break;
                case Installer.ACTION_INSTALL_COMPLETE:
                    appUpdateStatusManager.updateApk(canonicalUrl, AppUpdateStatusManager.Status.Installed, null);
                    Apk apkComplete = appUpdateStatusManager.getApk(canonicalUrl);
                    if (apkComplete != null && apkComplete.isApk()) {
                        try {
                            PackageManagerCompat.setInstaller(context, getPackageManager(), apkComplete.packageName);
                        } catch (SecurityException e) {
                        // Will happen if we fell back to DefaultInstaller for some reason.
                        }
                    }
                    localBroadcastManager.unregisterReceiver(this);
                    break;
                case Installer.ACTION_INSTALL_INTERRUPTED:
                    apk = intent.getParcelableExtra(Installer.EXTRA_APK);
                    String errorMessage = intent.getStringExtra(Installer.EXTRA_ERROR_MESSAGE);
                    if (!TextUtils.isEmpty(errorMessage)) {
                        appUpdateStatusManager.setApkError(apk, errorMessage);
                    } else {
                        appUpdateStatusManager.removeApk(canonicalUrl);
                    }
                    localBroadcastManager.unregisterReceiver(this);
                    break;
                case Installer.ACTION_INSTALL_USER_INTERACTION:
                    apk = intent.getParcelableExtra(Installer.EXTRA_APK);
                    PendingIntent installPendingIntent = intent.getParcelableExtra(Installer.EXTRA_USER_INTERACTION_PI);
                    appUpdateStatusManager.addApk(apk, AppUpdateStatusManager.Status.ReadyToInstall, installPendingIntent);
                    break;
                default:
                    throw new RuntimeException("intent action not handled!");
            }
        }
    };
    localBroadcastManager.registerReceiver(installReceiver, Installer.getInstallIntentFilter(canonicalUrl));
}
Also used : Context(android.content.Context) Intent(android.content.Intent) PendingIntent(android.app.PendingIntent) PendingIntent(android.app.PendingIntent) BroadcastReceiver(android.content.BroadcastReceiver) Apk(org.fdroid.fdroid.data.Apk)

Example 14 with Apk

use of org.fdroid.fdroid.data.Apk in project fdroidclient by f-droid.

the class InstallManagerService method onStartCommand.

/**
 * This goes through a series of checks to make sure that the incoming
 * {@link Intent} is still valid.  The default {@link Intent#getAction() action}
 * in the logic is {@link #ACTION_INSTALL} since it is the most complicate
 * case.  Since the {@code Intent} will be redelivered by Android if the
 * app was killed, this needs to check that it still makes sense to handle.
 * <p>
 * For example, if F-Droid is killed while installing, it might not receive
 * the message that the install completed successfully. The checks need to be
 * as specific as possible so as not to block things like installing updates
 * with the same {@link PackageInfo#versionCode}, which happens sometimes,
 * and is allowed by Android.
 */
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    Utils.debugLog(TAG, "onStartCommand " + intent);
    String canonicalUrl = intent.getDataString();
    if (TextUtils.isEmpty(canonicalUrl)) {
        Utils.debugLog(TAG, "empty canonicalUrl, nothing to do");
        return START_NOT_STICKY;
    }
    String action = intent.getAction();
    if (ACTION_CANCEL.equals(action)) {
        DownloaderService.cancel(this, canonicalUrl);
        Apk apk = appUpdateStatusManager.getApk(canonicalUrl);
        if (apk != null) {
            Utils.debugLog(TAG, "also canceling OBB downloads");
            DownloaderService.cancel(this, apk.getPatchObbUrl());
            DownloaderService.cancel(this, apk.getMainObbUrl());
        }
        return START_NOT_STICKY;
    } else if (ACTION_INSTALL.equals(action)) {
        if (!isPendingInstall(canonicalUrl)) {
            Log.i(TAG, "Ignoring INSTALL that is not Pending Install: " + intent);
            return START_NOT_STICKY;
        }
    } else {
        Log.i(TAG, "Ignoring unknown intent action: " + intent);
        return START_NOT_STICKY;
    }
    if (!intent.hasExtra(EXTRA_APP) || !intent.hasExtra(EXTRA_APK)) {
        Utils.debugLog(TAG, canonicalUrl + " did not include both an App and Apk instance, ignoring");
        return START_NOT_STICKY;
    }
    if ((flags & START_FLAG_REDELIVERY) == START_FLAG_REDELIVERY && !DownloaderService.isQueuedOrActive(canonicalUrl)) {
        Utils.debugLog(TAG, canonicalUrl + " finished downloading while InstallManagerService was killed.");
        appUpdateStatusManager.removeApk(canonicalUrl);
        return START_NOT_STICKY;
    }
    App app = intent.getParcelableExtra(EXTRA_APP);
    Apk apk = intent.getParcelableExtra(EXTRA_APK);
    if (app == null || apk == null) {
        Utils.debugLog(TAG, "Intent had null EXTRA_APP and/or EXTRA_APK: " + intent);
        return START_NOT_STICKY;
    }
    PackageInfo packageInfo = Utils.getPackageInfo(this, apk.packageName);
    if ((flags & START_FLAG_REDELIVERY) == START_FLAG_REDELIVERY && packageInfo != null && packageInfo.versionCode == apk.versionCode && TextUtils.equals(packageInfo.versionName, apk.versionName)) {
        Log.i(TAG, "INSTALL Intent no longer valid since its installed, ignoring: " + intent);
        return START_NOT_STICKY;
    }
    FDroidApp.resetMirrorVars();
    DownloaderService.setTimeout(FDroidApp.getTimeout());
    appUpdateStatusManager.addApk(apk, AppUpdateStatusManager.Status.Downloading, null);
    registerPackageDownloaderReceivers(canonicalUrl);
    getMainObb(canonicalUrl, apk);
    getPatchObb(canonicalUrl, apk);
    File apkFilePath = ApkCache.getApkDownloadPath(this, apk.getCanonicalUrl());
    long apkFileSize = apkFilePath.length();
    if (!apkFilePath.exists() || apkFileSize < apk.size) {
        Utils.debugLog(TAG, "download " + canonicalUrl + " " + apkFilePath);
        DownloaderService.queueUsingRandomMirror(this, apk.repoId, canonicalUrl);
    } else if (ApkCache.apkIsCached(apkFilePath, apk)) {
        Utils.debugLog(TAG, "skip download, we have it, straight to install " + canonicalUrl + " " + apkFilePath);
        sendBroadcast(intent.getData(), Downloader.ACTION_STARTED, apkFilePath);
        sendBroadcast(intent.getData(), Downloader.ACTION_COMPLETE, apkFilePath);
    } else {
        Utils.debugLog(TAG, "delete and download again " + canonicalUrl + " " + apkFilePath);
        apkFilePath.delete();
        DownloaderService.queueUsingRandomMirror(this, apk.repoId, canonicalUrl);
    }
    // if killed before completion, retry Intent
    return START_REDELIVER_INTENT;
}
Also used : FDroidApp(org.fdroid.fdroid.FDroidApp) App(org.fdroid.fdroid.data.App) PackageInfo(android.content.pm.PackageInfo) Apk(org.fdroid.fdroid.data.Apk) File(java.io.File)

Example 15 with Apk

use of org.fdroid.fdroid.data.Apk in project fdroidclient by f-droid.

the class AppDetailsRecyclerViewAdapter method updateItems.

public void updateItems(@NonNull App app) {
    this.app = app;
    // Get versions
    versions = new ArrayList<>();
    compatibleVersionsDifferentSig = new ArrayList<>();
    final List<Apk> apks = ApkProvider.Helper.findByPackageName(context, this.app.packageName);
    ensureInstalledApkExists(apks);
    boolean showIncompatibleVersions = Preferences.get().showIncompatibleVersions();
    for (final Apk apk : apks) {
        boolean allowByCompatibility = apk.compatible || showIncompatibleVersions;
        boolean allowBySig = this.app.installedSig == null || showIncompatibleVersions || TextUtils.equals(this.app.installedSig, apk.sig);
        if (allowByCompatibility) {
            compatibleVersionsDifferentSig.add(apk);
            if (allowBySig) {
                versions.add(apk);
                if (!versionsExpandTracker.containsKey(apk.apkName)) {
                    versionsExpandTracker.put(apk.apkName, false);
                }
            }
        }
    }
    if (items == null) {
        items = new ArrayList<>();
    } else {
        items.clear();
    }
    addItem(VIEWTYPE_HEADER);
    if (app.getAllScreenshots(context).length > 0) {
        addItem(VIEWTYPE_SCREENSHOTS);
    }
    addItem(VIEWTYPE_DONATE);
    addItem(VIEWTYPE_LINKS);
    addItem(VIEWTYPE_PERMISSIONS);
    if (versions.isEmpty()) {
        addItem(VIEWTYPE_NO_VERSIONS);
    } else {
        addItem(VIEWTYPE_VERSIONS);
        if (showVersions) {
            setShowVersions(true);
        }
    }
    notifyDataSetChanged();
}
Also used : Apk(org.fdroid.fdroid.data.Apk)

Aggregations

Apk (org.fdroid.fdroid.data.Apk)63 Test (org.junit.Test)17 Uri (android.net.Uri)16 File (java.io.File)12 Intent (android.content.Intent)11 App (org.fdroid.fdroid.data.App)10 Repo (org.fdroid.fdroid.data.Repo)10 ArrayList (java.util.ArrayList)8 PendingIntent (android.app.PendingIntent)7 Context (android.content.Context)7 PackageInfo (android.content.pm.PackageInfo)7 FileCompatTest (org.fdroid.fdroid.compat.FileCompatTest)7 BroadcastReceiver (android.content.BroadcastReceiver)6 PackageManager (android.content.pm.PackageManager)5 IOException (java.io.IOException)4 HashSet (java.util.HashSet)4 FDroidProviderTest (org.fdroid.fdroid.data.FDroidProviderTest)4 LocalBroadcastManager (androidx.localbroadcastmanager.content.LocalBroadcastManager)3 RepoDetails (org.fdroid.fdroid.mock.RepoDetails)3 SuppressLint (android.annotation.SuppressLint)2