① the first one


进入Camera 设置里面默认 Video quality 摄录像fine 1920*1088 使用 eclipse Dump view hierarchy for ui automator 工具捕获要索引的关键字,关于Dump view hierarchy for ui 

automator 工具的使用问题,不懂的可以留言,索引关键字以及 Linux find cmd 得到相关关联的资源文件,我们来看看这些文件的关系


packages\apps\Camera\res\values\array.xml  Note that the parameters pref_video_quality_entryvalues

 

<strong><span style="color:#3366ff;">    <!-- Camera Preferences Video Quality entries --><string-array name="pref_video_quality_entries" translatable="false"><item>@string/pref_video_quality_entry_low_cam</item><item>@string/pref_video_quality_entry_medium_cam</item><item>@string/pref_video_quality_entry_high_cam</item><item>@string/pref_video_quality_entry_fine_cam</item><item>@string/pref_video_quality_entry_fine_4k2k</item><item>@string/pref_video_quality_entry_1080p</item></string-array><string-array name="pref_video_quality_entryvalues" translatable="false"><!-- The integer value of CamcorderProfileEx.QUALITY_LOW --><item>108</item><!-- The integer value of CamcorderProfileEx.QUALITY_MEDIUM --><item>109</item><!-- The integer value of CamcorderProfileEx.QUALITY_HIGH --><item>110</item><!-- The integer value of CamcorderProfileEx.QUALITY_FINE --><item>111</item><!-- The integer value of CamcorderProfileEx.QUALITY_FINE_4k2k --><item>123</item><!-- The integer value of CamcorderProfileEx.QUALITY_1080P --><item>118</item></string-array></span></strong>


这两个 array 其实就是对应关系,那我们只需要设置一个默认的 key 即可,具体在哪里设置这个key呢?我们继续往下!

packages\apps\Camera\res_ext\values\string.xmlNote that the parameters pref_video_record_quality_default

<strong><span style="color:#3366ff;"><string name="pref_video_record_quality_default" translatable="false">110</string></span></strong>


这里 setttings default value is 110 , 改成 111 即设置开机系统默认摄录像 fine ,make -jxx 工程,xx线程数,烧录固件,效果如下


② the second

移除系统自带壁纸,包括动态壁纸和静态的,添加所有客供的壁纸,并且在 luncher3 长按 home 可以显示

首先我们要去掉动态壁纸,静态的在我这个项目上只有一张,之前博客已经讲了

device/mediatek/$你的项目名称/ProjectConfig.mk中的


MTK_LIVEWALLPAPER_APP = yes
MTK_LIVE_PHOTO_SUPPORT = yes
修改为
MTK_LIVEWALLPAPER_APP = no
MTK_LIVE_PHOTO_SUPPORT = no

个别可能因为平台不同,具体文件所在也不同,但是索引上述关键字也可查找到相关设置,好,刚刚我们已经完成了第一步,现在走第二步

动态壁纸所在 package 为  LiveWallpapers,所以只要你知道编译系统的工作原理以及mk的相关配置,就知道怎么去查找自己要得文件,我使用命令查找关键字

原始壁纸图:



找到了这个mk文件,接下来只需要把我们的mk编译命令加#注释掉即可,注释如下:

<strong><span style="color:#3366ff;"># Engineer-Jsp add remove system livewallpaper
#ifeq ($(strip $(MTK_LIVEWALLPAPER_APP)), yes)
#  PRODUCT_PACKAGES += LiveWallpapers
#  PRODUCT_PACKAGES += LiveWallpapersPicker
#  PRODUCT_PACKAGES += MagicSmokeWallpapers
#  PRODUCT_PACKAGES += VisualizationWallpapers
#  PRODUCT_PACKAGES += Galaxy4
#  PRODUCT_PACKAGES += HoloSpiralWallpaper
#  PRODUCT_PACKAGES += NoiseField
#  PRODUCT_PACKAGES += PhaseBeam
#endif</span></strong>


这里我们已经把系统动态壁纸去掉了,接下来就是添加客供壁纸到 launcher3 ,这里其实开始的时候我也没有思路,我是根据系统原生 launcher3 AndroidMainfest.xml 分析出

来的,关于壁纸添加的函数

WallpaperPickerActivity extends WallpaperCropActivity 相关处理就在 WallpaperPickerActivity 类 ,WallpaperPickerActivity 有一个 init 函数,init 函数重要信息

<strong><span style="color:#3366ff;">    // called by onCreate; this is subclassed to overwrite WallpaperCropActivityprotected void init() {setContentView(R.layout.wallpaper_picker);
......// Populate the built-in wallpapersArrayList<WallpaperTileInfo> wallpapers = findBundledWallpapers();// 我们要找的关键函数mWallpapersView = (LinearLayout) findViewById(R.id.wallpaper_list);SimpleWallpapersAdapter ia = new SimpleWallpapersAdapter(this, wallpapers);populateWallpapersFromAdapter(mWallpapersView, ia, false);// Populate the saved wallpapers
......}</span></strong>


findBundledWallpapers() 函数


<strong><span style="color:#3366ff;">    private ArrayList<WallpaperTileInfo> findBundledWallpapers() {final PackageManager pm = getPackageManager();// 保存 WallpaperTileInfo 的集合final ArrayList<WallpaperTileInfo> bundled = new ArrayList<WallpaperTileInfo>(24);// 获取单例 partner实例对象Partner partner = Partner.get(pm);if (partner != null) {final Resources partnerRes = partner.getResources();// getIdentifier 机制加载res文件,但是 Partner.RES_WALLPAPERS并不存在,所以我们跳过该段final int resId = partnerRes.getIdentifier(Partner.RES_WALLPAPERS, "array",partner.getPackageName());......}Pair<ApplicationInfo, Integer> r = getWallpaperArrayResourceId();//主要加载资源在该处if (r != null) {try {Resources wallpaperRes = getPackageManager().getResourcesForApplication(r.first);addWallpapers(bundled, wallpaperRes, r.first.packageName, r.second);// 加载壁纸资源的函数} catch (PackageManager.NameNotFoundException e) {}}if (partner == null || !partner.hideDefaultWallpaper()) {// Add an entry for the default wallpaper (stored in system resources)WallpaperTileInfo defaultWallpaperInfo =(Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT)? getPreKKDefaultWallpaperInfo(): getDefaultWallpaper();if (defaultWallpaperInfo != null) {bundled.add(0, defaultWallpaperInfo);}}return bundled;}</span></strong>


Partner.RES_WALLPAPERS

<strong><span style="color:#3366ff;">public class Partner {static final String TAG = "Launcher.Partner";/** Marker action used to discover partner */private static final StringACTION_PARTNER_CUSTOMIZATION = "com.android.launcher3.action.PARTNER_CUSTOMIZATION";public static final String RES_FOLDER = "partner_folder";public static final String RES_WALLPAPERS = "partner_wallpapers";// partner_wallpapers
......</span></strong>

getWallpaperArrayResourceId() 函数

<strong><span style="color:#3366ff;">    public Pair<ApplicationInfo, Integer> getWallpaperArrayResourceId() {// Context.getPackageName() may return the "original" package name,// com.android.launcher3; Resources needs the real package name,// com.android.launcher3. So we ask Resources for what it thinks the// package name should be.final String packageName = getResources().getResourcePackageName(R.array.wallpapers);try {ApplicationInfo info = getPackageManager().getApplicationInfo(packageName, 0);return new Pair<ApplicationInfo, Integer>(info, R.array.wallpapers);} catch (PackageManager.NameNotFoundException e) {return null;}}</span></strong>


getWallpaperArrayResourceId() 函数加载了一个 array ,索引这个array,他确实是存在的,下面我们继续看

addWallpapers(x,x,x,x)函数

<strong><span style="color:#3366ff;">    private void addWallpapers(ArrayList<WallpaperTileInfo> known, Resources res,String packageName, int listResId) {final String[] extras = res re.getStringArray(listResId);for (String extra : extras) {int resId = res.getIdentifier(extra, "drawable", packageName);if (resId != 0) {final int thumbRes = res.getIdentifier(extra + "_small", "drawable", packageName);if (thumbRes != 0) {ResourceWallpaperInfo wallpaperInfo =new ResourceWallpaperInfo(res, resId, res.getDrawable(thumbRes));known.add(wallpaperInfo);// Log.d(TAG, "add: [" + packageName + "]: " + extra + " (" + res + ")");}} else {Log.e(TAG, "Couldn't find wallpaper " + extra);}}}</span></strong>


addWallpapers(x,x,x,x)函数拿到 Resources 对象后,随即取出它的每一个子项保存在 String[] ,遍历每一个资源文件的对应name,通过Identifier机制获取 resID,但是在后面又

执行了

<strong><span style="color:#3366ff;">final int thumbRes = res.getIdentifier(extra + "_small", "drawable", packageName);if (thumbRes != 0) {ResourceWallpaperInfo wallpaperInfo =new ResourceWallpaperInfo(res, resId, res.getDrawable(thumbRes));known.add(wallpaperInfo);// Log.d(TAG, "add: [" + packageName + "]: " + extra + " (" + res + ")");}</span></strong>

在获得的资源名称中后缀.png之前添加了 _small ,看到这我已经猜出代码的用意了,然后判断该资源文件id是否存在,存在即保存到info在保存到集合,下面解释下添加后缀

_small 的用意,起始就是在我们长按系统 launcher 主界面之后,会弹出 wallpaper 和 widget 选项,当我们选择壁纸之后,会看到一个水平划动得滚动跳,里面有壁纸的缩略

图,而_small就是缩略图,而与之对应的不带这个后缀的则是高清壁纸图,于是我在 wallpapers array 添加了9张壁纸文件的名字,并且将图片资源放进了对应的drawable-

xxxx文件中

wallpapers array:

<strong><span style="color:#3366ff;"><!--Engineer-Jsp add -->
<resources><string-array name="wallpapers" translatable="false"><item>wallpaper_01</item><item>wallpaper_02</item><item>wallpaper_03</item><item>wallpaper_04</item><item>wallpaper_05</item><item>wallpaper_06</item><item>wallpaper_07</item><item>wallpaper_08</item><item>wallpaper_09</item></string-array>
</resources></span></strong>


 剩下的就是制作缩略图,但是缩略图的大小我们是不知道的,所以要继续查看代码

在导出的系统原生 launcher code 中使用eclipse快捷键 ctrl+o(字母o),输入get...看到 getDefaultThumbnailSize()函数,即意为缩略图的默认大小

getDefaultThumbnailSize()函数

<strong><span style="color:#3366ff;">    private static Point getDefaultThumbnailSize(Resources res) {return new Point(res.getDimensionPixelSize(R.dimen.wallpaperThumbnailWidth),res.getDimensionPixelSize(R.dimen.wallpaperThumbnailHeight));}</span></strong>


<strong><span style="color:#3366ff;"><resources>
<!-- Wallpaper picker --><dimen name="wallpaperThumbnailWidth">106.5dp</dimen><dimen name="wallpaperThumbnailHeight">94.5dp</dimen><dimen name="wallpaperItemIconSize">32dp</dimen>
</resources></span></strong>


这样就拿到了系统加载缩略图的默认宽高了,接下来就是ps设置,因为本人对ps是相当的精通,所以这里我也介绍一下怎么去编辑这个缩略图,并且教你最傻瓜式的快捷键操

作,几不到一分钟就可以全部搞定

首先打开photoshop工具,ctrl+o(选择要编辑的资源文件后回车)→ ctrl+alt+i (设置宽高后回车)→ ctrl+shift+s(另存为原文件名字+“_samll”+.png)+回车 ,OK制作完成!



文件列表:


修改完毕之后 make clean 工程,在执行 make -jxx 编译系统源码,效果图如下


③ remove system shared tiem Android Beam


这个看似似乎没有难度,等到你自己去改的时候就不会这样想了,不信你可以去试试,嘿嘿,当练手

那我就不介绍索引步骤了,反正关联文件不再最上层,而是在源码里面,改的地方也是在源码,我改之前也走过很多弯路,最后才纠正这个错误

那我就直接讲我的改法吧,改之前的搜索努力就不提了,直接讲改法,及常见错误

frameworks\base\core\java\android\widget\ActivityChooserView.java

ActivityChooserView 里有一个内部类,即 ActivityChooserViewAdapter extends BaseAdapter 直接查看 getView()函数,因为这里是加载每一个ITEM的入口

<strong><span style="color:#3366ff;">        public View getView(int position, View convertView, ViewGroup parent) {final int itemViewType = getItemViewType(position);switch (itemViewType) {case ITEM_VIEW_TYPE_FOOTER: // 这里的分支为see all选项,默认 getcount+1 即最后一项,并且是 size>=5的情况下,这是系统做的自适应if (convertView == null || convertView.getId() != ITEM_VIEW_TYPE_FOOTER) {convertView = LayoutInflater.from(getContext()).inflate(R.layout.activity_chooser_view_list_item, parent, false);convertView.setId(ITEM_VIEW_TYPE_FOOTER);TextView titleView = (TextView) convertView.findViewById(R.id.title);titleView.setText(mContext.getString(R.string.activity_chooser_view_see_all));}return convertView;// 我第一次修改的地方,也是第一次犯错的地方   case ITEM_VIEW_TYPE_ACTIVITY:// 默认3个item显示see all 如果size<5的情况下,see all 将隐藏,显示所有item(<5的情况下)// 该处未被注释之前,这是我走的第二个错误
//                  if(!activity.activityInfo.packageName.equals("com.android.nfc")){if (convertView == null || convertView.getId() != R.id.list_item) {convertView = LayoutInflater.from(getContext()).inflate(R.layout.activity_chooser_view_list_item, parent, false);}PackageManager packageManager = mContext.getPackageManager();// resolve.activityInfo.packageName ------ com.android.nfcResolveInfo activity = (ResolveInfo) getItem(position);// Set the iconImageView iconView = (ImageView) convertView.findViewById(R.id.icon);iconView.setImageDrawable(activity.loadIcon(packageManager));// Set the title.TextView titleView = (TextView) convertView.findViewById(R.id.title);titleView.setText(activity.loadLabel(packageManager));// 这是我走的第一个错误,即阻止系统编译该分享apk文件// titleView.setText(activity.activityInfo.packageName); // 在这一块我注释掉了 label ,取而代之的是包名,因为我打算把这个应用直接在 系统编译之前,不编译这个系统app// 取到的包名 com.android.nfc,之后执行命令,索引项目所在 project// Highlight the default.if (mShowDefaultActivity && position == 0 && mHighlightDefaultActivity) {convertView.setActivated(true);} else {convertView.setActivated(false);}
//                  }return convertView;default:throw new IllegalArgumentException();}</span></strong>


索引 package name


project name is Nfc ,那么问题来了,我们怎么取消系统编译这个apk呢,继续索引mk文件


编辑 mk 文件


注释掉该处之后,使用抓包工具和在后台查看发现nfc确实不存在了,但是令我不爽的是,Android Beam 分享子项依然还在!这就是我犯得第一个错误,后来我尝试通过包名来

隐藏对应的position选项,但是出现了莫名的错误,同时出现了好几个不见,然后下一次又是其他的不见,很奇怪,至今不知道原因,因为我已经把限制条件写死了!这是我犯

得第二个错误,于是乎我打算从BaseAdapter的原始加载数据模型下手,查看 ActivityChooserViewAdapter 这个内部类适配器,追朔如下函数

<strong><span style="color:#3366ff;">private ActivityChooserModel mDataModel;</span></strong>
<strong><span style="color:#3366ff;">        public void setDataModel(ActivityChooserModel dataModel) {Log.d(LOG_TAG, "ActivityChooserViewAdapter.setDataModel" +", dataModel = " + dataModel + ", isShown = " + isShown());ActivityChooserModel oldDataModel = mAdapter.getDataModel();if (oldDataModel != null && isShown()) {oldDataModel.unregisterObserver(mModelDataSetOberver);}mDataModel = dataModel;if (dataModel != null && isShown()) {dataModel.registerObserver(mModelDataSetOberver);}notifyDataSetChanged();}</span></strong>


<strong><span style="color:#3366ff;">        public int getCount() {int count = 0;int activityCount = mDataModel.getActivityCount();if (!mShowDefaultActivity && mDataModel.getDefaultActivity() != null) {activityCount--;}count = Math.min(activityCount, mMaxActivityCount);if (mShowFooterView) {count++;}return count;}</span></strong>


我继续追朔 ActivityChooserModel.getDefaultActivity() 的函数,意图在原始数据模型改变这个模型的内部结构

<strong><span style="color:#3366ff;">    /*** Gets the default activity, The default activity is defined as the one* with highest rank i.e. the first one in the list of activities that can* handle the intent.** @return The default activity, <code>null</code> id not activities.** @see #getActivity(int)*/public ResolveInfo getDefaultActivity() {synchronized (mInstanceLock) {ensureConsistentState();if (!mActivities.isEmpty()) {return mActivities.get(0).resolveInfo;}}return null;}</span></strong>


ensureConsistentState()

<strong><span style="color:#3366ff;">    /*** Ensures the model is in a consistent state which is the* activities for the current intent have been loaded, the* most recent history has been read, and the activities* are sorted.*/private void ensureConsistentState() {boolean stateChanged = loadActivitiesIfNeeded();stateChanged |= readHistoricalDataIfNeeded();pruneExcessiveHistoricalRecordsIfNeeded();if (stateChanged) {dumpActivities();// 我追朔的函数sortActivitiesIfNeeded();notifyChanged();}}</span></strong>


<strong><span style="color:#3366ff;">    /*** M: For debug. Dump activities associated with the current intent.*/private void dumpActivities() {Log.d(LOG_TAG, "dumpActivities starts.");List<ActivityResolveInfo> activities = mActivities;//追朔 mActivities的add()函数final int activityCount = activities.size();for (int i = 0; i < activityCount; i++) {ActivityResolveInfo currentActivity = activities.get(i);Log.d(LOG_TAG, "  i = " + i + ", activity = " + currentActivity);}Log.d(LOG_TAG, "dumpActivities ends.");}</span></strong>
<strong><span style="color:#3366ff;">    /*** Loads the activities for the current intent if needed which is* if they are not already loaded for the current intent.** @return Whether loading was performed.*/private boolean loadActivitiesIfNeeded() {if (mReloadActivities && mIntent != null) {mReloadActivities = false;mActivities.clear();// 加载本次数据模型之前,清除掉之前的数据模型集List<ResolveInfo> resolveInfos = mContext.getPackageManager().queryIntentActivities(mIntent, 0);final int resolveInfoCount = resolveInfos.size();for (int i = 0; i < resolveInfoCount; i++) {// 循环读取ResolveInfo resolveInfo = resolveInfos.get(i);ActivityInfo activityInfo = resolveInfo.activityInfo;if (ActivityManager.checkComponentPermission(activityInfo.permission,android.os.Process.myUid(), activityInfo.applicationInfo.uid,activityInfo.exported) == PackageManager.PERMISSION_GRANTED) { 判断获取该应用是否具备某一项权限// Engineer-Jsp add remove system default share application com.android.nfcif(android.os.SystemProperties.isWalPadVersion()){// 我在此处添加了我的限制模型条件,即 model 值 为 walpad c 返回true if(!resolveInfo.activityInfo.packageName.equals("com.android.nfc")){// 包名不为 com.android.nfc 时加载,这样就可以剔除掉Android Beam,因为ActivityChooser.ActivityChooserViewAdapter的getcount是根据模型而改变的mActivities.add(new ActivityResolveInfo(resolveInfo));}}else{mActivities.add(new ActivityResolveInfo(resolveInfo));}}}Log.d(LOG_TAG, "loadActivitiesIfNeeded, activities updated, mIntent = " + mIntent);return true;}return false;}</span></strong>


改完代码之后,重新make 工程,烧录固件,效果如下:


因为getcount<5,所以系统把see all 隐藏掉了,即最后一项(getcount+1)的查看所有可分享的子项

至此,今天所有分享的都已经分享完了,谢谢大家观博

Android系统之路(初识MTK) ------ (详细精华)添加客供系统壁纸去除系统动态壁纸/Camera默认fine/remove android beam相关推荐

  1. Android系统之路(初识MTK) ------ Default Voice Control/输入法校准、自动校准、首字母大写、按键声音

    今天给大家分享MTK平台系统编程与修改的另一个部分,分别是输入法校准.自动校准默认关.首字母大写默认开.按键声音默认关.Voice Control 移除系统中文,默认 英文,下面一个一个的介绍给大家 ...

  2. Android系统之路(初识MTK) ------Android11.0给系统相机添加闪光灯低电Toast提醒

    Android11.0给相机添加低电Toast提醒 修改前的效果:当电量小于等于15%时,可以点击按钮进行操作但没有实际去打开闪光灯,因为底层添加了判断,当系统电量小于等于15%时,是不会去执行打开闪 ...

  3. Android系统之路(初识MTK) ------ 内置三方apk到Rom可移动/可卸载

    客户给了一个内置他们自己apk的需求,定制到Rom里,我们需要在编译系统源码的时候配置好相关的文件即可将apk一起打包到ROM里面,下面我们就来一起打包apk到系统 首先需要在 device/medi ...

  4. Android系统之路(初识MTK) ------ OTA打包ROM安装系统img等到ZIP

    在做OTA升级包的时候,我编译了好多次都没过,老是IO异常,刚开始以为是我 make 的错误,后来多次检查 Error 发现是我的配置信息写错了,与驱动工程师一起检查源码, 修改配置信息后再次 OTA ...

  5. Android系统之路(初识MTK) ------ 设置系统默认语言/客制化可选语言/设置默认时区

    在这一版本的平板系统定制中,客户需要定制系统默认语言,默认英语,可选语种分别是 语言代码      国家/地区 bn_BD      孟加拉语(孟加拉) en_US      英文  ar       ...

  6. linux系统下的动态壁纸,桌面应用|动态壁纸给linux发行版添加活力背景

    我们知道你想拥有一个有格调的ubuntu桌面来炫耀一下 :) 在linxu上费一点点劲搭建一个出色的工作环境是很简单的.今天,我们(重新)着重来探讨长驻你脑海中那些东西 :一款自由,开源,能够给你的截 ...

  7. Android动态壁纸选择器插件,动态壁纸选择器(动态壁纸插件安装)

    动态壁纸选择器(动态壁纸插件安装) macOS 10.14 开始加入了一项可以根据时间变化动态调整桌面的新特性:动态桌面.它可以让我们的桌面壁纸跟随一天从早到晚的时间变化呈现不同的视觉效果.配合明.暗 ...

  8. Android 壁纸应用之动态壁纸

    效果图,图中桌面背景为一段视频 对动态壁纸进行一些设置 在res下创建一个xml文件夹,在创建一个wallpager标签文件 <?xml version="1.0" enco ...

  9. android壁纸制作,安卓动态壁纸制做壁纸的方法教程

    现在很 多人 都喜欢为自己心爱的手机加上手机套和手机里的独特 壁纸 .如果我们已经不满住与壁纸软件里的那些常见壁纸,想要自己制作独一无二的壁纸时,该怎么操作呢?下面小编来为大家介绍 一下使用安卓动态壁 ...

最新文章

  1. 3dmax做的模型导入U3d后 当模型靠近摄像机时镂空问题
  2. 上传文件到 Web 服务器
  3. iphone导出照片到电脑_如何把 iPhone 中的照片快速传到电脑上?
  4. Rust:集所有语言之大成者
  5. 【转】Maya Mel – Search String in String
  6. 自定义sql_一个简单易用的开源BI软件,专为SQL用户设计的开源库
  7. 在Spring Boot中使用@ConfigurationProperties
  8. 西交大计算机考博学术英语,2018年西安交通大学考博英语真题
  9. mysql linux设置密码_Linux下第一次使用MySQL数据库,设置密码
  10. python RTL自动生成_用Python自动生成快闪文字视频
  11. xcode9真机调试
  12. 论述多媒体技术和计算机技术的发展,多媒体技术的发展现状和未来.doc
  13. H.323-SIP信令网关
  14. 微信小程序——1、搭建自己的Https服务器
  15. Java 标识符的命名规则与规范
  16. 白名单模板_亚马逊白名单申请流程全解析
  17. 大数据开发工程师岗位分析
  18. MySQL 中STD、STDDEV、STDDEV_SAMP 标准差函数的区别
  19. Win11如何更改屏幕刷新率?Win11更改屏幕刷新率的方法
  20. ui设计需要学编程吗难不难学习

热门文章

  1. Stable Diffusion公司新作Gen-1:基于扩散模型的视频合成新模型,加特效杠杠的!...
  2. 志向在沉重的青春下腾飞
  3. C++通过邻接矩阵求连通分量(BFS)
  4. 利用GEE计算城市遥感生态指数(RSEI)——Landsat 8为例
  5. 遭遇auto.exe,Hack.ArpCheater.a(ARP欺骗工具),Trojan.PSW.ZhengTu等2
  6. 小孩鼻子出血七种原因(小孩流鼻血是什么原因儿童鼻出血怎么回事
  7. 软件项目将死的27个征兆
  8. Eclipse在包下新建子包
  9. js 获取当前域名的写法
  10. 对接合作加入社区团购平台快速卖货,你都知道吗?