安卓框架13-设置[08电池]
作者:访客发布时间:2023-11-16分类:程序开发学习浏览:111
导读:1.简介简单学习电池页面的数据获取,这里暂时就看下电量以及百分比下边的提示文字1.2.top_Level_settings.xml入口<com.android.set...
1.简介
简单学习电池页面的数据获取,这里暂时就看下电量以及百分比下边的提示文字
1.2.top_Level_settings.xml
入口
<com.android.settings.widget.HomepagePreference
android:fragment="com.android.settings.fuelgauge.batteryusage.PowerUsageSummary"
android:icon="@drawable/ic_settings_battery_white"
android:key="top_level_battery"
android:order="-110"
android:title="@string/power_usage_summary_title"
android:summary="@string/summary_placeholder"
settings:highlightableMenuKey="@string/menu_key_battery"
settings:controller="com.android.settings.fuelgauge.TopLevelBatteryPreferenceController"/>
2.PowerUsageSummary.java
public class PowerUsageSummary extends PowerUsageBase implements
BatteryTipPreferenceController.BatteryTipListener {
2.1.POWER_USAGE_SUMMARTY.xml
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:key="power_usage_summary_screen"
android:title="@string/power_usage_summary_title"
settings:keywords="@string/keywords_battery">
<!--进度条-->
<com.android.settingslib.widget.UsageProgressBarPreference
android:key="battery_header"
android:title="@string/summary_placeholder"
android:selectable="false"
settings:controller="com.android.settings.fuelgauge.BatteryHeaderPreferenceController" />
<!--帮助消息,电池不可用的时候才可见-->
<com.android.settingslib.widget.LayoutPreference
android:key="battery_help_message"
android:layout="@layout/preference_battery_error"
android:selectable="false"
settings:searchable="false" />
<!--提示-->
<com.android.settings.widget.CardPreference
android:key="battery_tip"
android:title="@string/summary_placeholder"
settings:controller="com.android.settings.fuelgauge.batterytip.BatteryTipPreferenceController" />
<!--电量使用情况-->
<Preference
android:fragment="com.android.settings.fuelgauge.batteryusage.PowerUsageAdvanced"
android:key="battery_usage_summary"
android:title="@string/advanced_battery_preference_title"
settings:keywords="@string/keywords_battery_usage" />
<!--省点模式设置-->
<Preference
android:fragment="com.android.settings.fuelgauge.batterysaver.BatterySaverSettings"
android:key="battery_saver_summary"
android:title="@string/battery_saver"
settings:keywords="@string/keywords_battery_saver"
settings:controller="com.android.settings.fuelgauge.BatterySaverController" />
<!--电池管理-->
<Preference
android:fragment="com.android.settings.fuelgauge.SmartBatterySettings"
android:key="smart_battery_manager"
android:title="@string/smart_battery_manager_title"
settings:controller="com.android.settings.fuelgauge.batterytip.BatteryManagerPreferenceController"
settings:keywords="@string/keywords_battery_adaptive_preferences" />
<!--是否显示百分比-->
<SwitchPreference
android:key="battery_percentage"
android:title="@string/battery_percentage"
android:summary="@string/battery_percentage_description"
settings:controller="com.android.settings.display.BatteryPercentagePreferenceController" />
<!--底部的提示-->
<com.android.settingslib.widget.FooterPreference
android:key="power_usage_footer"
android:title="@string/battery_footer_summary"
android:selectable="false"
settings:searchable="false" />
</PreferenceScreen>
2.BATTERY_ESTIMATS_LAST_UPDATE_TIME
final ContentObserver mSettingsObserver = new ContentObserver(new Handler()) {
@Override
public void onChange(boolean selfChange, Uri uri) {
restartBatteryInfoLoader();
}
};
@Override
public void onResume() {
super.onResume();
getContentResolver().registerContentObserver(
Global.getUriFor(Global.BATTERY_ESTIMATES_LAST_UPDATE_TIME),
false,
mSettingsObserver);
}
@Override
public void onPause() {
getContentResolver().unregisterContentObserver(mSettingsObserver);
super.onPause();
}
2.3.mBatteryInfoLoaderCallbacks
加载电池信息的任务回调
LoaderManager.LoaderCallbacks<BatteryInfo> mBatteryInfoLoaderCallbacks =
new LoaderManager.LoaderCallbacks<BatteryInfo>() {
@Override
public Loader<BatteryInfo> onCreateLoader(int i, Bundle bundle) {
//这个就是执行任务的对象
return new BatteryInfoLoader(getContext());
}
@Override
public void onLoadFinished(Loader<BatteryInfo> loader, BatteryInfo batteryInfo) {
//更新数据
mBatteryHeaderPreferenceController.updateHeaderPreference(batteryInfo);
mBatteryHeaderPreferenceController.updateHeaderByBatteryTips(
mBatteryTipPreferenceController.getCurrentBatteryTip(), batteryInfo);
mBatteryInfo = batteryInfo;
}
@Override
public void onLoaderReset(Loader<BatteryInfo> loader) {
// do nothing
}
};
>;BatteryInfoLoader
public BatteryInfoLoader(Context context) {
super(context);
mBatteryUtils = BatteryUtils.getInstance(context);
}
public BatteryInfo loadInBackground() {
//具体见5.1
return mBatteryUtils.getBatteryInfo(LOG_TAG);
}
2.4.mBatteryTipsCallbacks
加载TIP的任务回调
private LoaderManager.LoaderCallbacks<List<BatteryTip>> mBatteryTipsCallbacks =
new LoaderManager.LoaderCallbacks<List<BatteryTip>>() {
@Override
public Loader<List<BatteryTip>> onCreateLoader(int id, Bundle args) {
return new BatteryTipLoader(getContext(), mBatteryUsageStats);
}
@Override
public void onLoadFinished(Loader<List<BatteryTip>> loader,
List<BatteryTip> data) {
mBatteryTipPreferenceController.updateBatteryTips(data);
mBatteryHeaderPreferenceController.updateHeaderByBatteryTips(
mBatteryTipPreferenceController.getCurrentBatteryTip(), mBatteryInfo);
}
@Override
public void onLoaderReset(Loader<List<BatteryTip>> loader) {
}
};
>;BatteryTipLoader
public BatteryTipLoader(Context context, BatteryUsageStats batteryUsageStats) {
super(context);
mBatteryUsageStats = batteryUsageStats;
mBatteryUtils = BatteryUtils.getInstance(context);
}
@Override
public List<BatteryTip> loadInBackground() {
if (USE_FAKE_DATA) {
return getFakeData();
}
final List<BatteryTip> tips = new ArrayList<>();
//这个里边读取了一堆变量,下边6种Detector里用
final BatteryTipPolicy policy = new BatteryTipPolicy(getContext());
//同样先获取电池info
final BatteryInfo batteryInfo = mBatteryUtils.getBatteryInfo(TAG);
final Context context = getContext();
//添加6种tip
tips.add(new LowBatteryDetector(context, policy, batteryInfo).detect());
tips.add(new HighUsageDetector(context, policy, mBatteryUsageStats, batteryInfo).detect());
tips.add(new SmartBatteryDetector(
context, policy, batteryInfo, context.getContentResolver()).detect());
tips.add(new EarlyWarningDetector(policy, context).detect());
tips.add(new BatteryDefenderDetector(
batteryInfo, context.getApplicationContext()).detect());
tips.add(new DockDefenderDetector(batteryInfo, context.getApplicationContext()).detect());
Collections.sort(tips);
return tips;
}
2.5.onAttach
电量以及TIP用到的控制器
public void onAttach(Context context) {
super.onAttach(context);
final SettingsActivity activity = (SettingsActivity) getActivity();
mBatteryHeaderPreferenceController = use(BatteryHeaderPreferenceController.class);
mBatteryHeaderPreferenceController.setActivity(activity);
mBatteryHeaderPreferenceController.setFragment(this);
mBatteryHeaderPreferenceController.setLifecycle(getSettingsLifecycle());
mBatteryTipPreferenceController = use(BatteryTipPreferenceController.class);
mBatteryTipPreferenceController.setActivity(activity);
mBatteryTipPreferenceController.setFragment(this);
mBatteryTipPreferenceController.setBatteryTipListener(this::onBatteryTipHandled);
}
2.6.BatteryTipPreferenceController
>;显示首选项
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mPrefContext = screen.getContext();
mCardPreference = screen.findPreference(getPreferenceKey());
//默认还没有tips,先不可见
mCardPreference.setVisible(false);
}
>;更新电池提示
public void updateBatteryTips(List<BatteryTip> batteryTips) {
if (batteryTips == null) {
return;
}
if (mBatteryTips == null) {
mBatteryTips = batteryTips;
} else {
//有旧数据就直接更新旧数据即可
// mBatteryTips and batteryTips always have the same length and same sequence.
for (int i = 0, size = batteryTips.size(); i < size; i++) {
mBatteryTips.get(i).updateState(batteryTips.get(i));
}
}
//不可见
mCardPreference.setVisible(false);
for (int i = 0, size = batteryTips.size(); i < size; i++) {
final BatteryTip batteryTip = mBatteryTips.get(i);
batteryTip.validateCheck(mContext);
if (batteryTip.getState() != BatteryTip.StateType.INVISIBLE) {
//有状态是非不可见的,那么card可见,后边直接break了,可见只处理第一条数据
mCardPreference.setVisible(true);
//更新数据,见7.3
batteryTip.updatePreference(mCardPreference);
mBatteryTipMap.put(mCardPreference.getKey(), batteryTip);
batteryTip.log(mContext, mMetricsFeatureProvider);
mNeedUpdate = batteryTip.needUpdate();
break;
}
}
}
3.PowerUsageBase
这个基类的核心就是注册了一个监听电池改变的广播
public abstract class PowerUsageBase extends DashboardFragment {
定义几个任务加载器用的索引
public @interface LoaderIndex {
int BATTERY_USAGE_STATS_LOADER = 0;
int BATTERY_INFO_LOADER = 1;
int BATTERY_TIP_LOADER = 2;
int BATTERY_HISTORY_LOADER = 3;
}
3.1.BatteryBroadcastReceiver
广播的监听,注册逻辑
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
mBatteryBroadcastReceiver = new BatteryBroadcastReceiver(getContext());
mBatteryBroadcastReceiver.setBatteryChangedListener(type -> {
if (type == BatteryBroadcastReceiver.BatteryUpdateType.BATTERY_NOT_PRESENT) {
mIsBatteryPresent = false;
}
restartBatteryStatsLoader(type);
});
}
@Override
public void onStart() {
super.onStart();
mBatteryBroadcastReceiver.register();
}
@Override
public void onStop() {
super.onStop();
mBatteryBroadcastReceiver.unRegister();
closeBatteryUsageStatsIfNeeded();
}
3.2.restartBatteryStatsLoader
电池状态变化,重新获取数据
protected void restartBatteryStatsLoader(int refreshType) {
final Bundle bundle = new Bundle();
bundle.putInt(KEY_REFRESH_TYPE, refreshType);
getLoaderManager().restartLoader(0, bundle, new PowerLoaderCallback());
}
3.3.PowerLoaderCallback
/**
* {@link android.app.LoaderManager.LoaderCallbacks} for {@link PowerUsageBase} to load
* the {@link BatteryStatsHelper}
*/
public class PowerLoaderCallback implements LoaderManager.LoaderCallbacks<BatteryStatsHelper> {
private int mRefreshType;
@Override
public Loader<BatteryStatsHelper> onCreateLoader(int id,
Bundle args) {
mRefreshType = args.getInt(KEY_REFRESH_TYPE);
return new BatteryStatsHelperLoader(getContext());
}
@Override
public void onLoadFinished(Loader<BatteryStatsHelper> loader,
BatteryStatsHelper statsHelper) {
mStatsHelper = statsHelper;
refreshUi(mRefreshType);
}
@Override
public void onLoaderReset(Loader<BatteryStatsHelper> loader) {
}
}
4.BatteryBroadcastReceiver.java
4.1.注册/注销
可以看到有3个行动,电池状态,省电模式,底座模式?
@Override
public void onReceive(Context context, Intent intent) {
//监听action的变化
updateBatteryStatus(intent, false /* forceUpdate */);
}
public void setBatteryChangedListener(OnBatteryChangedListener lsn) {
mBatteryListener = lsn;
}
public void register() {
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
intentFilter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
intentFilter.addAction(BatteryUtils.BYPASS_DOCK_DEFENDER_ACTION);
final Intent intent = mContext.registerReceiver(this, intentFilter);
//注册的时候强制更新数据
updateBatteryStatus(intent, true /* forceUpdate */);
}
public void unRegister() {
mContext.unregisterReceiver(this);
}
4.2.updateBatteryStatus
private void updateBatteryStatus(Intent intent, boolean forceUpdate) {
if (intent != null && mBatteryListener != null) {
if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {
final String batteryLevel = Utils.getBatteryPercentage(intent);
final String batteryStatus =
Utils.getBatteryStatus(mContext, intent, /* compactStatus= */ false);
final int batteryHealth = intent.getIntExtra(
BatteryManager.EXTRA_HEALTH, BatteryManager.BATTERY_HEALTH_UNKNOWN);
if (!Utils.isBatteryPresent(intent)) {
Log.w(TAG, "Problem reading the battery meter.");
//电池异常
mBatteryListener.onBatteryChanged(BatteryUpdateType.BATTERY_NOT_PRESENT);
} else if (forceUpdate) {
//强制更新
mBatteryListener.onBatteryChanged(BatteryUpdateType.MANUAL);
} else if (batteryHealth != mBatteryHealth) {
//健康状态变化
mBatteryListener.onBatteryChanged(BatteryUpdateType.BATTERY_HEALTH);
} else if(!batteryLevel.equals(mBatteryLevel)) {
//电量变化
mBatteryListener.onBatteryChanged(BatteryUpdateType.BATTERY_LEVEL);
} else if (!batteryStatus.equals(mBatteryStatus)) {
//电池状态变化
mBatteryListener.onBatteryChanged(BatteryUpdateType.BATTERY_STATUS);
}
mBatteryLevel = batteryLevel;
mBatteryStatus = batteryStatus;
mBatteryHealth = batteryHealth;
} else if (PowerManager.ACTION_POWER_SAVE_MODE_CHANGED.equals(intent.getAction())) {
mBatteryListener.onBatteryChanged(BatteryUpdateType.BATTERY_SAVER);
//省点模式变化
} else if (BatteryUtils.BYPASS_DOCK_DEFENDER_ACTION.equals(intent.getAction())) {
mBatteryListener.onBatteryChanged(BatteryUpdateType.BATTERY_STATUS);
}
}
}
4.3.Utils.java
Packages/apps/Settings/src/com/android/settings/Utils.java这个类在
public final class Utils extends com.android.settingslib.Utils {
Frameworks/base/packages/SettingsLib/src/com/android/settingslib/Utils.java父类在
>;获取电池百分比
public static String getBatteryPercentage(Intent batteryChangedIntent) {
return formatPercentage(getBatteryLevel(batteryChangedIntent));
}
父类里
/** Formats an integer from 0..100 as a percentage. */
public static String formatPercentage(int percentage) {
return formatPercentage(((double) percentage) / 100.0);
}
/** Formats a double from 0.0..1.0 as a percentage. */
public static String formatPercentage(double percentage) {
return NumberFormat.getPercentInstance().format(percentage);
}
public static int getBatteryLevel(Intent batteryChangedIntent) {
int level = batteryChangedIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
int scale = batteryChangedIntent.getIntExtra(BatteryManager.EXTRA_SCALE, 100);
return (level * 100) / scale;
}
>;获取电池状态
根据充电状态返回对应的字符串,比如充电中,无线充电中
public static String getBatteryStatus(Context context, Intent batteryChangedIntent,
boolean compactStatus) {
final int status = batteryChangedIntent.getIntExtra(BatteryManager.EXTRA_STATUS,
BatteryManager.BATTERY_STATUS_UNKNOWN);
final Resources res = context.getResources();
String statusString = res.getString(R.string.battery_info_status_unknown);
final BatteryStatus batteryStatus = new BatteryStatus(batteryChangedIntent);
if (batteryStatus.isCharged()) {
statusString = res.getString(compactStatus
? R.string.battery_info_status_full_charged
: R.string.battery_info_status_full);
} else {
if (status == BatteryManager.BATTERY_STATUS_CHARGING) {
if (compactStatus) {
statusString = res.getString(R.string.battery_info_status_charging);
} else if (batteryStatus.isPluggedInWired()) {
switch (batteryStatus.getChargingSpeed(context)) {
case BatteryStatus.CHARGING_FAST:
statusString = res.getString(
R.string.battery_info_status_charging_fast);
break;
case BatteryStatus.CHARGING_SLOWLY:
statusString = res.getString(
R.string.battery_info_status_charging_slow);
break;
default:
statusString = res.getString(R.string.battery_info_status_charging);
break;
}
} else {
statusString = res.getString(R.string.battery_info_status_charging_wireless);
}
} else if (status == BatteryManager.BATTERY_STATUS_DISCHARGING) {
statusString = res.getString(R.string.battery_info_status_discharging);
} else if (status == BatteryManager.BATTERY_STATUS_NOT_CHARGING) {
statusString = res.getString(R.string.battery_info_status_not_charging);
}
}
return statusString;
}
>;isBatteryPresent
public static boolean isBatteryPresent(Intent batteryChangedIntent) {
return batteryChangedIntent.getBooleanExtra(BatteryManager.EXTRA_PRESENT, true);
}
5.BatteryUtils.java
5.1.getBatteryInfo
public BatteryInfo getBatteryInfo(final String tag) {
final BatteryStatsManager systemService = mContext.getSystemService(
BatteryStatsManager.class);
BatteryUsageStats batteryUsageStats;
try {
batteryUsageStats = systemService.getBatteryUsageStats(
new BatteryUsageStatsQuery.Builder().includeBatteryHistory().build());
} catch (RuntimeException e) {
Log.e(TAG, "getBatteryInfo() error from getBatteryUsageStats()", e);
// Use default BatteryUsageStats.
batteryUsageStats = new BatteryUsageStats.Builder(new String[0]).build();
}
final long startTime = System.currentTimeMillis();
//这个广播是个粘性广播,所以可以直接获取旧的数据
final Intent batteryBroadcast = mContext.registerReceiver(null,
new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
final long elapsedRealtimeUs = PowerUtil.convertMsToUs(
SystemClock.elapsedRealtime());
BatteryInfo batteryInfo;
Estimate estimate = getEnhancedEstimate();
// couldn't get estimate from cache or provider, use fallback
if (estimate == null) {
estimate = new Estimate(
batteryUsageStats.getBatteryTimeRemainingMs(),
false /* isBasedOnUsage */,
EstimateKt.AVERAGE_TIME_TO_DISCHARGE_UNKNOWN);
}
//这里把intent传进去,读取数据生成一个对象返回,见6.1
batteryInfo = BatteryInfo.getBatteryInfo(mContext, batteryBroadcast,
batteryUsageStats, estimate, elapsedRealtimeUs, false /* shortString */);
try {
batteryUsageStats.close();
} catch (Exception e) {
}
return batteryInfo;
}
6.BatteryInfo.java
6.1.getBatteryInfo
public static BatteryInfo getBatteryInfo(Context context, Intent batteryBroadcast,
@NonNull BatteryUsageStats batteryUsageStats, Estimate estimate,
long elapsedRealtimeUs, boolean shortString) {
final long startTime = System.currentTimeMillis();
final boolean isCompactStatus = context.getResources().getBoolean(
com.android.settings.R.bool.config_use_compact_battery_status);
BatteryInfo info = new BatteryInfo();
info.mBatteryUsageStats = batteryUsageStats;
info.batteryLevel = Utils.getBatteryLevel(batteryBroadcast);
info.batteryPercentString = Utils.formatPercentage(info.batteryLevel);
info.pluggedStatus = batteryBroadcast.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0);
info.mCharging = info.pluggedStatus != 0;
info.averageTimeToDischarge = estimate.getAverageDischargeTime();
info.isOverheated = batteryBroadcast.getIntExtra(
BatteryManager.EXTRA_HEALTH, BatteryManager.BATTERY_HEALTH_UNKNOWN)
== BatteryManager.BATTERY_HEALTH_OVERHEAT;
info.statusLabel = Utils.getBatteryStatus(context, batteryBroadcast, isCompactStatus);
info.batteryStatus = batteryBroadcast.getIntExtra(
BatteryManager.EXTRA_STATUS, BatteryManager.BATTERY_STATUS_UNKNOWN);
if (!info.mCharging) {
updateBatteryInfoDischarging(context, shortString, estimate, info);
} else {
updateBatteryInfoCharging(context, batteryBroadcast, batteryUsageStats,
info, isCompactStatus);
}
BatteryUtils.logRuntime(LOG_TAG, "time for getBatteryInfo", startTime);
return info;
}
7.BatteryTip
7.1.变量
有4个变量
private static final String KEY_PREFIX = "key_battery_tip";
protected int mType;
protected int mState;
protected boolean mShowDialog;
/**
* Whether we need to update battery tip when configuration change
*/
protected boolean mNeedUpdate;
7.2.type|状态
//状态3种:新的,已处理的,不可见的
@Retention(RetentionPolicy.SOURCE)
@IntDef({StateType.NEW,
StateType.HANDLED,
StateType.INVISIBLE})
public @interface StateType {
int NEW = 0;
int HANDLED = 1;
int INVISIBLE = 2;
}
//类型有10种
@Retention(RetentionPolicy.SOURCE)
@IntDef({TipType.SUMMARY,
TipType.BATTERY_SAVER,
TipType.HIGH_DEVICE_USAGE,
TipType.SMART_BATTERY_MANAGER,
TipType.APP_RESTRICTION,
TipType.REDUCED_BATTERY,
TipType.LOW_BATTERY,
TipType.REMOVE_APP_RESTRICTION,
TipType.BATTERY_DEFENDER,
TipType.DOCK_DEFENDER})
7.3.updatePreference
public void updatePreference(Preference preference) {
final Context context = preference.getContext();
preference.setTitle(getTitle(context));
preference.setSummary(getSummary(context));
preference.setIcon(getIconId());
@IdRes int iconTintColorId = getIconTintColorId();
if (iconTintColorId != View.NO_ID) {
preference.getIcon().setTint(context.getColor(iconTintColorId));
}
}
下边4个方法是抽象的,不同的TIP自己实现
public abstract CharSequence getTitle(Context context);
public abstract CharSequence getSummary(Context context);
@IdRes
public abstract int getIconId();
public abstract void updateState(BatteryTip tip);
7.4.compareTo
根据定义的类型对应的顺序来排序的。
public int compareTo(BatteryTip o) {
return TIP_ORDER.get(mType) - TIP_ORDER.get(o.mType);
}
下边就是类型的顺序
static {
TIP_ORDER = new SparseIntArray();
TIP_ORDER.append(TipType.BATTERY_SAVER, 0);
TIP_ORDER.append(TipType.LOW_BATTERY, 1);
TIP_ORDER.append(TipType.BATTERY_DEFENDER, 2);
TIP_ORDER.append(TipType.DOCK_DEFENDER, 3);
TIP_ORDER.append(TipType.APP_RESTRICTION, 4);
TIP_ORDER.append(TipType.HIGH_DEVICE_USAGE, 5);
TIP_ORDER.append(TipType.SUMMARY, 6);
TIP_ORDER.append(TipType.SMART_BATTERY_MANAGER, 7);
TIP_ORDER.append(TipType.REDUCED_BATTERY, 8);
TIP_ORDER.append(TipType.REMOVE_APP_RESTRICTION, 9);
}
8.总结
- 暂时就看了电量和对应的TIP2个控件
- 程序开发学习排行
-
- 1鸿蒙HarmonyOS:Web组件网页白屏检测
- 2HTTPS协议是安全传输,为啥还要再加密?
- 3HarmonyOS鸿蒙应用开发——数据持久化Preferences
- 4记解决MaterialButton背景颜色与设置值不同
- 5鸿蒙HarmonyOS实战-ArkUI组件(RelativeContainer)
- 6鸿蒙HarmonyOS实战-ArkUI组件(Stack)
- 7[Android][NDK][Cmake]一文搞懂Android项目中的Cmake
- 8Android广播如何解决Sending non-protected broadcast问题
- 9鸿蒙HarmonyOS实战-ArkUI组件(mediaquery)
- 最近发表
-
- WooCommerce最好的WordPress常用插件下载博客插件模块的相关产品
- 羊驼机器人最好的WordPress常用插件下载博客插件模块
- IP信息记录器最好的WordPress常用插件下载博客插件模块
- Linkly for WooCommerce最好的WordPress常用插件下载博客插件模块
- 元素聚合器Forms最好的WordPress常用插件下载博客插件模块
- Promaker Chat 最好的WordPress通用插件下载 博客插件模块
- 自动更新发布日期最好的WordPress常用插件下载博客插件模块
- WordPress官方最好的获取回复WordPress常用插件下载博客插件模块
- Img to rss最好的wordpress常用插件下载博客插件模块
- WPMozo为Elementor最好的WordPress常用插件下载博客插件模块添加精简版