关于SDK
软件开发工具包(Software Development Kit, SDK)。SDK一般封装了一些功能(常见的比如:账号管理、支付、推送、统计等等),并提供了相关编程接口让第三方调用,SDK还经常包括示例代码、支持性的技术注解或者其他的为基本参考资料澄清疑点的支持文档。
SDK工程
首先我新建一个Android工程,并创建一个SDK类,该类提供两个方法:init用于初始化SDK,login是显示登录界面的方法。
package linchaolong.sdk;
import android.content.Context;
import android.content.Intent;
public class SDK {
private static Context _ctx;
/**
* 初始化SDK
*
* @param ctx
*/
public static void init(Context ctx){
_ctx = ctx;
// 使用动态加载资源id工具类方法前必须先设置上下文
Res.setContext(ctx);
}
/**
* 登录
*/
public static void login(){
_ctx.startActivity(new Intent(_ctx, SDKActivity.class));
}
}
现在我想把这两个接口提供给第三方调用。java代码可以打成jar,但资源文件,如layout、drawble、raw等等,不能直接打到jar里,否则找不到资源。一般资源文件是直接拷贝到第三方工程,或者提供一个库工程第三方引用库工程,或者资源放到assets目录下。
而且,在导出java代码的时候,不能把R.java导出到jar里面,资源id在第三方工程编译时才确定,在SDK工程里如果直接使用R.xxx.xxx(如R.layout.main),第三方工程运行时查找资源就会出错。所以这里资源的id需要动态加载。一般有两种解决方法:
1.通过Android SDK提供的方法获取资源id。Context.getResources().getIdentifier("资源名称", "资源类型", “包名”)方法获取资源id
2.通过java中的反射获取资源id。Class.forName("包名.R")得到R文件class对象,然后getField方法得到资源id。
这里使用的是第一种方法,我新建了一个Res类并提供了相关方法获取不同类型的资源的id。
package linchaolong.sdk;
import android.content.Context;
/**
* 动态获取资源id工具类
*/
public class Res {
/** 上下文 **/
private static Context sContext = null;
/**
* 在调用其他方法之前必须先调用该方法设置上下文
*
* @param ctx 上下文
*/
public static void setContext(Context ctx){
sContext = ctx;
}
/**
* 获取id
*
* @param resName 资源名称
* @return 资源id
*/
public static int id(String resName){
return sContext.getResources().getIdentifier(resName, "id", sContext.getPackageName());
}
/**
* 获取anim类型资源id
*
* @param resName 资源名称
* @return 资源id
*/
public static int anim(String resName){
return sContext.getResources().getIdentifier(resName, "anim", sContext.getPackageName());
}
/**
* 获取layout类型资源id
*
* @param resName 资源名称
* @return 资源id
*/
public static int layout(String resName){
return sContext.getResources().getIdentifier(resName, "layout", sContext.getPackageName());
}
/**
* 获取drawable类型资源id
*
* @param resName 资源名称
* @return 资源id
*/
public static int drawable(String resName){
return sContext.getResources().getIdentifier(resName, "drawable", sContext.getPackageName());
}
/**
* 获取string类型资源id
*
* @param resName 资源名称
* @return 资源id
*/
public static int string(String resName){
return sContext.getResources().getIdentifier(resName, "string", sContext.getPackageName());
}
/**
* 获取raw类型资源id
*
* @param resName 资源名称
* @return 资源id
*/
public static int raw(String resName){
return sContext.getResources().getIdentifier(resName, "raw", sContext.getPackageName());
}
/**
* 获取style类型资源id
*
* @param resName 资源名称
* @return 资源id
*/
public static int style(String resName) {
return sContext.getResources().getIdentifier(resName, "style", sContext.getPackageName());
}
}
SDK中的login方法会跳转到SDKActivity,SDKActivity在创建时调用setContentView方法设置布局,布局资源的id是通过Res.layout动态获取的。
public class SDKActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 通过Res.layout获取布局界面的id
setContentView(Res.layout("activity_sdk"));
}
}
库工程
1.我这里再创建了一个Android工程,并且勾选了Is Library选项,表示这是一个库工程,并不能运行,只是供其它工程引用。
2.把SDK工程中的java源码导出为jar(选择src目录,右键Export,我这里导出为sdk.jar),一般这一步还会对非SDK接口代码做混淆,然后把jar放到库工程的libs目录。
3.把SDK工程res目录下资源拷贝到库工程res目录下。
库工程项目结构:
第三方应用调用SDK
第三方应用调用SDK时,只需要把库工程导入到自己的工作空间,并引用库工程,然后在清单文件配置相关的组件和权限即可。
1.我这里新建了一个Test工程,并引用库工程。
2.调用SDK相关接口,MainActivity的布局文件中有一个按钮,点击会调用toSDKActivity方法,调用SDK的login方法。
public class MainActivity extends Activity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 初始化SDK
SDK.init(this);
}
/**
* 跳转到SDK的Activity
*
* @param button
*/
public void toSDKActivity(View button){
SDK.login();
}
}
3.在AndroidMenifest.xml配置SDKActivity。
点击按钮后跳转到SDKActivity