/* * Copyright (C) 2016 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 android.content.Context; import android.net.Uri; import android.support.v4.content.FileProvider; import org.fdroid.fdroid.data.Apk; import org.fdroid.fdroid.data.SanitizedFile; import java.io.File; import java.io.IOException; /** * This class has helper methods for preparing apks for installation. * <p/> * APK handling for installations: * 1. APKs are downloaded into a cache directory that is either created on SD card * <i>"/Android/data/[app_package_name]/cache/apks"</i> (if card is mounted and app has * appropriate permission) or on device's file system depending incoming parameters. * 2. Before installation, the APK is copied into the private data directory of the F-Droid, * <i>"/data/data/[app_package_name]/files/install-$random.apk"</i>. * 3. The hash of the file is checked against the expected hash from the repository * 4. For Android < 7, a file Uri pointing to the File is returned, for Android >= 7, * a content Uri is returned using support lib's FileProvider. */ public class ApkFileProvider extends FileProvider { private static final String AUTHORITY = "org.fdroid.fdroid.installer.ApkFileProvider"; /** * Copies the APK into private data directory of F-Droid and returns a "file" or "content" Uri * to be used for installation. */ public static Uri getSafeUri(Context context, Uri localApkUri, Apk expectedApk, boolean useContentUri) throws IOException { File apkFile = new File(localApkUri.getPath()); SanitizedFile sanitizedApkFile = ApkCache.copyApkFromCacheToFiles(context, apkFile, expectedApk); if (useContentUri) { // return a content Uri using support libs FileProvider return getUriForFile(context, AUTHORITY, sanitizedApkFile); } // Need the apk to be world readable, so that the installer is able to read it. // Note that saving it into external storage for the purpose of letting the installer // have access is insecure, because apps with permission to write to the external // storage can overwrite the app between F-Droid asking for it to be installed and // the installer actually installing it. sanitizedApkFile.setReadable(true, false); return Uri.fromFile(sanitizedApkFile); } }