android14 下新增导航栏/状态栏 显示开关功能

嵌入式开发板网络配置避坑

RK3576 Android14 有线网卡静态 IP 配置全攻略,附数据实操

  • 平板下用的导航栏是taskbar,back home recents 这些按钮不是居中是靠右,这个代码在launcher3里面。
  • 手机模式用的导航栏是NavitionBar,代码在SystemUi下
  • 源码里判断是否是平板模式,也就是isLargeScreen 都是看屏幕最小宽度是否大于600dp
  • 需求,平板设备,设置-显示里面新增 导航栏/状态栏 显示开关,动态隐藏/显示导航栏/状态栏

总共分几步进行

1.在设置界面里面新增导航栏/状态栏 显示开关,并按照设置发送广播

2.在launcher3里面关闭taskbar创建

3.在SystemUi下增加接收广播设置,按照广播带的参数,动态隐藏/显示导航栏/状态栏

下面具体说明修改点

1.设置界面里面新增导航栏/状态栏 显示开关,并按照设置发送广播

修改点

packages/apps/Settings

diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index 21fbb7b16c..472848dd4d 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -1002,6 +1002,8 @@
     <string name="color_mode_option_automatic" msgid="2281217686509980870">"自适应"</string>
     <string name="brightness" msgid="6216871641021779698">"亮度"</string>
     <string name="auto_brightness_title" msgid="4239324728760986697">"自适应亮度"</string>
+    <string name="show_navigate" >"显示导航栏"</string>
+    <string name="show_statusbar" >"显示状态栏"</string>
     <string name="auto_brightness_description" msgid="6807117118142381193">"系统会根据您的环境和活动自动调节屏幕亮度。您可以手动移动滑块,帮助“自适应亮度”功能了解您偏好的亮度。"</string>
     <string name="auto_brightness_summary_on" msgid="2748088951224387004">"已开启"</string>
     <string name="auto_brightness_summary_off" msgid="8077066192887677956">"已关闭"</string>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index f5399d0734..5fe0baf5c7 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -2383,6 +2383,8 @@
     <string name="brightness">Brightness level</string>
     <!-- Sound & display settings screen, setting option name to enable adaptive brightness [CHAR LIMIT=30] -->
     <string name="auto_brightness_title">Adaptive brightness</string>
+    <string name="show_navigate" >"Show navigate bar"</string>
+    <string name="show_statusbar" >"Show status bar"</string>
     <!-- Description about the feature adaptive brightness -->
     <string name="auto_brightness_description">Your screen brightness will automatically adjust to your environment and activities. You can move the slider manually to help adaptive brightness learn your preferences.</string>
     <!-- Setting option summary when adaptive brightness is on [CHAR LIMIT=NONE] -->
diff --git a/res/xml/display_settings.xml b/res/xml/display_settings.xml
old mode 100644
new mode 100755
index 7d60562637..fb9507a5f4
--- a/res/xml/display_settings.xml
+++ b/res/xml/display_settings.xml
@@ -66,6 +66,16 @@
     <PreferenceCategory
         android:title="@string/category_name_appearance">

+        <SwitchPreference
+            android:key="show_navigate"
+            android:title="@string/show_navigate"
+            settings:controller="com.android.settings.display.ShowNavigatePreferenceController" />
+
+        <SwitchPreference
+            android:key="show_statusbar"
+            android:title="@string/show_statusbar"
+            settings:controller="com.android.settings.display.ShowStatusBarPreferenceController" />
+
         <com.android.settings.display.darkmode.DarkModePreference
             android:key="dark_ui_mode"
             android:title="@string/dark_ui_mode"
diff --git a/src/com/android/settings/DisplaySettings.java b/src/com/android/settings/DisplaySettings.java
old mode 100644
new mode 100755
index 8c6b1b6be2..9ad4241427
--- a/src/com/android/settings/DisplaySettings.java
+++ b/src/com/android/settings/DisplaySettings.java
@@ -53,6 +53,8 @@ public class DisplaySettings extends DashboardFragment {

     //-----------------------rk code----------
     private static final String KET_HDMI_SETTINGS = "hdmi_settings";
+    private static final String KEY_SHOW_NAVIGATE = "show_navigate";
+    private static final String KEY_SHOW_STATUSBAR = "show_statusbar";
     private static final String KET_EYE_CARE_SETTING = "eye_care_setting";
     private static final String KET_EYE_CARE_GAIN_SETTING = "eye_care_gain";
     private static final String KET_EBOOK_MODE_SETTING = "ebook_mode_setting";
diff --git a/src/com/android/settings/display/ShowNavigatePreferenceController.java b/src/com/android/settings/display/ShowNavigatePreferenceController.java
new file mode 100755
index 0000000000..1dabde3f94
--- /dev/null
+++ b/src/com/android/settings/display/ShowNavigatePreferenceController.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+package com.android.settings.display;
+
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.text.TextUtils;
+
+import androidx.preference.Preference;
+
+import com.android.internal.view.RotationPolicy;
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settings.core.TogglePreferenceController;
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.OnPause;
+import com.android.settingslib.core.lifecycle.events.OnResume;
+import android.util.Log;
+import android.app.StatusBarManager;
+import android.provider.Settings;
+import android.content.Intent;
+import com.android.settings.R;
+
+public class ShowNavigatePreferenceController extends TogglePreferenceController implements
+        PreferenceControllerMixin, Preference.OnPreferenceChangeListener, LifecycleObserver,
+        OnResume, OnPause {
+
+    private final MetricsFeatureProvider mMetricsFeatureProvider;
+    StatusBarManager mStatusBarManager;
+    private Preference mPreference;
+    private RotationPolicy.RotationPolicyListener mRotationPolicyListener;
+
+    public ShowNavigatePreferenceController(Context context, String key) {
+        super(context, key);
+        mStatusBarManager = (StatusBarManager) context.getSystemService(Context.STATUS_BAR_SERVICE);
+//        statusBarManager.disable(StatusBarManager.DISABLE_EXPAND);
+        mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        mPreference = preference;
+        super.updateState(preference);
+    }
+
+    @Override
+    public void onResume() {
+        if (mRotationPolicyListener == null) {
+            mRotationPolicyListener = new RotationPolicy.RotationPolicyListener() {
+                @Override
+                public void onChange() {
+                    if (mPreference != null) {
+                        updateState(mPreference);
+                    }
+                }
+            };
+        }
+        RotationPolicy.registerRotationPolicyListener(mContext,
+                mRotationPolicyListener);
+    }
+
+    @Override
+    public void onPause() {
+        if (mRotationPolicyListener != null) {
+            RotationPolicy.unregisterRotationPolicyListener(mContext, mRotationPolicyListener);
+        }
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return RotationPolicy.isRotationLockToggleVisible(mContext)
+                ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
+    }
+
+    @Override
+    public boolean isSliceable() {
+        return TextUtils.equals(getPreferenceKey(), "show_navigate");
+    }
+
+    @Override
+    public boolean isPublicSlice() {
+        return true;
+    }
+
+    @Override
+    public boolean isChecked() {
+        return (Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.SHOW_NAVIGATE, 0) == 1);
+    }
+
+    @Override
+    public boolean setChecked(boolean isChecked) {
+        Intent i = new Intent("com.fuzhou.statusbar.SHOW_OR_HIDE");
+        if(isChecked)
+            i.putExtra("mode", 1);
+        else
+            i.putExtra("mode", 2);
+        mContext.sendBroadcast(i);
+        Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.SHOW_NAVIGATE,
+                isChecked ? 1 : 0 /* Backwards because setting is for disabling */);
+        return true;
+    }
+
+    @Override
+    public int getSliceHighlightMenuRes() {
+        return R.string.menu_key_display;
+    }
+}
diff --git a/src/com/android/settings/display/ShowStatusBarPreferenceController.java b/src/com/android/settings/display/ShowStatusBarPreferenceController.java
new file mode 100755
index 0000000000..ac4892cb4b
--- /dev/null
+++ b/src/com/android/settings/display/ShowStatusBarPreferenceController.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+package com.android.settings.display;
+
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.text.TextUtils;
+
+import androidx.preference.Preference;
+
+import com.android.internal.view.RotationPolicy;
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settings.core.TogglePreferenceController;
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.OnPause;
+import com.android.settingslib.core.lifecycle.events.OnResume;
+import android.util.Log;
+import android.app.StatusBarManager;
+import android.provider.Settings;
+import android.content.Intent;
+import com.android.settings.R;
+public class ShowStatusBarPreferenceController extends TogglePreferenceController implements
+        PreferenceControllerMixin, Preference.OnPreferenceChangeListener, LifecycleObserver,
+        OnResume, OnPause {
+
+    private final MetricsFeatureProvider mMetricsFeatureProvider;
+    StatusBarManager mStatusBarManager;
+    private Preference mPreference;
+    private RotationPolicy.RotationPolicyListener mRotationPolicyListener;
+
+    public ShowStatusBarPreferenceController(Context context, String key) {
+        super(context, key);
+        mStatusBarManager = (StatusBarManager) context.getSystemService(Context.STATUS_BAR_SERVICE);
+        mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        mPreference = preference;
+        super.updateState(preference);
+    }
+
+    @Override
+    public void onResume() {
+        if (mRotationPolicyListener == null) {
+            mRotationPolicyListener = new RotationPolicy.RotationPolicyListener() {
+                @Override
+                public void onChange() {
+                    if (mPreference != null) {
+                        updateState(mPreference);
+                    }
+                }
+            };
+        }
+        RotationPolicy.registerRotationPolicyListener(mContext,
+                mRotationPolicyListener);
+    }
+
+    @Override
+    public void onPause() {
+        if (mRotationPolicyListener != null) {
+            RotationPolicy.unregisterRotationPolicyListener(mContext, mRotationPolicyListener);
+        }
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return RotationPolicy.isRotationLockToggleVisible(mContext)
+                ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
+    }
+
+    @Override
+    public boolean isSliceable() {
+        return TextUtils.equals(getPreferenceKey(), "show_statusbar");
+    }
+
+    @Override
+    public boolean isPublicSlice() {
+        return true;
+    }
+
+    @Override
+    public boolean isChecked() {
+        return (Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.SHOW_STATUSBAR, 0) == 1);
+    }
+
+    @Override
+    public boolean setChecked(boolean isChecked) {
+        Intent i = new Intent("com.fuzhou.statusbar.SHOW_OR_HIDE");
+        if(isChecked) {
+            i.putExtra("mode", 3);
+        }
+        else{
+            i.putExtra("mode", 4);
+        }
+
+        mContext.sendBroadcast(i);
+        Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.SHOW_STATUSBAR,
+                isChecked ? 1 : 0 /* Backwards because setting is for disabling */);
+        return true;
+    }
+
+    @Override
+    public int getSliceHighlightMenuRes() {
+        return R.string.menu_key_display;
+    }
+}

2,关闭taskbar的创建 

修改点

packages/apps/Launcher3

diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
index b115ca8032..ffd2c9b15e 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
@@ -491,7 +491,8 @@ public class TaskbarManager {
     }

     private boolean isTaskbarPresent(DeviceProfile deviceProfile) {
-        return FLAG_HIDE_NAVBAR_WINDOW || deviceProfile.isTaskbarPresent;
+        //return FLAG_HIDE_NAVBAR_WINDOW || deviceProfile.isTaskbarPresent;
+        return false;
     }

     public void onRotationProposal(int rotation, boolean isValid) {

3.接收广播设置,按照广播带的参数,动态隐藏/显示导航栏/状态栏,

还有为了保存新增设置 的修改,否则重启后设置会丢失

修改点

diff --git a/core/api/current.txt b/core/api/current.txt
index f5a761106106..3402e29bdc6c 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -37514,7 +37514,9 @@ package android.provider {
     field public static final String RADIO_NFC = "nfc";
     field public static final String RADIO_WIFI = "wifi";
     field public static final String SECURE_FRP_MODE = "secure_frp_mode";
+    field public static final String SHOW_NAVIGATE = "show_navigate";
     field @Deprecated public static final String SHOW_PROCESSES = "show_processes";
+    field public static final String SHOW_STATUSBAR = "show_statusbar";
     field public static final String STAY_ON_WHILE_PLUGGED_IN = "stay_on_while_plugged_in";
     field public static final String TRANSITION_ANIMATION_SCALE = "transition_animation_scale";
     field public static final String USB_MASS_STORAGE_ENABLED = "usb_mass_storage_enabled";
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 12934d06bb3d..e27948f55e83 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -11895,6 +11895,11 @@ public final class Settings {
         @Readable
         public static final String THEATER_MODE_ON = "theater_mode_on";

+        @SuppressLint("NoSettingsProvider")
+        public static final String SHOW_STATUSBAR= "show_statusbar";
+        @SuppressLint("NoSettingsProvider")
+        public static final String SHOW_NAVIGATE= "show_navigate";
+
         /**
          * Constant for use in AIRPLANE_MODE_RADIOS or SATELLITE_MODE_RADIOS to specify Bluetooth
          * radio.
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index aaaad047426a..35d903447fdd 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -17,6 +17,8 @@
  */
 -->
 <resources>
+    <bool name="def_show_statusbar">true</bool>
+    <bool name="def_show_navigate">true</bool>
     <bool name="def_dim_screen">true</bool>
     <integer name="def_screen_off_timeout">60000</integer>
     <integer name="def_sleep_timeout">-1</integer>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index c125481b3a14..9b59d053af9f 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -2410,6 +2410,9 @@ class DatabaseHelper extends SQLiteOpenHelper {
             stmt = db.compileStatement("INSERT OR IGNORE INTO global(name,value)"
                     + " VALUES(?,?);");

+            loadBooleanSetting(stmt, Settings.Global.SHOW_NAVIGATE,R.bool.def_show_navigate);
+            loadBooleanSetting(stmt, Settings.Global.SHOW_STATUSBAR,R.bool.def_show_statusbar);
+
             // --- Previously in 'system'
             loadBooleanSetting(stmt, Settings.Global.AIRPLANE_MODE_ON,
                     R.bool.def_airplane_mode_on);
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java
index 751a3f8458bd..d1a5fe04f5a3 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java
@@ -143,7 +143,8 @@ public class Utilities {

         float smallestWidth = dpiFromPx(Math.min(bounds.width(), bounds.height()),
                 context.getResources().getConfiguration().densityDpi);
-        return smallestWidth >= TABLET_MIN_DPS;
+        //return smallestWidth >= TABLET_MIN_DPS;
+        return false;
     }

     public static float dpiFromPx(float size, int densityDpi) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
index 0e6835c03d49..e9cf418e63f3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -285,7 +285,6 @@ import javax.inject.Provider;
  */
 @SysUISingleton
 public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
-
     private static final String BANNER_ACTION_CANCEL =
             "com.android.systemui.statusbar.banner_action_cancel";
     private static final String BANNER_ACTION_SETUP =
@@ -940,6 +939,36 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
         bubbles.setExpandListener(listener);
     }

+    private final BroadcastReceiver mStatusShowHide  = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+            if ("com.fuzhou.statusbar.SHOW_OR_HIDE".equals(action)) {
+                final int mode = intent.getIntExtra("mode", 1);
+                switch (mode){
+                    case 1:
+                        if(getNavigationBarView() != null)
+                            getNavigationBarView().getRootView().setVisibility(View.VISIBLE);
+                        break;
+                    case 2:
+                        if(getNavigationBarView() != null)
+                            getNavigationBarView().getRootView().setVisibility(View.GONE);
+                        break;
+                    case 3:
+                        if(mStatusBarView != null)
+                            mStatusBarView.getRootView().setVisibility(View.VISIBLE);
+                            mCommandQueue.mEnablePanel = true;
+                        break;
+                    case 4:
+                        if(mStatusBarView != null)
+                            mStatusBarView.getRootView().setVisibility(View.GONE);
+                            mCommandQueue.mEnablePanel = false;
+                        break;
+                }
+            }
+        }
+    };
+
     @Override
     public void start() {
         mScreenLifecycle.addObserver(mScreenObserver);
@@ -985,6 +1014,10 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {

         createAndAddWindows(result);

+        IntentFilter statusFilter = new IntentFilter();
+        statusFilter.addAction("com.fuzhou.statusbar.SHOW_OR_HIDE");
+        mBroadcastDispatcher.registerReceiver(mStatusShowHide, statusFilter);
+
         // Set up the initial notification state. This needs to happen before CommandQueue.disable()
         setUpPresenter();

diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 6304c1ea2635..85fb73f3deb5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -79,6 +79,7 @@ import java.io.FileOutputStream;
 import java.io.OutputStream;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import android.provider.Settings;

 /**
  * This class takes the functions from IStatusBar that come in on
@@ -180,6 +181,7 @@ public class CommandQueue extends IStatusBar.Stub implements
     public static final int FLAG_EXCLUDE_COMPAT_MODE_PANEL = 1 << 4;

     private static final String SHOW_IME_SWITCHER_KEY = "showImeSwitcherKey";
+    public Boolean mEnablePanel = true;

     private final Object mLock = new Object();
     private ArrayList<Callbacks> mCallbacks = new ArrayList<>();
@@ -542,14 +544,16 @@ public class CommandQueue extends IStatusBar.Stub implements
         }, new HandlerExecutor(mHandler));
         // We always have default display.
         setDisabled(mDisplayTracker.getDefaultDisplayId(), DISABLE_NONE, DISABLE2_NONE);
+        mEnablePanel = Settings.Global.getInt(context.getContentResolver(),Settings.Global.SHOW_STATUSBAR, 0)== 1;
     }

     // TODO(b/118592525): add multi-display support if needed.
     public boolean panelsEnabled() {
-        final int disabled1 = getDisabled1(mDisplayTracker.getDefaultDisplayId());
-        final int disabled2 = getDisabled2(mDisplayTracker.getDefaultDisplayId());
-        return (disabled1 & StatusBarManager.DISABLE_EXPAND) == 0
-                && (disabled2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE) == 0;
+//        final int disabled1 = getDisabled1(mDisplayTracker.getDefaultDisplayId());
+//        final int disabled2 = getDisabled2(mDisplayTracker.getDefaultDisplayId());
+//        return (disabled1 & StatusBarManager.DISABLE_EXPAND) == 0
+//                && (disabled2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE) == 0;
+        return mEnablePanel;
     }

     @Override

嵌入式开发板网络配置避坑

RK3576 Android14 有线网卡静态 IP 配置全攻略,附数据实操

评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值