基于android的主题插件编写
前一段,写了一个主题插件,刚接到这个任务时,根本不知道从哪下手,于是就上网搜了一些资料,下面来讲一下我是怎么做这个主题插件的。
首先,我们需要引入一个插件包。这个架包是从网上下的,该作者的博客地址:
http://hangxin1940.cnblogs.com/
。这个架包封装了查找插件的功能,查找插件功能的功能等等,不需要我们自己在写,很方便。大家可以看看。
其次,我们要对自己的主程序的AndroidManifest.xml进行修改.
<
manifest
xmlns:android
=
“http://schemas.android.com/apk/res/android”
package
=
”
你的app
包名”
android:sharedUserId
=
”
你自己设的”
android:versionCode
=
“1”
android:versionName
=
“1.0”
>
这里的package和sharedUserId都是必须写的。写package方便我们在主程序中获取插件的Context对象,去引用插件的内部资源。而sharedUserId的值必须和主程序一致,可以保证我们的插件和主程序共享一个进程,消除权限堡垒,方便我们共享两个程序之间的资源
。
接下来,我们需要在主程序中写查找插件的代码
//
首先,就是查找插件
PluginSearchpsearch =
new
PluginSearch();
List<Plugin>plugins = psearch.getPlugins(context);
//
然后将插件再组装一下
PluginBuilderpbuilder =
new
PluginBuilder(context);
plugins= pbuilder.buildPluginsDescrition(plugins);
//
显示出所有插件
flateUI(plugins);
then,我们要显示插件皮肤,并调用插件中写的方法(即实现的功能)
for
(
final
Pluginplug : plugins) {
//
加入插件
ThemePluginItemitem =
new
ThemePluginItem(
this
);
//
获取插件的描述对象
PluginDescription<MainDescript> pdes =
new
PluginDescription<MainDescript>(
MainDescript.
class
);
MainDescriptdes;
try
{
des= pdes.getDescription(
this
, plug);
//
设置插件item
的描述信息
Drawabled = plug.getContext().getResources()
.getDrawable(des.getIconResId());
item.setDrawableTheme(d);
}
catch
(java.lang.InstantiationException e1) {
//
TODO
Auto-generated catch block
e1.printStackTrace();
}
//
获得当前插件的功能
List<PluginFeature>features = plug.getFeatures();
//
遍历功能
for
(
final
PluginFeature pf : features) {
for
(
final
PluginFeatureMethod fm : pf.getMethods()) {
//
添加插件,并且设置执行事件
item.addPluginMethod(fm,
new
OnClickListener(){
@Override
public
void
onClick(View v) {
PluginInvokepi =
new
PluginInvoke(getApplicationContext());
try
{
try
{
pi.invoke(plug,pf, fm);
}
catch
(java.lang.InstantiationExceptione) {
e.printStackTrace();
}
//注意这个地方:我本想用反射在插件中调用主程序的方法,但是一直出错。
//并不是主程序的所有资源我们都可以调用的,比如说控件,我们是不可能使用其他应用程序的//插件的,所以一些功能还是要在主程序中写的
if
(
mIsUpdate
){
setBabySkinIsupdate();
}
else
{
setBabySkin();
}
alertDialog
.dismiss();
}
catch
(SecurityException e) {
//
TODO
Auto-generated catch block
e.printStackTrace();
}
catch
(IllegalArgumentException e) {
//
TODO
Auto-generated catch block
e.printStackTrace();
}
catch
(NameNotFoundException e) {
//
TODO
Auto-generated catch block
e.printStackTrace();
}
catch
(ClassNotFoundException e) {
//
TODO
Auto-generated catch block
e.printStackTrace();
}
catch
(IllegalAccessException e) {
//
TODO
Auto-generated catch block
}
catch
(InstantiationException e) {
//
TODO
Auto-generated catch block
e.printStackTrace();
}
catch
(NoSuchMethodException e) {
//
TODO
Auto-generated catch block
e.printStackTrace();
}
catch
(InvocationTargetException e) {
//
TODO
Auto-generated catch block
e.printStackTrace();
}
}
});
}
}
//
将插件加入到
ui
addThemeLayout
.addView(item);
}
主程序中还需要再写一个类,来调用执行插件的功能,这是ThemePluginItem类中执行插件方法的代码
public
void
addPluginMethod(PluginFeatureMethod method,OnClickListener ocl){
//这是调用插件方法的接口形式,可以是Button控件在主程序中显示,也可以是ImageView等其他控件。
ImageViewthemeImageView =
new
ImageView(
mContext
);
LinearLayout.LayoutParamslayoutParams =
new
LinearLayout.LayoutParams(75, 75);
layoutParams.setMargins(7,5, 5, 5);
themeImageView.setLayoutParams(layoutParams);
//themeImageView.setImageResource(R.drawable.baby_info_pink);
themeImageView.setImageDrawable(getDrawableTheme());
themeImageView.setAdjustViewBounds(
false
);
themeImageView.setClickable(
true
);
themeImageView.setScaleType(ScaleType.
CENTER
);
//这是触发插件的功能
themeImageView.setOnClickListener(ocl);
//我们要把插件放到主程序中显示
otherThemeLayout
.addView(themeImageView);
}
以上是主程序中查找插件并调用插件的过程,下面讲一下插件中的功能是怎么共享主程序的文件。
我们知道在写主题功能时,为了分清我们触发的是哪个皮肤,我们需要为每个皮肤进行编号,并把这些内容用Sharepreference方法存储到一个文件中,方便我们调用和使用,但是在插件中如何去共享并操作这份文件呢,android已经为我们提供这样一些参数
MODE_PRIVATE 0 代表了该文件只为本程序所访问
MODE_WORLD_READABLE 1 代表了该文件可以被其他程序读取
MODE_WORLD_WRITEABLE 2 代表了该文件可以被其他程序写
//首先,我们需要得到主程序的context对象
Contextc= context.createPackageContext(
你要调用的项目的包名
, Context.
CONTEXT_INCLUDE_CODE
|Context.
CONTEXT_IGNORE_SECURITY
);
//这里面有两个参数,第一个是你的文件名,第二个:设置你的文件权限
SharedPreferencesmSharedPreferences = c.getSharedPreferences(
你要调用的项目的包名
, context.
MODE_WORLD_READABLE
|context.
MODE_WORLD_WRITEABLE
);
EditormEditor = mSharedPreferences.edit();
//获取该文件的isupdate对应的值
boolean
mIsUpdate= mSharedPreferences.getBoolean(
“isupdate”
,
false
);
//在文件中写入自己想存入的值
mEditor.putInt(mBabyID+ “”, mNewBabySkin);
这样我们就达到了共享文件的功能。
前面已经说明我们无法共享控件,所以设置主程序的皮肤还是要是要在主程序中设置。
在这个环节,最重要的就是获取插件的资源
//获取插件的Context对象
Context c=context.createPackageContext(
你要调用的项目的包名
,
Context.
CONTEXT_INCLUDE_CODE
|Context.
CONTEXT_IGNORE_SECURITY
);
//获取插件的资源resources对象,这样我们就可以获取插件中的资源
ResourcespluginResources = c.getResources();
//获取插件中的图片,这里千万不要以为只用获取插件图片的ID,就可以让主程序来引用,我们要知道每个应用程序都有一个R文件,这里面的数都是自动生成且唯一的,而且只包含本程序的资源,所以我们要用这种方法获得插件中的图片资源
babyYellowBg =pluginResources.getDrawable(pluginResources.getIdentifier(
”
你的图片名称”
,
“drawable”
,
你要调用的项目的包名
));
在这里我们的主程序就可以直接引用了
scrollView.setBackgroundDrawable(babyYellowBg);
最后,
我需要告诉你大家,我们在主程序中引用插件中的资源或者插件引用主程序中的资源时,不能引用style.xml中的值,因为他属于多属性值,android还没有提供相应的方法来直接引用,如果哪位读者找到了读取插件style文件的方法,还望不吝赐教
基于android的主题插件编写
前一段,写了一个主题插件,刚接到这个任务时,根本不知道从哪下手,于是就上网搜了一些资料,下面来讲一下我是怎么做这个主题插件的。
首先,我们需要引入一个插件包。这个架包是从网上下的,该作者的博客地址:
http://hangxin1940.cnblogs.com/
。这个架包封装了查找插件的功能,查找插件功能的功能等等,不需要我们自己在写,很方便。大家可以看看。
其次,我们要对自己的主程序的AndroidManifest.xml进行修改.
<
manifest
xmlns:android
=
“http://schemas.android.com/apk/res/android”
package
=
”
你的app
包名”
android:sharedUserId
=
”
你自己设的”
android:versionCode
=
“1”
android:versionName
=
“1.0”
>
这里的package和sharedUserId都是必须写的。写package方便我们在主程序中获取插件的Context对象,去引用插件的内部资源。而sharedUserId的值必须和主程序一致,可以保证我们的插件和主程序共享一个进程,消除权限堡垒,方便我们共享两个程序之间的资源
。
接下来,我们需要在主程序中写查找插件的代码
//
首先,就是查找插件
PluginSearchpsearch =
new
PluginSearch();
List<Plugin>plugins = psearch.getPlugins(context);
//
然后将插件再组装一下
PluginBuilderpbuilder =
new
PluginBuilder(context);
plugins= pbuilder.buildPluginsDescrition(plugins);
//
显示出所有插件
flateUI(plugins);
then,我们要显示插件皮肤,并调用插件中写的方法(即实现的功能)
for
(
final
Pluginplug : plugins) {
//
加入插件
ThemePluginItemitem =
new
ThemePluginItem(
this
);
//
获取插件的描述对象
PluginDescription<MainDescript> pdes =
new
PluginDescription<MainDescript>(
MainDescript.
class
);
MainDescriptdes;
try
{
des= pdes.getDescription(
this
, plug);
//
设置插件item
的描述信息
Drawabled = plug.getContext().getResources()
.getDrawable(des.getIconResId());
item.setDrawableTheme(d);
}
catch
(java.lang.InstantiationException e1) {
//
TODO
Auto-generated catch block
e1.printStackTrace();
}
//
获得当前插件的功能
List<PluginFeature>features = plug.getFeatures();
//
遍历功能
for
(
final
PluginFeature pf : features) {
for
(
final
PluginFeatureMethod fm : pf.getMethods()) {
//
添加插件,并且设置执行事件
item.addPluginMethod(fm,
new
OnClickListener(){
@Override
public
void
onClick(View v) {
PluginInvokepi =
new
PluginInvoke(getApplicationContext());
try
{
try
{
pi.invoke(plug,pf, fm);
}
catch
(java.lang.InstantiationExceptione) {
e.printStackTrace();
}
//注意这个地方:我本想用反射在插件中调用主程序的方法,但是一直出错。
//并不是主程序的所有资源我们都可以调用的,比如说控件,我们是不可能使用其他应用程序的//插件的,所以一些功能还是要在主程序中写的
if
(
mIsUpdate
){
setBabySkinIsupdate();
}
else
{
setBabySkin();
}
alertDialog
.dismiss();
}
catch
(SecurityException e) {
//
TODO
Auto-generated catch block
e.printStackTrace();
}
catch
(IllegalArgumentException e) {
//
TODO
Auto-generated catch block
e.printStackTrace();
}
catch
(NameNotFoundException e) {
//
TODO
Auto-generated catch block
e.printStackTrace();
}
catch
(ClassNotFoundException e) {
//
TODO
Auto-generated catch block
e.printStackTrace();
}
catch
(IllegalAccessException e) {
//
TODO
Auto-generated catch block
}
catch
(InstantiationException e) {
//
TODO
Auto-generated catch block
e.printStackTrace();
}
catch
(NoSuchMethodException e) {
//
TODO
Auto-generated catch block
e.printStackTrace();
}
catch
(InvocationTargetException e) {
//
TODO
Auto-generated catch block
e.printStackTrace();
}
}
});
}
}
//
将插件加入到
ui
addThemeLayout
.addView(item);
}
主程序中还需要再写一个类,来调用执行插件的功能,这是ThemePluginItem类中执行插件方法的代码
public
void
addPluginMethod(PluginFeatureMethod method,OnClickListener ocl){
//这是调用插件方法的接口形式,可以是Button控件在主程序中显示,也可以是ImageView等其他控件。
ImageViewthemeImageView =
new
ImageView(
mContext
);
LinearLayout.LayoutParamslayoutParams =
new
LinearLayout.LayoutParams(75, 75);
layoutParams.setMargins(7,5, 5, 5);
themeImageView.setLayoutParams(layoutParams);
//themeImageView.setImageResource(R.drawable.baby_info_pink);
themeImageView.setImageDrawable(getDrawableTheme());
themeImageView.setAdjustViewBounds(
false
);
themeImageView.setClickable(
true
);
themeImageView.setScaleType(ScaleType.
CENTER
);
//这是触发插件的功能
themeImageView.setOnClickListener(ocl);
//我们要把插件放到主程序中显示
otherThemeLayout
.addView(themeImageView);
}
以上是主程序中查找插件并调用插件的过程,下面讲一下插件中的功能是怎么共享主程序的文件。
我们知道在写主题功能时,为了分清我们触发的是哪个皮肤,我们需要为每个皮肤进行编号,并把这些内容用Sharepreference方法存储到一个文件中,方便我们调用和使用,但是在插件中如何去共享并操作这份文件呢,android已经为我们提供这样一些参数
MODE_PRIVATE 0 代表了该文件只为本程序所访问
MODE_WORLD_READABLE 1 代表了该文件可以被其他程序读取
MODE_WORLD_WRITEABLE 2 代表了该文件可以被其他程序写
//首先,我们需要得到主程序的context对象
Contextc= context.createPackageContext(
你要调用的项目的包名
, Context.
CONTEXT_INCLUDE_CODE
|Context.
CONTEXT_IGNORE_SECURITY
);
//这里面有两个参数,第一个是你的文件名,第二个:设置你的文件权限
SharedPreferencesmSharedPreferences = c.getSharedPreferences(
你要调用的项目的包名
, context.
MODE_WORLD_READABLE
|context.
MODE_WORLD_WRITEABLE
);
EditormEditor = mSharedPreferences.edit();
//获取该文件的isupdate对应的值
boolean
mIsUpdate= mSharedPreferences.getBoolean(
“isupdate”
,
false
);
//在文件中写入自己想存入的值
mEditor.putInt(mBabyID+ “”, mNewBabySkin);
这样我们就达到了共享文件的功能。
前面已经说明我们无法共享控件,所以设置主程序的皮肤还是要是要在主程序中设置。
在这个环节,最重要的就是获取插件的资源
//获取插件的Context对象
Context c=context.createPackageContext(
你要调用的项目的包名
,
Context.
CONTEXT_INCLUDE_CODE
|Context.
CONTEXT_IGNORE_SECURITY
);
//获取插件的资源resources对象,这样我们就可以获取插件中的资源
ResourcespluginResources = c.getResources();
//获取插件中的图片,这里千万不要以为只用获取插件图片的ID,就可以让主程序来引用,我们要知道每个应用程序都有一个R文件,这里面的数都是自动生成且唯一的,而且只包含本程序的资源,所以我们要用这种方法获得插件中的图片资源
babyYellowBg =pluginResources.getDrawable(pluginResources.getIdentifier(
”
你的图片名称”
,
“drawable”
,
你要调用的项目的包名
));
在这里我们的主程序就可以直接引用了
scrollView.setBackgroundDrawable(babyYellowBg);
最后,
我需要告诉你大家,我们在主程序中引用插件中的资源或者插件引用主程序中的资源时,不能引用style.xml中的值,因为他属于多属性值,android还没有提供相应的方法来直接引用,如果哪位读者找到了读取插件style文件的方法,还望不吝赐教
转载至:http://blog.csdn.net/a1027317350/article/details/9032417
