Android插件化的思考仿QQ一键换肤思考比实现更重要.docx

上传人:b****5 文档编号:2889902 上传时间:2022-11-16 格式:DOCX 页数:15 大小:489.67KB
下载 相关 举报
Android插件化的思考仿QQ一键换肤思考比实现更重要.docx_第1页
第1页 / 共15页
Android插件化的思考仿QQ一键换肤思考比实现更重要.docx_第2页
第2页 / 共15页
Android插件化的思考仿QQ一键换肤思考比实现更重要.docx_第3页
第3页 / 共15页
Android插件化的思考仿QQ一键换肤思考比实现更重要.docx_第4页
第4页 / 共15页
Android插件化的思考仿QQ一键换肤思考比实现更重要.docx_第5页
第5页 / 共15页
点击查看更多>>
下载资源
资源描述

Android插件化的思考仿QQ一键换肤思考比实现更重要.docx

《Android插件化的思考仿QQ一键换肤思考比实现更重要.docx》由会员分享,可在线阅读,更多相关《Android插件化的思考仿QQ一键换肤思考比实现更重要.docx(15页珍藏版)》请在冰豆网上搜索。

Android插件化的思考仿QQ一键换肤思考比实现更重要.docx

Android插件化的思考仿QQ一键换肤思考比实现更重要

Android插件化的思考——仿QQ一键换肤,思考比实现更重要!

关于QQ的换肤,他们的实现思路我不是很清楚,但是你可以看一下这张换肤的截图

我们想使用哪个主题就直接下载就好了,这一实现的过程我们大致的可以猜想:

首选是下载到本地指定文件夹,然后通过插件加载到我们的apk,最后应用为皮肤,逻辑大致是这样的逻辑了,那我们是不是应该动动手啊动动脑?

首选我们新建一个工程好了——PlugInSample

一.实现思路

其实说起来,这个插件的实现思路,确实是比较的麻烦,思来想去,还是一种办法比较靠谱,首先,我们刻意去获取手机上所有的安装的/未安装的程序,过滤掉没用的,留下我们的插件apk,我们的插件apk怎么去辨别呢?

我们可用通过设置sharedUserId,然后用实体类把插件名称和包名保存下来,有了包名,就比较好说了,我们可用获取插件的上下文,也就是createPackageContext,然后就可以做点坏事了,我们可以去剖析我们的R文件

因为R文件里面都是静态的原因,我们很容易联想到反射机制,是的,我们可以再一次过滤掉无用的信息,通过我们的PathClassLoader去加载,访问我们的内加载器反射到我们的图片ID,也就是后面的那段数字,然后,嘿嘿,就可以使用了,是不是思路比较清晰了?

这里要注意的就是图片命名统一,这样就比较号过来,那具体我们应该怎么做?

二.PlugIn主程序

我们写一个Spinner,每次切换就直接换肤怎么样?

OK,每次换的时候就从插件APK里加载我们的图片资源,看起来是比较顺畅的逻辑,那我们具体该怎么做呢?

xmlversion="1.0"encoding="utf-8"?

>

android:

id="@+id/mLinearLayout"

xmlns:

android="

android:

layout_width="match_parent"

android:

layout_height="match_parent"

android:

gravity="center"

android:

orientation="vertical">

android:

id="@+id/mSpinner"

android:

layout_width="wrap_content"

android:

layout_height="wrap_content"/>

1.初始化

/**

*初始化View

*/

privatevoidinitView(){

//初始化控件

mSpinner=(Spinner)findViewById(R.id.mSpinner);

}

当然,我这刚应用就一个View,但是实际开发当中可不止,所以步骤一定要明了

2.获取所有的插件

/**

*获取手机里的插件

*

*@return

*/

privateListfindPlugIn(){

mList=newArrayList<>();

//获取相关信息

PackageManagermPackageManager=getPackageManager();

//获取卸载/未安装的安装包信息

ListmUninstallPackage=mPackageManager.getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES);

//遍历拿到我们的信息

for(PackageInfoinfo:

mUninstallPackage){

StringpkgNmae=info.packageName;

//获取shareId,根据id判断是否是我们的ID

StringshareUserId=info.sharedUserId;

if(!

TextUtils.isEmpty(shareUserId)){

//如果id相同

if(shareUserId.equals("com.liuguilin.share")){

//且排除自己的包名

if(!

pkgNmae.equals(getPackageName())){

//这个就是我们的插件了

Stringlable=mPackageManager.getApplicationLabel(info.applicationInfo).toString();

PlugInBeanbean=newPlugInBean();

bean.setLabelNmae(lable);

bean.setPackagNmae(pkgNmae);

mList.add(bean);

}

}

}

}

returnmList;

}

这里就是过滤了一下,通过sharedUserId去拿到我们的插件APK了,然后就可以拿到我们的包名和应用名,他返回给我们一个数据集

//所有的插件

ListallPlugIn=findPlugIn();

3.加载皮肤数据

/**

*加载皮肤

*

*@paramallPlugIn

*/

privatevoidLoadSkin(ListallPlugIn){

//遍历

for(PlugInBeanbean:

allPlugIn){

HashMapmMap=newHashMap<>();

mMap.put("lable",bean.getLabelNmae());

mMap.put("package",bean.getPackagNmae());

mData.add(mMap);

}

//建立Adapter并且绑定数据源

mAdapter=newSimpleAdapter(this,mData,android.R.layout.simple_list_item_1,newString[]{"lable"},newint[]{android.R.id.text1});

//设置数据

mSpinner.setAdapter(mAdapter);

//设置监听事件

mSpinner.setOnItemSelectedListener(this);

}

我们通过刚才的数据集便可以把我们拿到的数据给直接显示出来了,这里其实可以判断一下size是否为0,如果为0的话也就没有插件,OK,我们设置adapter和监听,做到这里,其实你可以运行一下,虽然我们现在什么都没有,我们要做的还有很多

4.获取插件Context

/**

*选中监听事件

*

*@paramadapterView

*@paramview

*@parami

*@paraml

*/

@Override

publicvoidonItemSelected(AdapterView

>adapterView,Viewview,inti,longl){

PlugInBeanbean=mList.get(i);

//插件的包名

StringpackageNmae=bean.getPackagNmae();

ContextmContext=null;

try{

//无视警告访问代码

mContext=createPackageContext(packageNmae,CONTEXT_IGNORE_SECURITY|CONTEXT_INCLUDE_CODE);

}catch(PackageManager.NameNotFoundExceptione){

e.printStackTrace();

}

//获取图片

getImg(packageNmae,mContext);

//通过ID加载插件的图片

getWindow().setBackgroundDrawable(mContext.getResources().getDrawable(mListId.get(i)));

}

@Override

publicvoidonNothingSelected(AdapterView

>adapterView){

}

这里的代码就比较有意思,一定要仔细看,我们首先拿到选中的item的包名,通过我们的createPackageContext拿到我们的上下文,通过这两个我们可用拿到我们的资源ID,也就是R清单里面的ID,然后直接设置window的背景,这里为了好看才设置window的背景,实际上你要设置的是你根布局的背景,那好,我们来看一下如何通过插件的上下文和包名拿到R清单的资源ID

5.获取插件图片/返回图片R文件ID/反射R文件

/**

*获取插件图片/返回图片R文件ID/反射R文件

*

*@parampackageNmae

*@parammContext

*/

privatevoidgetImg(StringpackageNmae,ContextmContext){

//类加载器反射插件

PathClassLoaderpathClass=newPathClassLoader(mContext.getPackageResourcePath(),ClassLoader.getSystemClassLoader());

//反射$访问类加载器

try{

Class

>forNmae=Class.forName(packageNmae+".R$drawable",true,pathClass);

//拿到所有图片的id

Field[]files=forNmae.getDeclaredFields();

for(Fieldid:

files){

//过滤/这里的命名可以注意一下

if(id.getName().startsWith("img")){

intdrawId=0;

////这就是我们图片R下的ID

drawId=id.getInt(R.drawable.class);

mListId.add(drawId);

}

}

}catch(ClassNotFoundExceptione){

e.printStackTrace();

}catch(IllegalAccessExceptione){

e.printStackTrace();

}

}

这里我们做了很多事情,首选是拿到我们的类加载器去反射我们的插件,然后通过Class去拿我们的资源,这里注意packageNmae是我们的文件目录,他下面的R文件,$代表类部类的意思,他下面的drawable子节点,然后再一次过滤,过滤之后我们可用遍历一遍拿到我们的ID用List保存起来,也就有了我们选中的时候的设置,好的,到这里主程序算是编写完成了,不过要注意的是,记住要添加sharedUserId啊,至关重要!

android:

sharedUs

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 表格模板 > 调查报告

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1