/*
* Materialize - Materialize all those not material
* Copyright (C) 2015 XiNGRZ <xxx@oxo.ooo>
*
* This program 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.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package ooo.oxo.apps.materialize;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.util.Log;
import android.util.TypedValue;
import com.github.stuxuhai.jpinyin.PinyinFormat;
import com.github.stuxuhai.jpinyin.PinyinHelper;
import ooo.oxo.apps.materialize.io.IconCacheManager;
import ooo.oxo.apps.materialize.util.DisplayMetricsCompat;
/**
* A wrapper of {@link ActivityInfo}
*/
public class AppInfo {
private static final String TAG = "AppInfo";
private static int[] DENSITIES = new int[]{
DisplayMetricsCompat.DENSITY_XXXHIGH,
DisplayMetricsCompat.DENSITY_XXHIGH,
DisplayMetricsCompat.DENSITY_XHIGH,
DisplayMetricsCompat.DENSITY_HIGH // 这都没有狗带吧
};
public final ActivityInfo activityInfo;
public ComponentName component;
public String label;
public Pinyin labelPinyin;
public Resources res;
public int iconResId;
public TypedValue iconValue = new TypedValue();
public Bitmap icon = null;
public Uri cache = null;
private AppInfo(ActivityInfo activityInfo) {
this.activityInfo = activityInfo;
}
/**
* Wraps and resolve an {@link ActivityInfo}
*
* @param activityInfo The {@link ActivityInfo} object to resolve
* @param packageManager A {@link PackageManager} instance to resolve the {@link ActivityInfo}
* @return An {@link AppInfo} instance with its {@link #label} and icon resolved
*/
@Nullable
public static AppInfo from(ActivityInfo activityInfo, PackageManager packageManager) {
AppInfo app = new AppInfo(activityInfo);
return app.resolve(packageManager) ? app : null;
}
@Nullable
public static AppInfo from(ActivityInfo activityInfo, PackageManager packageManager, IconCacheManager iconCacheManager) {
AppInfo app = from(activityInfo, packageManager);
if (app != null) {
app.resolveCache(iconCacheManager);
}
return app;
}
public boolean resolve(PackageManager packageManager) {
component = new ComponentName(activityInfo.packageName, activityInfo.name);
label = activityInfo.loadLabel(packageManager).toString();
labelPinyin = Pinyin.from(label);
String app = activityInfo.applicationInfo.packageName;
try {
res = packageManager.getResourcesForApplication(activityInfo.applicationInfo);
} catch (PackageManager.NameNotFoundException e) {
Log.e(TAG, "Failed to get resources from " + app, e);
return false;
}
iconResId = activityInfo.getIconResource();
if (iconResId == 0) {
Log.e(TAG, "No icon found in " + app);
return false;
}
if (!resolveIconValue()) {
Log.e(TAG, "Failed to resolve icon drawable for " + app);
return false;
}
return true;
}
private boolean resolveIconValue() {
for (int density : DENSITIES) {
try {
res.getValueForDensity(iconResId, density, iconValue, true);
return true;
} catch (Exception ignored) {
}
}
return false;
}
public boolean resolveIcon() {
if (iconResId == 0) {
return false;
}
icon = BitmapFactory.decodeStream(res.openRawResource(iconResId, iconValue));
return icon != null;
}
public boolean resolveCache(IconCacheManager iconCacheManager) {
cache = iconCacheManager.get(this);
return cache != null;
}
public Intent getIntent() {
return new Intent(Intent.ACTION_MAIN)
.putExtra("__materialize_nonce__", System.currentTimeMillis())
.setComponent(component)
.setFlags(activityInfo.flags);
}
@Override
public String toString() {
return "AppInfo{" + (component == null ? "(not resolved)" : component.flattenToShortString()) + "}";
}
public static class Pinyin {
public final String pinyinLong;
public final String pinyinShort;
private Pinyin(String[] source) {
StringBuilder builderLong = new StringBuilder();
StringBuilder builderShort = new StringBuilder();
for (String s : source) {
s = s.trim();
if (TextUtils.isGraphic(s)) {
builderLong.append(s);
builderShort.append(s.charAt(0));
}
}
this.pinyinLong = builderLong.toString();
this.pinyinShort = builderShort.toString();
}
public static Pinyin from(String source) {
return new Pinyin(PinyinHelper.convertToPinyinString(source, " ", PinyinFormat.WITHOUT_TONE)
.toLowerCase()
.split(" "));
}
}
}