package com.mcxiaoke.next.utils;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.Signature;
import android.content.res.Configuration;
import android.database.Cursor;
import android.media.MediaScannerConnection;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.BatteryManager;
import android.os.Build;
import android.os.Build.VERSION_CODES;
import android.os.Environment;
import android.os.StatFs;
import android.os.StrictMode;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.view.View;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.Toast;
import com.mcxiaoke.next.core.BuildConfig;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.regex.Pattern;
/**
* User: mcxiaoke
* Date: 13-5-3
* Time: 上午10:06
*/
public final class AndroidUtils {
public static final boolean DEBUG = BuildConfig.DEBUG;
public static final String TAG = AndroidUtils.class.getSimpleName();
public static final String FILENAME_NOMEDIA = ".nomedia";
public static final int HEAP_SIZE_LARGE = 48 * 1024 * 1024;
private static final Pattern SAFE_FILENAME_PATTERN = Pattern.compile("[\\w%+,./=_-]+");
private AndroidUtils() {
}
/**
* Check if a filename is "safe" (no metacharacters or spaces).
*
* @param file The file to check
*/
public static boolean isFilenameSafe(File file) {
// Note, we check whether it matches what's known to be safe,
// rather than what's known to be unsafe. Non-ASCII, control
// characters, etc. are all unsafe by default.
return SAFE_FILENAME_PATTERN.matcher(file.getPath()).matches();
}
public static File getCacheDir(Context context) {
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
File cacheDir = context.getExternalCacheDir();
File noMedia = new File(cacheDir, FILENAME_NOMEDIA);
if (!noMedia.exists()) {
try {
noMedia.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
return cacheDir;
} else {
return context.getCacheDir();
}
}
/**
* Get a file path from a Uri. This will get the the path for Storage Access
* Framework Documents, as well as the _data field for the MediaStore and
* other file-based ContentProviders.
*
* @param context The context.
* @param uri The Uri to query.
* @author paulburke
*/
@SuppressLint("NewApi")
public static String getPath(final Context context, final Uri uri) {
final boolean isKitKat = Build.VERSION.SDK_INT >= VERSION_CODES.KITKAT;
if (DEBUG) {
LogUtils.v(TAG, "getRealPath() uri=" + uri + " isKitKat=" + isKitKat);
}
// DocumentProvider
if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
// ExternalStorageProvider
if (isExternalStorageDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
if ("primary".equalsIgnoreCase(type)) {
return Environment.getExternalStorageDirectory() + "/" + split[1];
}
}
// DownloadsProvider
else if (isDownloadsDocument(uri)) {
final String id = DocumentsContract.getDocumentId(uri);
final Uri contentUri = ContentUris.withAppendedId(
Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
return getDataColumn(context, contentUri, null, null);
}
// MediaProvider
else if (isMediaDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
Uri contentUri = null;
if ("image".equals(type)) {
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
} else if ("video".equals(type)) {
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
} else if ("audio".equals(type)) {
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
}
final String selection = "_id=?";
final String[] selectionArgs = new String[]{
split[1]
};
return getDataColumn(context, contentUri, selection, selectionArgs);
}
}
// MediaStore (and general)
else if (ContentResolver.SCHEME_CONTENT.equalsIgnoreCase(uri.getScheme())) {
// Return the remote address
if (isGooglePhotosUri(uri))
return uri.getLastPathSegment();
return getDataColumn(context, uri, null, null);
}
// File
else if (ContentResolver.SCHEME_FILE.equalsIgnoreCase(uri.getScheme())) {
return uri.getPath();
}
return uri.getPath();
}
/**
* Get the value of the data column for this Uri. This is useful for
* MediaStore Uris, and other file-based ContentProviders.
*
* @param context The context.
* @param uri The Uri to query.
* @param selection (Optional) Filter used in the query.
* @param selectionArgs (Optional) Selection arguments used in the query.
* @return The value of the _data column, which is typically a file path.
*/
private static String getDataColumn(Context context, Uri uri, String selection,
String[] selectionArgs) {
Cursor cursor = null;
final String column = MediaStore.MediaColumns.DATA;
final String[] projection = {column};
try {
cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
null);
if (cursor != null && cursor.moveToFirst()) {
final int index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(index);
}
} finally {
if (cursor != null)
cursor.close();
}
return null;
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is ExternalStorageProvider.
*/
public static boolean isExternalStorageDocument(Uri uri) {
return "com.android.externalstorage.documents".equals(uri.getAuthority());
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is DownloadsProvider.
*/
public static boolean isDownloadsDocument(Uri uri) {
return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is MediaProvider.
*/
public static boolean isMediaDocument(Uri uri) {
return "com.android.providers.media.documents".equals(uri.getAuthority());
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is Google Photos.
*/
public static boolean isGooglePhotosUri(Uri uri) {
return "com.google.android.apps.photos.content".equals(uri.getAuthority());
}
public static boolean isLargeHeap() {
return Runtime.getRuntime().maxMemory() > HEAP_SIZE_LARGE;
}
public static boolean noSdcard() {
return !Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState());
}
/**
* check if free size of SDCARD and CACHE dir is OK
*
* @param needSize how much space should release at least
* @return true if has enough space
*/
public static boolean noFreeSpace(long needSize) {
long freeSpace = getFreeSpace();
return freeSpace < needSize * 3;
}
@SuppressWarnings("deprecation")
public static long getFreeSpace() {
StatFs stat = new StatFs(Environment.getExternalStorageDirectory()
.getPath());
long blockSize = stat.getBlockSize();
long availableBlocks = stat.getAvailableBlocks();
return availableBlocks * blockSize;
}
public static void hideSoftKeyboard(Context context, EditText editText) {
InputMethodManager imm = (InputMethodManager) context.getSystemService(
Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);
}
public static void showSoftKeyboard(Context context, EditText editText) {
if (editText.requestFocus()) {
InputMethodManager imm = (InputMethodManager)
context.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(editText, InputMethodManager.SHOW_IMPLICIT);
}
}
public static void toggleSoftInput(Context context, View view) {
if (view.requestFocus()) {
InputMethodManager imm = (InputMethodManager)
context.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(0, 0);
}
}
public static void showToast(Context context, int resId) {
Toast.makeText(context, resId, Toast.LENGTH_SHORT).show();
}
public static void showToast(Context context, CharSequence text) {
Toast.makeText(context, text, Toast.LENGTH_SHORT).show();
}
public static void showLongToast(Context context, int resId) {
Toast.makeText(context, resId, Toast.LENGTH_LONG).show();
}
public static void showLongToast(Context context, CharSequence text) {
Toast.makeText(context, text, Toast.LENGTH_LONG).show();
}
/**
* Execute an {@link AsyncTask} on a thread pool.
*
* @param task Task to add.
* @param args Optional arguments to pass to {@link AsyncTask#execute(Object[])}.
* @param <T> Task argument type.
*/
@SuppressWarnings("unchecked")
@TargetApi(VERSION_CODES.HONEYCOMB)
public static <T> void execute(AsyncTask<T, ?, ?> task, T... args) {
if (Build.VERSION.SDK_INT < VERSION_CODES.HONEYCOMB) {
task.execute(args);
} else {
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, args);
}
}
public static boolean hasCamera(Context context) {
PackageManager pm = context.getPackageManager();
return pm.hasSystemFeature(PackageManager.FEATURE_CAMERA)
|| pm.hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT);
}
public static void mediaScan(Context context, Uri uri) {
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
intent.setData(uri);
context.sendBroadcast(intent);
}
// another media scan way
public static void addToMediaStore(Context context, File file) {
String[] path = new String[]{file.getPath()};
MediaScannerConnection.scanFile(context, path, null, null);
}
public static boolean isMediaMounted() {
return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState());
}
public static void setFullScreen(final Activity activity,
final boolean fullscreen) {
if (fullscreen) {
activity.getWindow().addFlags(
WindowManager.LayoutParams.FLAG_FULLSCREEN);
activity.getWindow().clearFlags(
WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
} else {
activity.getWindow().addFlags(
WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
activity.getWindow().clearFlags(
WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
}
public static void setPortraitOrientation(final Activity activity,
final boolean portrait) {
if (portrait) {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
} else {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}
}
public static void lockScreenOrientation(final Activity context, final boolean portrait) {
if (portrait) {
context.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
} else {
if (context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
context.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
if (context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
context.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
}
}
public static void unlockScreenOrientation(final Activity context) {
context.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}
public static boolean hasIceCreamSandwich() {
return Build.VERSION.SDK_INT >= VERSION_CODES.ICE_CREAM_SANDWICH;
}
public static boolean isPreIceCreamSandwich() {
return Build.VERSION.SDK_INT < VERSION_CODES.ICE_CREAM_SANDWICH;
}
public static boolean hasJellyBean() {
return Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN;
}
public static boolean hasKitkat() {
return Build.VERSION.SDK_INT >= VERSION_CODES.KITKAT;
}
public static boolean isPreLollipop() {
return Build.VERSION.SDK_INT < VERSION_CODES.LOLLIPOP;
}
public static boolean hasLollipop() {
return Build.VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP;
}
@SuppressWarnings({"ResourceType", "unchecked"})
public <T> T getSystemService(final Context context, final String name) {
return (T) context.getSystemService(name);
}
@TargetApi(11)
public static void setStrictMode(boolean enable) {
if (!enable) {
return;
}
StrictMode.ThreadPolicy.Builder threadPolicyBuilder =
new StrictMode.ThreadPolicy.Builder()
.detectAll()
.penaltyLog();
StrictMode.VmPolicy.Builder vmPolicyBuilder =
new StrictMode.VmPolicy.Builder()
.detectAll()
.penaltyLog();
StrictMode.setThreadPolicy(threadPolicyBuilder.build());
StrictMode.setVmPolicy(vmPolicyBuilder.build());
}
/**
* 重启一个Activity
*
* @param activity Activity
*/
public static void restartActivity(final Activity activity) {
Intent intent = activity.getIntent();
activity.overridePendingTransition(0, 0);
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
activity.finish();
activity.overridePendingTransition(0, 0);
activity.startActivity(intent);
}
public static Intent getBatteryStatus(Context context) {
Context appContext = context.getApplicationContext();
return appContext.registerReceiver(null,
new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
}
public static float getBatteryLevel(Intent batteryIntent) {
int level = batteryIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
int scale = batteryIntent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
return level / (float) scale;
}
public static String getBatteryInfo(Intent batteryIntent) {
int status = batteryIntent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING ||
status == BatteryManager.BATTERY_STATUS_FULL;
int chargePlug = batteryIntent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
boolean usbCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_USB;
boolean acCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_AC;
int level = batteryIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
int scale = batteryIntent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
float batteryPct = level / (float) scale;
return "Battery Info: isCharging=" + isCharging
+ " usbCharge=" + usbCharge + " acCharge=" + acCharge
+ " batteryPct=" + batteryPct;
}
@SuppressLint("PackageManagerGetSignatures")
private static Signature getPackageSignature(Context context) {
final PackageManager pm = context.getPackageManager();
PackageInfo info = null;
try {
info = pm.getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNATURES);
} catch (Exception ignored) {
}
Signature signature = null;
if (info != null) {
Signature[] signatures = info.signatures;
if (signatures != null && signatures.length > 0) {
signature = signatures[0];
}
}
if (DEBUG) {
LogUtils.v(TAG, "getSignature() " + signature);
}
return signature;
}
public static String getSignature(Context context) {
final Signature signature = getPackageSignature(context);
if (signature != null) {
try {
return CryptoUtils.HASH.sha1(signature.toByteArray());
} catch (Exception e) {
LogUtils.e(TAG, "getSignature() ex=" + e);
}
}
return "";
}
public static String getSignatureInfo(Context context) {
final Signature signature = getPackageSignature(context);
if (signature == null) {
return "";
}
final StringBuilder builder = new StringBuilder();
try {
final byte[] signatureBytes = signature.toByteArray();
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
final InputStream is = new ByteArrayInputStream(signatureBytes);
X509Certificate cert = (X509Certificate) certFactory.generateCertificate(is);
final String chars = signature.toCharsString();
final String hex = CryptoUtils.HEX.encodeHex(signatureBytes, false);
final String md5 = CryptoUtils.HASH.md5(signatureBytes);
final String sha1 = CryptoUtils.HASH.sha1(signatureBytes);
builder.append("SignName:").append(cert.getSigAlgName()).append("\n");
builder.append("Chars:").append(chars).append("\n");
builder.append("Hex:").append(hex).append("\n");
builder.append("MD5:").append(md5).append("\n");
builder.append("SHA1:").append(sha1).append("\n");
builder.append("SignNumber:").append(cert.getSerialNumber()).append("\n");
builder.append("SubjectDN:").append(cert.getSubjectDN().getName()).append("\n");
builder.append("IssuerDN:").append(cert.getIssuerDN().getName()).append("\n");
} catch (Exception e) {
LogUtils.e(TAG, "parseSignature() ex=" + e);
}
final String text = builder.toString();
if (DEBUG) {
LogUtils.v(TAG, text);
}
return text;
}
}