blob: a24340ea80509639d680d45cc1b24dd13b6d5c23 [file] [log] [blame]
/*
* Copyright (C) 2004-2019 Savoir-faire Linux Inc.
*
* Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package cx.ring.utils;
import android.content.ContentResolver;
import android.content.Context;
import android.content.res.Resources;
import android.net.Uri;
import android.os.Build;
import androidx.annotation.NonNull;
import androidx.core.content.FileProvider;
import java.io.File;
import cx.ring.BuildConfig;
/**
* This class distributes content uri used to pass along data in the app
*/
public class ContentUriHandler {
private final static String TAG = ContentUriHandler.class.getSimpleName();
public static final String AUTHORITY = BuildConfig.APPLICATION_ID;
public static final String AUTHORITY_FILES = AUTHORITY + ".file_provider";
public static final String SCHEME_TV = "jamitv";
public static final String PATH_TV_HOME = "home";
public static final String PATH_TV_CONVERSATION = "conversation";
private static final Uri AUTHORITY_URI = Uri.parse("content://" + AUTHORITY);
public static final Uri CONVERSATION_CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "conversation");
public static final Uri ACCOUNTS_CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "accounts");
public static final Uri CONTACT_CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "contact");
private ContentUriHandler() {
// hidden constructor
}
/**
* The following is a workaround used to mitigate getUriForFile exceptions
* on Huawei devices taken from stackoverflow
* https://stackoverflow.com/a/41309223
*/
private static final String HUAWEI_MANUFACTURER = "Huawei";
public static Uri getUriForResource(@NonNull Context context, int resourceId) {
Resources resources = context.getResources();
return new Uri.Builder()
.scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
.authority(resources.getResourcePackageName(resourceId))
.appendPath(resources.getResourceTypeName(resourceId))
.appendPath(resources.getResourceEntryName(resourceId))
.build();
}
public static Uri getUriForFile(@NonNull Context context, @NonNull String authority, @NonNull File file) {
if (HUAWEI_MANUFACTURER.equalsIgnoreCase(Build.MANUFACTURER)) {
try {
return FileProvider.getUriForFile(context, authority, file);
} catch (IllegalArgumentException e) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
Log.w(TAG, "Returning Uri.fromFile to avoid Huawei 'external-files-path' bug for pre-N devices", e);
return Uri.fromFile(file);
} else {
Log.w(TAG, "ANR Risk -- Copying the file the location cache to avoid Huawei 'external-files-path' bug for N+ devices", e);
// Note: Periodically clear this cache
final File cacheFolder = new File(context.getCacheDir(), HUAWEI_MANUFACTURER);
final File cacheLocation = new File(cacheFolder, file.getName());
if (FileUtils.copyFile(file, cacheLocation)) {
Log.i(TAG, "Completed Android N+ Huawei file copy. Attempting to return the cached file");
return FileProvider.getUriForFile(context, authority, cacheLocation);
}
Log.e(TAG, "Failed to copy the Huawei file. Re-throwing exception");
throw new IllegalArgumentException("Huawei devices are unsupported for Android N");
}
}
} else {
return FileProvider.getUriForFile(context, authority, file);
}
}
}