Java tutorial
/* * Copyright (C) 2010-2014 - JavocSoft - Javier Gonzalez Serrano * http://javocsoft.es/proyectos/code-libs/android/javocsoft-toolbox-android-library * * This file is part of JavocSoft Android Toolbox library. * * JavocSoft Android Toolbox library 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. * * JavocSoft Android Toolbox library 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 JavocSoft Android Toolbox library. If not, see * <http://www.gnu.org/licenses/>. * */ package es.javocsoft.android.lib.toolbox; import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.lang.reflect.Method; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.SocketTimeoutException; import java.net.URISyntaxException; import java.net.URL; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Random; import java.util.Set; import java.util.UUID; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpDelete; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpRequestBase; import org.apache.http.conn.ConnectTimeoutException; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.params.CoreConnectionPNames; import android.annotation.SuppressLint; import android.app.Activity; import android.app.AlertDialog; import android.app.Application; import android.app.Dialog; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.ComponentName; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ResolveInfo; import android.content.pm.Signature; import android.content.res.AssetFileDescriptor; import android.content.res.Configuration; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.ColorMatrix; import android.graphics.ColorMatrixColorFilter; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Point; import android.graphics.Typeface; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.media.AudioManager; import android.media.ExifInterface; import android.media.MediaPlayer; import android.media.Ringtone; import android.media.RingtoneManager; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Environment; import android.os.Parcelable; import android.os.PowerManager; import android.provider.Settings.Secure; import android.support.v7.app.ActionBarActivity; import android.telephony.TelephonyManager; import android.util.DisplayMetrics; import android.util.Log; import android.view.Display; import android.view.Gravity; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewConfiguration; import android.view.Window; import android.view.WindowManager; import android.webkit.WebView; import android.widget.Button; import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; import com.google.android.gms.ads.AdRequest; import com.google.android.gms.ads.AdView; import com.google.android.gms.analytics.GoogleAnalytics; import com.google.android.gms.analytics.HitBuilders; import com.google.android.gms.analytics.HitBuilders.EventBuilder; import com.google.android.gms.analytics.Logger.LogLevel; import com.google.android.gms.analytics.Tracker; import es.javocsoft.android.lib.toolbox.encoding.Base64; import es.javocsoft.android.lib.toolbox.io.IOUtils; /** * This class will hold utility functions related with Android. * * @author JavocSoft 2013 * @since 2012 */ public final class ToolBox { /** Enables or disables log */ public static boolean LOG_ENABLE = true; /** Shared Preferences file under some data is saved by the Android Toolbox Library */ public static final String PREF_FILE_NAME = "prefs_toolbox"; /** Http Method type for a request. */ public static enum HTTP_METHOD { POST, DELETE, GET }; public static final String TAG = "javocsoft-toolbox: ToolBox"; private static final int CONNECTION_DEFAULT_TIMEOUT = 5000; // 5 sgs. private static final int CONNECTION_DEFAULT_DATA_RECEIVAL_TIMEOUT = 10000; // 10 sgs. private static final int HTTP_CACHE_SIZE = 10 * 1024 * 1024; // 10 MiB public static final String NETWORK_OPERATOR_EMU = "Android"; public static final String NETWORK_OPERATOR_NOSIM = "NO_SIM"; public static enum ApiLevel { LEVEL_1(1), LEVEL_2(2), LEVEL_3(3), LEVEL_4(4), LEVEL_5(5), LEVEL_6(6), LEVEL_7(7), LEVEL_8(8), LEVEL_9( 9), LEVEL_10(10), LEVEL_11(11), LEVEL_12( 12), LEVEL_13(13), LEVEL_14(14), LEVEL_15(15), LEVEL_16(16), LEVEL_17(17), LEVEL_18(18); private int value; ApiLevel(int value) { this.value = value; } public int getValue() { return value; } } public static enum NETWORK_PROVIDER { MOVISTAR, YOIGO, VODAFONE, ORANGE, EMU, NOSIM, UNKNOWN }; public static enum SCREEN_ORIENTATION { PORTRAIT, LANDSCAPE, SQUARE }; public static enum HASH_TYPE { md5, sha1 }; /** The type of device by screen. */ public static enum DEVICE_BY_SCREEN { DP320_NORMAL, DP480_TWEENER, DP600_7INCH, DP720_10INCH }; /** The type of resolution that is using the device. */ public enum DEVICE_RESOLUTION_TYPE { ldpi, mdpi, hdpi, xhdpi, xxhdpi }; private static PowerManager.WakeLock wakeLock = null; private static Random random = null; private static Set<String> systemAppsList = null; private ToolBox() { } //--------------- ANALYTICS ------------------------------------------------------------------------ /** * Gets a new Analytics v4 tracker. * * See: https://developers.google.com/analytics/devguides/collection/android/v4/ * * @param context * @param analyticsTrackingId * @param debugMode If enabled, GA operations will not be sent to Analytics but * are logged. * @return */ public static synchronized Tracker analytics_getTracker(Context context, String analyticsTrackingId, boolean debugMode) { GoogleAnalytics analytics = GoogleAnalytics.getInstance(context); if (debugMode) { // When dry run is set, hits will not be dispatched, but will still be logged as // though they were dispatched. analytics.setDryRun(true); //Enable logging for GA. analytics.getLogger().setLogLevel(LogLevel.VERBOSE); } return analytics.newTracker(analyticsTrackingId); } /** * Sends to Google Analytics an event. * * @param tracker The analytics tracker to use when sending the * event. * @param eventCategory Category of the event * @param eventAction Action of the event * @param eventlabel label of the event */ public static void analytics_sendEvent(Tracker tracker, String eventCategory, String eventAction, String eventlabel, Long eventValue) { EventBuilder eBuilder = new HitBuilders.EventBuilder(); eBuilder.setCategory(eventCategory).setAction(eventAction).setLabel(eventlabel); if (eventValue != null) { eBuilder.setValue(eventValue); } tracker.send(eBuilder.build()); } /** * Sends to Google Analytics a screen view event. * * @param tracker The analytics tracker to use when sending the * event. * @param screenName The screen name. */ public static void analytics_sendScreenName(Tracker tracker, String screenName) { tracker.setScreenName(screenName); tracker.send(new HitBuilders.AppViewBuilder().build()); } //--------------- SYSTEM --------------------------------------------------------------------------- /** * Tells if an application is installed or not. * * @param context Your application context * @param appPackage The application package. * @return */ public static boolean system_isAppInstalled(Context context, String appPackage) { PackageManager pm = context.getPackageManager(); boolean app_installed = false; try { pm.getPackageInfo(appPackage, PackageManager.GET_ACTIVITIES); app_installed = true; } catch (PackageManager.NameNotFoundException e) { app_installed = false; } return app_installed; } /** * Gets the list of system applications. * * @return The list. If error the list will be empty. */ public static Set<String> system_getSystemApplicationList(Context context) { Set<String> systemApps = new HashSet<String>(); try { final PackageManager pm = context.getPackageManager(); final List<ApplicationInfo> installedApps = pm.getInstalledApplications(PackageManager.GET_META_DATA); for (ApplicationInfo app : installedApps) { if (system_isSystemPackage(app)) { systemApps.add(app.packageName); } } } catch (Exception e) { if (LOG_ENABLE) { Log.e(TAG, "Error getting system application list [" + e.getMessage() + "]", e); } } return systemApps; } /** * Checks if an application is a system application. * * @param appPackage * @return */ public static boolean system_isSystemApplication(Context context, String appPackage) { boolean res = false; if (systemAppsList == null) { systemAppsList = system_getSystemApplicationList(context); } for (String sysAppPackage : systemAppsList) { if (appPackage.equals(sysAppPackage)) { res = true; break; } } return res; } /** * Return whether the given PackgeInfo represents a system package or not. * User-installed packages should not be denoted as system packages. * * @param appInfo * @return */ public static boolean system_isSystemPackage(ApplicationInfo appInfo) { return ((appInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) ? true : false; } /** * This function allows to know if there is an application that responds to * the specified action. * * @param context * @param action Action that requires an application. * @return */ public static boolean system_isIntentAvailable(Context context, String action) { final PackageManager packageManager = context.getPackageManager(); final Intent intent = new Intent(action); List<ResolveInfo> list = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY); return list.size() > 0; } //--------------- ADDMOB --------------------------------------------------------------------------- /** * This disables correctly the AdMob ads. * * @param activity * @param adLayout The AdView view. */ public static void adMob_hideAds(Activity activity, final AdView adLayout) { activity.runOnUiThread(new Runnable() { @Override public void run() { adLayout.setEnabled(false); adLayout.setVisibility(View.GONE); } }); } /** * This enables again the AdMob ads. * * @param activity * @param adLayout The AdView view. */ public static void adMob_showAds(Activity activity, final AdView adLayout) { activity.runOnUiThread(new Runnable() { @Override public void run() { adLayout.setEnabled(true); adLayout.setVisibility(View.VISIBLE); AdRequest.Builder adBuilder = new AdRequest.Builder().addTestDevice(AdRequest.DEVICE_ID_EMULATOR); adLayout.loadAd(adBuilder.build()); } }); } /** * This enables again the AdMob ads. * * @param activity * @param adLayout * @param excludedDevices */ public static void adMob_showAds(Activity activity, final AdView adLayout, final List<String> excludedDevices) { activity.runOnUiThread(new Runnable() { @Override public void run() { adLayout.setEnabled(true); adLayout.setVisibility(View.VISIBLE); AdRequest.Builder adBuilder = new AdRequest.Builder().addTestDevice(AdRequest.DEVICE_ID_EMULATOR); for (String dev : excludedDevices) { adBuilder.addTestDevice(dev); } adLayout.loadAd(adBuilder.build()); } }); } //--------------- APPLICATIONS RELATED ------------------------------------------------------------- /** * gets the application icon. * * @param context * @param packageName * @return */ public static Drawable appInfo_getIconFromPackageName(Context context, String packageName) { PackageManager pm = context.getPackageManager(); ApplicationInfo appInfo = null; try { appInfo = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA); } catch (NameNotFoundException e) { return null; } return appInfo.loadIcon(pm); } /** * Gets the size of an APK. * * @param installPath * @return */ public static String appInfo_getSize(String installPath) { File file = new File(installPath); String unit = "Bytes"; double sizeInUnit = 0d; if (file.exists()) { double size = (double) file.length(); if (size > 1024 * 1024 * 1024) { // Gigabyte sizeInUnit = size / (1024 * 1024 * 1024); unit = "GB"; } else if (size > 1024 * 1024) { // Megabyte sizeInUnit = size / (1024 * 1024); unit = "MB"; } else if (size > 1024) { // Kilobyte sizeInUnit = size / 1024; unit = "KB"; } else { // Byte sizeInUnit = size; } } // only show two digits after the comma return new DecimalFormat("###.##").format(sizeInUnit) + " " + unit; } /** * Creates a application informative dialog with options to * uninstall/launch or cancel. * * @param context * @param appPackage */ public static void appInfo_getLaunchUninstallDialog(final Context context, String appPackage) { try { final PackageManager packageManager = context.getPackageManager(); final PackageInfo app = packageManager.getPackageInfo(appPackage, PackageManager.GET_META_DATA); AlertDialog dialog = new AlertDialog.Builder(context).create(); dialog.setTitle(app.applicationInfo.loadLabel(packageManager)); String description = null; if (app.applicationInfo.loadDescription(packageManager) != null) { description = app.applicationInfo.loadDescription(packageManager).toString(); } String msg = app.applicationInfo.loadLabel(packageManager) + "\n\n" + "Version " + app.versionName + " (" + app.versionCode + ")" + "\n" + (description != null ? (description + "\n") : "") + app.applicationInfo.sourceDir + "\n" + appInfo_getSize(app.applicationInfo.sourceDir); dialog.setMessage(msg); dialog.setCancelable(true); dialog.setButton(AlertDialog.BUTTON_NEUTRAL, "Cancel", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.dismiss(); } }); dialog.setButton(AlertDialog.BUTTON_NEGATIVE, "Uninstall", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { Intent intent = new Intent(Intent.ACTION_DELETE); intent.setData(Uri.parse("package:" + app.packageName)); context.startActivity(intent); } }); dialog.setButton(AlertDialog.BUTTON_POSITIVE, "Launch", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { Intent i = packageManager.getLaunchIntentForPackage(app.packageName); context.startActivity(i); } }); dialog.show(); } catch (Exception e) { if (LOG_ENABLE) { Log.e(TAG, "Dialog could not be made for the specified application '" + appPackage + "'. [" + e.getMessage() + "].", e); } } } /** * Allows to install a new icon for the application. * * This method need two additional permissions in the application: * * <code> * <uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" /> * </code> * * @param context The application context. * @param appMain The application main class * @param appName The application name * @param appIcon The bitmap of the application icon. Can be null. If null, the * appIconResId must be provided. * @param appIconResId Specify this only if no bitmap is set in the call to this method. */ public static void application_shortcutAdd(Context context, Class appMain, String appName, Bitmap appIcon, int appIconResId, boolean removeCurrent) { // Intent launcher of the application Intent shortcutIntent = new Intent("android.intent.action.MAIN"); shortcutIntent.addCategory("android.intent.category.LAUNCHER"); shortcutIntent.setClass(context, appMain); shortcutIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); //Intent to add the new application icon. // // Decorate the shortcut Intent addIntent = new Intent(); addIntent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent); addIntent.putExtra(Intent.EXTRA_SHORTCUT_NAME, appName); if (appIcon != null) { addIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON, appIcon); } else if (appIconResId != 0) { addIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, Intent.ShortcutIconResource.fromContext(context.getApplicationContext(), appIconResId)); } // Inform launcher to create shortcut addIntent.setAction("com.android.launcher.action.INSTALL_SHORTCUT"); context.sendBroadcast(addIntent); } /** * Deletes a application desktop shortcut icon. * * This method need two additional permissions in the application: * * <code> * <uses-permission android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT" /> * </code> * * @param context The application context. * @param appClass Shortcut's activity class. * @param appName The shortcut's name */ public static void application_shortcutRemove_method1(Context context, Class appClass, String appName) { Intent shortcutIntent = new Intent(context, appClass); shortcutIntent.setAction(Intent.ACTION_MAIN); Intent delIntent = new Intent(); delIntent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent); delIntent.putExtra(Intent.EXTRA_SHORTCUT_NAME, appName); // Inform launcher to remove shortcut delIntent.setAction("com.android.launcher.action.UNINSTALL_SHORTCUT"); context.sendBroadcast(delIntent); } /** * Deletes a application desktop shortcut icon. * * Note: * Manual way. * * This method need two additional permissions in the application: * * <code> * <uses-permission android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT" /> * </code> * * @param context The application context. * @param appClass Shortcut's activity class. */ public static void application_shortcutRemove_method2(Context context, Class appClass, String appName) { Intent intent = new Intent(); String oldShortcutUri = "#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;package=" + appClass.getPackage().getName() + ";component=" + appClass.getPackage().getName() + "/." + appClass.getSimpleName() + ";end"; try { Intent altShortcutIntent = Intent.parseUri(oldShortcutUri, 0); intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, altShortcutIntent); intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, appName); //intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); //intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); } catch (URISyntaxException e) { } intent.setAction("com.android.launcher.action.UNINSTALL_SHORTCUT"); context.sendBroadcast(intent); } /** * Disables the component status of an Activity. If the activity has the * android.intent.category.LAUNCHER intent, it will remove the launcher icon * in the applications menu. * * @param context The application context * @param appClass Class of the activity */ public static void application_activityDisable(Context context, Class appClass) { application_activityStatusSwitch(context, appClass, PackageManager.COMPONENT_ENABLED_STATE_DISABLED); } /** * Enables the component status of an Activity. If the activity has the * android.intent.category.LAUNCHER intent, it will add the launcher icon * in the applications menu. * * @param context The application context * @param appClass Class of the activity */ public static void application_activityEnable(Context context, Class appClass) { application_activityStatusSwitch(context, appClass, PackageManager.COMPONENT_ENABLED_STATE_ENABLED); } /* * Enables or disables an activity component status. * * @param context The application context * @param appClass Class of the activity * @param status The desired status. */ private static void application_activityStatusSwitch(Context context, Class appClass, int status) { ComponentName component = new ComponentName(appClass.getPackage().getName(), appClass.getName()); if (status == PackageManager.COMPONENT_ENABLED_STATE_DISABLED && (context.getPackageManager() .getComponentEnabledSetting(component) == PackageManager.COMPONENT_ENABLED_STATE_ENABLED || context.getPackageManager() .getComponentEnabledSetting(component) == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT)) { context.getPackageManager().setComponentEnabledSetting(component, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP); } else if (status == PackageManager.COMPONENT_ENABLED_STATE_ENABLED && (context.getPackageManager() .getComponentEnabledSetting(component) == PackageManager.COMPONENT_ENABLED_STATE_DISABLED || context.getPackageManager() .getComponentEnabledSetting(component) == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT)) { context.getPackageManager().setComponentEnabledSetting(component, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP); } } /** * Enables the component status of an Activity Alias. If the activity alias points to an * Activity with android.intent.category.LAUNCHER intent, it will add the launcher icon * in the applications menu. * * @param context * @param appClass * @param appLaunchAlias */ public static void application_activityAliasEnable(Context context, Class appClass, String appLaunchAlias) { application_activityAliasStatusSwitch(context, appClass, appLaunchAlias, PackageManager.COMPONENT_ENABLED_STATE_ENABLED); } /** * Disables the component status of an Activity Alias. If the activity alias points to an * Activity with android.intent.category.LAUNCHER intent, it will remove the launcher icon * in the applications menu. * * @param context The application context * @param appClass Class of the activity alias * @param appLaunchAlias The android:name of the activity-alias entry in the manifest. */ public static void application_activityAliasDisable(Context context, Class appClass, String appLaunchAlias) { application_activityAliasStatusSwitch(context, appClass, appLaunchAlias, PackageManager.COMPONENT_ENABLED_STATE_DISABLED); } /** * Switches the component status of an Activity Alias. Use this to enable or disable it. If the * activity alias points to an Activity with android.intent.category.LAUNCHER intent, it will * remove/add the launcher icon in the applications menu. * * @param context The application context * @param appClass Class of the activity alias * @param appLaunchAlias The android:name of the activity-alias entry in the manifest. */ public static void application_activityAliasSwitchStatus(Context context, Class appClass, String appLaunchAlias) { ComponentName component = new ComponentName(appClass.getPackage().getName(), appClass.getPackage().getName() + "." + appLaunchAlias); if (context.getPackageManager() .getComponentEnabledSetting(component) == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) { application_activityAliasStatusSwitch(context, appClass, appLaunchAlias, PackageManager.COMPONENT_ENABLED_STATE_DISABLED); } else if (context.getPackageManager() .getComponentEnabledSetting(component) == PackageManager.COMPONENT_ENABLED_STATE_DISABLED) { application_activityAliasStatusSwitch(context, appClass, appLaunchAlias, PackageManager.COMPONENT_ENABLED_STATE_ENABLED); } } /* * Enables or disables an activity alias component status. * * @param context The application context * @param appClass Class of the activity alias * @param appLaunchAlias The android:name of the activity-alias entry in the manifest. * @param status The desired status. */ private static void application_activityAliasStatusSwitch(Context context, Class appClass, String appLaunchAlias, int status) { ComponentName component = new ComponentName(appClass.getPackage().getName(), appClass.getPackage().getName() + "." + appLaunchAlias); if (status == PackageManager.COMPONENT_ENABLED_STATE_DISABLED && (context.getPackageManager() .getComponentEnabledSetting(component) == PackageManager.COMPONENT_ENABLED_STATE_ENABLED || context.getPackageManager() .getComponentEnabledSetting(component) == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT)) { context.getPackageManager().setComponentEnabledSetting(component, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP); } else if (status == PackageManager.COMPONENT_ENABLED_STATE_ENABLED && (context.getPackageManager() .getComponentEnabledSetting(component) == PackageManager.COMPONENT_ENABLED_STATE_DISABLED || context.getPackageManager() .getComponentEnabledSetting(component) == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT)) { context.getPackageManager().setComponentEnabledSetting(component, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP); } } /** * This method reads the info form the App. Manifest file. * * @return */ public static boolean application_isAppInDebugMode(Context context) { boolean res = false; try { PackageInfo info = context.getPackageManager().getPackageInfo(context.getApplicationInfo().packageName, 0); int flags = info.applicationInfo.flags; if ((flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) { // development mode res = true; } else { // release mode } } catch (Exception e) { if (LOG_ENABLE) Log.e("IS_DEBUG_MODE:ERROR", e.getMessage(), e); } return res; } /** * This method reads the info form the App. Manifest file. * * @return */ public static String application_getVersion(Context context) { String res = null; try { PackageInfo info = context.getPackageManager().getPackageInfo(context.getApplicationInfo().packageName, 0); res = info.versionName; } catch (Exception e) { if (LOG_ENABLE) Log.e("GET_APP_VERSION:ERROR", e.getMessage(), e); } return res; } /** * This method reads the info form the App. Manifest file. * * @return */ public static int application_getVersionCode(Context context) { int res = -1; try { PackageInfo info = context.getPackageManager().getPackageInfo(context.getApplicationInfo().packageName, 0); res = info.versionCode; } catch (Exception e) { if (LOG_ENABLE) Log.e("GET_APP_VERSION:ERROR", e.getMessage(), e); } return res; } public static boolean application_isCallable(Activity activity, Intent intent) { List<ResolveInfo> list = activity.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY); return list.size() > 0; } /** * Returns a list with the current signatures of the * application. * * @param context Application context * @param appPackageName The package name of the application. * @return A list or null if no signatures are found or error. */ public static List<String> application_getSignatures(Context context, String appPackageName) { List<String> appSignatures = null; try { if (appPackageName != null && appPackageName.length() > 0) { PackageInfo info = context.getPackageManager().getPackageInfo(appPackageName, PackageManager.GET_SIGNATURES); appSignatures = new ArrayList<String>(); String signatureString = null; for (Signature signature : info.signatures) { MessageDigest md = MessageDigest.getInstance("SHA"); md.update(signature.toByteArray()); signatureString = android.util.Base64.encodeToString(md.digest(), android.util.Base64.DEFAULT); Log.d(ToolBox.TAG, "KeyHash (" + appPackageName + "): " + signatureString); appSignatures.add(signatureString); } } else { Log.d(ToolBox.TAG, "No package name to get signaturs from."); } } catch (NameNotFoundException e) { Log.e(ToolBox.TAG, "Error getting application (" + appPackageName + ") signatures. Package not found [" + e.getMessage() + "].", e); } catch (NoSuchAlgorithmException e) { Log.e(ToolBox.TAG, "Error getting application (" + appPackageName + ") signatures. Algorithm SHA not found [" + e.getMessage() + "].", e); } return appSignatures; } //-------------------- ACTIVITY----------------------------------------------------------------------- /** * This method changes the ActionBar Icon. * * Requires API level 14 or higher. * * @param context * @param activity Should be a ActionBarActivity of support compatibility pack. * @param iconResourceId */ public static void activity_actionBar_changeIcon(Context context, ActionBarActivity activity, int iconResourceId) { activity.getSupportActionBar().setIcon(iconResourceId); } /** * Converts the ActionBar icon to Back icon mode. Must be used * in the onCreate method. * * Requires API level 14 or higher. * * @param context * @param activity Should be a ActionBarActivity of support compatibility pack. * @param iconResourceId */ public static void activity_actionBar_enableBackButton(Context context, ActionBarActivity activity, int iconResourceId) { activity.getSupportActionBar().setHomeButtonEnabled(true); activity.getSupportActionBar().setDisplayHomeAsUpEnabled(true); } //-------------------- DIALOGS ------------------------------------------------------------------------ /** * creates an exit popup dialog. * * @param context * @param title * @param message * @param yesLabel * @param cancelLabel */ public static void dialog_showExitConfirmationDialog(final Context context, int title, int message, int yesLabel, int cancelLabel) { new AlertDialog.Builder(context).setIcon(android.R.drawable.ic_dialog_alert) .setTitle(context.getResources().getString(title)) .setMessage(context.getResources().getString(message)) .setPositiveButton(context.getResources().getString(yesLabel), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { ((Activity) context).finish(); } }) .setNegativeButton(context.getResources().getString(cancelLabel), null).show(); } /** * Creates an alert with an OK button. * * @param context * @param msgResourceId */ public static void dialog_showAlertOkDialog(Context context, int titleResourceId, int msgResourceId) { AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setMessage(context.getResources().getString(msgResourceId)).setCancelable(false) .setPositiveButton("Ok", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } }); if (titleResourceId != 0) { builder.setTitle(context.getResources().getString(titleResourceId)); } AlertDialog alert = builder.create(); alert.show(); } /** * Creates an alert with an OK button. * * @param context * @param message */ public static void dialog_showAlertOkDialog(Context context, String tittle, String message) { AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setMessage(message).setCancelable(false).setPositiveButton("Ok", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } }); if (tittle != null && tittle.length() > 0) { builder.setTitle(tittle); } AlertDialog alert = builder.create(); alert.show(); } /** * Creates and shows a custom Alert dialog that will execute * the actions specified for positive, negative and * neutral buttons. * * @param context * @param title * @param message * @param positiveBtnActions Can be null. When null button is not shown. * @param negativeBtnActions Can be null. When null button is not shown. * @param neutralBtnActions Can be null. */ public static void dialog_showCustomActionsDialog(Context context, String title, String message, String positiveBtnText, final Runnable positiveBtnActions, String negativeBtnText, final Runnable negativeBtnActions, String neutralBtnText, final Runnable neutralBtnActions) { AlertDialog dialog = new AlertDialog.Builder(context).create(); dialog.setTitle(title); dialog.setMessage(message); dialog.setCancelable(true); dialog.setButton(AlertDialog.BUTTON_NEUTRAL, neutralBtnText, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { if (neutralBtnActions != null) { neutralBtnActions.run(); } dialog.dismiss(); } }); if (negativeBtnActions != null) { dialog.setButton(AlertDialog.BUTTON_NEGATIVE, negativeBtnText, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { negativeBtnActions.run(); } }); } if (positiveBtnActions != null) { dialog.setButton(AlertDialog.BUTTON_POSITIVE, positiveBtnText, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { positiveBtnActions.run(); } }); } dialog.show(); } /** * Opens a url in an alert dialog. * * @param context * @param title * @param url */ public static void dialog_showUrlInDialog(Context context, String title, String url) { AlertDialog.Builder alert = new AlertDialog.Builder(context); alert.setTitle(title); WebView wv = new WebView(context); wv.loadUrl(url); wv.setHorizontalScrollBarEnabled(false); alert.setView(wv); alert.setNegativeButton("Close", null); alert.show(); } /** * "Coach mark" (help overlay image) * * @param context * @param coachMarkLayoutId Is "Help overlay" layout id in UX talk :-) * [coach_mark.xml is your coach mark layout] * @param coachMarkMasterViewId is the id of the top most view in coach_mark.xml */ public static void dialog_onCoachMark(Context context, int coachMarkLayoutId, int coachMarkMasterViewId, int bgColor) { final Dialog dialog = new Dialog(context); dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); dialog.getWindow().setBackgroundDrawable(new ColorDrawable(bgColor)); dialog.setContentView(coachMarkLayoutId); dialog.setCanceledOnTouchOutside(true); //for dismissing anywhere you touch View masterView = dialog.findViewById(coachMarkMasterViewId); masterView.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { dialog.dismiss(); } }); dialog.show(); } /** * Shows a Toast alert. * * @param context * @param message * @param centerOnScreen Set to TRUE to center on the screen. */ public static void dialog_showToastAlert(Context context, String message, boolean centerOnScreen) { Toast msg = Toast.makeText(context, message, Toast.LENGTH_SHORT); if (centerOnScreen) { msg.setGravity(Gravity.CENTER, msg.getXOffset() / 2, msg.getYOffset() / 2); } msg.show(); } //-------------------- GRAPHICS ---------------------------------------------------------------------- public static Bitmap graphics_addWaterMarkToImage(Bitmap src, String watermark, Point location, int size, boolean underline) { Bitmap result = null; try { int w = src.getWidth(); int h = src.getHeight(); result = Bitmap.createBitmap(w, h, src.getConfig()); Canvas canvas = new Canvas(result); canvas.drawBitmap(src, 0, 0, null); Paint paint = new Paint(); paint.setColor(Color.RED); //paint.setAlpha(alpha); paint.setTextSize(size); paint.setAntiAlias(true); paint.setUnderlineText(underline); canvas.drawText(watermark, location.x, location.y, paint); } catch (Exception e) { result = null; if (LOG_ENABLE) Log.e(TAG, "ERROR: graphics_addWaterMarkToImage() [" + e.getMessage() + "]", e); } return result; } //-------------------- VIEWS ------------------------------------------------------------------------- public static void view_showAboutDialog(Context context, int titleResourceId, int aboutLayout, int okButtonId) { final Dialog dialog = new Dialog(context); dialog.setContentView(aboutLayout); dialog.setTitle(titleResourceId); Button dialogButton = (Button) dialog.findViewById(okButtonId); dialogButton.setOnClickListener(new OnClickListener() { public void onClick(View v) { dialog.dismiss(); } }); dialog.show(); } //SYSTEM NOTIFICATIONS --------------------------------------------------------------------------------------------------------------------- /** * Creates a system notification. * * @param context Context. * @param notSound Enable or disable the sound * @param notSoundRawId Custom raw sound id. If enabled and not set * default notification sound will be used. Set to -1 to * default system notification. * @param multipleNot Setting to True allows showing multiple notifications. * @param groupMultipleNotKey If is set, multiple notifications can be grupped by this key. * @param notAction Action for this notification * @param notTitle Title * @param notMessage Message * @param notClazz Class to be executed * @param extras Extra information * */ public static void notification_generate(Context context, boolean notSound, int notSoundRawId, boolean multipleNot, String groupMultipleNotKey, String notAction, String notTitle, String notMessage, Class<?> notClazz, Bundle extras, boolean wakeUp) { try { int iconResId = notification_getApplicationIcon(context); long when = System.currentTimeMillis(); Notification notification = new Notification(iconResId, notMessage, when); // Hide the notification after its selected notification.flags |= Notification.FLAG_AUTO_CANCEL; if (notSound) { if (notSoundRawId > 0) { try { notification.sound = Uri.parse("android.resource://" + context.getApplicationContext().getPackageName() + "/" + notSoundRawId); } catch (Exception e) { if (LOG_ENABLE) { Log.w(TAG, "Custom sound " + notSoundRawId + "could not be found. Using default."); } notification.defaults |= Notification.DEFAULT_SOUND; notification.sound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); } } else { notification.defaults |= Notification.DEFAULT_SOUND; notification.sound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); } } Intent notificationIntent = new Intent(context, notClazz); notificationIntent.setAction(notClazz.getName() + "." + notAction); if (extras != null) { notificationIntent.putExtras(extras); } //Set intent so it does not start a new activity // //Notes: // - The flag FLAG_ACTIVITY_SINGLE_TOP makes that only one instance of the activity exists(each time the // activity is summoned no onCreate() method is called instead, onNewIntent() is called. // - If we use FLAG_ACTIVITY_CLEAR_TOP it will make that the last "snapshot"/TOP of the activity it will // be this called this intent. We do not want this because the HOME button will call this "snapshot". // To avoid this behaviour we use FLAG_ACTIVITY_BROUGHT_TO_FRONT that simply takes to foreground the // activity. // //See http://developer.android.com/reference/android/content/Intent.html notificationIntent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_SINGLE_TOP); PendingIntent intent = PendingIntent.getActivity(context, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT); int REQUEST_UNIQUE_ID = 0; if (multipleNot) { if (groupMultipleNotKey != null && groupMultipleNotKey.length() > 0) { REQUEST_UNIQUE_ID = groupMultipleNotKey.hashCode(); } else { if (random == null) { random = new Random(); } REQUEST_UNIQUE_ID = random.nextInt(); } PendingIntent.getActivity(context, REQUEST_UNIQUE_ID, notificationIntent, PendingIntent.FLAG_ONE_SHOT); } notification.setLatestEventInfo(context, notTitle, notMessage, intent); //This makes the device to wake-up is is idle with the screen off. if (wakeUp) { powersaving_wakeUp(context); } NotificationManager notificationManager = (NotificationManager) context .getSystemService(Context.NOTIFICATION_SERVICE); //We check if the sound is disabled to enable just for a moment AudioManager amanager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); int previousAudioMode = amanager.getRingerMode(); ; if (notSound && previousAudioMode != AudioManager.RINGER_MODE_NORMAL) { amanager.setRingerMode(AudioManager.RINGER_MODE_NORMAL); } notificationManager.notify(REQUEST_UNIQUE_ID, notification); //We restore the sound setting if (previousAudioMode != AudioManager.RINGER_MODE_NORMAL) { //We wait a little so sound is played try { Thread.sleep(3000); } catch (Exception e) { } } amanager.setRingerMode(previousAudioMode); Log.d(TAG, "Android Notification created."); } catch (Exception e) { if (LOG_ENABLE) Log.e(TAG, "The notification could not be created (" + e.getMessage() + ")", e); } } /* * Gets the application Icon. * * @param context * @return * @throws ApplicationPackageNotFoundException */ private static int notification_getApplicationIcon(Context context) throws Exception { try { ApplicationInfo app = context.getPackageManager().getApplicationInfo(context.getPackageName(), 0); return app.icon; } catch (NameNotFoundException e) { if (LOG_ENABLE) Log.e(TAG, "Application package not found!."); throw e; } } // Power saving ---------------------------------------------------------------------------------------------------------------------------- /* * Makes the device to wake-up. yeah! * * Requires the permission android.permission.WAKE_LOCK * * @param ctx */ public static void powersaving_wakeUp(Context ctx) { if (wakeLock != null) wakeLock.release(); PowerManager pm = (PowerManager) ctx.getSystemService(Context.POWER_SERVICE); wakeLock = pm.newWakeLock( PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.ON_AFTER_RELEASE, "javocsoft_library_wakeup"); wakeLock.acquire(); } // Net Related ----------------------------------------------------------------------------------------------------------------------------- /** * Makes a Http operation. * * This method set a parameters to the request that avoid being waiting * for the server response or once connected, being waiting to receive * the data. * * @param method Method type to execute. @See HTTP_METHOD. * @param url Url of the request. * @param jsonData The body content of the request (JSON). Can be null. * @param headers The headers to include in the request. * @return The content of the request if there is one. * @throws Exception */ public static String net_httpclient_doAction(HTTP_METHOD method, String url, String jsonData, Map<String, String> headers) throws ConnectTimeoutException, SocketTimeoutException, Exception { String responseData = null; DefaultHttpClient httpclient = new DefaultHttpClient(); // The time it takes to open TCP connection. httpclient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, CONNECTION_DEFAULT_TIMEOUT); // Timeout when server does not send data. httpclient.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, CONNECTION_DEFAULT_DATA_RECEIVAL_TIMEOUT); // Some tuning that is not required for bit tests. //httpclient.getParams().setParameter(CoreConnectionPNames.STALE_CONNECTION_CHECK, false); httpclient.getParams().setParameter(CoreConnectionPNames.TCP_NODELAY, true); HttpRequestBase httpMethod = null; switch (method) { case POST: httpMethod = new HttpPost(url); //Add the body to the request. StringEntity se = new StringEntity(jsonData); ((HttpPost) httpMethod).setEntity(se); break; case DELETE: httpMethod = new HttpDelete(url); break; case GET: httpMethod = new HttpGet(url); break; } //Add the headers to the request. if (headers != null) { for (String header : headers.keySet()) { httpMethod.setHeader(header, headers.get(header)); } } HttpResponse response = httpclient.execute(httpMethod); if (LOG_ENABLE) { Log.d(TAG, "HTTP OPERATION: Read from server - Status Code: " + response.getStatusLine().getStatusCode()); Log.d(TAG, "HTTP OPERATION: Read from server - Status Message: " + response.getStatusLine().getReasonPhrase()); } //Get the response body if there is one. HttpEntity entity = response.getEntity(); if (entity != null) { //responseData = EntityUtils.toString(entity, "UTF-8"); InputStream instream = entity.getContent(); responseData = IOUtils.convertStreamToString(instream); if (LOG_ENABLE) Log.i(TAG, "HTTP OPERATION: Read from server - return: " + responseData); } if (response.getStatusLine().getStatusCode() != 200) { throw new Exception("Http operation " + method.name() + " failed with error code " + response.getStatusLine().getStatusCode() + "(" + response.getStatusLine().getReasonPhrase() + ")"); } return responseData; } public static boolean net_isNetworkAvailable(Context context) { ConnectivityManager connectivityManager = (ConnectivityManager) context .getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo(); return activeNetworkInfo != null && activeNetworkInfo.isConnected(); } /** * Gets the network carrier. * * If the device is an emulator returns "EMU", if no SIM is present returns * NOSIM. * * @See NETWORK_PROVIDER. * * @param ctx * @return */ public static NETWORK_PROVIDER net_getCurrentNetworkOperator(Context ctx) { final String emulatorDevice = "Android"; final String noSIMDevice = ""; // if(Debug.isDebuggerConnected()){} TelephonyManager tm = (TelephonyManager) ctx.getSystemService(Context.TELEPHONY_SERVICE); String networkOperator = tm.getNetworkOperatorName(); if (emulatorDevice.equalsIgnoreCase(networkOperator)) { return NETWORK_PROVIDER.EMU; } else if (emulatorDevice.equalsIgnoreCase(noSIMDevice)) { return NETWORK_PROVIDER.NOSIM; } else { try { return NETWORK_PROVIDER.valueOf(networkOperator.toUpperCase()); } catch (Exception e) { // Non expected network provider. return NETWORK_PROVIDER.UNKNOWN; } } } // Storage Related ----------------------------------------------------------------------------------------------------------------------------- public static byte[] storage_readAssetResource(Context context, String fileName) { try { InputStream asset = context.getAssets().open(fileName); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); byte[] buffer = new byte[asset.available()]; asset.read(buffer); byteArrayOutputStream.write(buffer); asset.close(); return byteArrayOutputStream.toByteArray(); } catch (Exception e) { if (LOG_ENABLE) Log.e("TollBox_ERROR", "storage_readRawResource() Error obtaining raw data: " + e.getMessage(), e); return null; } } public static byte[] storage_readRawResource(Context context, String fileName) { int resId = context.getResources().getIdentifier(fileName, "raw", context.getPackageName()); try { InputStream raw = context.getResources().openRawResource(resId); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); byte[] buffer = new byte[raw.available()]; raw.read(buffer); byteArrayOutputStream.write(buffer); raw.close(); return byteArrayOutputStream.toByteArray(); } catch (Exception e) { if (LOG_ENABLE) Log.e("TollBox_ERROR", "storage_readRawResource() Error obtaining raw data: " + e.getMessage(), e); return null; } } /** * This method returns the application external folder. All the stuff * saved in this folder is deleted when the application is uninstalled. * * If the SD folder is not mounted null is returned. * * @param app Application context. * @param folder The type of files directory to return. * May be null for the root of the app. data directory or * some folder value. * * @return */ public static File storage_getAppExternalStorageFolder(Application app, String folder) { File res = null; if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { res = app.getExternalFilesDir(folder); } return res; } /** * This function returns a File object pointing to the specified folder. If none is * specified, root dir of the SD is returned. * * Returns null if the media is not mounted. * * @param folderType The type of files directory to return. * May be null to get the root of the SD or * any of the Environment.DIRECTORY_ options. * * @return */ public static File storage_getExternalFolder(String folderType) { File res = null; if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { res = new File(Environment.getExternalStorageDirectory(), folderType); } return res; } /** * This function returns a File object pointing to a public folder of the the specified * type in the external drive. * * User media is saved here. Be carefull. * * Returns null if the media is not mounted. * * @param folderType The type of files directory to return. Use one of the avaliable * Environment.DIRECTORY_ values. * @param folder An specific folder in the public folder. May be null to get * the root of the public folder type. * @param createFolder Set to TRUE to create the folder if it does not exists. * * @return */ public static File storage_getExternalPublicFolder(String folderType, String folder, boolean createFolder) { File res = null; if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { res = new File(Environment.getExternalStoragePublicDirectory(folderType), folder); if (!res.exists()) { //We create the folder if is desired. if (folder != null && folder.length() > 0 && createFolder) { if (!res.mkdir()) { res = null; } } else { res = null; } } } return res; } /** * Saves the content of the specified input stream into the outputFile. * * @param is * @param outputFile * @param closeInput */ public static void storage_saveInputData(InputStream is, File outputFile, boolean closeInput) throws Exception { try { OutputStream os = new FileOutputStream(outputFile); storage_copyStream(is, os, 1024); os.close(); if (closeInput) { is.close(); } } catch (Exception e) { if (LOG_ENABLE) Log.e(TAG, "storage_saveInputData(): " + e.getMessage(), e); throw new Exception(TAG + "[storage_saveInputData()]: " + e.getMessage(), e); } } /** * Gets the application internal storage path. * * @param context * @param file * @return */ public static File storage_getAppInternalStorageFilePath(Context context, String file) { String filePath = context.getFilesDir().getAbsolutePath();//returns current directory. if (file == null) { return new File(filePath); } else { return new File(filePath, file); } } /** * Reads a text file returning its contents as an string. * * @param file * @return * @throws Exception */ public static String storage_getTextFileContentAsString(String file, String encoding) throws Exception { String res; try { BufferedReader bufferedReader = new BufferedReader( new InputStreamReader(new FileInputStream(file), encoding)); String read; StringBuilder builder = new StringBuilder(""); while ((read = bufferedReader.readLine()) != null) { builder.append(read + "\n"); } res = builder.toString(); bufferedReader.close(); } catch (Exception e) { if (LOG_ENABLE) Log.e(TAG, "storage_getTextFileContentAsString(): " + e.getMessage(), e); throw new Exception(TAG + "[storage_getTextFileContentAsString()]: " + e.getMessage(), e); } return res; } /** * This method copies the input to the specified output. * * @param is Input source * @param os Output destiny * @return Total bytes read */ public static int storage_copyStream(InputStream is, OutputStream os, int buffer_size) throws IOException { int readbytes = 0; if (buffer_size <= 0) { buffer_size = 1024; } try { byte[] bytes = new byte[buffer_size]; for (;;) { int count = is.read(bytes, 0, buffer_size); if (count == -1) break; os.write(bytes, 0, count); readbytes += count; } } catch (Exception e) { throw new IOException("Failed to save data (" + e.getMessage() + ").", e); } return readbytes; } /** * Saves data to the application internal folder. * * @param context * @param fileName * @param data * @throws Exception */ public static synchronized void storage_storeDataInInternalStorage(Context context, String fileName, byte[] data) throws Exception { try { /* We have to use the openFileOutput()-method * the ActivityContext provides, to * protect your file from others and * This is done for security-reasons. * We chose MODE_WORLD_READABLE, because * we have nothing to hide in our file */ FileOutputStream fOut = context.openFileOutput(fileName, Context.MODE_WORLD_READABLE); // Write the string to the file fOut.write(data); /* ensure that everything is really written out and close */ fOut.flush(); fOut.close(); } catch (Exception e) { throw new Exception("Error saving data to '" + fileName + "' (internal storage) : " + e.getMessage(), e); } } /** * Reads data from the application internal storage data folder. * * @param context * @param fileName * @return * @throws Exception */ public static byte[] storage_readDataFromInternalStorage(Context context, String fileName) throws Exception { FileInputStream fIn; try { fIn = context.openFileInput(fileName); byte[] buffer = new byte[fIn.available()]; fIn.read(buffer); fIn.close(); return buffer; } catch (Exception e) { throw new Exception("Error reading data '" + fileName + "' (internal storage) : " + e.getMessage(), e); } } /** * Deletes a file from the application internal storage private folder. * * @param context * @param fileName * @throws Exception */ public static void storage_deleteDataFromInternalStorage(Context context, String fileName) throws Exception { try { context.deleteFile(fileName); } catch (Exception e) { throw new Exception("Error deleting data '" + fileName + "' (internal storage) : " + e.getMessage(), e); } } /** * Checks if a file exists in the application internal private data folder. * * @param context * @param fileName * @return */ public static boolean storage_checkIfFileExistsInInternalStorage(Context context, String fileName) { try { context.openFileInput(fileName); return true; } catch (FileNotFoundException e) { return false; } } /** * Saves an URL link into the external SD card of the Device. * * @param dataUrl * @param fileName * @param bufferSize * @return * @throws Exception */ public static String storage_saveUrlToExternal(String dataUrl, String fileName, int bufferSize) throws Exception { String res; InputStream input = null; OutputStream output = null; try { URL url = new URL(dataUrl); input = url.openStream(); //The sdcard directory '/sdcard' can be used directly but is //better and safety if we use "getExternalStorageDirectory()" :) File storagePath = Environment.getExternalStorageDirectory(); File f = new File(storagePath, fileName); output = new FileOutputStream(f); byte[] buffer = new byte[bufferSize]; int bytesRead = 0; while ((bytesRead = input.read(buffer, 0, buffer.length)) >= 0) { output.write(buffer, 0, bytesRead); } res = f.getAbsolutePath(); } catch (Exception e) { throw new Exception("Error saving data in external storage : " + e.getMessage(), e); } finally { try { input.close(); output.close(); } catch (Exception e) { } } return res; } /** * Saves the Url link into the internal memory card in the application private zone. * * @param context * @param dataUrl * @param bufferSize * @return * @throws Exception */ public static String storage_saveUrlToInternal(Context context, String dataUrl, int bufferSize) throws Exception { String res = null; try { String filename = String .valueOf(dataUrl.hashCode() + dataUrl.substring(dataUrl.lastIndexOf("."), dataUrl.length())); if (!storage_checkIfFileExistsInInternalStorage(context, filename)) { URL url = new URL(dataUrl); InputStream input = url.openStream(); ByteArrayOutputStream output = new ByteArrayOutputStream(); try { byte[] buffer = new byte[bufferSize]; int bytesRead = 0; while ((bytesRead = input.read(buffer, 0, buffer.length)) >= 0) { output.write(buffer, 0, bytesRead); } } finally { output.close(); } byte[] data = output.toByteArray(); storage_storeDataInInternalStorage(context, filename, data); } res = filename; } catch (Exception e) { throw new Exception("Error saving data in internal storage : " + e.getMessage(), e); } return res; } /** * * @param context * @param dataUrl * @param bufferSize * @param watermark * @param watermark_underlined * @return * @throws Exception */ public static String storage_saveImageUrlToInternalAddingWatermark(Context context, String dataUrl, int bufferSize, String watermark, boolean watermark_underlined) throws Exception { String res = null; try { String filename = String .valueOf(dataUrl.hashCode() + dataUrl.substring(dataUrl.lastIndexOf("."), dataUrl.length())); if (!storage_checkIfFileExistsInInternalStorage(context, filename)) { URL url = new URL(dataUrl); InputStream input = url.openStream(); ByteArrayOutputStream output = new ByteArrayOutputStream(); try { byte[] buffer = new byte[bufferSize]; int bytesRead = 0; while ((bytesRead = input.read(buffer, 0, buffer.length)) >= 0) { output.write(buffer, 0, bytesRead); } } finally { output.close(); } byte[] data = output.toByteArray(); //Add watermark -------------------------------------------------------------------------------- try { Bitmap image = BitmapFactory.decodeByteArray(data, 0, data.length); Bitmap imageW = graphics_addWaterMarkToImage(image, watermark, new Point(5, image.getHeight() - 5), 24, watermark_underlined); if (imageW != null) { //Get modified image bytes to save it ByteArrayOutputStream stream = new ByteArrayOutputStream(); imageW.compress(Bitmap.CompressFormat.PNG, 100, stream); data = stream.toByteArray(); stream.close(); } } catch (Exception e) { } //Nothing needs to be done. //---------------------------------------------------------------------------------------------- storage_storeDataInInternalStorage(context, filename, data); } res = filename; } catch (Exception e) { throw new Exception("Error saving data in internal storage : " + e.getMessage(), e); } return res; } /** * Return a temporal empty file. * * @param filePrefix * @param fileSuffix * @param outputDirectory * @return * @throws java.io.IOException */ public static File storage_createUniqueFileName(String filePrefix, String fileSuffix, File outputDirectory) throws IOException { String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date()); String fileName = filePrefix + timeStamp; File filePath = File.createTempFile(fileName, fileSuffix, outputDirectory); if (filePath.exists()) { return filePath; } else { return null; } } //--------------- PREFS --------------------------------------------------------------------------- public static boolean prefs_savePreference(Context ctx, String prefName, String key, Class<?> valueType, Object value) { boolean res = false; SharedPreferences prefs = ctx.getSharedPreferences(prefName, Context.MODE_PRIVATE); if (value == null) { prefs.edit().remove(key).commit(); } else { if (valueType == Long.class) { res = prefs.edit().putLong(key, (Long) value).commit(); } else if (valueType == Boolean.class) { res = prefs.edit().putBoolean(key, (Boolean) value).commit(); } else if (valueType == Float.class) { res = prefs.edit().putFloat(key, (Float) value).commit(); } else if (valueType == Integer.class) { res = prefs.edit().putInt(key, (Integer) value).commit(); } else if (valueType == String.class) { res = prefs.edit().putString(key, (String) value).commit(); } else if (valueType == Set.class) { if (((Set<String>) value).size() == 0) { prefs.edit().remove(key).commit(); } else { //res = prefs.edit().putStringSet(key, (Set<String>)value).commit(); //Only from 11 API level. res = saveSetListAsCommaSeparatedString(ctx, prefName, key, (Set<String>) value); } } } return res; } public static Object prefs_readPreference(Context ctx, String prefName, String key, Class<?> valueType) { SharedPreferences prefs = ctx.getSharedPreferences(prefName, Context.MODE_PRIVATE); if (valueType == Long.class) { return prefs.getLong(key, Long.valueOf(-1)); } else if (valueType == Boolean.class) { return prefs.getBoolean(key, Boolean.valueOf(false)); } else if (valueType == Float.class) { return prefs.getFloat(key, Float.valueOf(-1)); } else if (valueType == Integer.class) { return prefs.getInt(key, Integer.valueOf(-1)); } else if (valueType == String.class) { return prefs.getString(key, null); } else if (valueType == Set.class) { //return prefs.getStringSet(key, null); //Only from 11 API level. return getSetListFromCommaSeparatedString(ctx, prefName, key); } return null; } /** * Tells if the preferemce exists. * * @param ctx * @param prefName * @param key * @return */ public static Boolean prefs_existsPref(Context ctx, String prefName, String key) { SharedPreferences prefs = ctx.getSharedPreferences(prefName, Context.MODE_PRIVATE); if (prefs.contains(key)) { return true; } else { return false; } } /* * This method is for compatibility mode because SharedPreferences only works with * Set data values starting at API Level 11. * * @param context * @param prefName * @param key * @return */ private static Set<String> getSetListFromCommaSeparatedString(Context context, String prefName, String key) { Set<String> res = new HashSet<String>(); String resString = (String) ToolBox.prefs_readPreference(context, prefName, key, String.class); if (resString != null && resString.length() > 0) { res = new HashSet<String>(Arrays.asList(resString.split(","))); } return res; } /* * This method is for compatibility mode because SharedPreferences only works with * Set data values starting at API Level 11. * * @param context * @param prefName * @param key * @param value * @return */ private static boolean saveSetListAsCommaSeparatedString(Context context, String prefName, String key, Set<String> value) { boolean res = false; if (value != null && value.size() > 0) { StringBuffer buff = new StringBuffer(); int pos = 0; for (String s : value) { if (pos > 0) { buff.append(","); } buff.append(s); pos++; } String data = buff.toString(); if (data != null && data.length() > 0) { res = prefs_savePreference(context, prefName, key, String.class, data); } } return res; } //--------------- SHARE --------------------------------------------------------------------------- /** * Allows to create a share intent and it can be launched. * * @param context * @param type Mime type. * @param nameApp You can filter the application you want to share with. Use "wha", "twitt", etc. * @param title The title of the share.Take in account that sometimes is not possible to add the title. * @param data The data, can be a file or a text. * @param isBinaryData If the share has a data file, set to TRUE otherwise FALSE. */ @SuppressLint("DefaultLocale") public static Intent share_newSharingIntent(Context context, String type, String nameApp, String title, String data, boolean isBinaryData, boolean launch) { Intent res = null; Intent share = new Intent(Intent.ACTION_SEND); share.setType(type); List<Intent> targetedShareIntents = new ArrayList<Intent>(); List<ResolveInfo> resInfo = context.getPackageManager().queryIntentActivities(share, 0); if (!resInfo.isEmpty()) { for (ResolveInfo info : resInfo) { Intent targetedShare = new Intent(Intent.ACTION_SEND); targetedShare.setType(type); if (title != null) { targetedShare.putExtra(Intent.EXTRA_SUBJECT, title); targetedShare.putExtra(Intent.EXTRA_TITLE, title); if (data != null && !isBinaryData) { targetedShare.putExtra(Intent.EXTRA_TEXT, data); } } if (data != null && isBinaryData) { targetedShare.putExtra(Intent.EXTRA_TEXT, title); targetedShare.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(data))); } if (nameApp != null) { if (info.activityInfo.packageName.toLowerCase().contains(nameApp) || info.activityInfo.name.toLowerCase().contains(nameApp)) { targetedShare.setPackage(info.activityInfo.packageName); targetedShareIntents.add(targetedShare); } } else { targetedShare.setPackage(info.activityInfo.packageName); targetedShareIntents.add(targetedShare); } } Intent chooserIntent = Intent.createChooser(targetedShareIntents.remove(0), "Select app to share"); chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetedShareIntents.toArray(new Parcelable[] {})); res = chooserIntent; if (launch) { context.startActivity(chooserIntent); } } return res; } //--------------- IO RELATED ----------------------------------------------------------------------- /** * Reads the data of an input stream to a String. * * @param is * @return * @throws java.io.IOException */ public static String io_convertStreamToString(InputStream is) throws IOException { /* * To convert the InputStream to String we use the * BufferedReader.readLine() method. We iterate until the BufferedReader * return null which means there's no more data to read. Each line will * appended to a StringBuilder and returned as String. */ if (is != null) { StringBuilder sb = new StringBuilder(); String line; try { BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8")); while ((line = reader.readLine()) != null) { sb.append(line).append("\n"); } } finally { is.close(); } return sb.toString(); } else { return ""; } } /** * Reads the byte data from a input stream. * * @param input * @return * @throws java.io.IOException */ public static byte[] io_inputStreamToByteArray(InputStream input) throws IOException { byte[] res = null; try { // this dynamically extends to take the bytes you read ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream(); // this is storage overwritten on each iteration with bytes int bufferSize = 1024; byte[] buffer = new byte[bufferSize]; // we need to know how may bytes were read to write them to the byteBuffer int len = 0; while (input.available() > 0 && (len = input.read(buffer)) != -1) { byteBuffer.write(buffer, 0, len); } byteBuffer.flush(); res = byteBuffer.toByteArray(); byteBuffer.close(); } catch (Exception e) { throw new IOException("Failed to read byte data from the stream (" + e.getMessage() + ").", e); } return res; } //--------------- MARKET ---------------------------------------------------------------------------- /** * Prepares an intent for the Android Market application. In an * error occurs a url is used. * * @param appName * @return */ public static Intent market_getMarketAppIntent(String appName) { Intent i = new Intent(Intent.ACTION_VIEW); try { i.setData(Uri.parse("market://details?id=" + appName)); } catch (android.content.ActivityNotFoundException anfe) { i.setData(Uri.parse("http://play.google.com/store/apps/details?id=" + appName)); } return i; } //--------------- SCREEN ---------------------------------------------------------------------------- /** * Sets LinearLayout parameters using density points. * * @param context * @param container * @param viewId * @param height * @param width * @param weight */ public static void screen_setLinearLayoutParams(Context context, View container, int viewId, float height, float width, float weight) { container.findViewById(viewId).setLayoutParams(new LinearLayout.LayoutParams( screen_getDensityPoints(context, width), screen_getDensityPoints(context, height), weight)); } /** * Gets the current orientation. * * @param context * @return {@link es.javocsoft.android.lib.toolbox.ToolBox.SCREEN_ORIENTATION} */ @SuppressWarnings("deprecation") public static SCREEN_ORIENTATION screen_getOrientation(Context context) { SCREEN_ORIENTATION res = SCREEN_ORIENTATION.PORTRAIT; Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); //int orientation = Configuration.ORIENTATION_UNDEFINED; if (display.getWidth() == display.getHeight()) { res = SCREEN_ORIENTATION.SQUARE; //orientation = Configuration.ORIENTATION_SQUARE; } else { if (display.getWidth() < display.getHeight()) { res = SCREEN_ORIENTATION.PORTRAIT; //orientation = Configuration.ORIENTATION_PORTRAIT; } else { res = SCREEN_ORIENTATION.LANDSCAPE; //orientation = Configuration.ORIENTATION_LANDSCAPE; } } return res; } /** * Gets the density points for a given size. * * @param context * @param size * @return */ public static int screen_getDensityPoints(Context context, float size) { float d = context.getResources().getDisplayMetrics().density; return (int) (size * d); // margin in pixels } //--------------- WEB RELATED ----------------------------------------------------------------------- /** * Checks if the url exists. * * @param URLName * @return */ public static boolean web_fileExists(String URLName) { try { HttpURLConnection.setFollowRedirects(false); // It may also needed // HttpURLConnection.setInstanceFollowRedirects(false) HttpURLConnection con = (HttpURLConnection) new URL(URLName).openConnection(); con.setRequestMethod("HEAD"); return (con.getResponseCode() == HttpURLConnection.HTTP_OK); } catch (Exception e) { if (LOG_ENABLE) Log.d("ToolBox", "Url does not exist (" + URLName + ")."); return false; } } /** * Enables http cache. (when using webview for example) * * @param ctx */ public static void web_enableHttpResponseCache(Context ctx) { try { long httpCacheSize = HTTP_CACHE_SIZE; File httpCacheDir = new File(ctx.getCacheDir(), "http"); Class.forName("android.net.http.HttpResponseCache").getMethod("install", File.class, long.class) .invoke(null, httpCacheDir, httpCacheSize); } catch (Exception e) { if (LOG_ENABLE) Log.e(TAG, "Http Response cache could not be initialized [" + e.getMessage() + "]", e); } } // Media Related ----------------------------------------------------------------------------------------------------------------------------- /** * Corrects the orientation of a Bitmap. Orientation, depending of the device * , is not correctly set in the EXIF data of the taken image when it is saved * into disk. * * Explanation: * Camera orientation is not working ok (as is when capturing an image) because * OEMs do not adhere to the standard. So, each company does this following their * own way. * * @param imagePath path to the file * @return */ public static Bitmap media_correctImageOrientation(String imagePath) { Bitmap res = null; try { File f = new File(imagePath); ExifInterface exif = new ExifInterface(f.getPath()); int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL); int angle = 0; if (orientation == ExifInterface.ORIENTATION_ROTATE_90) { angle = 90; } else if (orientation == ExifInterface.ORIENTATION_ROTATE_180) { angle = 180; } else if (orientation == ExifInterface.ORIENTATION_ROTATE_270) { angle = 270; } Matrix mat = new Matrix(); mat.postRotate(angle); BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = 2; Bitmap bmp = BitmapFactory.decodeStream(new FileInputStream(f), null, options); res = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), mat, true); } catch (OutOfMemoryError e) { if (LOG_ENABLE) Log.e(TAG, "media_correctImageOrientation() [OutOfMemory!]: " + e.getMessage(), e); } catch (Exception e) { if (LOG_ENABLE) Log.e(TAG, "media_correctImageOrientation(): " + e.getMessage(), e); } catch (Throwable e) { if (LOG_ENABLE) Log.e(TAG, "media_correctImageOrientation(): " + e.getMessage(), e); } return res; } /** * Converts an image file to Base64 string. * * @param pathToFile * @return */ public static String media_getAssetImageAsB64(Context context, String pathToFile) { String encodedImage = null; byte[] b = storage_readAssetResource(context, pathToFile); encodedImage = Base64.encodeToString(b, false); return encodedImage; } /** * Decodes the specified image of the provided URL, scales it to reduce memory * consumption and returning as a Bitmap object. * * First tries from the cache, if does not exists it tries from the net. * * @param storageDir * @param urlImage * @param cacheExists * @return */ public static Bitmap media_getBitmapFromNet(File storageDir, String urlImage, boolean cacheExists) throws Exception { Bitmap res = null; //I creates the names of the images by the hashcode of its url String filename = String.valueOf(urlImage.hashCode()); File f = new File(storageDir, filename); try { //First, try to load then from the cache SD dir if (cacheExists) { Bitmap b = media_getBitmapFromFile(f); if (b != null) return b; } //If is not in the cache (or cache is not activated), tries from web // //...get the image from the net Bitmap bitmap = null; if (cacheExists) { //We store the image in the cache storage_saveInputData(new URL(urlImage).openStream(), f, true); //...and get from the cache bitmap = media_getBitmapFromFile(f); } else { //Read directly from the net without saving in cache URL imageURL = new URL(urlImage); InputStream is = imageURL.openConnection().getInputStream(); BufferedInputStream bis = new BufferedInputStream(is); bitmap = BitmapFactory.decodeStream(bis); bis.close(); is.close(); } res = bitmap; } catch (Exception e) { if (LOG_ENABLE) Log.e(TAG, "media_getBitmapFromNet(): " + e.getMessage(), e); throw new Exception(TAG + "[media_getBitmapFromNet()]: " + e.getMessage(), e); } return res; } /** * Decodes the specified image from the storage, scales it to reduce memory consumption * and returning as a Bitmap object. * * @param imgFile File to get as a Bitmap object. * @return */ public static Bitmap media_getBitmapFromFile(File imgFile) throws Exception { Bitmap res = null; try { //Decode image size BitmapFactory.Options o = new BitmapFactory.Options(); o.inJustDecodeBounds = true; BitmapFactory.decodeStream(new FileInputStream(imgFile), null, o); //Find the correct scale value. It should be the power of 2. final int REQUIRED_SIZE = 70; int width_tmp = o.outWidth, height_tmp = o.outHeight; int scale = 1; while (true) { if (width_tmp / 2 < REQUIRED_SIZE || height_tmp / 2 < REQUIRED_SIZE) break; width_tmp /= 2; height_tmp /= 2; scale *= 2; } //Decode with inSampleSize BitmapFactory.Options o2 = new BitmapFactory.Options(); o2.inSampleSize = scale; res = BitmapFactory.decodeStream(new FileInputStream(imgFile), null, o2); } catch (FileNotFoundException e) { if (LOG_ENABLE) Log.e(TAG, "media_generateBitmapFromFile() - FileNotFoundException: " + e.getMessage(), e); throw new Exception(TAG + "[media_generateBitmapFromFile() - FileNotFoundException]: " + e.getMessage(), e); } catch (Exception e) { if (LOG_ENABLE) Log.e(TAG, "media_generateBitmapFromFile(): " + e.getMessage(), e); throw new Exception(TAG + "[media_generateBitmapFromFile()]: " + e.getMessage(), e); } return res; } /** * Grabs an image direct from a URL into a Drawable without saving a cache * * @param urlImage * @param src_name * @return * @throws Exception */ public static Drawable media_getDrawableFromNet(String urlImage, String src_name) throws Exception { Drawable res = null; try { InputStream is = ((InputStream) new URL(urlImage).getContent()); res = Drawable.createFromStream(is, src_name); is.close(); } catch (MalformedURLException e) { if (LOG_ENABLE) Log.e(TAG, "media_generateBitmapFromFile() - MalformedURLException: " + e.getMessage(), e); throw new Exception(TAG + "[media_generateBitmapFromFile() - MalformedURLException]: " + e.getMessage(), e); } catch (IOException e) { if (LOG_ENABLE) Log.e(TAG, "media_generateBitmapFromFile() - IOException: " + e.getMessage(), e); throw new Exception(TAG + "[media_generateBitmapFromFile() - IOException]: " + e.getMessage(), e); } catch (Exception e) { if (LOG_ENABLE) Log.e(TAG, "media_generateBitmapFromFile(): " + e.getMessage(), e); throw new Exception(TAG + "[media_generateBitmapFromFile()]: " + e.getMessage(), e); } return res; } /** * Grabs an image direct from a file into a Drawable without saving a cache * * @param filePath * @return * @throws Exception */ public static Drawable media_getDrawableFromFile(String filePath) throws Exception { Drawable res = null; try { res = Drawable.createFromPath(filePath); } catch (Exception e) { if (LOG_ENABLE) Log.e(TAG, "media_getDrawableFromFile(): " + e.getMessage(), e); throw new Exception(TAG + "[media_getDrawableFromFile()]: " + e.getMessage(), e); } return res; } /** * Loads a Bitmap image form the internal storage. * * @param context * @param fileName * @return * @throws Exception */ public static Bitmap media_loadBitmapFromInternalStorage(Context context, String fileName) throws Exception { try { FileInputStream is = context.openFileInput(fileName); Bitmap b = BitmapFactory.decodeStream(is); return b; } catch (Exception e) { throw new Exception("Error reading data '" + fileName + "' (internal storage) : " + e.getMessage(), e); } } /** * Makes rounded corners on a bitmap. * * Requires Level 17 of Android API!! * * @param bitmap * @return */ /*public static Bitmap media_getRoundedCornerBitmap(Bitmap bitmap) { Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Config.ARGB_8888); Canvas canvas = new Canvas(output); final int color = 0xff424242; final Paint paint = new Paint(); final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); final RectF rectF = new RectF(rect); final float roundPx = 8; paint.setAntiAlias(true); canvas.drawARGB(0, 0, 0, 0); paint.setColor(color); canvas.drawRoundRect(rectF, roundPx, roundPx, paint); paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); canvas.drawBitmap(bitmap, rect, rect, paint); return output; }*/ /** * Convers a Bitmap to grayscale. * * @param bmpOriginal * @return */ public static Bitmap media_getGrayScale(Bitmap bmpOriginal) { int width, height; height = bmpOriginal.getHeight(); width = bmpOriginal.getWidth(); Bitmap bmpGrayscale = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); Canvas c = new Canvas(bmpGrayscale); Paint paint = new Paint(); ColorMatrix cm = new ColorMatrix(); cm.setSaturation(0); ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm); paint.setColorFilter(f); c.drawBitmap(bmpOriginal, 0, 0, paint); return bmpGrayscale; } /** * Plays the specified ringtone from the application raw folder. * * @param appPackage Application package. (you can get it by using: * AppVigilant.thiz.getApplicationContext().getPackageName()) * @param soundResourceId Sound resource id */ public static void media_soundPlayFromRawFolder(Context context, String appPackage, int soundResourceId) { try { Uri soundUri = Uri.parse("android.resource://" + appPackage + "/" + soundResourceId); Ringtone r = RingtoneManager.getRingtone(context, soundUri); r.play(); } catch (Exception e) { if (LOG_ENABLE) { Log.e(TAG, "Error playing sound with resource id: '" + soundResourceId + "' (" + e.getMessage() + ")", e); } } } /** * Plays the default system notification ringtone. * * @param context */ public static void media_soundPlayNotificationDefault(Context context) { try { Uri soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); Ringtone r = RingtoneManager.getRingtone(context, soundUri); r.play(); } catch (Exception e) { if (LOG_ENABLE) { Log.e(TAG, "Error playing default notification sound (" + e.getMessage() + ")", e); } } } /** * Plays the specified sound from the application asset folder. * * @param context * @param assetSoundPath Path to the sound in the assets folder. */ public static void media_soundPlayFromAssetFolder(Context context, String assetSoundPath) { try { AssetFileDescriptor afd = context.getAssets().openFd(assetSoundPath); MediaPlayer player = new MediaPlayer(); player.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength()); player.prepare(); player.start(); } catch (Exception e) { if (LOG_ENABLE) { Log.e(TAG, "Error playing sound: '" + assetSoundPath + "' (" + e.getMessage() + ")", e); } } } // Device Related ----------------------------------------------------------------------------------------------------------------------------- /** * Returns a unique UUID for the an android device. As with any UUIDs, * this unique ID is "very highly likely" to be unique across all Android * devices. Much more than ANDROID_ID is. * * It uses as the base the ANDROID_ID only if is not null and not the * some device manufacturers buggy ID 9774d56d682e549c for 2.2, 2.3 android * version (@see http://code.google.com/p/android/issues/detail?id=10603). * If is not available or is the buggy one, a unique UUID will be * generated using the SERIAL property of the device and if not available, * a bunch of device properties will be used to generated a unique UUID string. * * @param context * @return a UUID that may be used, in most cases, to uniquely identify your * device for most. */ public static String device_getId(Context context) { UUID uuid = null; String androidId = Secure.getString(context.getContentResolver(), Secure.ANDROID_ID); if (androidId == null) { uuid = generateUniqueDeviceUUIDId(); } else { //Several devices by several manufacturers are affected by the ANDROID_ID bug in 2.2. //All affected devices have the same ANDROID_ID, which is 9774d56d682e549c. Which is //also the same device id reported by the emulator. if (!"9774d56d682e549c".equals(androidId)) { try { uuid = UUID.nameUUIDFromBytes(androidId.getBytes("utf8")); } catch (UnsupportedEncodingException e) { Log.e(TAG, "UnsupportedEncodingException (" + e.getMessage() + ").", e); } } else { uuid = generateUniqueDeviceUUIDId(); } } return uuid.toString(); } /** * Generates a unique device id using the device * "serial" property if is available. If not, a bunch * of device properties will be used to get a reliable * unique string key for the device. * * If there is an error in UUID generation null is * returned. * * @return The unique UUID or nul in case of error. */ private static UUID generateUniqueDeviceUUIDId() { UUID uuid = null; try { //We generate a unique id String serial = null; if (Build.VERSION.SDK_INT > Build.VERSION_CODES.FROYO) { serial = Build.SERIAL; uuid = UUID.nameUUIDFromBytes(serial.getBytes("utf8")); } else { //This bunch of data should be enough to "ensure" the //uniqueness. String m_szDevIDAlterbative = "35" + //To look like a valid IMEI Build.BOARD.length() % 10 + Build.BRAND.length() % 10 + Build.CPU_ABI.length() % 10 + Build.DEVICE.length() % 10 + Build.DISPLAY.length() % 10 + Build.HOST.length() % 10 + Build.ID.length() % 10 + Build.MANUFACTURER.length() % 10 + Build.MODEL.length() % 10 + Build.PRODUCT.length() % 10 + Build.TAGS.length() % 10 + Build.TYPE.length() % 10 + Build.USER.length() % 10; //13 digits uuid = UUID.nameUUIDFromBytes(m_szDevIDAlterbative.getBytes("utf8")); } } catch (UnsupportedEncodingException e) { Log.e(TAG, "UnsupportedEncodingException (" + e.getMessage() + ").", e); } return uuid; } /** * Gets the device screen size in pixels. * * @param context * @return */ @SuppressWarnings("deprecation") @SuppressLint("NewApi") public static Point device_screenSize(Context context) { Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); final Point size = new Point(); try { display.getSize(size); } catch (NoSuchMethodError ignore) { // Older device size.x = display.getWidth(); size.y = display.getHeight(); } return size; } public static DisplayMetrics device_screenMetrics(Context context) { DisplayMetrics metrics = new DisplayMetrics(); Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); display.getMetrics(metrics); //display.getRealMetrics(metrics); return metrics; } /** * Gets the device type from its screen properties. * * @param context * @param strictlyInInches This makes that all calculations be made by * inches, using the number of pixels per inch, * instead using density points. Useful for some * weird non standard devices. * @return {@link es.javocsoft.android.lib.toolbox.ToolBox.DEVICE_BY_SCREEN}. */ public static DEVICE_BY_SCREEN device_getTypeByScreen(Context context, boolean strictlyInInches) { DEVICE_BY_SCREEN res = DEVICE_BY_SCREEN.DP320_NORMAL; DisplayMetrics metrics = device_screenMetrics(context); int widthPixels = -1; int heightPixels = -1; //The width and height in pixels if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { // For JellyBeans and onward widthPixels = metrics.widthPixels; heightPixels = metrics.heightPixels; } else { //To avoid excluding the dimensions of the Navigation Bar try { Method mGetRawH = Display.class.getMethod("getRawHeight"); Method mGetRawW = Display.class.getMethod("getRawWidth"); widthPixels = (Integer) mGetRawW.invoke(metrics); heightPixels = (Integer) mGetRawH.invoke(metrics); } catch (Exception e) { if (LOG_ENABLE) Log.w(TAG, "Controlled error getting width and height in pixels [" + e.getMessage() + "]", e); } } if (widthPixels == -1 || heightPixels == -1) { //We do nothing, return NORMAL. } else { if (strictlyInInches) { //Physical pixels per inch float widthDpi = metrics.xdpi; float heightDpi = metrics.ydpi; float widthInches = widthPixels / widthDpi; float heightInches = heightPixels / heightDpi; /* However, we also know that given the height of a triangle and the width, * we can use the Pythagorean theorem to work out the length of the * hypotenuse (In this case, the size of the screen diagonal). * * a + b = c */ //The size of the diagonal in inches is equal to the square root of the height //in inches squared plus the width in inches squared. double diagonalInches = Math.sqrt((widthInches * widthInches) + (heightInches * heightInches)); if (diagonalInches >= 7) { res = DEVICE_BY_SCREEN.DP600_7INCH; } else if (diagonalInches >= 10) { res = DEVICE_BY_SCREEN.DP720_10INCH; } else { res = DEVICE_BY_SCREEN.DP320_NORMAL; } } else { //We get in density points (dp) float scaleFactor = metrics.density; float widthDp = widthPixels / scaleFactor; float heightDp = heightPixels / scaleFactor; /* * Now we get the inches according to Google: * * 320dp: a typical phone screen (240x320 ldpi, 320x480 mdpi, 480x800 hdpi, etc). * 480dp: a tweener tablet like the Streak (480x800 mdpi). * 600dp: a 7" tablet (600x1024 mdpi). * 720dp: a 10" tablet (720x1280 mdpi, 800x1280 mdpi, etc). */ float smallestWidth = Math.min(widthDp, heightDp); if (smallestWidth <= 320) { res = DEVICE_BY_SCREEN.DP320_NORMAL; } else if (smallestWidth > 320 && smallestWidth <= 480) { res = DEVICE_BY_SCREEN.DP480_TWEENER; } else if (smallestWidth > 600 && smallestWidth < 720) { res = DEVICE_BY_SCREEN.DP600_7INCH; } else if (smallestWidth > 720) { res = DEVICE_BY_SCREEN.DP720_10INCH; } } } return res; } /** * Returns the device resolution type. * * @param context * @return {@link es.javocsoft.android.lib.toolbox.ToolBox.DEVICE_RESOLUTION_TYPE} */ public static DEVICE_RESOLUTION_TYPE device_getResolutionType(Context context) { DEVICE_RESOLUTION_TYPE res = null; DisplayMetrics metrics = new DisplayMetrics(); WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); windowManager.getDefaultDisplay().getMetrics(metrics); switch (metrics.densityDpi) { case DisplayMetrics.DENSITY_LOW: res = DEVICE_RESOLUTION_TYPE.ldpi; break; case DisplayMetrics.DENSITY_MEDIUM: res = DEVICE_RESOLUTION_TYPE.mdpi; break; case DisplayMetrics.DENSITY_HIGH: res = DEVICE_RESOLUTION_TYPE.hdpi; break; case DisplayMetrics.DENSITY_XHIGH: res = DEVICE_RESOLUTION_TYPE.xhdpi; break; case DisplayMetrics.DENSITY_XXHIGH: res = DEVICE_RESOLUTION_TYPE.xxhdpi; break; } return res; } /** * Get the device language (two letter code value) * @return */ public static String device_getLanguage() { return Locale.getDefault().getLanguage(); } /** * Get the current android API Level. * * Android 4.2 17 * Android 4.1 16 * Android 4.0.3 15 * Android 4.0 14 * Android 3.2 13 * Android 3.1 12 * Android 3.0 11 * Android 2.3.3 10 * Android 2.3 9 * Android 2.2 8 * Android 2.1 7 * Android 2.0.1 6 * Android 2.0 5 * Android 1.6 4 * Android 1.5 3 * Android 1.1 2 * Android 1.0 1 * * @return */ public static int device_getAPILevel() { return Build.VERSION.SDK_INT; } /** * Gets the device number if is available. * * @param ctx * @return */ public static String device_getDeviceMobileNumber(Context ctx) { TelephonyManager tm = (TelephonyManager) ctx.getSystemService(Context.TELEPHONY_SERVICE); return tm.getLine1Number(); } public static String device_getIMEI(Context context) { TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); return telephonyManager.getDeviceId(); } public static String device_getOSVersion() { return String.valueOf(Build.VERSION.SDK_INT); } /** * Returns TRUE if a specified hardware feature is present. * * Use PackageManager.FEATURE_[feature] to specify the feature * to query. * * @param context * @param hardwareFeature Use PackageManager.FEATURE_[feature] to specify the feature to query. * @return */ public static boolean device_isHardwareFeatureAvailable(Context context, String hardwareFeature) { return context.getPackageManager().hasSystemFeature(hardwareFeature); } /** * Return TRUE if there is a hardware keyboard present. * * @param context * @return */ public static boolean device_isHardwareKeyboard(Context context) { //You can also get some of the features which are not testable by the PackageManager via the Configuration, e.g. the DPAD. Configuration c = context.getResources().getConfiguration(); if (c.keyboard != Configuration.KEYBOARD_NOKEYS) { return true; } else { return false; } } /** * Return TRUE if there is a hardware DPAD navigation button. * * @param context * @return */ public static boolean device_isHardwareDPAD(Context context) { //You can also get some of the features which are not testable by the PackageManager via the Configuration, e.g. the DPAD. Configuration c = context.getResources().getConfiguration(); if (c.navigation == Configuration.NAVIGATION_DPAD) { return true; } else { return false; } } /** * Return TRUE if there is a hardware keyboard and is being made hidden. * * @param context * @return */ public static boolean device_isHardwareKeyboardHidden(Context context) { //You can also get some of the features which are not testable by the PackageManager via the Configuration, e.g. the DPAD. Configuration c = context.getResources().getConfiguration(); if (c.hardKeyboardHidden != Configuration.HARDKEYBOARDHIDDEN_UNDEFINED && c.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_YES) { return true; } else { return false; } } /** * Return TRUE if there is a hardware keyboard and is being made visible. * * @param context * @return */ public static boolean device_isHardwareKeyboardVisible(Context context) { //You can also get some of the features which are not testable by the PackageManager via the Configuration, e.g. the DPAD. Configuration c = context.getResources().getConfiguration(); if (c.hardKeyboardHidden != Configuration.HARDKEYBOARDHIDDEN_UNDEFINED && c.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO) { return true; } else { return false; } } /** * Returns true if the menu hardware menu is present on the device * * This function requires API Level 14. * * @param context * @return */ @SuppressLint("NewApi") public static boolean device_isHardwareMenuButtonPresent(Context context) { if (device_getAPILevel() >= 14) { //This requires API Level 14 return ViewConfiguration.get(context).hasPermanentMenuKey(); } else { return false; } } //-------------------- CRYPTO ------------------------------------------------------------------------ public static String crypto_getHASH(byte[] data, HASH_TYPE hashType) { MessageDigest digest = null; byte[] resData = null; try { switch (hashType) { case md5: digest = MessageDigest.getInstance("MD5"); resData = digest.digest(data); break; case sha1: digest = MessageDigest.getInstance("SHA-1"); resData = digest.digest(data); break; } if (resData != null) return new String(resData); else return null; } catch (Exception e) { if (LOG_ENABLE) Log.e("TollBox_ERROR", "crypto_getHASH() Error getting HASH data: " + e.getMessage(), e); return null; } } //-------------------- FONTS ------------------------------------------------------------------------ /** * Set a font to a text view. * * @param context * @param textView * @param fontPath The path to the font resource. Must be placed in asset * folder. */ public static void font_applyTitleFont(Context context, TextView textView, String fontPath) { if (textView != null) { Typeface font = Typeface.createFromAsset(context.getAssets(), fontPath); textView.setTypeface(font); } } }