Created
February 17, 2016 13:04
-
-
Save joinAero/4795dda8ba93ddcfb8f8 to your computer and use it in GitHub Desktop.
Android - Helper for 3rd party roms: Flyme & MIUI.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) { | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Related: BuildProperties.java