package com.hokolinks.model; import android.content.Context; import android.content.pm.PackageInfo; import com.hokolinks.utils.log.HokoLog; import org.json.JSONException; import org.json.JSONObject; import java.lang.reflect.Field; /** * App is a helper class to get all the necessary information of the Application environment. */ public class App { private static final String ENVIRONMENT_DEBUG = "debug"; private static final String ENVIRONMENT_RELEASE = "release"; /** * Returns the name of the application Hoko is being run on. * * @param context A context object. * @return The name of the application. */ public static String getName(Context context) { try { int stringId = context.getApplicationInfo().labelRes; return context.getString(stringId); } catch (NullPointerException e) { HokoLog.e(e); return null; } } /** * Returns the package name of the application Hoko is being run on. * * @param context A context object. * @return The package name of the application. */ public static String getPackageName(Context context) { try { return context.getPackageName(); } catch (NullPointerException e) { HokoLog.e(e); return null; } } /** * Returns the version of the application Hoko is being run on. * * @param context A context object. * @return The version of the application. */ public static String getVersion(Context context) { try { PackageInfo packageInfo = context.getPackageManager().getPackageInfo( context.getPackageName(), 0); return packageInfo.versionName; } catch (Exception exception) { HokoLog.e(exception); } return null; } /** * Returns the version code of the application Hoko is being run on. * * @param context A context object. * @return The version code of the application. */ public static String getVersionCode(Context context) { try { PackageInfo packageInfo = context.getPackageManager().getPackageInfo( context.getPackageName(), 0); return String.valueOf(packageInfo.versionCode); } catch (Exception exception) { HokoLog.e(exception); } return null; } /** * Converts all the App information into a JSONObject to be sent to the Hoko backend * service. * * @param context A context object. * @return The JSONObject representation of App. */ public static JSONObject json(Context context) { try { JSONObject jsonObject = new JSONObject(); jsonObject.putOpt("name", getName(context)); jsonObject.putOpt("bundle", getPackageName(context)); jsonObject.putOpt("version", getVersion(context)); jsonObject.putOpt("build", getVersionCode(context)); return jsonObject; } catch (JSONException e) { HokoLog.e(e); } return null; } /** * Check whether the application is running in debug mode by checking the application's * BuildConfig static fields. This is done through reflection to avoid manually requesting the * developer to provide either the BuildConfig class or the actual debug variable. * Will default to a false debug mode in case it can't find the class or the field. * * @param context A context object. * @return true if the application is in debug mode, false otherwise. */ public static boolean isDebug(Context context) { try { Class buildConfigClass = getBuildConfigClass(context); if (buildConfigClass != null) { Field debugField = buildConfigClass.getDeclaredField("DEBUG"); return debugField.getBoolean(null); } } catch (Exception e) { HokoLog.e(e); } return false; } /** * Returns the environment with regards of finding DEBUG inside a BuildConfig. * * @param context A context object. * @return The environment string. */ public static String getEnvironment(Context context) { return isDebug(context) ? ENVIRONMENT_DEBUG : ENVIRONMENT_RELEASE; } /** * Retrieves the BuildConfig class from a given context. * Will try to get it from the context's package name, otherwise it will go through the * package hierarchy trying to find a BuildConfig class. * * @param context A context object. * @return A Class object or null. */ private static Class<?> getBuildConfigClass(Context context) { Class<?> klass = getBuildConfigClassFromPackage(context.getPackageName(), true); if (klass == null) { klass = getBuildConfigClassFromPackage(context.getClass().getPackage().getName(), true); } return klass; } /** * Retrieves the BuildConfig class from a package name. * Will try to get it from the supplied package name, if the class is not found, depending on * the traverse value it will try to recursively find the class on the package hierarchy. * * @param packageName The package name. * @param traverse true if it should traver the package hierarchy, false otherwise. * @return A Class object or null. */ private static Class<?> getBuildConfigClassFromPackage(String packageName, boolean traverse) { try { return Class.forName(packageName + ".BuildConfig"); } catch (ClassNotFoundException e) { if (traverse) { int indexOfLastDot = packageName.lastIndexOf('.'); if (indexOfLastDot != -1) { return getBuildConfigClassFromPackage(packageName.substring(0, indexOfLastDot), true); } } return null; } } }