/*
* Zirco Browser for Android
*
* Copyright (C) 2010 J. Devauchelle and contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 3 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
package org.shadowsocks.zirco.utils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;
import org.shadowsocks.R;
import org.shadowsocks.zirco.model.items.BookmarkItem;
import org.shadowsocks.zirco.model.items.HistoryItem;
import org.shadowsocks.zirco.providers.BookmarksProviderWrapper;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Environment;
import android.preference.PreferenceManager;
import android.text.ClipboardManager;
import android.util.DisplayMetrics;
import android.util.Log;
import android.widget.Toast;
/**
* Application utilities.
*/
public class ApplicationUtils {
private static String mAdSweepString = null;
private static String mRawStartPage = null;
private static String mRawStartPageStyles = null;
private static String mRawStartPageBookmarks = null;
private static String mRawStartPageHistory = null;
private static String mRawStartPageSearch = null;
private static int mFaviconSize = -1;
private static int mImageButtonSize = -1;
private static int mFaviconSizeForBookmarks = -1;
/**
* Check if the SD card is available. Display an alert if not.
*
* @param context
* The current context.
* @param showMessage
* If true, will display a message for the user.
* @return True if the SD card is available, false otherwise.
*/
public static boolean checkCardState(Context context, boolean showMessage) {
// Check to see if we have an SDCard
String status = Environment.getExternalStorageState();
if (!status.equals(Environment.MEDIA_MOUNTED)) {
int messageId;
// Check to see if the SDCard is busy, same as the music app
if (status.equals(Environment.MEDIA_SHARED)) {
messageId = R.string.Commons_SDCardErrorSDUnavailable;
} else {
messageId = R.string.Commons_SDCardErrorNoSDMsg;
}
if (showMessage) {
ApplicationUtils.showErrorDialog(context,
R.string.Commons_SDCardErrorTitle, messageId);
}
return false;
}
return true;
}
/**
* Copy a text to the clipboard.
*
* @param context
* The current context.
* @param text
* The text to copy.
* @param toastMessage
* The message to show in a Toast notification. If empty or null,
* does not display notification.
*/
public static void copyTextToClipboard(Context context, String text,
String toastMessage) {
ClipboardManager clipboard = (ClipboardManager) context
.getSystemService(Context.CLIPBOARD_SERVICE);
clipboard.setText(text);
if ((toastMessage != null) && (toastMessage.length() > 0)) {
Toast.makeText(context, toastMessage, Toast.LENGTH_SHORT).show();
}
}
/**
* Load the AdSweep script if necessary.
*
* @param context
* The current context.
* @return The AdSweep script.
*/
public static String getAdSweepString(Context context) {
if (mAdSweepString == null) {
InputStream is = context.getResources().openRawResource(
R.raw.adsweep);
if (is != null) {
StringBuilder sb = new StringBuilder();
String line;
try {
BufferedReader reader = new BufferedReader(
new InputStreamReader(is, "UTF-8"));
while ((line = reader.readLine()) != null) {
if ((line.length() > 0) && (!line.startsWith("//"))) {
sb.append(line).append("\n");
}
}
} catch (IOException e) {
Log.w("AdSweep",
"Unable to load AdSweep: " + e.getMessage());
} finally {
try {
is.close();
} catch (IOException e) {
Log.w("AdSweep",
"Unable to load AdSweep: " + e.getMessage());
}
}
mAdSweepString = sb.toString();
} else {
mAdSweepString = "";
}
}
return mAdSweepString;
}
/**
* Get the application version code.
*
* @param context
* The current context.
* @return The application version code.
*/
public static int getApplicationVersionCode(Context context) {
int result = -1;
try {
PackageManager manager = context.getPackageManager();
PackageInfo info = manager.getPackageInfo(context.getPackageName(),
0);
result = info.versionCode;
} catch (NameNotFoundException e) {
Log.w("ApplicationUtils",
"Unable to get application version: " + e.getMessage());
result = -1;
}
return result;
}
/**
* Build the html result of the most recent bookmarks.
*
* @param context
* The current context.
* @return The html result of the most recent bookmarks.
*/
private static String getBookmarksHtml(Context context) {
String result = "";
StringBuilder bookmarksSb = new StringBuilder();
if (PreferenceManager.getDefaultSharedPreferences(context).getBoolean(
Constants.PREFERENCES_START_PAGE_SHOW_BOOKMARKS, true)) {
int limit;
try {
limit = Integer
.parseInt(PreferenceManager
.getDefaultSharedPreferences(context)
.getString(
Constants.PREFERENCES_START_PAGE_BOOKMARKS_LIMIT,
"5"));
} catch (Exception e) {
limit = 5;
}
List<BookmarkItem> results = BookmarksProviderWrapper
.getStockBookmarksWithLimit(context.getContentResolver(),
limit);
for (BookmarkItem item : results) {
bookmarksSb.append(String.format(
"<li><a href=\"%s\">%s</a></li>", item.getUrl(),
item.getTitle()));
}
}
result = String.format(mRawStartPageBookmarks, context.getResources()
.getString(R.string.StartPage_Bookmarks), bookmarksSb
.toString());
return result;
}
/**
* Load the changelog string.
*
* @param context
* The current context.
* @return The changelog string.
*/
public static String getChangelogString(Context context) {
return getStringFromRawResource(context, R.raw.changelog);
}
/**
* Get the required size of the favicon, depending on current screen
* density.
*
* @param activity
* The current activity.
* @return The size of the favicon, in pixels.
*/
public static int getFaviconSize(Activity activity) {
if (mFaviconSize == -1) {
DisplayMetrics metrics = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
switch (metrics.densityDpi) {
case DisplayMetrics.DENSITY_LOW:
mFaviconSize = 12;
break;
case DisplayMetrics.DENSITY_MEDIUM:
mFaviconSize = 24;
break;
case DisplayMetrics.DENSITY_HIGH:
mFaviconSize = 32;
break;
default:
mFaviconSize = 24;
}
}
return mFaviconSize;
}
/**
* Get the required size of the favicon, depending on current screen
* density.
*
* @param activity
* The current activity.
* @return The size of the favicon, in pixels.
*/
public static int getFaviconSizeForBookmarks(Activity activity) {
if (mFaviconSizeForBookmarks == -1) {
DisplayMetrics metrics = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
switch (metrics.densityDpi) {
case DisplayMetrics.DENSITY_LOW:
mFaviconSizeForBookmarks = 12;
break;
case DisplayMetrics.DENSITY_MEDIUM:
mFaviconSizeForBookmarks = 16;
break;
case DisplayMetrics.DENSITY_HIGH:
mFaviconSizeForBookmarks = 24;
break;
default:
mFaviconSizeForBookmarks = 16;
}
}
return mFaviconSizeForBookmarks;
}
/**
* Build the html result of the most recent history.
*
* @param context
* The current context.
* @return The html result of the most recent history.
*/
private static String getHistoryHtml(Context context) {
String result = "";
StringBuilder historySb = new StringBuilder();
if (PreferenceManager.getDefaultSharedPreferences(context).getBoolean(
Constants.PREFERENCES_START_PAGE_SHOW_HISTORY, true)) {
int limit;
try {
limit = Integer.parseInt(PreferenceManager
.getDefaultSharedPreferences(context).getString(
Constants.PREFERENCES_START_PAGE_HISTORY_LIMIT,
"5"));
} catch (Exception e) {
limit = 5;
}
List<HistoryItem> results = BookmarksProviderWrapper
.getStockHistoryWithLimit(context.getContentResolver(),
limit);
for (HistoryItem item : results) {
historySb.append(String.format(
"<li><a href=\"%s\">%s</a></li>", item.getUrl(),
item.getTitle()));
}
}
result = String.format(mRawStartPageHistory, context.getResources()
.getString(R.string.StartPage_History), historySb.toString());
return result;
}
public static int getImageButtonSize(Activity activity) {
if (mImageButtonSize == -1) {
DisplayMetrics metrics = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
switch (metrics.densityDpi) {
case DisplayMetrics.DENSITY_LOW:
mImageButtonSize = 16;
break;
case DisplayMetrics.DENSITY_MEDIUM:
mImageButtonSize = 32;
break;
case DisplayMetrics.DENSITY_HIGH:
mImageButtonSize = 48;
break;
default:
mImageButtonSize = 32;
}
}
return mImageButtonSize;
}
/**
* Load the start page html.
*
* @param context
* The current context.
* @return The start page html.
*/
public static String getStartPage(Context context) {
if (mRawStartPage == null) {
mRawStartPage = getStringFromRawResource(context, R.raw.start);
mRawStartPageStyles = getStringFromRawResource(context,
R.raw.start_style);
mRawStartPageBookmarks = getStringFromRawResource(context,
R.raw.start_bookmarks);
mRawStartPageHistory = getStringFromRawResource(context,
R.raw.start_history);
mRawStartPageSearch = getStringFromRawResource(context,
R.raw.start_search);
}
String result = mRawStartPage;
String bookmarksHtml = getBookmarksHtml(context);
String historyHtml = getHistoryHtml(context);
String searchHtml = "";
if (PreferenceManager.getDefaultSharedPreferences(context).getBoolean(
Constants.PREFERENCES_START_PAGE_SHOW_SEARCH, false)) {
searchHtml = String
.format(mRawStartPageSearch,
context.getResources().getString(
R.string.StartPage_Search),
context.getResources().getString(
R.string.StartPage_SearchButton));
}
String bodyHtml = searchHtml + bookmarksHtml + historyHtml;
result = String
.format(mRawStartPage, mRawStartPageStyles, context
.getResources().getString(R.string.StartPage_Welcome),
bodyHtml);
return result;
}
/**
* Load a raw string resource.
*
* @param context
* The current context.
* @param resourceId
* The resource id.
* @return The loaded string.
*/
private static String getStringFromRawResource(Context context,
int resourceId) {
String result = null;
InputStream is = context.getResources().openRawResource(resourceId);
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");
}
} catch (IOException e) {
Log.w("ApplicationUtils", String.format(
"Unable to load resource %s: %s", resourceId,
e.getMessage()));
} finally {
try {
is.close();
} catch (IOException e) {
Log.w("ApplicationUtils", String.format(
"Unable to load resource %s: %s", resourceId,
e.getMessage()));
}
}
result = sb.toString();
} else {
result = "";
}
return result;
}
public static String getWeaveAuthToken(Context context) {
String server = PreferenceManager.getDefaultSharedPreferences(context)
.getString(Constants.PREFERENCE_WEAVE_SERVER,
Constants.WEAVE_DEFAULT_SERVER);
String userName = PreferenceManager
.getDefaultSharedPreferences(context).getString(
Constants.PREFERENCE_WEAVE_USERNAME, null);
String password = PreferenceManager
.getDefaultSharedPreferences(context).getString(
Constants.PREFERENCE_WEAVE_PASSWORD, null);
String key = PreferenceManager.getDefaultSharedPreferences(context)
.getString(Constants.PREFERENCE_WEAVE_KEY, null);
boolean ok = (server != null) && (server.length() > 0)
&& (UrlUtils.isUrl(server)) && (userName != null)
&& (userName.length() > 0) && (password != null)
&& (password.length() > 0) && (key != null)
&& (key.length() > 0);
if (ok) {
return String.format(Constants.WEAVE_AUTH_TOKEN_SCHEME, key,
password, userName, server);
} else {
return null;
}
}
/**
* Share a page.
*
* @param activity
* The parent activity.
* @param title
* The page title.
* @param url
* The page url.
*/
public static void sharePage(Activity activity, String title, String url) {
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("text/plain");
shareIntent.putExtra(Intent.EXTRA_TEXT, url);
shareIntent.putExtra(Intent.EXTRA_SUBJECT, title);
try {
activity.startActivity(Intent.createChooser(shareIntent,
activity.getString(R.string.Main_ShareChooserTitle)));
} catch (android.content.ActivityNotFoundException ex) {
// if no app handles it, do nothing
}
}
/**
* Display a continue / cancel dialog.
*
* @param context
* The current context.
* @param icon
* The dialog icon.
* @param title
* The dialog title.
* @param message
* The dialog message.
* @param onContinue
* The dialog listener for the continue button.
* @param onCancel
* The dialog listener for the cancel button.
*/
public static void showContinueCancelDialog(Context context, int icon,
String title, String message,
DialogInterface.OnClickListener onContinue,
DialogInterface.OnClickListener onCancel) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setCancelable(true);
builder.setIcon(icon);
builder.setTitle(title);
builder.setMessage(message);
builder.setInverseBackgroundForced(true);
builder.setPositiveButton(
context.getResources().getString(R.string.Commons_Continue),
onContinue);
builder.setNegativeButton(
context.getResources().getString(R.string.Commons_Cancel),
onCancel);
AlertDialog alert = builder.create();
alert.show();
}
/**
* Show an error dialog.
*
* @param context
* The current context.
* @param title
* The title string id.
* @param message
* The message string id.
*/
public static void showErrorDialog(Context context, int title, int message) {
new AlertDialog.Builder(context).setTitle(title)
.setIcon(android.R.drawable.ic_dialog_alert)
.setMessage(message)
.setPositiveButton(R.string.Commons_Ok, null).show();
}
public static void showErrorDialog(Context context, int title,
String message) {
new AlertDialog.Builder(context).setTitle(title)
.setIcon(android.R.drawable.ic_dialog_alert)
.setMessage(message)
.setPositiveButton(R.string.Commons_Ok, null).show();
}
/**
* Display a standard Ok / Cancel dialog.
*
* @param context
* The current context.
* @param icon
* The dialog icon.
* @param title
* The dialog title.
* @param message
* The dialog message.
* @param onYes
* The dialog listener for the yes button.
*/
public static void showOkCancelDialog(Context context, int icon,
String title, String message, DialogInterface.OnClickListener onYes) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setCancelable(true);
builder.setIcon(icon);
builder.setTitle(title);
builder.setMessage(message);
builder.setInverseBackgroundForced(true);
builder.setPositiveButton(
context.getResources().getString(R.string.Commons_Ok), onYes);
builder.setNegativeButton(
context.getResources().getString(R.string.Commons_Cancel),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
AlertDialog alert = builder.create();
alert.show();
}
/**
* Display a standard Ok dialog.
*
* @param context
* The current context.
* @param icon
* The dialog icon.
* @param title
* The dialog title.
* @param message
* The dialog message.
*/
public static void showOkDialog(Context context, int icon, String title,
String message) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setCancelable(false);
builder.setIcon(icon);
builder.setTitle(title);
builder.setMessage(message);
builder.setInverseBackgroundForced(true);
builder.setPositiveButton(
context.getResources().getString(R.string.Commons_Ok),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
AlertDialog alert = builder.create();
alert.show();
}
/**
* Display a standard yes / no dialog.
*
* @param context
* The current context.
* @param icon
* The dialog icon.
* @param title
* The dialog title.
* @param message
* The dialog message.
* @param onYes
* The dialog listener for the yes button.
*/
public static void showYesNoDialog(Context context, int icon, int title,
int message, DialogInterface.OnClickListener onYes) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setCancelable(true);
builder.setIcon(icon);
builder.setTitle(context.getResources().getString(title));
builder.setMessage(context.getResources().getString(message));
builder.setInverseBackgroundForced(true);
builder.setPositiveButton(
context.getResources().getString(R.string.Commons_Yes), onYes);
builder.setNegativeButton(
context.getResources().getString(R.string.Commons_No),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
AlertDialog alert = builder.create();
alert.show();
}
}