網(wǎng)站首頁 編程語言 正文
本文實例為大家分享了Android實現(xiàn)懸浮窗效果的具體代碼,供大家參考,具體內(nèi)容如下
一、權(quán)限:
二、懸浮窗其實就是 WindowManager.addView(view,layoutParams),直接上代碼
1、單例創(chuàng)建FloatWindowManager?
/** ? 懸浮Manager */ public class FloatWindowManager { ? ? private volatile static FloatWindowManager mInstance; ? ? private WindowManager mWindowManager; ? ? private Context mContext; ? ? private WindowManager.LayoutParams mLayoutParams; ? ? private int layoutY; ? ? private int layoutX; ? ? private ValueAnimator animator; ? ? private TextView textView; ? ? ? ? public static synchronized FloatWindowManager getInstance() { ? ? ? ? if (mInstance == null) { ? ? ? ? ? ? synchronized (FloatWindowManager.class) { ? ? ? ? ? ? ? ? if (mInstance == null) { ? ? ? ? ? ? ? ? ? ? mInstance = new FloatWindowManager(); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? return mInstance; ? ? } ? ? ? public FloatWindowManager initManager(Context context) { ? ? ? ? mContext = context; ? ? ? ? mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); ? ? ? ? showWindow(); ? ? ? ? return this; ? ? } ? ? ? ? /** ? ? ?* 是否有懸浮框權(quán)限 ? ? ?* ? ? ?* @return ? ? ?*/ ? ? public boolean requestPermission(Context context) { ? ? ? ? return SettingsCompat.canDrawOverlays(context, true, false); ? ? } ? ? ? /** ? ? ?* 加載 懸浮窗 ? 沒有內(nèi)容 ? ? ?*/ ? ? private synchronized void showWindow() { ? ? ? ? textView = new TextView(mContext); ? ? ? ? textView.setText("此為懸浮窗口View"); ? ? ? ? textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, dp2px(mContext, 15)); ? ? ? ? mLayoutParams = new WindowManager.LayoutParams(); ? ? ? ? if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { ? ? ? ? ? ? mLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; ? ? ? ? } else { ? ? ? ? ? ? mLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT; ? ? ? ? } ? ? ? ? mLayoutParams.format = PixelFormat.RGBA_8888; //窗口透明 ? ? ? ? mLayoutParams.gravity = Gravity.LEFT | Gravity.TOP; //窗口位置 ? ? ? ? mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; ? ? ? ? DisplayMetrics displayMetrics = mContext.getResources().getDisplayMetrics(); ? ? ? ? layoutY = displayMetrics.heightPixels / 2; ? ? ? ? layoutX = displayMetrics.widthPixels - textView.getMeasuredWidth(); ? ? ? ? mLayoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT; ? ? ? ? mLayoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT; ? ? ? ? mLayoutParams.x = layoutX; ? ? ? ? mLayoutParams.y = layoutY; ? ? ? ? setListener(); ? ? } ? ? ? public void showFloatWindow(){ ? ? ? ? mWindowManager.addView(textView, mLayoutParams); ? ? } ? ? ? /** ? ? ?* 設(shè)置 懸浮窗 view 滑動事件 ? ? ?*/ ? ? private void setListener() { ? ? ? ? if (textView != null) { ? ? ? ? ? ? textView.setOnTouchListener(new View.OnTouchListener() { ? ? ? ? ? ? ? ? private int moveX; ? //動畫平移距離 ? ? ? ? ? ? ? ? int startX, startY; ?//起始點 ? ? ? ? ? ? ? ? boolean isMove; ?//是否在移動 ? ? ? ? ? ? ? ? long startTime; ? ? ? ? ? ? ? ? int finalMoveX; ?//最后通過動畫將mView的X軸坐標(biāo)移動到finalMoveX ? ? ? ? ? ? ? ? boolean downMove = false; ? ? ? ? ? ? ? ? ? @Override ? ? ? ? ? ? ? ? public boolean onTouch(View v, MotionEvent event) { ? ? ? ? ? ? ? ? ? ? switch (event.getAction()) { ? ? ? ? ? ? ? ? ? ? ? ? case MotionEvent.ACTION_DOWN: ? ? ? ? ? ? ? ? ? ? ? ? ? ? startX = (int) event.getX(); ? ? ? ? ? ? ? ? ? ? ? ? ? ? startY = (int) event.getY(); ? ? ? ? ? ? ? ? ? ? ? ? ? ? startTime = System.currentTimeMillis(); ? ? ? ? ? ? ? ? ? ? ? ? ? ? isMove = false; ? ? ? ? ? ? ? ? ? ? ? ? ? ? downMove = false; ? ? ? ? ? ? ? ? ? ? ? ? ? ? return false; ? ? ? ? ? ? ? ? ? ? ? ? case MotionEvent.ACTION_MOVE: ? ? ? ? ? ? ? ? ? ? ? ? ? ? //當(dāng)移動距離大于2時候,刷新界面。 ? ? ? ? ? ? ? ? ? ? ? ? ? ? if (Math.abs(startX - event.getX()) > 2 || Math.abs(startY - event.getY()) > 2) { ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? downMove = true; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? mLayoutParams.x = (int) (event.getRawX() - startX); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? mLayoutParams.y = (int) (event.getRawY() - startY); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? updateViewLayout(); ? //更新mView 的位置 ? ? ? ? ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? ? ? ? ? return true; ? ? ? ? ? ? ? ? ? ? ? ? case MotionEvent.ACTION_UP: ? ? ? ? ? ? ? ? ? ? ? ? ? ? long curTime = System.currentTimeMillis(); ? ? ? ? ? ? ? ? ? ? ? ? ? ? isMove = curTime - startTime > 100; ? ? ? ? ? ? ? ? ? ? ? ? ? ? if (isMove){ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //判斷mView是在Window中的位置,以中間為界 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if (mLayoutParams.x + textView.getMeasuredWidth() / 2 >= mWindowManager.getDefaultDisplay().getWidth() / 2) { ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? finalMoveX = mWindowManager.getDefaultDisplay().getWidth() - textView.getMeasuredWidth(); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? } else { ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? finalMoveX = 0; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //使用動畫移動mView ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? animator = ValueAnimator.ofInt(mLayoutParams.x, finalMoveX).setDuration(Math.abs(mLayoutParams.x - finalMoveX)); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? animator.addUpdateListener((ValueAnimator animation) -> { ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if (animation != null) { ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? moveX = (int) animation.getAnimatedValue(); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? mLayoutParams.x = (int) animation.getAnimatedValue(); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? updateViewLayout(); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? animator.start(); ? ? ? ? ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? return isMove; ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? return false; ? ? ? ? ? ? ? ? } ? ? ? ? ? ? }); ? ? ? ? } ? ? } ? ? ? ? /** ? ? ?* 刷新 circle view 位置 ? ? ?*/ ? ? private void updateViewLayout() { ? ? ? ? if (null != textView && null != mLayoutParams && mWindowManager != null) { ? ? ? ? ? ? try { ? ? ? ? ? ? ? ? mWindowManager.updateViewLayout(textView, mLayoutParams); ? ? ? ? ? ? } catch (Exception e) { ? ? ? ? ? ? ? ? e.printStackTrace(); ? ? ? ? ? ? } ? ? ? ? } ? ? } ? ? ? ? /** ? ? ?* 根據(jù)手機(jī)的分辨率從 dp 的單位 轉(zhuǎn)成為 px(像素) ? ? ?*/ ? ? public static int dp2px(Context context, float dpValue) { ? ? ? ? if (context != null) { ? ? ? ? ? ? final float scale = context.getResources().getDisplayMetrics().density; ? ? ? ? ? ? return (int) (dpValue * scale + 0.5f); ? ? ? ? } ? ? ? ? return (int) dpValue; ? ? }
2、SettingsCompat 動態(tài)權(quán)限判斷(適配大部分廠商)
public class SettingsCompat { ? ? ? private static final int OP_WRITE_SETTINGS = 23; ? ? private static final int OP_SYSTEM_ALERT_WINDOW = 24; ? ? ? /** ? ? ?* 檢查懸浮窗權(quán)限 ?當(dāng)沒有權(quán)限,跳轉(zhuǎn)到權(quán)限設(shè)置界面 ? ? ?* ? ? ?* @param context ? ? ? ? ?上下文 ? ? ?* @param isShowDialog ? ? 沒有權(quán)限,是否彈框提示跳轉(zhuǎn)到權(quán)限設(shè)置界面 ? ? ?* @param isShowPermission 是否跳轉(zhuǎn)權(quán)限開啟界面 ? ? ?* @return true 有權(quán)限 ? false 沒有權(quán)限(跳轉(zhuǎn)權(quán)限界面、權(quán)限失敗 提示用戶手動設(shè)置權(quán)限) ? ? ?* @by 騰訊云直播 懸浮框判斷邏輯 ? ? ?*/ ? ? public static boolean canDrawOverlays(Context context, boolean isShowDialog, boolean isShowPermission) { ? ? ? ? if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { ? ? ? ? ? ? if (!Settings.canDrawOverlays(context)) { ? ? ? ? ? ? ? ? if (isShowDialog) { ? ? ? ? ? ? ? ? ? ? //去授權(quán) ? ? ? ? ? ? ? ? ? ? SettingsCompat.manageDrawOverlays(context); ? ? ? ? ? ? ? ? } else if (isShowPermission) { ? ? ? ? ? ? ? ? ? ? manageDrawOverlays(context); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? return false; ? ? ? ? ? ? } ? ? ? ? ? ? return true; ? ? ? ? } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { ? ? ? ? ? ? if (checkOp(context, OP_SYSTEM_ALERT_WINDOW)) { ? ? ? ? ? ? ? ? return true; ? ? ? ? ? ? } else { ? ? ? ? ? ? ? ? if (isShowPermission) ? ? ? ? ? ? ? ? ? ? startFloatWindowPermissionErrorToast(context); ? ? ? ? ? ? ? ? return false; ? ? ? ? ? ? } ? ? ? ? } else { ? ? ? ? ? ? return true; ? ? ? ? } ? ? } ? ? ? ? /** ? ? ?* 打開 懸浮窗 授權(quán)界面 ? ? ?* ? ? ?* @param context ? ? ?*/ ? ? public static void manageDrawOverlays(Context context) { ? ? ? ? if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { ? ? ? ? ? ? try { ? ? ? ? ? ? ? ? Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION); ? ? ? ? ? ? ? ? intent.setData(Uri.parse("package:" + context.getPackageName())); ? ? ? ? ? ? ? ? intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); ? ? ? ? ? ? ? ? context.startActivity(intent); ? ? ? ? ? ? } catch (Exception e) { ? ? ? ? ? ? ? ? e.printStackTrace(); ? ? ? ? ? ? ? ? startFloatWindowPermissionErrorToast(context); ? ? ? ? ? ? } ? ? ? ? } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { ? ? ? ? ? ? if (!manageDrawOverlaysForRom(context)) { ? ? ? ? ? ? ? ? startFloatWindowPermissionErrorToast(context); ? ? ? ? ? ? } ? ? ? ? } ? ? } ? ? ? /** ? ? ?* 權(quán)限設(shè)置 失敗提示。 ? ? ?* ? ? ?* @param context ? ? ?*/ ? ? public static void startFloatWindowPermissionErrorToast(Context context) { ? ? ? ? if (context != null) ? ? ? ? ? ? Toast.makeText(context, "進(jìn)入設(shè)置頁面失敗,請手動開啟懸浮窗權(quán)限", Toast.LENGTH_SHORT).show(); ? ? } ? ? ? private static boolean manageDrawOverlaysForRom(Context context) { ? ? ? ? if (RomUtil.isMiui()) { ? ? ? ? ? ? return manageDrawOverlaysForMiui(context); ? ? ? ? } ? ? ? ? if (RomUtil.isEmui()) { ? ? ? ? ? ? return manageDrawOverlaysForEmui(context); ? ? ? ? } ? ? ? ? if (RomUtil.isFlyme()) { ? ? ? ? ? ? return manageDrawOverlaysForFlyme(context); ? ? ? ? } ? ? ? ? if (RomUtil.isOppo()) { ? ? ? ? ? ? return manageDrawOverlaysForOppo(context); ? ? ? ? } ? ? ? ? if (RomUtil.isVivo()) { ? ? ? ? ? ? return manageDrawOverlaysForVivo(context); ? ? ? ? } ? ? ? ? if (RomUtil.isQiku()) { ? ? ? ? ? ? return manageDrawOverlaysForQihu(context); ? ? ? ? } ? ? ? ? if (RomUtil.isSmartisan()) { ? ? ? ? ? ? return manageDrawOverlaysForSmartisan(context); ? ? ? ? } ? ? ? ? return false; ? ? } ? ? ? ? private static boolean checkOp(Context context, int op) { ? ? ? ? AppOpsManager manager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); ? ? ? ? try { ? ? ? ? ? ? Method method = AppOpsManager.class.getDeclaredMethod("checkOp", int.class, int.class, String.class); ? ? ? ? ? ? return AppOpsManager.MODE_ALLOWED == (int) method.invoke(manager, op, Binder.getCallingUid(), context.getPackageName()); ? ? ? ? } catch (Exception e) { ? ? ? ? } ? ? ? ? return false; ? ? } ? ? ? // 可設(shè)置Android 4.3/4.4的授權(quán)狀態(tài) ? ? private static boolean setMode(Context context, int op, boolean allowed) { ? ? ? ? if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2 || Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { ? ? ? ? ? ? return false; ? ? ? ? } ? ? ? ? ? AppOpsManager manager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); ? ? ? ? try { ? ? ? ? ? ? Method method = AppOpsManager.class.getDeclaredMethod("setMode", int.class, int.class, String.class, int.class); ? ? ? ? ? ? method.invoke(manager, op, Binder.getCallingUid(), context.getPackageName(), allowed ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED); ? ? ? ? ? ? return true; ? ? ? ? } catch (Exception e) { ? ? ? ? ? } ? ? ? ? return false; ? ? } ? ? ? /** ? ? ?* 跳轉(zhuǎn)界面 ? ? ?* ? ? ?* @param context ? ? ?* @param intent ? ? ?* @return ? ? ?*/ ? ? private static boolean startSafely(Context context, Intent intent) { ? ? ? ? ListresolveInfos = null; ? ? ? ? try { ? ? ? ? ? ? resolveInfos = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY); ? ? ? ? ? ? if (resolveInfos != null && resolveInfos.size() > 0) { ? ? ? ? ? ? ? ? intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); ? ? ? ? ? ? ? ? context.startActivity(intent); ? ? ? ? ? ? ? ? return true; ? ? ? ? ? ? } ? ? ? ? } catch (Exception e) { ? ? ? ? ? ? e.printStackTrace(); ? ? ? ? } ? ? ? ? return false; ? ? } ? ? ? ? // 小米 ? ? private static boolean manageDrawOverlaysForMiui(Context context) { ? ? ? ? Intent intent = new Intent("miui.intent.action.APP_PERM_EDITOR"); ? ? ? ? intent.putExtra("extra_pkgname", context.getPackageName()); ? ? ? ? intent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.AppPermissionsEditorActivity"); ? ? ? ? if (startSafely(context, intent)) { ? ? ? ? ? ? return true; ? ? ? ? } ? ? ? ? intent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.PermissionsEditorActivity"); ? ? ? ? if (startSafely(context, intent)) { ? ? ? ? ? ? return true; ? ? ? ? } ? ? ? ? // miui v5 的支持的android版本最高 4.x ? ? ? ? // http://www.romzj.com/list/search?keyword=MIUI%20V5#search_result ? ? ? ? if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { ? ? ? ? ? ? Intent intent1 = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); ? ? ? ? ? ? intent1.setData(Uri.fromParts("package", context.getPackageName(), null)); ? ? ? ? ? ? return startSafely(context, intent1); ? ? ? ? } ? ? ? ? return false; ? ? } ? ? ? private final static String HUAWEI_PACKAGE = "com.huawei.systemmanager"; ? ? ? // 華為 ? ? private static boolean manageDrawOverlaysForEmui(Context context) { ? ? ? ? Intent intent = new Intent(); ? ? ? ? if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { ? ? ? ? ? ? intent.setClassName(HUAWEI_PACKAGE, "com.huawei.systemmanager.addviewmonitor.AddViewMonitorActivity"); ? ? ? ? ? ? if (startSafely(context, intent)) { ? ? ? ? ? ? ? ? return true; ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? // Huawei Honor P6|4.4.4|3.0 ? ? ? ? intent.setClassName(HUAWEI_PACKAGE, "com.huawei.notificationmanager.ui.NotificationManagmentActivity"); ? ? ? ? intent.putExtra("showTabsNumber", 1); ? ? ? ? if (startSafely(context, intent)) { ? ? ? ? ? ? return true; ? ? ? ? } ? ? ? ? intent.setClassName(HUAWEI_PACKAGE, "com.huawei.permissionmanager.ui.MainActivity"); ? ? ? ? if (startSafely(context, intent)) { ? ? ? ? ? ? return true; ? ? ? ? } ? ? ? ? return false; ? ? } ? ? ? // VIVO ? ? private static boolean manageDrawOverlaysForVivo(Context context) { ? ? ? ? // 不支持直接到達(dá)懸浮窗設(shè)置頁,只能到 i管家 首頁 ? ? ? ? Intent intent = new Intent("com.iqoo.secure"); ? ? ? ? intent.setClassName("com.iqoo.secure", "com.iqoo.secure.MainActivity"); ? ? ? ? // com.iqoo.secure.ui.phoneoptimize.SoftwareManagerActivity ? ? ? ? // com.iqoo.secure.ui.phoneoptimize.FloatWindowManager ? ? ? ? return startSafely(context, intent); ? ? } ? ? ? // OPPO ? ? private static boolean manageDrawOverlaysForOppo(Context context) { ? ? ? ? Intent intent = new Intent(); ? ? ? ? intent.putExtra("packageName", context.getPackageName()); ? ? ? ? // OPPO A53|5.1.1|2.1 ? ? ? ? intent.setAction("com.oppo.safe"); ? ? ? ? intent.setClassName("com.oppo.safe", "com.oppo.safe.permission.floatwindow.FloatWindowListActivity"); ? ? ? ? if (startSafely(context, intent)) { ? ? ? ? ? ? return true; ? ? ? ? } ? ? ? ? // OPPO R7s|4.4.4|2.1 ? ? ? ? intent.setAction("com.color.safecenter"); ? ? ? ? intent.setClassName("com.color.safecenter", "com.color.safecenter.permission.floatwindow.FloatWindowListActivity"); ? ? ? ? if (startSafely(context, intent)) { ? ? ? ? ? ? return true; ? ? ? ? } ? ? ? ? intent.setAction("com.coloros.safecenter"); ? ? ? ? intent.setClassName("com.coloros.safecenter", "com.coloros.safecenter.sysfloatwindow.FloatWindowListActivity"); ? ? ? ? return startSafely(context, intent); ? ? } ? ? ? // 魅族 ? ? private static boolean manageDrawOverlaysForFlyme(Context context) { ? ? ? ? Intent intent = new Intent("com.meizu.safe.security.SHOW_APPSEC"); ? ? ? ? intent.setClassName("com.meizu.safe", "com.meizu.safe.security.AppSecActivity"); ? ? ? ? intent.putExtra("packageName", context.getPackageName()); ? ? ? ? return startSafely(context, intent); ? ? } ? ? ? // 360 ? ? private static boolean manageDrawOverlaysForQihu(Context context) { ? ? ? ? Intent intent = new Intent(); ? ? ? ? intent.setClassName("com.android.settings", "com.android.settings.Settings$OverlaySettingsActivity"); ? ? ? ? if (startSafely(context, intent)) { ? ? ? ? ? ? return true; ? ? ? ? } ? ? ? ? intent.setClassName("com.qihoo360.mobilesafe", "com.qihoo360.mobilesafe.ui.index.AppEnterActivity"); ? ? ? ? return startSafely(context, intent); ? ? } ? ? ? // 錘子 ? ? private static boolean manageDrawOverlaysForSmartisan(Context context) { ? ? ? ? if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { ? ? ? ? ? ? return false; ? ? ? ? } ? ? ? ? if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { ? ? ? ? ? ? // 錘子 堅果|5.1.1|2.5.3 ? ? ? ? ? ? Intent intent = new Intent("com.smartisanos.security.action.SWITCHED_PERMISSIONS_NEW"); ? ? ? ? ? ? intent.setClassName("com.smartisanos.security", "com.smartisanos.security.SwitchedPermissions"); ? ? ? ? ? ? intent.putExtra("index", 17); // 不同版本會不一樣 ? ? ? ? ? ? return startSafely(context, intent); ? ? ? ? } else { ? ? ? ? ? ? // 錘子 堅果|4.4.4|2.1.2 ? ? ? ? ? ? Intent intent = new Intent("com.smartisanos.security.action.SWITCHED_PERMISSIONS"); ? ? ? ? ? ? intent.setClassName("com.smartisanos.security", "com.smartisanos.security.SwitchedPermissions"); ? ? ? ? ? ? intent.putExtra("permission", new String[]{Manifest.permission.SYSTEM_ALERT_WINDOW}); ? ? ? ? ? ? ? // ? ? ? ?Intent intent = new Intent("com.smartisanos.security.action.MAIN"); ? ? ? ? ? ? // ? ? ? ?intent.setClassName("com.smartisanos.security", "com.smartisanos.security.MainActivity"); ? ? ? ? ? ? return startSafely(context, intent); ? ? ? ? } ? ? } ? }
3、廠商 ?RomUtil
public class RomUtil { ? ? private static final String TAG = "RomUtil"; ? ? ? public static final String ROM_MIUI = "MIUI"; ? ? public static final String ROM_EMUI = "EMUI"; ? ? public static final String ROM_FLYME = "FLYME"; ? ? public static final String ROM_OPPO = "OPPO"; ? ? public static final String ROM_SMARTISAN = "SMARTISAN"; ? ? ? public static final String ROM_VIVO = "VIVO"; ? ? public static final String ROM_QIKU = "QIKU"; ? ? ? public static final String ROM_LENOVO = "LENOVO"; ? ? public static final String ROM_SAMSUNG = "SAMSUNG"; ? ? ? private static final String KEY_VERSION_MIUI = "ro.miui.ui.version.name"; ? ? private static final String KEY_VERSION_EMUI = "ro.build.version.emui"; ? ? private static final String KEY_VERSION_OPPO = "ro.build.version.opporom"; ? ? private static final String KEY_VERSION_SMARTISAN = "ro.smartisan.version"; ? ? private static final String KEY_VERSION_VIVO = "ro.vivo.os.version"; ? ? private static final String KEY_VERSION_GIONEE = "ro.gn.sv.version"; ? ? private static final String KEY_VERSION_LENOVO = "ro.lenovo.lvp.version"; ? ? private static final String KEY_VERSION_FLYME = "ro.build.display.id"; ? ? ? ? private static final String KEY_EMUI_VERSION_CODE = "ro.build.hw_emui_api_level"; ? ? ? private static final String KEY_MIUI_VERSION_CODE = "ro.miui.ui.version.code"; ? ? private static final String KEY_MIUI_HANDY_MODE_SF = "ro.miui.has_handy_mode_sf"; ? ? private static final String KEY_MIUI_REAL_BLUR = "ro.miui.has_real_blur"; ? ? ? private static final String KEY_FLYME_PUBLISHED = "ro.flyme.published"; ? ? private static final String KEY_FLYME_FLYME = "ro.meizu.setupwizard.flyme"; ? ? ? private static final String KEY_FLYME_ICON_FALG = "persist.sys.use.flyme.icon"; ? ? private static final String KEY_FLYME_SETUP_FALG = "ro.meizu.setupwizard.flyme"; ? ? private static final String KEY_FLYME_PUBLISH_FALG = "ro.flyme.published"; ? ? ? private static final String KEY_VIVO_OS_NAME = "ro.vivo.os.name"; ? ? private static final String KEY_VIVO_OS_VERSION = "ro.vivo.os.version"; ? ? private static final String KEY_VIVO_ROM_VERSION = "ro.vivo.rom.version"; ? ? ? public static boolean isEmui() { ? ? ? ? return check(ROM_EMUI); ? ? } ? ? ? public static boolean isMiui() { ? ? ? ? return check(ROM_MIUI); ? ? } ? ? ? public static boolean isVivo() { ? ? ? ? return check(ROM_VIVO); ? ? } ? ? ? public static boolean isOppo() { ? ? ? ? return check(ROM_OPPO); ? ? } ? ? ? public static boolean isFlyme() { ? ? ? ? return check(ROM_FLYME); ? ? } ? ? ? public static boolean isQiku() { ? ? ? ? return check(ROM_QIKU) || check("360"); ? ? } ? ? ? public static boolean isSmartisan() { ? ? ? ? return check(ROM_SMARTISAN); ? ? } ? ? ? private static String sName; ? ? ? public static String getName() { ? ? ? ? if (sName == null) { ? ? ? ? ? ? check(""); ? ? ? ? } ? ? ? ? return sName; ? ? } ? ? ? private static String sVersion; ? ? ? public static String getVersion() { ? ? ? ? if (sVersion == null) { ? ? ? ? ? ? check(""); ? ? ? ? } ? ? ? ? return sVersion; ? ? } ? ? ? public static boolean check(String rom) { ? ? ? ? if (sName != null) { ? ? ? ? ? ? return sName.equals(rom); ? ? ? ? } ? ? ? ? ? if (!TextUtils.isEmpty(sVersion = getProp(KEY_VERSION_MIUI))) { ? ? ? ? ? ? sName = ROM_MIUI; ? ? ? ? } else if (!TextUtils.isEmpty(sVersion = getProp(KEY_VERSION_EMUI))) { ? ? ? ? ? ? sName = ROM_EMUI; ? ? ? ? } else if (!TextUtils.isEmpty(sVersion = getProp(KEY_VERSION_OPPO))) { ? ? ? ? ? ? sName = ROM_OPPO; ? ? ? ? } else if (!TextUtils.isEmpty(sVersion = getProp(KEY_VERSION_VIVO))) { ? ? ? ? ? ? sName = ROM_VIVO; ? ? ? ? } else if (!TextUtils.isEmpty(sVersion = getProp(KEY_VERSION_SMARTISAN))) { ? ? ? ? ? ? sName = ROM_SMARTISAN; ? ? ? ? } else { ? ? ? ? ? ? sVersion = Build.DISPLAY; ? ? ? ? ? ? if (sVersion.toUpperCase().contains(ROM_FLYME)) { ? ? ? ? ? ? ? ? sName = ROM_FLYME; ? ? ? ? ? ? } else { ? ? ? ? ? ? ? ? sVersion = Build.UNKNOWN; ? ? ? ? ? ? ? ? sName = Build.MANUFACTURER.toUpperCase(); ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? return sName.equals(rom); ? ? } ? ? ? public static String getProp(String name) { ? ? ? ? String line = null; ? ? ? ? BufferedReader input = null; ? ? ? ? try { ? ? ? ? ? ? Process p = Runtime.getRuntime().exec("getprop " + name); ? ? ? ? ? ? input = new BufferedReader(new InputStreamReader(p.getInputStream()), 1024); ? ? ? ? ? ? line = input.readLine(); ? ? ? ? ? ? input.close(); ? ? ? ? } catch (IOException ex) { ? ? ? ? ? ? Log.e(TAG, "Unable to read prop " + name, ex); ? ? ? ? ? ? return null; ? ? ? ? } finally { ? ? ? ? ? ? if (input != null) { ? ? ? ? ? ? ? ? try { ? ? ? ? ? ? ? ? ? ? input.close(); ? ? ? ? ? ? ? ? } catch (IOException e) { ? ? ? ? ? ? ? ? ? ? e.printStackTrace(); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? return line; ? ? } }
原文鏈接:https://blog.csdn.net/qq_21467035/article/details/115177456
相關(guān)推薦
- 2021-12-06 Redis限流的幾種實現(xiàn)_Redis
- 2023-02-12 Jupyter?notebook如何實現(xiàn)打開數(shù)據(jù)集_python
- 2022-07-11 C++深入淺出講解內(nèi)存四區(qū)與new關(guān)鍵字的使用_C 語言
- 2022-01-09 webpack-code split代碼分割
- 2023-04-07 Redux?saga異步管理與生成器詳解_React
- 2022-11-22 Python?flask框架定時任務(wù)apscheduler應(yīng)用介紹_python
- 2022-04-19 Golang語言的多種變量聲明方式與使用場景詳解_Golang
- 2022-11-05 安裝ingress-nginx遇到的一些坑實戰(zhàn)記錄_云其它
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支