1. 程式人生 > >Adnroid ndk 中jni訪問java方法、物件、成員變數

Adnroid ndk 中jni訪問java方法、物件、成員變數

 JNI資料夾下,C++原始碼
extern "C"
{
	JNIEXPORT void JNICALL Java_ndk_test_JNI_accessJavaMethod(JNIEnv *env,jobject obj)
	{
		jclass ClassJNI = env->FindClass("ndk/test/JNI");
		jmethodID returnStringID = env->GetMethodID( ClassJNI, "InstanceMethod", "()Ljava/lang/String;");
		jstring jstr =(jstring)env->CallObjectMethod(obj,returnStringID);		//呼叫帶返回引數的java方法
		const char *c_str = env->GetStringUTFChars(jstr, NULL);					// 4. 將unicode編碼的java字串轉換成C風格字串
		LOGI("java中的方法執行結果是:%s",c_str);

		//呼叫有輸入引數與返回值的方法
		jmethodID paramID = env->GetMethodID(ClassJNI, "paramMethod", "(Ljava/lang/String;)Ljava/lang/String;");
		jstring param = env->NewStringUTF("這是java方法中需要的引數");
		jstring jstr2 =(jstring)env->CallObjectMethod(obj, paramID, param);
		const char *c_str2 = env->GetStringUTFChars(jstr2, NULL);
		LOGI("呼叫有輸入引數與返回值的方法java中的方法執行結果是:%s",c_str2);

		//呼叫java中多個引數的方法,並使用另一種查詢方式
		jmethodID muitleParamId = env->GetMethodID( ClassJNI, "MuitleParamMethod", "(ILjava/lang/String;[I)Ljava/lang/String;");

		jint a=119;
		jstring tmp_jstr = env->NewStringUTF("liuzheyu");
		jintArray ret = env->NewIntArray(3);							//例項化一個g一維陣列
		jint* buffer = new jint[1024];  								//固定陣列,測試用,注意別溢位
		for (int i = 0; i < 3; i++)
		{
			buffer[i]=i;
		}
		env->SetIntArrayRegion(ret, 0, 3, buffer);		   //從NativeType型別(jint)陣列中,拷貝0~y資料到jintArray物件中


		jstring jstr3 =(jstring)env->CallObjectMethod(obj,muitleParamId,a,tmp_jstr,ret);		//呼叫帶返回引數的java方法
		const char *c_str3 = env->GetStringUTFChars(jstr3, NULL);								// 4. 將unicode編碼的java字串轉換成C風格字串
		LOGI("呼叫java中多個引數的方法結果是:%s",c_str3);
		env->DeleteLocalRef(ret);

		/**
		 * 測試訪問靜態方法
		 */
		jmethodID staticId = env->GetStaticMethodID(ClassJNI,"staticMethod","()Ljava/lang/String;");
		jstring jstr_4 =(jstring) env->CallObjectMethod(obj,staticId);
		const char * c_str4=env->GetStringUTFChars(jstr_4,NULL);
		LOGI("訪問java中的靜態方法中結果是:%s",c_str4);


	}
}

JNI資料夾下:java物件

package ndk.test;

/**
 * JNI
 * @author Administrator
 * 2016-05-22
 */
public class JNI 
{
	
    public native String getString();  		
   
    public native int plus(int a,int b);    
    
   
    
    /**
     * 操作一維陣列
     * @param a
     * @param b
     * @return
     */
    public native int operateArray(int[] a,int[] b);
    
    /**
     * 獲取原生中的二維陣列
     * @param row
     * @param col
     * @return
     */
    public native int[][] get2Array(int row,int col);
    
    /**
     * 獲取一個數組的物件
     * @param row
     * @param col
     * @return
     */
    public native int[][] get2ArrayObject(int[][] a);
    
    
    /**
     * 原生代碼訪問例項物件
     * @param obj
     */
    public native static void accessInstanceField(ClassObject obj);  
    
    /**
     * 原生代碼訪問靜態域
     */
    private native static void accessStaticField(); 
    
    
    /**
     * 例項方法,在C++中呼叫
     * @return
     */
    public String InstanceMethod()
    {
    	return "JNI中通過方法id來獲取例項方法";
    }
    /**
     * 靜態方法,在C++中呼叫
     * @return
     */
    public static String staticMethod()
    {
    	return "JNI中通過方法id來獲取靜態方法";
    }
    /**
     * C++中測試呼叫帶引數的方法
     * @param info
     * @return
     */
    public String paramMethod(String info)
    {
    	return info;
    }
    
    /**
     * c++能過原生方法呼叫帶有多個不同型別的引數方法
     * @param a
     * @param str
     * @param array
     * @return
     */
    public String MuitleParamMethod(int a,String str,int[] array)
    {
    	int total=0;
    	for(int i=0;i<array.length;i++)
    	{
    		total+=array[i];
    	}
    	String result = a+str+total;
    	return result;
    }
    
    /**
     * 通過直接找類來訪問java中的物件
     * @param obj
     */
    public native void accessJavaMethod();
}

java測試類物件:
package ndk.test;

/**
 * 在原生代碼中進行修改
 * @author Administrator
 *
 */
public class ClassObject 
{
	
	/**
	 * 對應第一種方法:C++中訪問java物件
	 */
	public native ClassObject accessJavaObject();  
	
	/**
	 * 測試修改靜態成員變數
	 */
	private static int num;  

    private String str; 
    
    
	public static int getNum() {
		return num;
	}

	public static void setNum(int num) {
		ClassObject.num = num;
	}

	public String getStr() {
		return str;
	}

	public void setStr(String str) {
		this.str = str;
	}

	

}
Android activity類:
package ndk.test;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends Activity {

	
	static
	{  
        System.loadLibrary("NDKTest");  //匯入庫
    }  
      
    private Button javaObjBtn;
    JNI jni;
    
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		TextView text=(TextView)findViewById(R.id.t1);
		jni = new JNI();
		String tmp1 = jni.getString()+"和:"+jni.plus(2, 7);
		//text.setText(tmp1);
		
		int[] a = {1,2,3};
		int[] b = {4,5,6};
		int muitle = jni.operateArray(a, b);
		
		String tmp2 = "運算元組之後:"+ muitle;
		text.setText(tmp1+tmp2);
		
		int[][] array = {{1,2,3},{4,5,6},{7,8,9}};
		int[][] int2Array = jni.get2Array(3, 3);
		
		System.out.println("37-----------:"+int2Array[1][1]);
		
		int [][] tmpArray = jni.get2ArrayObject(array);
		System.out.println("40-----------:"+tmpArray [1][1]);
		
		//操作物件
		ClassObject obj = new ClassObject();
		obj.setStr("劉胡來");
		obj.setNum(26);
		jni.accessInstanceField(obj);
		
		/*ClassObject o = obj.accessJavaObject();
		System.out.println("測試修改物件,修改後名字:"+o.getStr()+":年齡:"+o.getNum());*/
		
		javaObjBtn = (Button)findViewById(R.id.button1);
		javaObjBtn.setOnClickListener(new BtnClick());
		
		Button javaMethodBtn = (Button)findViewById(R.id.button2);
		javaMethodBtn.setOnClickListener(new BtnClick());
	}
	
	private class BtnClick implements OnClickListener
	{

		@Override
		public void onClick(View v) {
			switch(v.getId())
			{
				case R.id.button2:
					jni.accessJavaMethod();
					/*int a =119;
					String str="liuzeyu";
					int [] array={1,2,3};
					jni.MuitleParamMethod(a, str, array);*/
				break;
			}
			
		}
		
	}
}