/*
* Geopaparazzi - Digital field mapping on Android based devices
* Copyright (C) 2016 HydroloGIS (www.hydrologis.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, see <http://www.gnu.org/licenses/>.
*/
package eu.geopaparazzi.library.util;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import eu.geopaparazzi.library.R;
import eu.geopaparazzi.library.core.ResourcesManager;
import eu.geopaparazzi.library.core.activities.DirectoryBrowserActivity;
import eu.geopaparazzi.library.images.ImageUtilities;
/**
* An utility to handle 3rd party apps.
*
* @author Andrea Antonello (www.hydrologis.com)
* @author Cesar Martinez Izquierdo (www.scolab.es)
*/
public class AppsUtilities {
public static final String AMAZE_PACKAGE = "com.amaze.filemanager";
public static final String AMAZE_TITLE = "com.amaze.filemanager.extra.TITLE";
/**
* Opens the comapss app.
*
* @param context the context to use.
*/
public static void checkAndOpenGpsStatus(final Context context) {
final String gpsStatusPackage = "com.android.gpstest";
boolean hasGpsStatus = false;
List<PackageInfo> installedPackages = new ArrayList<PackageInfo>();
{ // try to get the installed packages list. Seems to have troubles over different
// versions, so trying them all
try {
installedPackages = context.getPackageManager().getInstalledPackages(0);
} catch (Exception e) {
// ignore
}
if (installedPackages.size() == 0)
try {
installedPackages = context.getPackageManager().getInstalledPackages(PackageManager.GET_ACTIVITIES);
} catch (Exception e) {
// ignore
}
}
if (installedPackages.size() > 0) {
// if a list is available, check if the status gps is installed
for (PackageInfo packageInfo : installedPackages) {
String packageName = packageInfo.packageName;
if (packageName.startsWith(gpsStatusPackage)) {
hasGpsStatus = true;
break;
}
}
} else {
/*
* if no package list is available, for now try to fire it up anyways.
* This has been a problem for a user on droidx with android 2.2.1.
*/
hasGpsStatus = true;
}
if (hasGpsStatus) {
Intent launchIntent = context.getPackageManager().getLaunchIntentForPackage(gpsStatusPackage);
if (launchIntent != null) {
context.startActivity(launchIntent);//null pointer check in case package name was not found
}
} else {
new AlertDialog.Builder(context).setTitle(context.getString(R.string.installgpsstatus_title))
.setMessage(context.getString(R.string.installgpsstatus_message)).setIcon(android.R.drawable.ic_dialog_info)
.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
// ignore
}
}).setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("market://details?id=" + gpsStatusPackage));
context.startActivity(intent);
}
}).show();
}
}
/**
* Start a file picking activity.
*
* @param activityStarter
* @param requestCode
* @param title
* @param filterExtensions
* @param startPath
* @throws Exception
*/
public static void pickFile(IActivitySupporter activityStarter, int requestCode, String title, String[] filterExtensions, String startPath) throws Exception {
if (startPath == null) {
startPath = Utilities.getLastFilePath(activityStarter.getContext());
}
Intent browseIntent = new Intent(activityStarter.getContext(), DirectoryBrowserActivity.class);
browseIntent.putExtra(DirectoryBrowserActivity.EXTENSIONS, filterExtensions);
browseIntent.putExtra(DirectoryBrowserActivity.STARTFOLDERPATH, startPath);
activityStarter.startActivityForResult(browseIntent, requestCode);
}
/**
* Start activity to pick a file.
* <p>
* <p>
* For mimetype and uri one could use:
* <pre>
* String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension("gpx");
* if (mimeType == null) mimeType = "text/gpx";
* Uri uri = Uri.parse(ResourcesManager.getInstance(this).getMapsDir().getAbsolutePath());
* </pre>
* </p>
*
* @param activityStarter the activity that will recieve the picked file.
* @param requestCode the requestcode to use on result.
* @param title optional title.
* @param mimeType the mimetype.
* @param uri the uri of the start folder.
*/
public static void pickFileByExternalBrowser(IActivitySupporter activityStarter, int requestCode, String title, String mimeType, Uri uri) {
// first try with amaze
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setPackage(AppsUtilities.AMAZE_PACKAGE);
if (title != null)
intent.putExtra(AppsUtilities.AMAZE_TITLE, title);
intent.setDataAndType(uri, mimeType);
try {
activityStarter.startActivityForResult(intent, requestCode);
} catch (android.content.ActivityNotFoundException ex) {
// try with es explorer
intent = new Intent("com.estrongs.action.PICK_FILE ");
if (title != null)
intent.putExtra("com.estrongs.intent.extra.TITLE", title);
intent.setDataAndType(uri, mimeType);
try {
activityStarter.startActivityForResult(intent, requestCode);
} catch (android.content.ActivityNotFoundException ex2) {
// try with generic
intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setDataAndType(uri, mimeType);
Intent chooser = Intent.createChooser(intent, title);
try {
activityStarter.startActivityForResult(chooser, requestCode);
} catch (android.content.ActivityNotFoundException ex3) {
// direct to install a file manager
AppsUtilities.checkAmazeExplorer(activityStarter);
}
}
}
}
public static void pickFolder(IActivitySupporter activityStarter, int requestCode, String title, String startPath, String[] visibleExtensions) throws Exception {
if (startPath == null) {
startPath = Utilities.getLastFilePath(activityStarter.getContext());
}
Intent browseIntent = new Intent(activityStarter.getContext(), DirectoryBrowserActivity.class);
browseIntent.putExtra(DirectoryBrowserActivity.DOFOLDER, true);
browseIntent.putExtra(DirectoryBrowserActivity.EXTENSIONS, visibleExtensions);
browseIntent.putExtra(DirectoryBrowserActivity.STARTFOLDERPATH, startPath);
activityStarter.startActivityForResult(browseIntent, requestCode);
}
public static void checkAmazeExplorer(final IActivitySupporter activityStarter) {
Context context = activityStarter.getContext();
boolean hasPackage = hasPackage(context, AMAZE_PACKAGE);
if (!hasPackage) {
new AlertDialog.Builder(context).setTitle(context.getString(R.string.installamaze_title))
.setMessage(context.getString(R.string.installamaze_message)).setIcon(android.R.drawable.ic_dialog_info)
.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
// ignore
}
}).setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("market://search?q=" + AMAZE_PACKAGE));
activityStarter.startActivity(intent);
}
}).show();
}
}
private static boolean hasPackage(Context context, String searchedPackageName) {
boolean hasPackage = false;
List<PackageInfo> installedPackages = new ArrayList<PackageInfo>();
try {
installedPackages = context.getPackageManager().getInstalledPackages(0);
} catch (Exception e) {
// ignore
}
if (installedPackages.size() == 0)
try {
installedPackages = context.getPackageManager().getInstalledPackages(PackageManager.GET_ACTIVITIES);
} catch (Exception e) {
// ignore
}
if (installedPackages.size() > 0) {
// if a list is available, check if the status gps is installed
for (PackageInfo packageInfo : installedPackages) {
String packageName = packageInfo.packageName;
if (packageName.startsWith(searchedPackageName)) {
hasPackage = true;
break;
}
}
} else {
/*
* if no package list is available, for now try to fire it up anyways.
* This has been a problem for a user on droidx with android 2.2.1.
*/
hasPackage = true;
}
return hasPackage;
}
/**
* Show an image through intent.
*
* @param imageData the image data.
* @param imageName the image name.
* @param context the context to use.
* @throws Exception
*/
public static void showImage(byte[] imageData, String imageName, Context context) throws Exception {
File tempDir = ResourcesManager.getInstance(context).getTempDir();
String ext = ".jpg";
if (imageName.endsWith(".png")) {
ext = ".png";
}
File imageFile = new File(tempDir, ImageUtilities.getTempImageName(ext));
ImageUtilities.writeImageDataToFile(imageData, imageFile.getAbsolutePath());
showImage(imageFile, context);
}
/**
* Show and image.
*
* @param imageFile the image file.
* @param context the context to use.
* @throws Exception
*/
public static void showImage(File imageFile, Context context) throws Exception {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
Uri uri = Utilities.getFileUriInApplicationFolder(context, imageFile);
intent.setDataAndType(uri, "image/*"); //$NON-NLS-1$
grantPermission(context, intent, uri);
context.startActivity(intent);
}
/**
* Grant permission to access a file from another app.
*
* <p>This is necessary since Android 7.</p>
*
* @param context the context.
* @param intent the intent.
* @param uri the file uri.
*/
public static void grantPermission(Context context, Intent intent, Uri uri) {
List<ResolveInfo> resInfoList = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo resolveInfo : resInfoList) {
String packageName = resolveInfo.activityInfo.packageName;
context.grantUriPermission(packageName, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
}
}