Skip to content

Instantly share code, notes, and snippets.

@joinAero
Created February 17, 2016 13:04
Show Gist options
  • Star 14 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save joinAero/4795dda8ba93ddcfb8f8 to your computer and use it in GitHub Desktop.
Save joinAero/4795dda8ba93ddcfb8f8 to your computer and use it in GitHub Desktop.
Android - Helper for 3rd party roms: Flyme & MIUI.
package cc.cubone.turbo.core.rom;
import android.os.Build;
import android.view.Window;
import android.view.WindowManager;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* @see <a href="http://open-wiki.flyme.cn/index.php?title=Flyme%E7%B3%BB%E7%BB%9FAPI">Flyme系统API</a>
*/
public class FlymeUtils {
public static boolean isFlyme() {
try {
// Invoke Build.hasSmartBar()
final Method method = Build.class.getMethod("hasSmartBar");
return method != null;
} catch (Exception e) {
return false;
}
}
public static boolean setStatusBarDarkIcon(Window window, boolean dark) {
boolean result = false;
if (window != null) {
try {
WindowManager.LayoutParams lp = window.getAttributes();
Field darkFlag = WindowManager.LayoutParams.class.getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON");
Field meizuFlags = WindowManager.LayoutParams.class.getDeclaredField("meizuFlags");
darkFlag.setAccessible(true);
meizuFlags.setAccessible(true);
int bit = darkFlag.getInt(null);
int value = meizuFlags.getInt(lp);
if (dark) {
value |= bit;
} else {
value &= ~bit;
}
meizuFlags.setInt(lp, value);
window.setAttributes(lp);
result = true;
} catch (Exception ignored) {
}
}
return result;
}
}
package cc.cubone.turbo.core.rom;
import android.app.AppOpsManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Binder;
import android.os.Build;
import android.provider.Settings;
import android.view.Window;
import java.io.IOException;
import java.lang.reflect.Method;
import cc.cubone.turbo.core.os.BuildProperties;
/**
* @see <a href="http://dev.xiaomi.com/doc/?p=254">如何识别小米设备/MIUI系统</a>
* @see <a href="http://dev.xiaomi.com/docs/appsmarket/technical_docs/immersion/">MIUI 6 沉浸式状态栏调用方法</a>
* @see <a href="http://www.cnblogs.com/fangyucun/p/4027750.html">关于MIUI悬浮窗权限问题的解决方案</a>
*/
public class MIUIUtils {
public static final String MIUI_V5 = "V5";
public static final String MIUI_V6 = "V6";
public enum StatusBarMode {
TRANSPARENT, TRANSPARENT_DARK_TEXT, DARK_TEXT_CLEAN,
}
private static final String KEY_MIUI_VERSION_CODE = "ro.miui.ui.version.code";
private static final String KEY_MIUI_VERSION_NAME = "ro.miui.ui.version.name";
private static final String KEY_MIUI_INTERNAL_STORAGE = "ro.miui.internal.storage";
public static boolean isMIUI() {
try {
final BuildProperties prop = BuildProperties.newInstance();
return prop.getProperty(KEY_MIUI_VERSION_CODE, null) != null
|| prop.getProperty(KEY_MIUI_VERSION_NAME, null) != null
|| prop.getProperty(KEY_MIUI_INTERNAL_STORAGE, null) != null;
} catch (IOException e) {
return false;
}
}
public static boolean isMIUIV5() {
return getVersionName().equals(MIUI_V5);
}
public static boolean isMIUIV6() {
return getVersionName().equals(MIUI_V6);
}
public static String getVersionName() {
try {
final BuildProperties prop = BuildProperties.newInstance();
return prop.getProperty(KEY_MIUI_VERSION_NAME);
} catch (IOException e) {
return "";
}
}
@SuppressWarnings("IncompatibleBitwiseMaskOperation")
public static boolean isFloatWindowOpAllowed(Context context) {
if (Build.VERSION.SDK_INT >= 19) { // 19, 4.4, KITKAT
final AppOpsManager manager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
final int mode = manager.checkOp(AppOpsManager.OPSTR_SYSTEM_ALERT_WINDOW,
Binder.getCallingUid(), context.getPackageName());
return AppOpsManager.MODE_ALLOWED == mode;
} else {
return (context.getApplicationInfo().flags & 1 << 27) == 1;
}
}
public static Intent toPermissionManager(Context context, String packageName) {
Intent intent = new Intent("miui.intent.action.APP_PERM_EDITOR");
String version = getVersionName();
if (MIUI_V5.equals(version)) {
PackageInfo pInfo;
try {
pInfo = context.getPackageManager().getPackageInfo(packageName, 0);
} catch (PackageManager.NameNotFoundException ignored) {
return null;
}
intent.setClassName("com.android.settings", "com.miui.securitycenter.permission.AppPermissionsEditor");
intent.putExtra("extra_package_uid", pInfo.applicationInfo.uid);
} else { // MIUI_V6 and above
final String PKG_SECURITY_CENTER = "com.miui.securitycenter";
try {
context.getPackageManager().getPackageInfo(PKG_SECURITY_CENTER, PackageManager.GET_ACTIVITIES);
} catch (PackageManager.NameNotFoundException ignored) {
return null;
}
intent.setClassName(PKG_SECURITY_CENTER, "com.miui.permcenter.permissions.AppPermissionsEditorActivity");
intent.putExtra("extra_pkgname", packageName);
}
return intent;
}
public static Intent toAutoStartPermission() {
Intent intent = new Intent();
intent.setAction("miui.intent.action.OP_AUTO_START");
intent.addCategory(Intent.CATEGORY_DEFAULT);
return intent;
}
/**
* Note: V5的悬浮窗权限在应用详情里面
*/
public static Intent toFloatWindowPermission(Context context, String packageName) {
Uri packageUri = Uri.parse("package:" + packageName);
Intent detailsIntent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, packageUri);
detailsIntent.addCategory(Intent.CATEGORY_DEFAULT);
if (isMIUIV5()) {
return detailsIntent;
} else {
Intent permIntent = toPermissionManager(context, packageName);
return permIntent == null ? detailsIntent : permIntent;
}
}
public static Intent toRootPermission() {
Intent intent = new Intent();
intent.setAction("miui.intent.action.ROOT_MANAGER");
intent.addCategory(Intent.CATEGORY_DEFAULT);
return intent;
}
public static void setStatusBar(Window window, StatusBarMode mode) {
try {
Class layoutParamsClass = Class.forName("android.view.MiuiWindowManager$LayoutParams");
int tranceFlag = layoutParamsClass.getField("EXTRA_FLAG_STATUS_BAR_TRANSPARENT").getInt(null);
int darkModeFlag = layoutParamsClass.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE").getInt(null);
Method extraFlagsField = Window.class.getMethod("setExtraFlags", int.class, int.class);
switch (mode) {
case TRANSPARENT:
extraFlagsField.invoke(window, tranceFlag, tranceFlag); // 只需要状态栏透明
break;
case TRANSPARENT_DARK_TEXT:
extraFlagsField.invoke(window, tranceFlag | darkModeFlag, tranceFlag | darkModeFlag); // 状态栏透明且黑色字体
break;
case DARK_TEXT_CLEAN:
extraFlagsField.invoke(window, 0, darkModeFlag); // 清除黑色字体
break;
}
} catch (Exception ignored) {
}
}
}
package cc.cubone.turbo.core.rom;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.provider.Settings;
import android.support.v4.content.ContextCompat;
import static android.Manifest.permission.SYSTEM_ALERT_WINDOW;
/**
* Helper for accessing custom features for 3rd party roms.
*
* @see <a href="https://github.com/weikano/RomHelper">RomHelper</a>
*/
public final class RomCompat {
interface RomCompatImpl {
public String getVersionName();
public boolean isThirdParty();
public boolean isAutoStart();
public boolean hasPermissionManager();
public boolean hasFloatWindowPermission(Context context);
public Intent toAppDetails(Context context, String packageName);
public Intent toPermissionManager(Context context, String packageName);
public Intent toAutoStartPermission(Context context, String packageName);
public Intent toFloatWindowPermission(Context context, String packageName);
public Intent toRootPermission(Context context, String packageName);
}
static class BaseRomCompatImpl implements RomCompatImpl {
@Override
public String getVersionName() {
return String.valueOf(Build.VERSION.SDK_INT);
}
@Override
public boolean isThirdParty() {
return false;
}
@Override
public boolean isAutoStart() {
return true;
}
@Override
public boolean hasPermissionManager() {
return Build.VERSION.SDK_INT >= 23; // 23, 6.0, MARSHMALLOW
}
@Override
public boolean hasFloatWindowPermission(Context context) {
return ContextCompat.checkSelfPermission(context, SYSTEM_ALERT_WINDOW)
== PackageManager.PERMISSION_GRANTED;
}
@Override
public Intent toAppDetails(Context context, String packageName) {
Uri packageUri = Uri.parse("package:" + packageName);
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, packageUri);
intent.addCategory(Intent.CATEGORY_DEFAULT);
return intent;
}
@Override
public Intent toPermissionManager(Context context, String packageName) {
return null;
}
@Override
public Intent toAutoStartPermission(Context context, String packageName) {
return null;
}
@Override
public Intent toFloatWindowPermission(Context context, String packageName) {
return null;
}
@Override
public Intent toRootPermission(Context context, String packageName) {
return null;
}
}
@TargetApi(23) // 23, 6.0, MARSHMALLOW
static class MarshmallowRomCompatImpl extends BaseRomCompatImpl {
@Override
public boolean hasFloatWindowPermission(Context context) {
return Settings.canDrawOverlays(context);
}
@Override
public Intent toFloatWindowPermission(Context context, String packageName) {
return new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + packageName));
}
}
static class ThirdPartyRomCompatImpl extends BaseRomCompatImpl {
@Override
public boolean isThirdParty() {
return true;
}
@Override
public boolean hasPermissionManager() {
return true;
}
}
static class FlymeRomCompatImpl extends ThirdPartyRomCompatImpl {
@Override
public Intent toPermissionManager(Context context, String packageName) {
return toAppDetails(context, packageName);
}
@Override
public Intent toAutoStartPermission(Context context, String packageName) {
return toAppDetails(context, packageName);
}
@Override
public Intent toFloatWindowPermission(Context context, String packageName) {
return toAppDetails(context, packageName);
}
@Override
public Intent toRootPermission(Context context, String packageName) {
return null;
}
}
static class MIUIRomCompatImpl extends ThirdPartyRomCompatImpl {
@Override
public String getVersionName() {
return MIUIUtils.getVersionName();
}
@Override
public Intent toPermissionManager(Context context, String packageName) {
return MIUIUtils.toPermissionManager(context, packageName);
}
@Override
public Intent toAutoStartPermission(Context context, String packageName) {
return MIUIUtils.toAutoStartPermission();
}
@Override
public Intent toFloatWindowPermission(Context context, String packageName) {
return MIUIUtils.toFloatWindowPermission(context, packageName);
}
@Override
public Intent toRootPermission(Context context, String packageName) {
return MIUIUtils.toRootPermission();
}
}
static final RomCompatImpl IMPL;
static {
final int version = android.os.Build.VERSION.SDK_INT;
if (version >= 23) { // 23, 6.0, MARSHMALLOW
IMPL = new MarshmallowRomCompatImpl();
} else if (FlymeUtils.isFlyme()) {
IMPL = new FlymeRomCompatImpl();
} else if (MIUIUtils.isMIUI()) {
IMPL = new MIUIRomCompatImpl();
} else {
IMPL = new BaseRomCompatImpl();
}
}
public static String getVersionName() {
return IMPL.getVersionName();
}
public static boolean isThirdParty() {
return IMPL.isThirdParty();
}
public static boolean isAutoStart() {
return IMPL.isAutoStart();
}
public static boolean hasPermissionManager() {
return IMPL.hasPermissionManager();
}
public static boolean hasFloatWindowPermission(Context context) {
return IMPL.hasFloatWindowPermission(context);
}
public static Intent toAppDetails(Context context) {
return toAppDetails(context, context.getPackageName());
}
public static Intent toAppDetails(Context context, String packageName) {
return IMPL.toAppDetails(context, packageName);
}
public static Intent toPermissionManager(Context context) {
return toPermissionManager(context, context.getPackageName());
}
public static Intent toPermissionManager(Context context, String packageName) {
return IMPL.toPermissionManager(context, packageName);
}
public static Intent toAutoStartPermission(Context context) {
return toAutoStartPermission(context, context.getPackageName());
}
public static Intent toAutoStartPermission(Context context, String packageName) {
return IMPL.toAutoStartPermission(context, packageName);
}
public static Intent toFloatWindowPermission(Context context) {
return toFloatWindowPermission(context, context.getPackageName());
}
public static Intent toFloatWindowPermission(Context context, String packageName) {
return IMPL.toFloatWindowPermission(context, packageName);
}
public static Intent toRootPermission(Context context) {
return toRootPermission(context, context.getPackageName());
}
public static Intent toRootPermission(Context context, String packageName) {
return IMPL.toRootPermission(context, packageName);
}
}
@joinAero
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment