jniデバッグ

4856 ワード

12年の時にJNIを書いたことがありますが、あまり忘れていません.今もう一度書き直しましたが、いくつかの問題にぶつかったことに気づきました.書いて記録してください.
最初のステップ
アプリケーションjavaコード
package com.example.helloworld;

import java.util.Calendar;

import android.os.Bundle;
import android.app.Activity;
import android.app.AlarmManager;
import android.util.Log;


public class AlarmTest extends Activity
{
	AlarmManager aManager;
	Calendar currentTime = Calendar.getInstance();
	public static final int POWER_OFF_WAKE_UP = 8;//                      
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		Log.e("weiqifa", test());
	}
	public native String  test();
	static {
		try{
			Log.i("JNI", "Trying to load libhelloworld.so");
			System.loadLibrary("helloWorld");
		}catch(UnsatisfiedLinkError ule){
			Log.e("JNI", "Warning : could not load the libhelloworld.so");
		}
	}
}

コンパイルするとeclipseコンパイルでもjavaコマンドコンパイルでも構いません
コンパイル後、次のコード構造とディレクトリがあります.
weiqifa@weiqifa-Inspiron-3847:~/workspace/helloWorld/bin$ ls AndroidManifest.xml  classes  classes.dex  dexedLibs  helloWorld.apk  res  resources.ap_ weiqifa@weiqifa-Inspiron-3847:~/workspace/helloWorld/bin$
ステップ2
共有ヘッダファイルを生成するには、成功と失敗に最も重要な関係があります.
weiqifa@weiqifa-Inspiron-3847:~/workspace/helloWorld/bin$ javah -d header -classpath classes -jni com.example.helloworld.AlarmTest weiqifa@weiqifa-Inspiron-3847:~/workspace/helloWorld/bin$
このコマンド比較キーjavah-d headerとは、現在のディレクトリの下にこのヘッダファイルを生成することです.-classesを指定するディレクトリは、最初のステップで生成されます.
-jniとは、jniヘッダファイルcomを生成することを意味する.example.helloworldこれはパッケージ名AlarmTestクラス名ですこれらはすべて間違いありません
生成後は次のようになります.
weiqifa@weiqifa-Inspiron-3847:~/workspace/helloWorld/bin$ ls AndroidManifest.xml  classes  classes.dex  dexedLibs  header  helloWorld.apk  res  resources.ap_ weiqifa@weiqifa-Inspiron-3847:~/workspace/helloWorld/bin$ ls header/com_example_helloworld_AlarmTest.h weiqifa@weiqifa-Inspiron-3847:~/workspace/helloWorld/bin$
weiqifa@weiqifa-Inspiron-3847:~/workspace/helloWorld/bin$ cat header/com_example_helloworld_AlarmTest.h 
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_helloworld_AlarmTest */

#ifndef _Included_com_example_helloworld_AlarmTest
#define _Included_com_example_helloworld_AlarmTest
#ifdef __cplusplus
extern "C" {
#endif
#undef com_example_helloworld_AlarmTest_POWER_OFF_WAKE_UP
#define com_example_helloworld_AlarmTest_POWER_OFF_WAKE_UP 8L
/*
 * Class:     com_example_helloworld_AlarmTest
 * Method:    test
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_example_helloworld_AlarmTest_test
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

最初はわかりませんでしたが、実行中によくエラーが発生します.
weiqifa@weiqifa-Inspiron-3847:~/workspace/helloWorld/bin$ javah -jni com.example.helloworld error: cannot access com.example.helloworld class file for com.example.helloworld not found javadoc: error - Class com.example.helloworld not found. Error: No classes were specified on the command line.  Try -help. weiqifa@weiqifa-inspron-3847:~/workspace/helloWorld/bin$自動生成対応関数:Java_com_example_helloworld_AlarmTest_test
    Java_ + パッケージ名(com_example_helloworld)+クラス名(AlarmTest)+インタフェース名(test):このJNI仕様に従って操作する必要があります.
ステップ3
通過するhで作ります.c
私たちを見てください.c私たちはただ必要です.hの中のその関数の名前、.hは参照されず、コンパイルやプリコンパイルにも関与していない
helloworld.c以下:
#include <string.h>
#include <jni.h>


JNIEXPORT jstring JNICALL Java_com_example_helloworld_AlarmTest_test
  (JNIEnv *env, jobject thiz)
{
	return (*env)->NewStringUTF(env,"weiqifa hello for JNI");
}

ステップ4
soファイルの生成
私たちのmkファイルを見てください.
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE    := helloWorld
LOCAL_SRC_FILES := helloWorld.c

include $(BUILD_SHARED_LIBRARY)

次のsoファイルが生成されます.weiqifa@weiqifa-Inspiron-3847:~/workspace/helloWorld/libs/armeabi$ ls libhelloWorld.so weiqifa@weiqifa-Inspiron-3847:~/workspace/helloWorld/libs/armeabi$
ステップ5
検証の実行
直接eclipseでインストールするかadb pushで中に入ってadbを使う場合はsoファイルを手動でインストールして権限を変更します
10-20 03:06:45.241: E/weiqifa(12194): weiqifa hello for JNI 10-20 03:06:45.241: V/ActivityThread(12194): activityCreated r=ActivityRecord{41e7a890 token=android.os.BinderProxy@41e7a060 {com.example.helloworld/com.example.helloworld.AlarmTest}}
質問:
最初はAndroidにいましたmkに書いてあるLOCAL_MODULEが生成したモジュール名は大文字W,helloWorld
LOCAL_MODULE    := helloWorld

でもandroidソースには
System.loadLibrary("helloWorld");

中のhelloworldは小文字wで、それから運行はずっとロードに成功していません.後ろの友达が見てくれました.原因を見つけて、油断しましょう.