Android 6.0 Setting模块解析

Android 6.0 Settings模块解析(一) Android 6.0 Setting模块解析 这几天在学习 Android Settings 设置菜单的相关内容,原本打算一篇搞定,谁知入坑后发现 Android 6.0、7.0、8.0 设置菜单的加载方式各有千秋,妈耶,好坑,所以接下来我会从 6.0、7.0、8.0 去分别分析设置界面是怎么加载出来的。预计会分为三篇,本篇是第一篇 6.0 分析,下面请各位跟我的教程一步步走,喂喂喂!!说你呢,... 阅读详情

Android 6.0 Setting模块解析(一)

这几天在学习 Android Settings 设置菜单的相关内容,原本打算一篇搞定,谁知入坑后发现 Android 6.0、7.0、8.0 设置菜单的加载方式各有千秋,妈耶,好坑,所以接下来我会从 6.0、7.0、8.0 去分别分析设置界面是怎么加载出来的。预计会分为三篇,本篇是第一篇 6.0 分析,下面请各位跟我的教程一步步走,喂喂喂!!说你呢,小本本拿好,我要开讲啦!!
前言

偷偷告诉你 Android 源码和本篇文章结合起来看效果更好哦。

Android 源码查看地址:https://www.androidos.net.cn/sourcecode 。

另外本系列文章所涉及的所有 Android 源码在此网站上都可以找到,最后来看看 6.0 系统的设置菜单到底长什么样,瞅图:
在这里插入图片描述
6.0设置界面加载

首先我们来看 Settings 模块中的 AndroidManifest.xml 文件,这里会展示四大组件,默认启动入口Activity等信息,具体路径如下:/packages/apps/Settings/AndroidManifest.xml。

···       
<activity android:name="Settings"
            android:taskAffinity="com.android.settings"
            android:label="@string/settings_label_launcher"
            android:launchMode="singleTask">
            <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-alias可用来设置某个Activity的快捷入口,可以放在桌面上或者通过该别名被其他组件快速调起。                    
        //android:targetActivity为目标Activity.
        <activity-alias android:name="Settings"
                android:taskAffinity="com.android.settings"                android:label="@string/settings_label_launcher"
                android:launchMode="singleTask"
                android:targetActivity="Settings">
            <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>
        </activity-alias>
···

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26

可以看出入口Activity为Settings。
Settings

具体路径:/packages/apps/Settings/src/com/android/settings/Settings.java

public class Settings extends SettingsActivity {
     public static class BluetoothSettingsActivity extends SettingsActivity { /* empty */ }
    public static class WirelessSettingsActivity extends SettingsActivity { /* empty */ }
    public static class SimSettingsActivity extends SettingsActivity { /* empty */ }
    ···
}

    1
    2
    3
    4
    5
    6

可以看出 Settings 继承于 SettingsActivity ,而且其内部都是类的空实现。所以我们看其父类 SettingsActivity。
SettingsActivity

查看其类会发现,SettingsActivity 便是加载菜单的主 Activity。

它的具体路径为:/packages/apps/Settings/src/com/android/settings/SettingsActivity.java

首先来分析 onCreate() 方法

@Override
    protected void onCreate(Bundle savedState) {
        super.onCreate(savedState);
        ···
        //获取AndroidManiFest.xml中mate数据,从Settings(或桌面快捷图标)进入时获取是null
        getMetaData();
        //布局窗口UI
        final Intent intent = getIntent();
        if (intent.hasExtra(EXTRA_UI_OPTIONS)) {
          getWindow().setUiOptions(intent.getIntExtra(EXTRA_UI_OPTIONS, 0));
        }
        ···
     }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13

getMetaData() 代码如下

private void getMetaData() {
        try {
            ActivityInfo ai = getPackageManager().getActivityInfo(getComponentName(),
                    PackageManager.GET_META_DATA);
            if (ai == null || ai.metaData == null) return;
            //private static final String META_DATA_KEY_FRAGMENT_CLASS =
            //"com.android.settings.FRAGMENT_CLASS";
            mFragmentClass = ai.metaData.getString(META_DATA_KEY_FRAGMENT_CLASS);
        } catch (NameNotFoundException nnfe) {
            ···
        }
    }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

由此可知,getMetaData() 会在加载对应的设置项时会从 节点下获取到 fragmentclass 的值,即为含有 com.android.settings.FRAGMENT_CLASS 标签的值,进行加载。

接下来看getIntent()代码:

 @Override
    public Intent getIntent() {
        Intent superIntent = super.getIntent();
        //获取到要跳转的fragment
        String startingFragment = getStartingFragmentClass(superIntent);
        if (startingFragment != null) {
            Intent modIntent = new Intent(superIntent);
            modIntent.putExtra(EXTRA_SHOW_FRAGMENT, startingFragment);
            Bundle args = superIntent.getExtras();
            if (args != null) {
                args = new Bundle(args);
            } else {
                args = new Bundle();
            }
            args.putParcelable("intent", superIntent);
            modIntent.putExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS, args);
            return modIntent;
        }
        return superIntent;
    }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20

接着看onCreate()方法

@Override
    protected void onCreate(Bundle savedState) {
        super.onCreate(savedState);
        ···
        //获取到要显示的fragment
        final String initialFragmentName = intent.getStringExtra(EXTRA_SHOW_FRAGMENT);
        //判断是否属于快捷方式   
        //isShortCutIntent(intent)是获取到配置文件中定义的<category..节点下的数据判断是否包含某个字符串                        //isLikeShortCutIntent方法 是获取到<action..,判断是否有特定的action,如果有就属于快捷方式  
        //或者判断key为EXTRA_SHOW_FRAGMENT_AS_SHORTCUT中的值是否为true
        mIsShortcut = isShortCutIntent(intent) || isLikeShortCutIntent(intent) ||
                intent.getBooleanExtra(EXTRA_SHOW_FRAGMENT_AS_SHORTCUT, false);
        ////获取到组件名
        final ComponentName cn = intent.getComponent();
        //获取到类名
        final String className = cn.getClassName();
        //如果类名为Settings的类名,则为正在显示控制面板(设置主页)
        mIsShowingDashboard = className.equals(Settings.class.getName());
        //获取到所加载的activity是否属于SubSettings
        //this instanceof SubSettings:判断activity是否属于SubSettings
        //或者获取到EXTRA_SHOW_FRAGMENT_AS_SUBSETTINGS的值,该key会在加载BluetoothSettings时进行赋值
        final boolean isSubSettings = this instanceof SubSettings ||
                intent.getBooleanExtra(EXTRA_SHOW_FRAGMENT_AS_SUBSETTING, false);
        ···
        //加载布局文件,如果显示的设置主界面,即mIsShowingDashboard为true,所以加载settings_main_dashboard布局
        setContentView(mIsShowingDashboard ?
                R.layout.settings_main_dashboard : R.layout.settings_main_prefs);
    }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27

接下来看布局文件settings_main_dashboard.xml

具体路径如下:/packages/apps/Settings/res/layout/settings_main_dashboard.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
             android:id="@+id/main_content"
             android:layout_height="match_parent"
             android:layout_width="match_parent"
             />

    1
    2
    3
    4
    5

可以看出是个帧布局,里面什么都没有,ok 接下来继续看 onCreat 代码:

 @Override
    protected void onCreate(Bundle savedState) {
        super.onCreate(savedState);
        //为fragment所存在的栈添加监听事件         
        getFragmentManager().addOnBackStackChangedListener(this);
        //如果当前显示的为主面板,则会进行如下操作
        if (mIsShowingDashboard) {
            //isLowStorage方法 用于判断我们是否运行在低存储空间
            if (!Utils.isLowStorage(this)) {
                //如果存储空间足够的话,则进行update,即通过ContentProvider来读取数数据,并添加到一个list列表中,这些list列表中存放的是设置项的相关信息
                Index.getInstance(getApplicationContext()).update();
            } else {
               ···
            }
        }
        if (savedState != null) {
               ···
        } else {
            if (!mIsShowingDashboard) {
               ···
            } else {
                //展示主面板
                mDisplayHomeAsUpEnabled = false;             
                mDisplaySearch = true;
                mInitialTitleResId = R.string.dashboard_title;
                //切换加载 Fragment
                switchToFragment(DashboardSummary.class.getName(), null, false, false,
                        mInitialTitleResId, mInitialTitle, false);
            }
        }        
    }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31

由于mIsShowingDashboard是true的原因,代码执行了上面的这段代码。即执行了 switchToFragment() 方法

switchToFragment(DashboardSummary.class.getName(), null /* args */, false, false,
                mInitialTitleResId, mInitialTitle, false);

    1
    2

switchToFragment 又加载的 DashboardSummary,即切换到 DashboardSummary 这个 Fragment,switchToFragment 代码如下

private Fragment switchToFragment(String fragmentName, Bundle args, boolean validate,
            boolean addToBackStack, int titleResId, CharSequence title, boolean withTransition) {
        ···
        Fragment f = Fragment.instantiate(this, fragmentName, args);
        FragmentTransaction transaction = getFragmentManager().beginTransaction();
        //将fragment加载在控件ID为main_content的位置
        transaction.replace(R.id.main_content, f);
        ···
        transaction.commitAllowingStateLoss();
        getFragmentManager().executePendingTransactions();
        return f;
    }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

接下来看DashboardSummary.java

具体路径为:/packages/apps/Settings/src/com/android/settings/dashboard/DashboardSummary.java 。其中 onCreateView 方法如下:

@Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
        mLayoutInflater = inflater;
        final View rootView = inflater.inflate(R.layout.dashboard, container, false);
        mDashboard = (ViewGroup) rootView.findViewById(R.id.dashboard_container);
        return rootView;
    }

    1
    2
    3
    4
    5
    6
    7

从代码中可以看出来,DashboardSummary这个Fragment加载的dashboard.xml这个布局文件,接下来看下dashboard.xml布局,

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/dashboard"
    ···
        >
        <LinearLayout
                android:id="@+id/dashboard_container"                
                ···
                android:orientation="vertical"
                />
</ScrollView>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

最外层是ScrollView,内层是LinearLayout,在上图中的setting界面中,最外层是可滑动的原因就在此,设置选项都是放在LinearLayout中的,并且是动态添加上去的。

接着看DashboardSummary.onResume()方法,发现它最终跑到rebuildUI(context)中,并在这里加载 UI,代码如下:

private void rebuildUI(Context context) {
        ···
        final Resources res = getResources();
        //mDashboard为dashboard.xml布局中的LinearLayout的id,此处先移除LinearLayout里的所有控件
        mDashboard.removeAllViews();
        //获取菜单选项
        List<DashboardCategory> categories =
                ((SettingsActivity) context).getDashboardCategories(true);
        ···
    }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

那么接下来看看SettingsActivity.getDashboardCategories函数:

public List<DashboardCategory> getDashboardCategories(boolean forceRefresh) {
        if (forceRefresh || mCategories.size() == 0) {
            buildDashboardCategories(mCategories);
        }
        return mCategories;
    }

    1
    2
    3
    4
    5
    6

private void buildDashboardCategories(List<DashboardCategory> categories) {
        //先清空
        categories.clear();
        //加载dashboard_categories中的数据,解析xml,将解析好的数据资源存放到了List<DashboardCategory>这个集合中
        loadCategoriesFromResource(R.xml.dashboard_categories, categories, this);
        //更新categories到界面上,这里可以设置设置中某个categories(比如wifi、蓝牙设置)是否展示。
        updateTilesList(categories);
    }

    1
    2
    3
    4
    5
    6
    7
    8

到这里可以看出,该方法内部实现是解析dashboard_categories.xml文件,获取到所有的设置项的,所以6.0中Setting的显示内容的条目数量是由资源数量决定的,而这个资源就定义在dashboard_categories.xml中。

它的具体路径为:/packages/apps/Settings/res/xml/dashboard_categories.xml。所以getDashboardCategories会在显示UI之前会去加载资源,dashboard_categories.xml.代码如下:

<dashboard-categories
        xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- WIRELESS and NETWORKS -->
    <dashboard-category
            android:id="@+id/wireless_section"
            android:key="@string/category_key_wireless"
           android:title="@string/header_category_wireless_networks" >
        <!-- Wifi -->
        <dashboard-tile
                android:id="@+id/wifi_settings"
                android:title="@string/wifi_settings_title"
                android:fragment="com.android.settings.wifi.WifiSettings"               android:icon="@drawable/ic_settings_wireless"
                />
        <!-- Bluetooth -->
        ···
     </dashboard-category>
     ···
</dashboard-categories>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18

DashboardCategory的代码如下

文件路径为:/packages/apps/Settings/src/com/android/settings/dashboard/DashboardCategory.java

public class DashboardCategory implements Parcelable {
    
     //{@link com.android.settings.dashboard.DashboardCategory#id DashboardCategory.id}
     //的标识符为设置时他的默认值为-1.  所有其他值(包括低于-1的值)都有效    
    public static final long CAT_ID_UNDEFINED = -1;

   // 为title设置一个id,当他更新时会和一个新的list关联,默认没有id。     
    public long id = CAT_ID_UNDEFINED;

    
    //类别title的资源id.Resource ID of title of the category that is shown to the user.     
    public int titleRes;
    
    //类别title.     
    public CharSequence title;

    
     //设置额外的 title 时会用到.
     
    public String key;

    public int externalIndex = -1;

    
     //类别下面的一系列子设置选项
     
    public List<DashboardTile> tiles = new ArrayList<DashboardTile>();


    public DashboardCategory() {
        // Empty
    }

    ···

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        ···
    }

    public void readFromParcel(Parcel in) {
        ···
    }

    DashboardCategory(Parcel in) {
        readFromParcel(in);
    }

    public static final Creator<DashboardCategory> CREATOR = new Creator<DashboardCategory>() {
        public DashboardCategory createFromParcel(Parcel source) {
            return new DashboardCategory(source);
        }

        public DashboardCategory[] newArray(int size) {
            return new DashboardCategory[size];
        }
    };
}

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58

其中dashboard_categories.xml的dashboard-category节点对应的是DashboardCategory的对象,dashboard-tile节点对应的是DashboardTile的对象,而DashboardCategory对象内部有List tiles的集合对象,所解析出来的DashboardTile都有DashboardCategory保管,而每个DashboardCategory对象又由categories来保管,就这样数据资源就得到了.

所以如果想要添加一个设置项,只需要在dashboard_categories.xml文件中添加一个控件,如果要删除一个设置项可以在 SettingsActivity中 的 updateTilesList 方法中将 removetile 设置为 true,然后移除。

接着来看rebuildUI的代码:

 private void rebuildUI(Context context) {
     ···
        final int count = categories.size();
        for (int n = 0; n < count; n++) {
            //每一个大类里设置项的数量
            DashboardCategory category = categories.get(n);
            //每一个设置项为自定义的dashboard-tile,其布局文件为dashboard_category.xml
            View categoryView = mLayoutInflater.inflate(R.layout.dashboard_category, mDashboard,
                    false);

            TextView categoryLabel = (TextView) categoryView.findViewById(R.id.category_title);
            categoryLabel.setText(category.getTitle(res));

            ViewGroup categoryContent =
                    (ViewGroup) categoryView.findViewById(R.id.category_content);

            final int tilesCount = category.getTilesCount();
            for (int i = 0; i < tilesCount; i++) {
                DashboardTile tile = category.getTile(i);
                //dashboard_categories.xml的dashboard-category节点最终对应了DashboardTileView的对象
                DashboardTileView tileView = new DashboardTileView(context);
                updateTileView(context, res, tile, tileView.getImageView(),
                        tileView.getTitleTextView(), tileView.getStatusTextView());
                tileView.setTile(tile);
                categoryContent.addView(tileView);
            }
            // 添加一个类别
            mDashboard.addView(categoryView);
        }     
 }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30

可以看出rebuildUI接下来的代码便是循环遍历添加数据显示的过程。

其中 dashboard_category.xml (注意不是 dashboard_categories.xml )代码如下,代码路径为 :/packages/apps/Settings/res/layout/dashboard_category.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/category"
        android:orientation="vertical"
        android:background="@color/card_background"
        ···
            >
    <TextView android:id="@+id/category_title"
            ···
            />
    <com.android.settings.dashboard.DashboardContainerView
            android:id="@+id/category_content"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            />
</LinearLayout>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15

所以如果想要修改所有设置项的布局,可以修改 dashboard_category.xml 文件

那么 DashboardTileView 和 dashboard-category 到底是如何跳转到具体的某个Fragment呢?来看看 DashboardTileView,代码路径为:/packages/apps/Settings/src/com/android/settings/dashboard/DashboardTileView.java

 @Override
    public void onClick(View v) {
        if (mTile.fragment != null) {
            Utils.startWithFragment(getContext(), mTile.fragment, mTile.fragmentArguments, null, 0,mTile.titleRes, mTile.getTitle(getResources()));
        } else if (mTile.intent != null) {
            int numUserHandles = mTile.userHandle.size();
            if (numUserHandles > 1) {
                ProfileSelectDialog.show(((Activity) getContext()).getFragmentManager(), mTile);
            } else if (numUserHandles == 1) {
                getContext().startActivityAsUser(mTile.intent, mTile.userHandle.get(0));
            } else {
                getContext().startActivity(mTile.intent);
            }
        }
    }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15

所以当点击 DashboardTileView 的某个对象时就会跳转至一个具体的 Fragment,而这个 Fragment 已经在 dashboard-category 节点中声明。
小结

跟踪源码到最后,我们会发现 6.0 的设置菜单加载是通过读取 xml 文件完成的,整个过程浑然天成,不禁让人感叹 google 架构的厉害。。
---------------------
作者:一个人的世界ll
来源:CSDN
原文:https://blog.csdn.net/qq_29117915/article/details/83042759
版权声明:本文为博主原创文章,转载请附上博文链接!

Settings7.0添加新菜单列表项源码分析 Fragment配置Activity启动入口 Android6.0 Settings是通过加载dashboard_categories.xml,获取显示列表,所以在6.0上可以直接在dashboard_categories.xml添加icon、title、summary,同时也可以添加目标fragment和Intent.Android 7.0是通过在Androidmanifest.xml中配置intent-filter的Action,然后对指... 阅读详情

相关推荐

android9系统Settings操作,隐藏Settings的一级菜单二级菜单和隐藏Setting主页面的提示栏Suggestion

隐藏Settings的一级菜单 \packages\apps\Settings\AndroidManifest.xml Settings就是根据控制是否在一级菜单显示,以及定义优先级,值越大优先级越高,菜单越靠前 <intent-filter android:priority="2"> <action android:name="com.android.settings.action.SETTINGS" /> </i...

Alex的博客 5204

安卓系统设置包名

ACTION_INPUT_METHOD_SUBTYPE_SETTINGS:语言选择界面(多国语言选择,API 11及以上)ACTION_MANAGE_ALL_APPLICATIONS_SETTINGS:跳转到应用程序界面(所有的)com.android.settings.PhysicalKeyboardSettings 设置键盘。com.android.settings.ApplicationSettings 应用程序设置。

null 2062

Android11.0 Setting一级菜单加载

11.0设置中一级菜单加载,Google和其他系统应用在设置中的一级菜单动态加载分析

Framework-coder的博客 2152

com.android.settings.settings,android系统应用之Settings

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

weixin_28859539的博客 7325

安卓系统原生设置APP

安卓系统的原生设置,机顶盒刷机、手机刷机可以用到。

DIY音频必备:手把手教你用AB类功放模块打造高保真桌面音响(含电路图)

本文详细指导如何利用AB类功放模块DIY高保真桌面音响,涵盖选型指南、核心元器件清单、电路搭建与焊接工艺,以及系统调试与音质优化技巧。AB类功放以其接近A类功放的音质和B类功放的效率,成为音频爱好者的理想选择,适合有一定电子基础的实践者。

weixin_42665725的博客 436

Android6.0 源码修改之Setting列表配置项动态添加和静态添加

写在前面 最近客户有个需求,要求增加操作Setting列表配置项的功能,是不是一脸懵,没关系,一图胜千言,接下来就上图。诺,就是这么个意思。 原来的列表配置项 增加了单个配置项 增加了多个配置项 老铁们看懂了么,就是在原有的列表项中增加客户想要的项,来我给你们分析下,Setting是系统级APP,到时候直接打包进Room里这不用我多说吧。重点来了,如果你把这...

asd2222211的博客 794

RK3506开发板实战:5分钟搞定开源鸿蒙OpenHarmony5.1+星闪功能配置

本文提供了一份基于RK3506开发板快速配置开源鸿蒙OpenHarmony 5.1并启用星闪功能的实战指南。文章详细介绍了从开发环境搭建、系统镜像编译烧录,到星闪驱动加载验证、应用开发及性能调优的全流程,帮助开发者高效上手,将新一代短距无线通信技术应用于物联网项目。

time3的博客 649

android 7.0中Settings新功能全面解析

Settings N预览android N 在Settings中作了一些调整,如上面的截图。 - 增加了侧滑菜单,采用v4下的DrawerLayout来实现; - 在Settings主界面增加了Condition,能够在设置列表中显示状态; - 在Settings主界面增加了Suggestion。Dashboard category数据的加载首先来看下Settings的Dashboard ca

JasonGaoH的专栏 1万+

Palabos 并行计算与多物理场模拟实战指南

本文详细介绍了Palabos在并行计算与多物理场模拟中的实战应用。作为基于C++和LBM的开源CFD工具,Palabos通过MPI实现高效并行计算,特别适合处理复杂流体模拟问题。文章涵盖从基础安装、多物理场耦合技巧到性能优化策略,并分享工业级应用案例与调试经验,帮助开发者快速掌握这一强大工具。

4k5l6j7h8的博客 236

【PLC】三菱plc控件安装 component Movedata had the following error ... Error Number:-119

Windows 10 专业版/企业版本版本号:22H2操作系统内部版本:19045.3448。

少莫千华 7989

Android9.0 Wifi模块Framework层分析

Android 9.0 Wifi模块 Framework层的简要分析

weixin_44205232的博客 1912

定时移动鼠标点击鼠标,防止电脑息屏的vba脚本

定时移动鼠标,使系统始终处于激活状态,防止系统息屏。

panfei263031的博客 5922

安卓setting.gradle配置

安卓之前使用的build.gradle配置,但是在gradle插件7.0版本后推荐使用setting.gradle配置,但是之前的老配置依然生效,只是把老版本里面根目录下Build.gradle中的一些配置放到了setting.gradle中,app下的build.gradle还是一样,语法有些变化先看根目录build.gradle和setting.gradle两者新老版本的变化下面说明插件依赖仓库与项目依赖仓库的区别,以及新老版本的配置方法。

qq_35945801的博客 512

AUTOSAR进阶图解==>AUTOSAR_SWS_CANNetworkManagement

本文介绍了AUTOSAR架构中的CAN网络管理(CanNm)模块,主要内容包括: 模块概述:CanNm是协调CAN网络节点状态转换的基础组件,采用去中心化设计,通过周期性发送网络管理PDU保持网络活跃状态,支持网络唤醒、睡眠和部分网络功能。 架构设计:CanNm位于AUTOSAR中间层,连接上层通信管理器(ComM)和底层CAN接口(CanIf),包含状态管理、PDU处理和定时器管理等子组件。 状态机设计:定义了三种主要模式(总线睡眠、准备睡眠和网络模式)及其转换逻辑,网络模式又包含重复消息、正常操作和准备

一名留德华的,康德的信徒的,专注于汽车电子领域的博客 2031

ThingsBoard教程(七):模拟设备遥测

前言 各位读者好,截止目前,ThingsBoard系列文章已经做了六篇,分别是 ThingsBoard教程(一):ThingBoard介绍及安装 ThingsBoard教程(二):租户,租户配置,部件组模块的使用 ThingsBoard教程(三):系统设置模块的使用 ThingsBoard教程(四):规则链简介与操作 ThingsBoard教程(五):客户,资产管理 ThingsBoard教程(六):设备管理 上一篇我们讲解了如何使用设备管理来对设备进行增删改查,和设备配置的一些基本概念,本篇文章就带大

知无涯 4560

android6.0 Setting去除各功能选项总结

-- alps/packages/apps/Settings/src/com/android/settings/SettingsActivity.java -- index a1033ec..edb26c6 100755 @@ -1300,21 +1300,44 @@ public class SettingsActivity extends Activity ...

lwz的博客 1537

机器人中的数值优化(十四)——罚函数法(Penalty Method)、障碍函数法(Barrier Method)、拉格朗日松弛法(Lagrangian Relaxation)

本系列文章主要是我在学习《数值优化》过程中的一些笔记和相关思考,主要的学习资料是深蓝学院的课程《机器人中的数值优化》和高立编著的《数值最优化方法》等,本系列文章篇数较多,不定期更新,上半部分介绍无约束优化,下半部分介绍带约束的优化,中间会穿插一些路径规划方面的应用实例

慕羽★的博客 5210

教你如何在Android 6.0上创建系统悬浮窗

在Android上创建系统悬浮窗并不是什么新鲜技术,我的人生第一篇博客就是写的关于如何实现类似于360手机卫士悬浮窗的功能,大家有兴趣的可以到 http://guolin.tech 去翻翻历史。不过如果你将项目的targetSdkVersion指定成23或者更高,你会发现之前创建悬浮窗的方式在...

chuanao8829的博客 663

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Android Settings模块分析

Settings模块 第一部分 Settings涉及的模块 4.0设置的layout有很大的改变。将设置分为四个部分: WIRELESS & NETWORKS :SIM卡管理,流量使用情况,飞行模式,VPN,网络共享等 DEVICE : 情景模式,显示,存储,电池,应用程序 PERSONAL: 账户与同步,位置服务,安全,语言和输入法,备份和重置 ...

FLY_THINK2012的博客 123

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

安卓setting.gradle配置-真实代码解析版

首先知道两个概念,插件和项目依赖,插件需要指定仓库,项目依赖也要指定仓库(下载源),插件主要是用于构建项目,比如gradle插件,用于让项目知道如何使用gradle工具,项目依赖则简单,可以使用第三方库里面的各种方法,比如Okhttp等库。说白了,setting.gradle就是把原先根目录的Bulild.gradle中的插件仓库,插件申明,已经项目依赖的仓库转移过来,换个语法罢了,并没有什么新东西。先看老版本的根目录的build.gradle中的项目配置。

qq_35945801的博客 174

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

Android工作笔记:Android6.0中Settings启动流程

1、主页面初始化 1.1 时序图 1.2 启动流程 Setting主页面加载的是布局文件dashboard_categories.xml,具体的加载流程可以通过如下分析步骤进行分析。 首先看Setting模块下的AndroidManifest.xml文件,其中展示了四大组件,默认启动入口Activity等信息,并且包含了APP的配置信息,系统需要根据里面的内容运行后APP的代码以及显示...

weixin_36289667的博客 1203

android M(6.0) Settigs模块源码分析

博客参考链接:Android5.0 Settings各个子模块跳转和布局实现   android Settings 添加新菜单项参考链接:Settings源码6.0 7.0添加新菜单选项   Settings继承自SettingsActivity,该类除了实现的空内部类外,就是一个判断Fragment是否有效的方法。实现的空内部类作用:在加载类设置项时不适用SubSettings,当创建快捷方

蝈蝈 783

Android Framework 音频子系统(15)音量调节之Setting界面调节音量流程

本章节主要关注 滑动音量滑动条 音量值是如何一层层传递的处理流程。 1 从notification_settings.xml找到程序入口 在Setting应用中,通过文件(packages/apps/Settings/res/xml/notification_settings.xml)定义音量滑动条: <PreferenceScreen xmlns:android="http...

wangdsh的博客 2954

android setting模块,android O版本 设置(Settings)模块总结--设置的一级界面的加载

O版本的设置界面相对有N有了一些变化,O上面增加了顶级类别的菜单,而之前一些在一级菜单的则移动到了二级界面里面,如"WIFI","移动网络"等之前是在一级界面的,而在O上则移动到了新菜单"网络和互联网"中,但是在数据在加载方面,并未做较大的变化.(a)一级界面--顶级菜单的数据加载在上一篇 <> 中有说到DashboardSummary是顶级菜单的容器,那么数据的获取和它也就有关系了:...

weixin_34026997的博客 1148
上一篇: android6 usb默认文件管理,不弹RSA配对提示框
下一篇: Android6 修改Lanucher2屏幕数
木叶风
博客等级 码龄10年 52粉丝 26原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值