在此之前,用过的第三方sdk倒是不少,但是此次居然接到要提供SDK给客户的需求。听完后一脸懵逼,第一反应没做过,不会;后面经过两三天搜索思考,终于有了头绪,下面做下记录,以便日后翻看:
第一步:创建接口类,类里面放的是为客户提供的方法。
public interface IRfid { /** * 搜索标签 * * @param listener * 标签搜索回调接口 */ void searchTag(QueryCallbackListener listener); /** * 停止搜索标签 * * @param listener * rfid标签搜索停止回调接口 */ void stopSearchTag(CallbackListener listener); /** * FFID回调接口 * * @param success * true表示成功,false表示失败 * @param msg * 成功时返回回调信息,失败时返回失败原因 */ interface CallbackListener { public void callback(boolean success, String msg); } /** * RFID标签搜索回调接口 * * @param success * true表示成功,false表示失败 * @param msg * 成功时返回回调信息,失败时返回失败原因 * @param results * 表示查询操作的结果集 */ interface QueryCallbackListener { void callback(boolean success, String msg, List<String> results); } }
第二步:创建接口实现类,这个类是重点,将要实现的代码都写里面;
public class RfidImpl implements IRfid { @Override public void searchTag(QueryCallbackListener listener) { //具体代码略过。。。 } @Override public void stopSearchTag(CallbackListener listener) { //具体代码略过。。。 } }
第三步:当然是期待已久,生成jar包了;
生成jar包,先用eclipse的export导出jar包,将上面的实现类RfidImpl打包,再通过系统自带dx.bat工具将jar包转换成dex格式二进制的jar包。
dx --dex --output=target.jar(-output="输出的jar包名") origin.jar(原来的jar包)
第四步:代码中动态加载RfidImpl.jar,通过反射,得到RfidImpl对象,客户即可通过RfidImpl对象调用相应的方法了。
动态加载:先将要用的jar包放在工程的assets目录下,代码中通过将assets下的jar文件拷入内存,再通过DexClassLoader获得对象。具体代码如下:其中UHFLib_1.0.jar是RfidImpl.java依赖的代码,打jar包方式和RfidImpl一样,见步骤三
public class RfidLoader { private static IRfid iRfid; private static RfidLoader rfidLoader; public static IRfid getRfid(Context context) { if (iRfid == null) { rfidLoader = new RfidLoader(context); } return iRfid; } private RfidLoader(Context context) { loadDexClass(context); if (iRfid == null) { throw new RuntimeException("IRfid init failed"); } } /** * 加载dex文件中的class,并调用其中的sayHello方法 */ private void loadDexClass(Context context) { File cacheFile = FileUtils.getCacheDir(context.getApplicationContext()); String commonPath = cacheFile.getAbsolutePath() + File.separator + "UHFLib_1.0.jar"; File commonDesFile = new File(commonPath); try { if (!commonDesFile.exists()) { commonDesFile.createNewFile(); } FileUtils.copyFiles(context, "UHFLib_1.0.jar", commonDesFile); } catch (IOException e) { e.printStackTrace(); } String rfidImplPath = cacheFile.getAbsolutePath() + File.separator + "RFIDImpl.jar"; File rfidImplDesFile = new File(rfidImplPath); try { if (!rfidImplDesFile.exists()) { rfidImplDesFile.createNewFile(); } FileUtils.copyFiles(context, "RFIDImpl.jar", rfidImplDesFile); } catch (IOException e) { e.printStackTrace(); } // 优化的目录 File optimizedDexOutputPath = context.getDir("outdex", 0); //下面开始加载dex class DexClassLoader rfidDexClassLoader = new DexClassLoader(commonPath + ":" + rfidImplPath, optimizedDexOutputPath.getAbsolutePath(), null, context.getClassLoader()); Log.e("dexPath", rfidImplPath); try { //加载的类名为jar文件里面完整类名,写错会找不到此类hh Class libClazz = rfidDexClassLoader.loadClass("com.impl.RfidImpl"); iRfid = (IRfid) libClazz.newInstance(); } catch (Exception e) { e.printStackTrace(); } } }
public class FileUtils { public static void copyFiles(Context context, String fileName, File desFile) { InputStream in = null; OutputStream out = null; try { in = context.getApplicationContext().getAssets().open(fileName); out = new FileOutputStream(desFile.getAbsolutePath()); byte[] bytes = new byte[1024]; int i; while ((i = in.read(bytes)) != -1) out.write(bytes, 0, i); } catch (IOException e) { e.printStackTrace(); } finally { try { if (in != null) in.close(); if (out != null) out.close(); } catch (IOException e) { e.printStackTrace(); } } } public static boolean hasExternalStorage() { return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED); } /** * 获取缓存路径 * * @param context * @return 返回缓存文件路径 */ public static File getCacheDir(Context context) { File cache; if (hasExternalStorage()) { cache = context.getExternalCacheDir(); } else { cache = context.getCacheDir(); } if (!cache.exists()) cache.mkdirs(); return cache; } }
最后,通过以下方式调用代码:
以下是本次工作参考的连接^-^:
工具
资源引用问题:
动态加载: