/* * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 3 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301, USA. */ package org.fdroid.fdroid.installer; import java.io.File; import java.util.List; import android.annotation.TargetApi; import android.app.Activity; import android.content.ActivityNotFoundException; import android.content.Intent; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.net.Uri; import android.os.Build; /** * For Android >= 4.0: Default Installer using the public PackageManager API of * Android to install/delete packages. This starts a Activity from the Android * OS showing all permissions/changed permissions. The the user needs to * manually press an install button, this Installer cannot be used for * unattended installations. */ @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) public class DefaultInstallerSdk14 extends Installer { private Activity mActivity; public DefaultInstallerSdk14(Activity activity, PackageManager pm, InstallerCallback callback) throws AndroidNotCompatibleException { super(activity, pm, callback); this.mActivity = activity; } private static final int REQUEST_CODE_INSTALL = 0; private static final int REQUEST_CODE_DELETE = 1; @SuppressWarnings("deprecation") @Override protected void installPackageInternal(File apkFile) throws AndroidNotCompatibleException { Intent intent = new Intent(); intent.setAction(Intent.ACTION_INSTALL_PACKAGE); intent.setData(Uri.fromFile(apkFile)); intent.putExtra(Intent.EXTRA_RETURN_RESULT, true); // following extras only work when being installed as system-app // https://code.google.com/p/android/issues/detail?id=42253 intent.putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true); if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.JELLY_BEAN) { // deprecated in Android 4.1 intent.putExtra(Intent.EXTRA_ALLOW_REPLACE, true); } try { mActivity.startActivityForResult(intent, REQUEST_CODE_INSTALL); } catch (ActivityNotFoundException e) { throw new AndroidNotCompatibleException(e); } } @Override protected void installPackageInternal(List<File> apkFiles) throws AndroidNotCompatibleException { // TODO Auto-generated method stub } @Override protected void deletePackageInternal(String packageName) throws AndroidNotCompatibleException { PackageInfo pkgInfo = null; try { pkgInfo = mPm.getPackageInfo(packageName, 0); } catch (NameNotFoundException e) { // already checked in super class } Uri uri = Uri.fromParts("package", pkgInfo.packageName, null); Intent intent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE, uri); intent.putExtra(Intent.EXTRA_RETURN_RESULT, true); try { mActivity.startActivityForResult(intent, REQUEST_CODE_DELETE); } catch (ActivityNotFoundException e) { throw new AndroidNotCompatibleException(e); } } @Override public boolean handleOnActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { case REQUEST_CODE_INSTALL: if (resultCode == Activity.RESULT_OK) { mCallback.onSuccess(InstallerCallback.OPERATION_INSTALL); } else if (resultCode == Activity.RESULT_CANCELED) { mCallback.onError(InstallerCallback.OPERATION_INSTALL, InstallerCallback.ERROR_CODE_CANCELED); } else { mCallback.onError(InstallerCallback.OPERATION_INSTALL, InstallerCallback.ERROR_CODE_OTHER); } return true; case REQUEST_CODE_DELETE: if (resultCode == Activity.RESULT_OK) { mCallback.onSuccess(InstallerCallback.OPERATION_DELETE); } else if (resultCode == Activity.RESULT_CANCELED) { mCallback.onError(InstallerCallback.OPERATION_DELETE, InstallerCallback.ERROR_CODE_CANCELED); } else { // UninstallAppProgress actually returns // Activity.RESULT_FIRST_USER if something breaks mCallback.onError(InstallerCallback.OPERATION_DELETE, InstallerCallback.ERROR_CODE_OTHER); } return true; default: return false; } } @Override public boolean supportsUnattendedOperations() { return false; } }