转载地址: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一起打包。