android系统应用之Settings

2023-05-16

Setting作为安卓一个比较重要的系统级应用,为用户提供一些系统项的设置。原生android系统的源码路径:/packages/apps/Settings。但MTK厂商的源码包中对该应用进行了重构其源码路径:/vendor/mediatek/proprietary/packages/apps/MtkSettings。

一、Setting

1、入口Activity

android应用程序的入口比较简单,可以直接查看AndroidManifest.xml,里面有配置应用的包名、版本、权限、四大组件等。Setting配置文件代码如下:

<!--packages/apps/Settings/AndroidManifest.xml-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
        package="com.android.settings"
        coreApp="true"
        android:sharedUserId="android.uid.system">           <!--标识系统应用-->
    <!--包名-->
    <original-package android:name="com.android.settings" />  
    <!--应用配置-->
    <application android:label="@string/settings_label"
            android:icon="@drawable/ic_launcher_settings"
            android:theme="@style/Theme.Settings"
            android:hardwareAccelerated="true"
            android:requiredForAllUsers="true"
            android:supportsRtl="true"
            android:backupAgent="com.android.settings.backup.SettingsBackupHelper"
            android:usesCleartextTraffic="true"
            android:defaultToDeviceProtectedStorage="true"
            android:directBootAware="true"
            android:appComponentFactory="androidx.core.app.CoreComponentFactory">
        <uses-library android:name="org.apache.http.legacy" />
        <!-- Settings -->
        <activity android:name=".homepage.SettingsHomepageActivity"
                  android:label="@string/settings_label_launcher"
                  android:theme="@style/Theme.Settings.Home"
                  android:taskAffinity="com.android.settings.root"
                  android:launchMode="singleTask"
                  android:configChanges="keyboard|keyboardHidden">
            <intent-filter android:priority="1">
                <action android:name="android.settings.SETTINGS" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
            <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED" android:value="true" />
        </activity>
        <!--主界面,activity的别名,目标actvity是SettingsHomepageActivity-->
        <activity-alias android:name="Settings"
                android:label="@string/settings_label_launcher"
                android:taskAffinity="com.android.settings.root"
                android:launchMode="singleTask"
                android:targetActivity=".homepage.SettingsHomepageActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <meta-data android:name="android.app.shortcuts" android:resource="@xml/shortcuts"/>
        </activity-alias>
        <receiver android:name=".SettingsInitialize">
            <intent-filter>
                <action android:name="android.intent.action.USER_INITIALIZE"/>
                <action android:name="android.intent.action.PRE_BOOT_COMPLETED"/>
            </intent-filter>
        </receiver>
        <activity android:name=".SubSettings"/>
        <!--activity配置 省略......-->
    </application>
</manifest>

上面的配置文件第一个被android.intent.action.MAIN修饰的是一个activity-alias标签,该标签意思是一个activity的别名。即它是一个已经存在的activity的别名(这个已经存在的activity被属性targetActivity修饰),因此我们可以认为Settings程序的主界面是SettingsHomepageActivity.java。值得注意的是该标签的name属性并不会指定某个java文件,它只是一个命名标志而已,与他绑定相关的java文件是targetActivity对应的内容,因此这里只是把主界面命名为Settings,但是与源代码中的com.android.settings.Settings.java毫无关系。详情参考《activity-alias详解及应用》。

为了验证上面的理论如上图我分别在SettingsHomepageActivity.java和Settings.java的onCreate加了日志,在启动Settings的时候看看打印的日志是什么?

2、SettingsHomepageActivity

//packages/apps/Settings/src/com/android/settings/homepage/SettingsHomepageActivity.java
public class SettingsHomepageActivity extends FragmentActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 设置主界面布局文件:settings_homepage_container.xml
        setContentView(R.layout.settings_homepage_container);
        // 获取布局文件中homepage_container:主题内容
        final View root = findViewById(R.id.settings_homepage_container);
        root.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |  View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
        //获取布局文件中search_action_bar:顶部搜索控件
        final Toolbar toolbar = findViewById(R.id.search_action_bar);
        FeatureFactory.getFactory(this).getSearchFeatureProvider().initSearchToolbar(this, toolbar, SettingsEnums.SETTINGS_HOMEPAGE);
        //设置contextual_cards_content对应的fragment,不是低内存手机显示卡片布局视图
        if (!getSystemService(ActivityManager.class).isLowRamDevice()) {
            showFragment(new ContextualCardsFragment(), R.id.contextual_cards_content);
        }
        //设置main_content对应fragment为TopLevelSettings,即所有二级菜单选项
        showFragment(new TopLevelSettings(), R.id.main_content);
        ((FrameLayout) findViewById(R.id.main_content))
                .getLayoutTransition().enableTransitionType(LayoutTransition.CHANGING);
    }
}
<!--packages/apps/Settings/res/layout/settings_homepage_container.xml-->
<androidx.coordinatorlayout.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/settings_homepage_container"
    android:fitsSystemWindows="true"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <androidx.core.widget.NestedScrollView
        android:id="@+id/main_content_scrollable_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="com.android.settings.widget.FloatingAppBarScrollingViewBehavior">
        <!--主题内容布局-->
        <LinearLayout
            android:id="@+id/homepage_container"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">
            <!--显示一些通知卡片-->
            <FrameLayout
                android:id="@+id/contextual_cards_content"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginStart="@dimen/contextual_card_side_margin"
                android:layout_marginEnd="@dimen/contextual_card_side_margin"/>
            <!--所有的二级菜单-->
            <FrameLayout
                android:id="@+id/main_content"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:animateLayoutChanges="true"
                android:background="?android:attr/windowBackground"/>
        </LinearLayout>
    </androidx.core.widget.NestedScrollView>
    <!--顶部搜索栏-->
    <com.google.android.material.appbar.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:touchscreenBlocksFocus="false"
        android:keyboardNavigationCluster="false">
        <include layout="@layout/search_bar"/>
    </com.google.android.material.appbar.AppBarLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

如上Activity和对应的布局文件代码,很容易理解,整个布局主要分两大块:

  • 首先顶部的搜索栏通过包含search_bar.xml文件(实现了Settings的搜索设置功能),通过工厂方式来创建并初始化SearchFeatureProvider,可通过它来搜索Settings所有的子菜单
  • 最后内容主体部分使用了NestedScrollView滑动控件,它包含了两个部分:顶部的卡片内容和下面主体二级菜单选项。其中二级菜单选项视图被设置成了TopLevelSettings

2.1、SearchFeatureProvider搜索子菜单

2.2、TopLevelSettings二级菜单布局

//packages/apps/Settings/src/com/android/settings/homepage/TopLevelSettings.java
@SearchIndexable(forTarget = MOBILE)
public class TopLevelSettings extends DashboardFragment implements PreferenceFragmentCompat.OnPreferenceStartFragmentCallback {
    public TopLevelSettings() {
        final Bundle args = new Bundle();
        args.putBoolean(NEED_SEARCH_ICON_IN_ACTION_BAR, false); //是否禁用搜索图标
        setArguments(args);
    }
    @Override
    protected int getPreferenceScreenResId() {
        return R.xml.top_level_settings;  //对于视图布局文件
    }
    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        use(SupportPreferenceController.class).setActivity(getActivity());
    }
    @Override
    public boolean onPreferenceStartFragment(PreferenceFragmentCompat caller, Preference pref) {
        new SubSettingLauncher(getActivity())
                .setDestination(pref.getFragment())
                .setArguments(pref.getExtras())
                .setSourceMetricsCategory(caller instanceof Instrumentable ? ((Instrumentable) caller).getMetricsCategory() : Instrumentable.METRICS_CATEGORY_UNKNOWN)
                .setTitleRes(-1)
                .launch();
        return true;
    }
    @Override
    protected boolean shouldForceRoundedIcon() {
        return getContext().getResources()
                .getBoolean(R.bool.config_force_rounded_icon_TopLevelSettings);
    }
}

从上面的代码可以知道TopLevelSettings是一个fragment,大部分功能在DashboardFragment父类具体实现,这里只提供了几个接口,从名字上可以看出getPreferenceScreenResId对应于视图布局文件,top_level_settings.xml如下:

2.3、Preference偏好设置

如上小节,我们发现布局文件中在PreferenceScreen里面包含了一批Preference。这个是什么东西呢?其实Preference是android原生为了持久化数据的一种"控件",注意它并不是真正意义上的View。具体用法可以参考《Android之PreferenceFragment详解》

  • Preference家族

Preference源码路径如下图,其中比较重要的有前面已经见过的PreferenceScreen和Preference。

  • Preference是"控件"?

Preference并不是控件,它没有继承View,但是为什么我们的布局文件中可以使用他呢?其实只有继承了PreferenceFragment或者PreferenceActivity的才能使用上面以PreferenceScreen标签开头的xml文件,因为他们内部作了一系列解析,同时Preference有方法返回一个View对象,如下代码:

//android/frameworks/base/core/java/android/preference/Preference.java
@Deprecated
public class Preference implements Comparable<Preference> {
    private boolean mShouldDisableView = true;
    @UnsupportedAppUsage
    private int mLayoutResId = com.android.internal.R.layout.preference;
    @UnsupportedAppUsage
    private int mWidgetLayoutResId;
    public void setLayoutResource(@LayoutRes int layoutResId) {
        if (layoutResId != mLayoutResId)   mRecycleEnabled = false;
        mLayoutResId = layoutResId;
    }
    @LayoutRes
    public int getLayoutResource() {
        return mLayoutResId;
    }
    //返回一个视图控件View
    public View getView(View convertView, ViewGroup parent) {
        //如果第一次就创建视图View
        if (convertView == null)  convertView = onCreateView(parent);
        //给视图View填充数据和更新ui
        onBindView(convertView);
        return convertView;
    }
    //创建视图控件View,实际上还是inflate对应的资源ID文件
    @CallSuper
    protected View onCreateView(ViewGroup parent) {
        final LayoutInflater layoutInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        final View layout = layoutInflater.inflate(mLayoutResId, parent, false);
        final ViewGroup widgetFrame = (ViewGroup) layout.findViewById(com.android.internal.R.id.widget_frame);
       if (widgetFrame != null) {
            if (mWidgetLayoutResId != 0) layoutInflater.inflate(mWidgetLayoutResId, widgetFrame);
            else widgetFrame.setVisibility(View.GONE);
        }
        return layout;
    }
    //主要是给上面创建的视图View设置数据
    @CallSuper
    protected void onBindView(View view) {
        final TextView titleView = (TextView) view.findViewById(com.android.internal.R.id.title);
        if (titleView != null) {
            final CharSequence title = getTitle();
            if (!TextUtils.isEmpty(title)) {
                titleView.setText(title);
                titleView.setVisibility(View.VISIBLE);
                if (mHasSingleLineTitleAttr) titleView.setSingleLine(mSingleLineTitle);
            } else {
                titleView.setVisibility(View.GONE);
            }
        }
        final TextView summaryView = (TextView) view.findViewById( com.android.internal.R.id.summary);
        if (summaryView != null) {
            final CharSequence summary = getSummary();
            if (!TextUtils.isEmpty(summary)) {
                summaryView.setText(summary);
                summaryView.setVisibility(View.VISIBLE);
            } else {
                summaryView.setVisibility(View.GONE);
            }
        }
        final ImageView imageView = (ImageView) view.findViewById(com.android.internal.R.id.icon);
        if (imageView != null) {
            if (mIconResId != 0 || mIcon != null) {
                if (mIcon == null)  mIcon = getContext().getDrawable(mIconResId);
                if (mIcon != null) imageView.setImageDrawable(mIcon);
            }
            if (mIcon != null) imageView.setVisibility(View.VISIBLE);
            else imageView.setVisibility(mIconSpaceReserved ? View.INVISIBLE : View.GONE);
        }
        final View imageFrame = view.findViewById(com.android.internal.R.id.icon_frame);
        if (imageFrame != null) {
            if (mIcon != null) imageFrame.setVisibility(View.VISIBLE);
            else imageFrame.setVisibility(mIconSpaceReserved ? View.INVISIBLE : View.GONE);
        }
        if (mShouldDisableView) setEnabledStateOnViews(view, isEnabled());
    }
    //界面更改条目栏
    public void setTitle(CharSequence title) {
        if (title == null && mTitle != null || title != null && !title.equals(mTitle)) {
            mTitleRes = 0;
            mTitle = title;
            notifyChanged();
        }
    }
    //界面更改图标
    public void setIcon(Drawable icon) {
        if ((icon == null && mIcon != null) || (icon != null && mIcon != icon)) {
            mIcon = icon;
            notifyChanged();
        }
    }
    //界面有改变回调监听器
    protected void notifyChanged() {
        if (mListener != null)  mListener.onPreferenceChange(this);
    }
}
  • Preference如何持久化?

Settings为什么大量使用了Preference,而没有使用到我们常见的View和TextView呢,因为这里逻辑功能上主要是为了给系统进行一些设置,所有就涉及到了设置参数持久化(即断电后还继续生效),如下代码它内部已经通过PreferenceManager来进行对数据的持久化,实际上还是使用了四大存储方式之一。

//android/frameworks/base/core/java/android/preference/Preference.java
@Deprecated
public class Preference implements Comparable<Preference> {
    @Nullable
    private PreferenceManager mPreferenceManager;
    public SharedPreferences getSharedPreferences() {
        if (mPreferenceManager == null || getPreferenceDataStore() != null)   return null;
        return mPreferenceManager.getSharedPreferences();
    }
    public SharedPreferences.Editor getEditor() {
        if (mPreferenceManager == null || getPreferenceDataStore() != null)  return null;
        return mPreferenceManager.getEditor();
    }
    public boolean shouldCommit() {
        if (mPreferenceManager == null)  return false;
        return mPreferenceManager.shouldCommit();
    }
    public PreferenceManager getPreferenceManager() {
        return mPreferenceManager;
    }
}
  • Preference唯一标识
  • Preference如何自动跳转android:fragment?
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

android系统应用之Settings 的相关文章

  • java 基础 matches()方法的作用

    java lang包中的String类 xff0c java util regex包中的Pattern xff0c Matcher类中都有matches 方法 都与正则表达式有关 下面我分别举例 xff1a xff08 字符串 xff1a
  • 什么是建造者模式?

    为什么会有这个模式 xff1f 很多时候我们会构建非常复杂的类 xff0c 内部初始化构成需要进行很多复杂交互操作 xff0c 比如需要去数据库查询数据后作为属性初始值 xff0c 或者说我们想控制它的内部初始化的过程 xff0c 将构建过
  • Android Stdio引入kotlin-android-extensions插件

    在Activity中使用Toast lt xml version 61 34 1 0 34 encoding 61 34 utf 8 34 gt lt LinearLayout xmlns android 61 34 http schema
  • 微信小程序开发(一)

    微信小程序开发 目录 微信小程序开发 一 微信小程序开发 二 五 让小程序连接树莓派 六 xff1a 小程序控制面板设计 七 xff1a 树莓派如何解析小程序的信息 八 xff1a 树莓派如何回信息给小程序 九 xff1a 树莓派与微信小程
  • pancakeswap薄饼添加流动性后实现永久锁仓

    pancakeswap xff08 薄饼 xff09 添加流动性后永久锁仓的目的是彻底放弃对资金池的控制权限 xff0c 永久不能撤池 主要针对项目方在首次完成流动性的添加后 xff0c 永久锁仓 这样就放弃了对流动性的所有权 xff0c
  • GEO芯片数据探针id转化

    以数据集GSE89657为例 xff0c 芯片平台是GPL6244 1 下载表达谱数据 GEO网站手动下载表达谱数据 xff0c 解压 xff0c 去注释 gunzip GSE89657 series matrix txt gz cat G
  • R语言正态分布

    统计分布每一种分布有四个函数 xff1a d density xff08 密度函数 xff09 xff0c p 分布函数 xff0c q 分位数函数 xff0c r 随机数函数 正态曲线呈钟型 xff0c 两头低 xff0c 中间高 xff
  • R语言均匀分布

    在R中 xff0c unif是用来进行均匀分布分析的 xff0c 在其前面加上不同的前缀表示不同的函数 xff0c 各函数的使用格式如下所示 xff1a dunif x min 61 0 max 61 1 log 61 FALSE 分布密度
  • 转录本counts,FPKM,TPM相互转化

    FPKM Fragments Per Kilobase of exon model per Million mapped fragments 每千个碱基的转录每百万映射读取的fragments FPKM xff1a Fragments pe
  • R语言泊松(Poisson)分布

    Poisson分布 xff0c 是一种统计与概率学里常见到的离散概率分布 xff0c 由法国数学家西莫恩 德尼 泊松 xff08 Sim on Denis Poisson xff09 在1838年时发表 泊松分布的参数 是单位时间 或单位面
  • windows软件窗口或者对话框太大超出屏幕解决办法

    软件窗口太大显示不全 问题 xff1a 软件窗口或对话框太大 xff0c 最大化也无法显示全部 xff0c 拖动标题栏移动到屏幕顶部 xff0c 底部也显示不出来 具体见下面两张图片 解决方法 xff1a 使用第三方工具 xff1a 窗口移
  • R语言卡方(chisq)分布

    若n个相互独立的随机变量 xff0c xff0c n xff0c 均服从标准正态分布 xff08 也称独立同分布于标准正态分布 xff09 xff0c 则这n个服从标准正态分布的随机变量的平方和构成一新的随机变量 xff0c 其分布规律称为
  • liftOver进行基因组坐标转换

    Liftover是UCSC中用于基因组版本之间转换的一个工具 xff0c 既可以做某一物种内基因组版本的转换 xff0c 还可以做物种间基因组版本的转换 1 网页转换 http genome ucsc edu cgi bin hgLiftO
  • R语言ggraph包绘制环状网络图

    ggraph 是 ggplot2 的扩展 xff0c 用于绘制关系型数据结构 xff0c 如网络 图和树等 ggraph 包含 3 个核心概念 xff1a layout xff1a 定义图的布局 xff0c 如蜂巢图 圆堆积图等 nodes
  • 本地安装运行HiC数据可视化容器higlass-docker

    HiGlass xff0c 这是一个基于web技术的开源可视化工具 xff0c 它提供了一个丰富的界面 xff0c 用于快速 多重和多尺度导航2D基因组地图以及1D基因组轨迹 xff0c 允许用户组合各种数据类型 xff0c 同步多个可视化
  • R语言p值校正函数p.adjust

    调整方法包括Bonferroni校正 xff08 Bonferrroni xff09 xff0c 其中p值乘以比较次数 Holm xff08 1979 xff09 xff08 Holm xff09 Hochberg xff08 1988 x
  • R语言中Lasso Cox 筛选生存相关特征

    构建预后模型时 xff0c 通常先进行单因素Cox分析筛选出关联的变量 xff0c 再通过Lasso Cox 筛选生存相关特征 xff08 排除多重共线性的特征 xff09 xff0c 最后构建Cox多因素回归模型分析预后影响 Lasso
  • R包WGCNA分析代码

    WGCNA xff08 加权基因共表达网络分析 xff09 R软件包 xff0c 用于执行加权相关网络分析 xff0c 包括网络构建 模块检测 基因选择 拓扑结构计算 数据模拟 可视化以及与外部软件的接口等功能 WGCNA旨在寻找协同表达的
  • 单样本GSEA分析肿瘤组织免疫浸润

    单样本GSEA分析即ssGSEA xff0c 可以计算肿瘤组织中免疫细胞的比例 xff0c 从而量化免疫浸润 ssGSEA可以用R 当中的GSVA包来计算 1 下载 xff0c 读入免疫细胞特征基因集 http cis hku hk TIS
  • 如何进行服务器选型

    1 服务器要运行什么应用 Web服务器对硬件要求不高 xff0c 一般的硬件配置即可满足需求 xff0c 如果后期Web服务访问量上升 xff0c 只需要新增同等配置的服务器 xff0c 通过负载均衡进行集群 xff0c 即可实现Web服务

随机推荐

  • 约瑟夫环问题总结

    问题简介 xff1a 约瑟夫环 xff08 约瑟夫问题 xff09 是一个数学的应用问题 xff1a 已知n个人 xff08 以编号1 xff0c 2 xff0c 3 n分别表示 xff09 围坐在一张圆桌周围 从编号为k的人开始报数 xf
  • 文件夹重命名(或移动)却找不到指定该文件类型咋办?

    文件夹重命名 或移动 却找不到指定该文件类型咋办 xff1f 方法一 xff0c 导入FolderDescriptions reg 64位系统导入 xff1a FolderDescriptions x64 reg 32位系统导入 xff1a
  • ubuntu 18.04忘记登录密码的破解方法

    参考 xff1a https www linuxrumen com rmxx 889 html
  • Android 解决Toast不显示

    没有调用show方法 例如 xff1a Toast makeText MainActivity this 休眠 Toast LENGTH SHORT show
  • LwIP之TCP Server多client连接发送和接收Demo

    msh调用时对端口进行监听 xff0c 监听到有客户端连接时 xff0c 创建新的线程进行连接 监听时设置最大连接数为4 xff0c 使用SocketTool工具模拟client连接 xff0c 实际效果如下 span class toke
  • Manjaro配置攻略

    1 概述 本文主要讲述了新安装的Manjaro一些常用的配置 xff0c 包括源 常用软件 快捷键 终端以及一些效率工具的配置 2 pacman源 首先是pacman源的选择 xff1a span class token function
  • 真 ● 禁秘技 ● 奥义 ● 终端美化

    1 概述 作为一个程序员 xff0c 可以没钱 xff0c 没车 xff0c 没房 xff0c 没老婆 xff0c 没女朋友 但是 xff0c 一定要有一个漂亮骚气的终端 没错 xff0c 大骚特骚 说什么大实话 先来看看原生的终端 xff
  • NFS网络文件共享服务

    NFS用来做什么 以下说明节选自 xff0c 老男孩相关书籍 xff1a 在企业集群架构的工作场景中 xff0c NFS网络文件系统一般被用来存储共享视频 图片 附件等静态资源文件 xff0c 通常网站用户上传的文件都会放到NFS共享里 x
  • mariadb数据库基本使用

    mariadb数据库简介 自甲骨文公司收购MySQL后 xff0c 其在商业数据库与开源数据库领域市场的占有份额都跃居第一 xff0c 这样的格局引起了业内很多的人士的担忧 xff0c 因为商业数据库的老大有可能将MySQL闭源 为了避免O
  • Ubuntu-常见问题

    执行 sudo apt get update 报错 E Problem executing scripts APT Update Post Invoke Success 39 if usr bin test w var cache app
  • systemd --user进程CPU占用高问题分析

    原文链接 xff1a https www cnblogs com yaohong p 16046670 html xff0c 转载需经同意 1 问题由来 近期发现堡垒机环境有如下问题 xff0c systemd占用大量cpu xff1a 2
  • C语言回调函数的定义和写法

    C语言中的回调函数 xff08 Callback Function xff09 1 定义和使用场合 回调函数是指 使用者自己定义一个函数 xff0c 实现这个函数的程序内容 xff0c 然后把这个函数 xff08 入口地址 xff09 作为
  • Xshell超250+配色方案(主题) 及其推荐

    Xshell配色方案 主题 超290 43 xshell主题 xshell配色方案 xshell theme 超过290个xshell配色方案 xff0c 在这里都可以下载到 xff0c 而且一直还有新的主题添加进来 xff1a 地址 xf
  • ubuntu usb权限问题解决

    在 etc udev rules d 创建51 android rules SUBSYSTEM 61 61 34 usb 34 ENV DEVTYPE 61 61 34 usb device 34 MODE 61 34 0666 34 SU
  • 关于onConfigurationChanged方法及常见问题解决

    本篇文章已授权微信公众号 guolin blog xff08 郭霖 xff09 独家发布 1 public void onConfigurationChanged Configuration newConfig 方法介绍 newConfig
  • C_INCLUDES must be under the source or output directories: /securemsm/QSEEComAPI.

    高通编译报错如下 xff1a FAILED 10 57 33 build span class token operator span make span class token operator span core span class
  • 手写一个生产者--消费者模型例子

    在并发编程中 xff0c 比较经典的编程例子就是生产者和消费者模型 下面就是一个例子来诠释一下什么是生产者和消费者以及他们的特点和注意点 1 先定义一个数据对象 xff0c span class hljs keyword public sp
  • android R的一些selinux配置经验分享

    1 编译报 xff1a violated by allow avm3d service avm3d service exec file read getattr map execute open entrypoint 定位 xff1a 没有
  • 华为服务器安装Centos6.5

    1 登陆对应华为服务器 xff1a 100 100 100 206 默认ip为192 168 2 100 默认账号 xff1a root 默认密码 xff1a Huawei12 联想服务器 xff1a 默认ip为192 168 70 125
  • android系统应用之Settings

    Setting作为安卓一个比较重要的系统级应用 xff0c 为用户提供一些系统项的设置 原生android系统的源码路径 xff1a packages apps Settings 但MTK厂商的源码包中对该应用进行了重构其源码路径 xff1