转载地址:http://blog.csdn.net/xiaanming/article/details/9257853
这两天在学习将自己的Android项目打成Jar包,但是测试自己的Jar包的时候会提示找不到Activity的layout,我打Jar包的时候是把资源文件也放进来了,这样是不对的,Android项目打Jar应该只包含src里的内容。
一、下面根据反射资源的方式对Android项目进行打Jar包:
1. 首先,在项目中新建一个名为MRsource的类,该类的作用是利用反射根据资源名字获取资源ID。其实,系统也自带了根据资源名字获取资源ID的方法,getResource().getIdentifier("main_activity", "layout", getPackageName()); 第一个参数是资源的名字,第二个参数是资源的类型,如layout, string等,第三个是包名。
MRsource类的内容如下:
package com....; import android.content.Context; /** * 根据资源的名字获取其ID值 * @author mining * */ public class MResource { public static int getIdByName(Context context, String className, String name) { String packageName = context.getPackageName(); Class r = null; int id = 0; try { r = Class.forName(packageName + ".R"); Class[] classes = r.getClasses(); Class desireClass = null; for (int i = 0; i < classes.length; ++i) { if (classes[i].getName().split("\\$")[1].equals(className)) { desireClass = classes[i]; break; } } if (desireClass != null) id = desireClass.getField(name).getInt(desireClass); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); } return id; } }当我们的资源ID是一个数组的时候,我们要用下面的方法:
public static int[] getIdsByName(Context context, String className, String name) { String packageName = context.getPackageName(); Class r = null; int[] ids = null; try { r = Class.forName(packageName + ".R"); Class[] classes = r.getClasses(); Class desireClass = null; for (int i = 0; i < classes.length; ++i) { if (classes[i].getName().split("\\$")[1].equals(className)) { desireClass = classes[i]; break; } } if ((desireClass != null) && (desireClass.getField(name).get(desireClass) != null) && (desireClass.getField(name).get(desireClass).getClass().isArray())) ids = (int[])desireClass.getField(name).get(desireClass); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); } return ids; }
我的Activity是一个WebViewActivity,进度条可能会不太清晰,可以另外自定义进度条的颜色,刚开始的时候这条语句
Progress progressBar = (ProgressBar) findViewById(MResource.getIdByName(getApplication(), "id", "progressBar"));
是这样写的,progress.setProgress(newProgress);中的progress会报错,原来我在前面已经定义了progress了,所以要把Progress去掉。
具体内容如下:
package com....; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.os.Bundle; import android.view.Window; import android.webkit.WebChromeClient; import android.webkit.WebSettings; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.ProgressBar; import android.widget.TextView; public class WebViewActivity extends Activity { private static final String TAG = "WebViewActivity"; private WebView webView; private WebSettings webSettings; private ProgressBar progressBar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); PaSysApplication.getInstance().addActivity(this); // 将该Activity放入一个栈中,本文请忽略 requestWindowFeature(Window.FEATURE_NO_TITLE); if (isNetworkAvailable(this)) { // 进行联网判断,没网络的话无法进入 // setContentView(R.layout.paactivity_webview); setContentView(MResource.getIdByName(getApplication(), "layout", "activity_webview")); // webView = (WebView) findViewById(R.id.webView); webView = (WebView) findViewById(MResource.getIdByName(getApplication(), "id", "webView")); // progressBar = (ProgressBar) findViewById(R.id.bar_progress); progressBar = (ProgressBar) findViewById(MResource.getIdByName(getApplication(), "id", "bar_progress")); webSettings = webView.getSettings(); webSettings.setJavaScriptEnabled(true); AccountManager.getInstance(this).setActivity(this); // 本文请忽略 webView.addJavascriptInterface(AccountManager.getInstance(this).getJavascriptObject(), "Obj"); // 添加接口,本文请忽略 // 添加进度条 webView.setWebChromeClient(new WebChromeClient() { @Override public void onProgressChanged(WebView view, int newProgress) { progressBar.setProgress(newProgress); } }); webView.setWebViewClient(new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { return false; } }); Intent intent = getIntent(); String url = intent.getStringExtra("url"); webView.loadUrl(url); } else { finish(); } } public boolean isNetworkAvailable(Context context) { ConnectivityManager connectivityManager = (ConnectivityManager) context .getSystemService(Context.CONNECTIVITY_SERVICE); if (connectivityManager == null) { return false; } else { NetworkInfo[] networkInfo = connectivityManager.getAllNetworkInfo(); if (networkInfo != null && networkInfo.length > 0) { for (int i = 0; i < networkInfo.length; i++) { if (networkInfo[i].getState() == NetworkInfo.State.CONNECTED) { return true; } } } } return false; } }WebViewActivity对应的layout内容如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <!-- <ProgressBar android:id="@+id/bar_progress" style="?android:attr/progressBarStyleHorizontal" android:layout_width="match_parent" android:layout_height="2dp" android:background="@color/transparent" /> --!> <WebView android:id="@+id/webView" android:layout_width="match_parent" android:layout_height="match_parent" > </WebView> </LinearLayout>2. 将该Android项目打成Jar包,注意修改setContentView()和findViewById()的地方,这样反射才会有效。Jar包只包含src。打包过程略,具体请看转载链接。
3. 将Jar包放入测试项目的lib目录下,选中该测试项目,右键打开Properties,选择java Build Path--->Libraries--->Add Jars,选择放入测试项目lib目录下的Jar包,Apply,OK。
4. 将WebViewActivity所需的资源文件放入测试项目对应的文件夹中,我只有一个layout,所以我把我的activity_webview.xml放入测试项目的layout中。
还要记得在AndroidManifest.xml文件中添加所需的权限,Activity声明等内容,注意,Activity需要使用全包名。我需要添加的如下:
<application ...... <activity android:name="com.example.accounttest.WebViewActivity" /> </application> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />5. 至此,就可以成功调用Jar包中的layout等其它资源了。
二、除了这个提供Jar包的方法外,还可以使用Library的方法,将我们的WebViewActivity所属的项目当作Library提供给其它人使用,但是这样会暴露我们的源码。
http://developer.android.com/tools/projects/projects-eclipse.html
三、Android Studio提供了aar包,可以将资源文件和src一起打包。