/* * Copyright (C) 2014 WillowTree Apps Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.willowtreeapps.saguaro.android; import com.willowtreeapps.saguaro.android.model.License; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.res.Resources; import android.net.Uri; import android.os.Build; import android.text.SpannableString; import android.text.SpannableStringBuilder; import android.text.TextUtils; import android.text.method.LinkMovementMethod; import android.text.method.MovementMethod; import android.text.style.ClickableSpan; import android.util.Log; import android.view.View; import android.widget.TextView; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class Saguaro { private static final String TAG = "Saguaro"; private static final String WTA_ATTRIBUTION_URL = "http://www.willowtreeapps.com/?utm_source=%s&utm_medium=%s&utm_campaign=attribution"; private static final String UTM_CAMPAIGN = "android"; public static Intent getAttributionIntent(Context context) { Intent attributionIntent = new Intent(Intent.ACTION_VIEW); attributionIntent .setData(Uri.parse(String.format(WTA_ATTRIBUTION_URL, context.getPackageName(), UTM_CAMPAIGN))); return attributionIntent; } public static String getDeviceName() { String manufacturer = Build.MANUFACTURER; String model = Build.MODEL; if (model.startsWith(manufacturer)) { return capitalize(model); } else { return capitalize(manufacturer) + " " + model; } } public static String getOsVersion() { return "Android " + Build.VERSION.RELEASE + " API Level " + Build.VERSION.SDK_INT; } public static String getFullVersionString(Context context) { return getVersionInfo(context, R.string.saguaro__full_version_text_dynamic); } public static String getMinVersionString(Context context) { return getVersionInfo(context, R.string.default_version_text_dynamic); } public static AlertDialog showOpenSourceDialog(final Context context) { Resources resources = context.getResources(); AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(R.string.saguaro__acknowledgments); builder.setMessage(getOpenSourceText(context, resources)); builder.setNegativeButton(resources.getString(R.string.saguaro__close), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); builder.setCancelable(true); builder.setIcon(android.R.drawable.ic_menu_info_details); AlertDialog dialog = builder.create(); dialog.show(); TextView message = (TextView) dialog.findViewById(android.R.id.message); message.setMovementMethod(LinkMovementMethod.getInstance()); return dialog; } public static String getOpenSourceText(final Context context, final Resources resources) { SpannableStringBuilder sb = new SpannableStringBuilder(); sb.append(String.format(resources.getString(R.string.saguaro__licenses_header), getApplicationName(context))); sb.append("\n\n"); // Iterate over "Other" projects String otherAcknowldgments = resources.getString(R.string.prepend_acknowledgments_text); if (!TextUtils.isEmpty(otherAcknowldgments)) { sb.append(otherAcknowldgments); sb.append("\n\n"); } List<License> licenses = getOpenSourceLicenses(context, resources); for (final License license : licenses) { for (String project : license.projects) { sb.append("\u2022 ").append(project).append("\n"); } sb.append("\n"); String subHeader = resources.getString(R.string.saguaro__license_subheader, license.name); ClickableSpan clickableSpan = new ClickableSpan() { @Override public void onClick(View widget) { showLicenseDialog(context, license.textResId); } }; int start = sb.length(); int nameStart = subHeader.indexOf(license.name); sb.append(subHeader); sb.setSpan(clickableSpan, start + nameStart, start + nameStart + license.name.length(), 0); sb.append("\n\n"); } return sb.toString(); } public static List<License> getOpenSourceLicenses(final Context context, final Resources resources) { List<License> licenses = new ArrayList<License>(); String[] baseLicenses = resources.getStringArray(R.array.saguaro__base_licenses); String[] userLicenses = resources.getStringArray(R.array.saguaro_licenses); List<String> licensesAsStrings = new ArrayList<String>(); licensesAsStrings.addAll(Arrays.asList(baseLicenses)); licensesAsStrings.addAll(Arrays.asList(userLicenses)); for (String licenseString : licensesAsStrings) { int licenseNameId = resources.getIdentifier(licenseString + "_name", "string", context.getPackageName()); final int licenseTextId = resources.getIdentifier(licenseString, "raw", context.getPackageName()); int licenseProjectsId = resources .getIdentifier(licenseString + "_projects", "array", context.getPackageName()); // Skip if no licenses defined if (licenseProjectsId == 0) { continue; } String[] projects = resources.getStringArray(licenseProjectsId); if (projects.length > 0) { License license = new License(); license.name = resources.getString(licenseNameId); license.textResId = licenseTextId; license.projects = projects; licenses.add(license); } } return licenses; } private static AlertDialog showLicenseDialog(Context context, int licenseTextId) { String licenseText = ""; try { licenseText = readRawToString(context.getResources(), licenseTextId); } catch (IOException e) { Log.e(TAG, e.getMessage(), e); } AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(R.string.saguaro__acknowledgments) .setMessage(licenseText) .setNegativeButton(R.string.saguaro__close, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }) .setIcon(android.R.drawable.ic_menu_info_details); AlertDialog dialog = builder.create(); dialog.show(); return dialog; } public static String readRawToString(Resources resources, int rawId) throws IOException { InputStream in = null; try { in = resources.openRawResource(rawId); return readToString(in); } finally { if (in != null) { in.close(); } } } private static String readToString(InputStream inputStream) throws IOException { byte[] bytes = new byte[1000]; StringBuilder x = new StringBuilder(); int numRead; while ((numRead = inputStream.read(bytes)) >= 0) { x.append(new String(bytes, 0, numRead)); } return x.toString(); } public static SpannableString makeLinkSpan(CharSequence text, View.OnClickListener listener) { SpannableString link = new SpannableString(text); link.setSpan(new ClickableString(listener), 0, text.length(), SpannableString.SPAN_INCLUSIVE_EXCLUSIVE); return link; } public static void makeLinksFocusable(TextView tv) { MovementMethod m = tv.getMovementMethod(); if ((m == null) || !(m instanceof LinkMovementMethod)) { if (tv.getLinksClickable()) { tv.setMovementMethod(LinkMovementMethod.getInstance()); } } } public static Intent getSendFeedbackIntent(Context context) { Intent sendFeedbackIntent = new Intent(Intent.ACTION_SENDTO); StringBuilder uriBuilder = new StringBuilder(); uriBuilder.append("mailto:"); uriBuilder.append(context.getString(R.string.send_feedback_email)); uriBuilder.append("?subject="); String subject = context.getString(R.string.send_feedback_optional_subject); if (TextUtils.isEmpty(subject)) { uriBuilder.append(Uri.encode( String.format(context.getString(R.string.saguaro__feedback_subject), getApplicationName(context)))); } else { uriBuilder.append(Uri.encode(subject)); } uriBuilder.append("&body="); String body = context.getString(R.string.send_feedback_optional_body); if (TextUtils.isEmpty(body)) { uriBuilder.append(Uri.encode("\n\n")); uriBuilder.append(Uri.encode(getFullVersionString(context))); uriBuilder.append(Uri.encode("\n")); uriBuilder.append(Uri.encode(getDeviceName())); uriBuilder.append(Uri.encode("\n")); uriBuilder.append(Uri.encode(getOsVersion())); } else { uriBuilder.append(Uri.encode(body)); } sendFeedbackIntent.setData(Uri.parse(uriBuilder.toString())); return sendFeedbackIntent; } private static String getVersionInfo(Context context, int stringResId) { String versionString = ""; int versionCode = 0; PackageManager pm = context.getPackageManager(); String packageName = context.getPackageName(); try { versionString = pm.getPackageInfo(packageName, 0).versionName; versionCode = pm.getPackageInfo(packageName, 0).versionCode; } catch (PackageManager.NameNotFoundException e) { //Failed } return String.format(context.getResources().getString(stringResId), versionString, versionCode); } private static String capitalize(String s) { if (s == null || s.length() == 0) { return ""; } char first = s.charAt(0); if (Character.isUpperCase(first)) { return s; } else { return Character.toUpperCase(first) + s.substring(1); } } private static String getApplicationName(Context context) { final PackageManager pm = context.getPackageManager(); ApplicationInfo ai; try { ai = pm.getApplicationInfo(context.getPackageName(), 0); } catch (final PackageManager.NameNotFoundException e) { ai = null; } return (String) (ai != null ? pm.getApplicationLabel(ai) : context.getString(R.string.saguaro__this_application)); } private static class ClickableString extends ClickableSpan { private View.OnClickListener mListener; public ClickableString(View.OnClickListener listener) { mListener = listener; } @Override public void onClick(View v) { mListener.onClick(v); } } }