Android 11 系统开发增加低电量弹窗提示 手机 平板 车载 TV 投影 通用

这篇具有很好参考价值的文章主要介绍了Android 11 系统开发增加低电量弹窗提示 手机 平板 车载 TV 投影 通用。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1、PowerUI是系统中控制电量提示的模块,低电量提醒、低电量关机提醒、高温关机提醒、省电模式都在其中实现

SystemUIService 中启动PowerUI

public class SystemUIService extends Service {
 
    @Override
    public void onCreate() {
        super.onCreate();
        ((SystemUIApplication) getApplication()).startServicesIfNeeded();
 
        // For debugging RescueParty
        if (Build.IS_DEBUGGABLE && SystemProperties.getBoolean("debug.crash_sysui", false)) {
            throw new RuntimeException();
        }
 
        if (Build.IS_DEBUGGABLE) {
            // b/71353150 - looking for leaked binder proxies
            BinderInternal.nSetBinderProxyCountEnabled(true);
            BinderInternal.nSetBinderProxyCountWatermarks(1000,900);
            BinderInternal.setBinderProxyCountCallback(
                    new BinderInternal.BinderProxyLimitListener() {
                        @Override
                        public void onLimitReached(int uid) {
                            Slog.w(SystemUIApplication.TAG,
                                    "uid " + uid + " sent too many Binder proxies to uid "
                                    + Process.myUid());
                        }
                    }, Dependency.get(Dependency.MAIN_HANDLER));
        }
    }SystemUIService 启动时,启动SystemUIApplicationstartServicesIfNeeded() 来启动SystemUI的各种服务
  在SystemUIApplication中 启动PowerUI
  config.xml 中config_systemUIServiceComponents
  <string-array name="config_systemUIServiceComponents" translatable="false">
        <item>com.android.systemui.Dependency$DependencyCreator</item>
        <item>com.android.systemui.util.NotificationChannels</item>
        <item>com.android.systemui.statusbar.CommandQueue$CommandQueueStart</item>
        <item>com.android.systemui.keyguard.KeyguardViewMediator</item>
        <item>com.android.systemui.recents.Recents</item>
        <item>com.android.systemui.volume.VolumeUI</item>
        <item>com.android.systemui.stackdivider.Divider</item>
        <item>com.android.systemui.SystemBars</item>
        <item>com.android.systemui.usb.StorageNotification</item>
        <item>com.android.systemui.power.PowerUI</item>
        <item>com.android.systemui.media.RingtonePlayer</item>
        <item>com.android.systemui.keyboard.KeyboardUI</item>
        <item>com.android.systemui.pip.PipUI</item>
        <item>com.android.systemui.shortcut.ShortcutKeyDispatcher</item>
        <item>@string/config_systemUIVendorServiceComponent</item>
        <item>com.android.systemui.util.leak.GarbageMonitor$Service</item>
        <item>com.android.systemui.LatencyTester</item>
        <item>com.android.systemui.globalactions.GlobalActionsComponent</item>
        <item>com.android.systemui.ScreenDecorations</item>
        <item>com.android.systemui.biometrics.BiometricDialogImpl</item>
        <item>com.android.systemui.SliceBroadcastRelayHandler</item>
        <item>com.android.systemui.SizeCompatModeActivityController</item>
        <item>com.android.systemui.statusbar.notification.InstantAppNotifier</item>
        <item>com.android.systemui.theme.ThemeOverlayController</item>
    </string-array>
      /**
     * Makes sure that all the SystemUI services are running. If they are already running, this is a
     * no-op. This is needed to conditinally start all the services, as we only need to have it in
     * the main process.
     * <p>This method must only be called from the main thread.</p>
     */
    public void startServicesIfNeeded() {
        String[] names = SystemUIFactory.getInstance().getSystemUIServiceComponents(getResources());
        startServicesIfNeeded(/* metricsPrefix= */ "StartServices", names);
    }
   SystemUIFactorygetSystemUIServiceComponents(Resources resources)
   public String[] getSystemUIServiceComponents(Resources resources) {
          return resources.getStringArray(R.array.config_systemUIServiceComponents);
     }
   private void startServicesIfNeeded(String[] services) {
        if (mServicesStarted) {
            return;
        }
        mServices = new SystemUI[services.length];
 
        if (!mBootCompleted) {
            // check to see if maybe it was already completed long before we began
            // see ActivityManagerService.finishBooting()
            if ("1".equals(SystemProperties.get("sys.boot_completed"))) {
                mBootCompleted = true;
                if (DEBUG) Log.v(TAG, "BOOT_COMPLETED was already sent");
            }
        }
 
        Log.v(TAG, "Starting SystemUI services for user " +
                Process.myUserHandle().getIdentifier() + ".");
        TimingsTraceLog log = new TimingsTraceLog("SystemUIBootTiming",
                Trace.TRACE_TAG_APP);
        log.traceBegin("StartServices");
        final int N = services.length;
        for (int i = 0; i < N; i++) {
            String clsName = services[i];
            if (DEBUG) Log.d(TAG, "loading: " + clsName);
            log.traceBegin("StartServices" + clsName);
            long ti = System.currentTimeMillis();
            Class cls;
            try {
                cls = Class.forName(clsName);
                Object o = cls.newInstance();
                if (o instanceof SystemUI.Injector) {
                    o = ((SystemUI.Injector) o).apply(this);
                }
                mServices[i] = (SystemUI) o;
            } catch(ClassNotFoundException ex){
                throw new RuntimeException(ex);
            } catch (IllegalAccessException ex) {
                throw new RuntimeException(ex);
            } catch (InstantiationException ex) {
                throw new RuntimeException(ex);
            }
 
            mServices[i].mContext = this;
            mServices[i].mComponents = mComponents;
            if (DEBUG) Log.d(TAG, "running: " + mServices[i]);
            mServices[i].start();
            log.traceEnd();
 
            // Warn if initialization of component takes too long
            ti = System.currentTimeMillis() - ti;
            if (ti > 1000) {
                Log.w(TAG, "Initialization of " + cls.getName() + " took " + ti + " ms");
            }
            if (mBootCompleted) {
                mServices[i].onBootCompleted();
            }
        }
        Dependency.get(InitController.class).executePostInitTasks();
        log.traceEnd();
        final Handler mainHandler = new Handler(Looper.getMainLooper());
        Dependency.get(PluginManager.class).addPluginListener(
                new PluginListener<OverlayPlugin>() {
                    private ArraySet<OverlayPlugin> mOverlays = new ArraySet<>();
 
                    @Override
                    public void onPluginConnected(OverlayPlugin plugin, Context pluginContext) {
                        mainHandler.post(new Runnable() {
                            @Override
                            public void run() {
                                StatusBar statusBar = getComponent(StatusBar.class);
                                if (statusBar != null) {
                                    plugin.setup(statusBar.getStatusBarWindow(),
                                            statusBar.getNavigationBarView(), new Callback(plugin));
                                }
                            }
                        });
                    }
 
                    @Override
                    public void onPluginDisconnected(OverlayPlugin plugin) {
                        mainHandler.post(new Runnable() {
                            @Override
                            public void run() {
                                mOverlays.remove(plugin);
                                Dependency.get(StatusBarWindowController.class).setForcePluginOpen(
                                        mOverlays.size() != 0);
                            }
                        });
                    }
 
                    class Callback implements OverlayPlugin.Callback {
                        private final OverlayPlugin mPlugin;
 
                        Callback(OverlayPlugin plugin) {
                            mPlugin = plugin;
                        }
 
                        @Override
                        public void onHoldStatusBarOpenChange() {
                            if (mPlugin.holdStatusBarOpen()) {
                                mOverlays.add(mPlugin);
                            } else {
                                mOverlays.remove(mPlugin);
                            }
                            mainHandler.post(new Runnable() {
                                @Override
                                public void run() {
                                    Dependency.get(StatusBarWindowController.class)
                                            .setStateListener(b -> mOverlays.forEach(
                                                    o -> o.setCollapseDesired(b)));
                                    Dependency.get(StatusBarWindowController.class)
                                            .setForcePluginOpen(mOverlays.size() != 0);
                                }
                            });
                        }
                    }
                }, OverlayPlugin.class, true /* Allow multiple plugins */);
 
        mServicesStarted = true;
    }

2、PowerUI 电量的分析

public void start() {
mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
mScreenOffTime = mPowerManager.isScreenOn() ? -1 : SystemClock.elapsedRealtime();
mWarnings = Dependency.get(WarningsUI.class);
mEnhancedEstimates = Dependency.get(EnhancedEstimates.class);
mLastConfiguration.setTo(mContext.getResources().getConfiguration());
 
ContentObserver obs = new ContentObserver(mHandler) {
@Override
public void onChange(boolean selfChange) {
updateBatteryWarningLevels();
}
};
final ContentResolver resolver = mContext.getContentResolver();
resolver.registerContentObserver(Settings.Global.getUriFor(
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL),
false, obs, UserHandle.USER_ALL);
updateBatteryWarningLevels();
mReceiver.init();
 
// Check to see if we need to let the user know that the phone previously shut down due
// to the temperature being too high.
showWarnOnThermalShutdown();
 
// Register an observer to configure mEnableSkinTemperatureWarning and perform the
// registration of skin thermal event listener upon Settings change.
resolver.registerContentObserver(
Settings.Global.getUriFor(Settings.Global.SHOW_TEMPERATURE_WARNING),
false /*notifyForDescendants*/,
new ContentObserver(mHandler) {
@Override
public void onChange(boolean selfChange) {
doSkinThermalEventListenerRegistration();
}
});
// Register an observer to configure mEnableUsbTemperatureAlarm and perform the
// registration of usb thermal event listener upon Settings change.
resolver.registerContentObserver(
Settings.Global.getUriFor(Settings.Global.SHOW_USB_TEMPERATURE_ALARM),
false /*notifyForDescendants*/,
new ContentObserver(mHandler) {
@Override
public void onChange(boolean selfChange) {
doUsbThermalEventListenerRegistration();
}
});
initThermalEventListeners();
mCommandQueue.addCallback(this);
}
 
@VisibleForTesting
final class Receiver extends BroadcastReceiver {
 
private boolean mHasReceivedBattery = false;
 
public void init() {
// Register for Intent broadcasts for...
IntentFilter filter = new IntentFilter();
filter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
filter.addAction(Intent.ACTION_BATTERY_CHANGED);
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_USER_SWITCHED);
mBroadcastDispatcher.registerReceiverWithHandler(this, filter, mHandler);
// Force get initial values. Relying on Sticky behavior until API for getting info.
if (!mHasReceivedBattery) {
// Get initial state
Intent intent = mContext.registerReceiver(
null,
new IntentFilter(Intent.ACTION_BATTERY_CHANGED)
);
if (intent != null) {
onReceive(mContext, intent);
}
}
}
 
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (PowerManager.ACTION_POWER_SAVE_MODE_CHANGED.equals(action)) {
ThreadUtils.postOnBackgroundThread(() -> {
if (mPowerManager.isPowerSaveMode()) {
mWarnings.dismissLowBatteryWarning();
}
});
} else if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
mHasReceivedBattery = true;
final int oldBatteryLevel = mBatteryLevel;
mBatteryLevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 100);
final int oldBatteryStatus = mBatteryStatus;
mBatteryStatus = intent.getIntExtra(BatteryManager.EXTRA_STATUS,
BatteryManager.BATTERY_STATUS_UNKNOWN);
final int oldPlugType = mPlugType;
mPlugType = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 1);
final int oldInvalidCharger = mInvalidCharger;
mInvalidCharger = intent.getIntExtra(BatteryManager.EXTRA_INVALID_CHARGER, 0);
mLastBatteryStateSnapshot = mCurrentBatteryStateSnapshot;
 
final boolean plugged = mPlugType != 0;
final boolean oldPlugged = oldPlugType != 0;
 
int oldBucket = findBatteryLevelBucket(oldBatteryLevel);
int bucket = findBatteryLevelBucket(mBatteryLevel);
 
if (DEBUG) {
Slog.d(TAG, "buckets   ....." + mLowBatteryAlertCloseLevel
+ " .. " + mLowBatteryReminderLevels[0]
+ " .. " + mLowBatteryReminderLevels[1]);
Slog.d(TAG, "level          " + oldBatteryLevel + " --> " + mBatteryLevel);
Slog.d(TAG, "status         " + oldBatteryStatus + " --> " + mBatteryStatus);
Slog.d(TAG, "plugType       " + oldPlugType + " --> " + mPlugType);
Slog.d(TAG, "invalidCharger " + oldInvalidCharger + " --> " + mInvalidCharger);
Slog.d(TAG, "bucket         " + oldBucket + " --> " + bucket);
Slog.d(TAG, "plugged        " + oldPlugged + " --> " + plugged);
}
 
mWarnings.update(mBatteryLevel, bucket, mScreenOffTime);
if (oldInvalidCharger == 0 && mInvalidCharger != 0) {
Slog.d(TAG, "showing invalid charger warning");
mWarnings.showInvalidChargerWarning();
return;
} else if (oldInvalidCharger != 0 && mInvalidCharger == 0) {
mWarnings.dismissInvalidChargerWarning();
} else if (mWarnings.isInvalidChargerWarningShowing()) {
// if invalid charger is showing, don't show low battery
if (DEBUG) {
Slog.d(TAG, "Bad Charger");
}
return;
}
// Show the correct version of low battery warning if needed
if (mLastShowWarningTask != null) {
mLastShowWarningTask.cancel(true);
if (DEBUG) {
Slog.d(TAG, "cancelled task");
}
}
//
mLastShowWarningTask = ThreadUtils.postOnBackgroundThread(() -> {
maybeShowBatteryWarningV2(
plugged, bucket);
});
} else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
mScreenOffTime = SystemClock.elapsedRealtime();
} else if (Intent.ACTION_SCREEN_ON.equals(action)) {
mScreenOffTime = -1;
} else if (Intent.ACTION_USER_SWITCHED.equals(action)) {
mWarnings.userSwitched();
} else {
Slog.w(TAG, "unknown intent: " + intent);
}
}
}PowerUIstart()方法中启动广播监听电量变化
mLastShowWarningTask = ThreadUtils.postOnBackgroundThread(() -> {
maybeShowBatteryWarningV2(
plugged, bucket);
});
来判断是否开启低电量警告
protected void maybeShowBatteryWarningV2(boolean plugged, int bucket) {
final boolean hybridEnabled = mEnhancedEstimates.isHybridNotificationEnabled();
final boolean isPowerSaverMode = mPowerManager.isPowerSaveMode();
// Stick current battery state into an immutable container to determine if we should show
// a warning.
if (DEBUG) {
Slog.d(TAG, "evaluating which notification to show");
}
if (hybridEnabled) {
if (DEBUG) {
Slog.d(TAG, "using hybrid");
}
Estimate estimate = refreshEstimateIfNeeded();
mCurrentBatteryStateSnapshot = new BatteryStateSnapshot(mBatteryLevel, isPowerSaverMode,
plugged, bucket, mBatteryStatus, mLowBatteryReminderLevels[1],
mLowBatteryReminderLevels[0], estimate.getEstimateMillis(),
estimate.getAverageDischargeTime(),
mEnhancedEstimates.getSevereWarningThreshold(),
mEnhancedEstimates.getLowWarningThreshold(), estimate.isBasedOnUsage(),
mEnhancedEstimates.getLowWarningEnabled());
} else {
if (DEBUG) {
Slog.d(TAG, "using standard");
}
mCurrentBatteryStateSnapshot = new BatteryStateSnapshot(mBatteryLevel, isPowerSaverMode,
plugged, bucket, mBatteryStatus, mLowBatteryReminderLevels[1],
mLowBatteryReminderLevels[0]);
}
mWarnings.updateSnapshot(mCurrentBatteryStateSnapshot);
if (mCurrentBatteryStateSnapshot.isHybrid()) {
maybeShowHybridWarning(mCurrentBatteryStateSnapshot, mLastBatteryStateSnapshot);
} else {
//低电量警告
maybeShowBatteryWarning(mCurrentBatteryStateSnapshot, mLastBatteryStateSnapshot);
}
protected void maybeShowBatteryWarning(
              BatteryStateSnapshot currentSnapshot,
             BatteryStateSnapshot lastSnapshot) {
         final boolean playSound = currentSnapshot.getBucket() != lastSnapshot.getBucket()
                  || lastSnapshot.getPlugged();
  
         if (shouldShowLowBatteryWarning(currentSnapshot, lastSnapshot)) {
              mWarnings.showLowBatteryWarning(playSound);//低电量警告
          } else if (shouldDismissLowBatteryWarning(currentSnapshot, lastSnapshot)) {
              mWarnings.dismissLowBatteryWarning();//去掉低电量警告
          } else {
              mWarnings.updateLowBatteryWarning();
          }
      }
  PowerNotificationWarnings.java的低电量提醒方法
       @Override
      public void showLowBatteryWarning(boolean playSound) {
          Slog.i(TAG,
                  "show low battery warning: level=" + mBatteryLevel
                         + " [" + mBucket + "] playSound=" + playSound);
          mPlaySound = playSound;
          mWarning = true;
          updateNotification();
      }
}

3、增加低电量的弹窗 PowerNotificationWarnings.java的showLowBatteryWarning()方法

import android.app.AlertDialog;
    import android.view.WindowManager;
    import android.content.DialogInterface;
    private AlertDialog mbatteryLowDialog = null;
      // 自定义电池温度Dialog弹窗
    private void batterylowDialog(String lowbattery) {
        mbatteryLowDialog = new AlertDialog(mContext);
        AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
        builder.setTitle(mContext.getResources().getString(
                com.android.internal.R.string.lowbatteryWarning));
        builder.setCancelable(false);
        builder.setMessage(lowbattery);
        builder.setIconAttribute(android.R.attr.alertDialogIcon);
        builder.setPositiveButton(com.android.internal.R.string.batteryLow111,
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                        dialog.cancel();
                        mbatteryLowDialog = null;
                    }
                });
        mbatteryLowDialog = builder.create();
        mbatteryLowDialog.getWindow().setType(
                WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
        if (mbatteryLowDialog != null&& !mbatteryLowDialog.isShowing()) {
            mbatteryLowDialog.show();
        }
 
    }
 
       @Override
      public void showLowBatteryWarning(boolean playSound) {
          Slog.i(TAG,
                  "show low battery warning: level=" + mBatteryLevel
                         + " [" + mBucket + "] playSound=" + playSound);
          mPlaySound = playSound;
          mWarning = true;
          updateNotification();
        + batterylowDialog("低电量")
      }

4、增加低电量提醒的xml资源

主要修改

frameworks/base/core/res/res/values/string.xml
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
    ... ...
    <!-- Shutdown if the battery temperature exceeds (this value * 0.1) Celsius. -->
    <string name="lowbatteryWarning">低电量提醒</integer>
    <!-- add code begin-->
    <string name="batteryLow111">111</integer>
    <!-- add code end-->
    ... ...
</resources>

5、在symbols 文件中添加对应java-symbol方便Framework代码引用code文章来源地址https://www.toymoban.com/news/detail-839966.html

在symbols文件中为全部string,int值注册,方便Framework层代码的引用。
frameworks/base/core/res/res/values/symbols.xml
 
<?xml version="1.0" encoding="utf-8"?>
<resources>
  <!-- Private symbols that we need to reference from framework code.  See
       frameworks/base/core/res/MakeJavaSymbols.sed for how to easily generate
       this.
 
       Can be referenced in java code as: com.android.internal.R.<type>.<name>
       and in layout xml as: "@*android:<type>/<name>"
  -->
 
  <!-- add code begin-->
  <java-symbol type="string" name="lowbatteryWarning" />
  <java-symbol type="string" name="batteryLow111" />

到了这里,关于Android 11 系统开发增加低电量弹窗提示 手机 平板 车载 TV 投影 通用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 关于在Android 11系统手机上请求READ_PHONE_STATE权限的问题

    起因是因为bugly报错: 上网查了下,原来在Android11及以上机型上调用telephonyManager.getNetworkType()需要READ_PHONE_STATE权限,于是我就在应用启动时加上了申请该权限的代码,并且在调用getNetworkType()方法的地方加了判断,如果系统版本大于等于11并且没有被授予READ_PHONE_STATE权限,就

    2024年02月12日
    浏览(49)
  • 【电量计芯片】鼎盛合分享手机电量显示电量芯片技术

    不知道有没有人会跟我一样曾经有手机电量焦虑症,电量没有满格出门一定会焦虑,电量低于三分之一就已经在想要不要充电了,而一旦电量颜色变黄以下我就不敢再玩手机,立即去充电。这种问题我相信肯定不是只有我一个人有,更有甚者看到手机电量的电量槽空了一截就

    2024年02月08日
    浏览(52)
  • APP安卓开发之Android Studio从安装到创建项目(一键解决gradle下载缓慢以及写代码没提示问题,包含如何创建手机模拟器)教程

    选择NEXT 选择NEXT 选择要安装的地址,然后选择NEXT 选择Install 先启动刚安装好的Android Studio 选择Do not import settings,然后选择OK 选择Cancel 先选择D\\\'ont send,然后选择NEXT 这里选择Custom,然后NEXT 选择Android Studio自带JDK的安装位置,然后NEXT 选择一个自己喜欢的主题颜色,然后NEXT 选

    2024年04月29日
    浏览(72)
  • Android11编译第六弹:user版本增加su+内置root用户

    问题1:user版本默认不开放root,adb登录后默认采用system用户,收紧用户权限; 问题2:因为有些功能需要用到root用户,例如设置网卡地址,网卡开启和关闭等,因为线上设备user版本没有root用户开放,很不方便。采用允许登录root用户的方式,登录时增加密码验证。 问题3:默

    2024年01月23日
    浏览(39)
  • 如何实现”系统可能不会保存您所做的更改”的弹窗提示

    在本文框输入内容,关闭页面或者刷新页面时会弹出提示“系统可能不会保存您所做的更改”: 谷歌浏览器效果: Safari浏览器效果:

    2024年02月07日
    浏览(48)
  • IOS手机耗电量测试

    1. 耗电量原始测试方法 1.1 方法原理: 根据iPhone手机右上角的电池百分比变化来计算耗电量。 1.2实际操作: 在iOS通用设置中打开电池百分比数值显示,然后操作30分钟,60分钟,90分钟,看开始时和结束时电池百分比数值的差值。 1.3 优缺点分析: 1、电池百分比数据非常粗略

    2024年02月06日
    浏览(47)
  • android多屏触摸相关的详解方案-安卓framework开发手机车载车机系统开发课程

    直播免费视频课程地址:https://www.bilibili.com/video/BV1hN4y1R7t2/ 在做双屏相关需求开发过程中,经常会有对两个屏幕都要求可以正确触摸的场景。但是目前我们模拟器默认创建的双屏其实是没有办法进行触摸的 静态修改方案 使用命令查看display2即副屏的信息情况 adb shell dumpsys d

    2024年02月11日
    浏览(51)
  • 华为主题开发分享-在windows 11操作系统上识别不到P50等华为手机的解决方案

    在开发华为手机主题时,我们都是采用Them studio进行实际测试,无它,官方工具的“同步”功能实在是好用。一键就能将主题推到手机上进行测试,高效方便。 但对于有的老款手机比如p50,在windows 11操作系统上,会遇到无法识别硬件的苦恼。 这里分享下解决方案。 1、首先,

    2024年02月12日
    浏览(89)
  • Android Framework最难模块WMS实战作业-手机车机系统开发必备

    0-整体介绍 1-window-container.mp4 窗口层级树实战启动篇 2-displayarea-feature.mp4 窗口层级树源码分析相关 3-displayarea-draw-feature.mp4 窗口层级树绘制实战1 4-displayarea-draw-leaf.mp4 窗口层级树绘制实战2 5-displayarea-draw-leaf-2.mp4 窗口层级树绘制实战3 6-displayarea-surfacelayer.mp4 窗口层级树相关sur

    2024年02月12日
    浏览(49)
  • hal深入剖析之aidl实战-android framework车机车载手机系统开发

    这个是hal工程根目录 接下来要创建aidl的文件存放目录 注意mkdir -p android/hardware/mytest其实就是包名目录,即模块包名就是android.hardware.mytest. 提示:这个如果为了项目的更加好的维护性建议到自己项目目标的vendor下面进行,目前只是为了演示方便,直接在system的hardware下面 创建

    2024年02月19日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包