Pure Java 完成了 , 改換 JNI 方式吧 !! 將 a + b 的動作 用 C library 來完成 .
一樣使用之前 pure java 的 code , 如下列修改方式.
private OnClickListener mAddListener = new OnClickListener()
{
@Override
public void onClick(View view)
{
int a = Integer.parseInt(mEditText1.getText().toString());
int b = Integer.parseInt(mEditText2.getText().toString());
- int result = a+b;
+ int result = addJNI(a, b);
mButton.setText(String.valueOf("A+B=" + result));
}
};
並且在 .java 中加入 :
public native int addJNI(int a, int b);
static
{
System.loadLibrary("androint-jni");
}
## 注意 library 的名稱為 libandroint-jni.so , java 會自動將 lib prefix 補上去 , 所以JNI 產生的 so file , 要注意 , 也需要 lib 這個 perfix.
接著先 產生 .class file , 在由 .class file 產生 .h , 然後 .c file include 這個 .h 並且完成 function 的功能.
產生 .class 的方式可以用下列的command :
javac -d ./ -cp /${HOME}/android-sdk-linux/platforms/android-15/android.jar src/com/eps/william/androint/AndroIntActivity.java <source top>/out/target/common/R/com/eps/william/androint/R.java
接著用 javah 來產生 .h file , command 如下:
javah -jni -classpath ../bin com.eps.william.androint.AndroIntActivity
經過測試 ,沒有問題 , 只是..... 一切都不自動 , 需要手動產生, 並且還要先編譯 java 程式 , 然後手動產生 .h file , 然後 修正 .c file , 最後在 Android.mk 中加入 .so 的 make 部份 . 一點都不優......
經過幾天的 study , 修改了一下 Android.mk 內容 , 讓整個 make 過程中自動產生 .h 然後接著 compile .c file 產生 .so ...... , 修改後的 Android.mk 如下:
# Android.mk
#
# Copyright 2012 Jeff Hsieh <jeff@instant-jeff.instant>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301, USA.
#
#
LOCAL_PATH:= $(call my-dir)
############################################
#### Jave APK
############################################
$(warning DEBUG **** BUILD_APK)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_PACKAGE_NAME := Sample_4
include $(BUILD_PACKAGE)
############################################
#### Jni Library.
############################################
#~ $(warning DEBUG **** BUILD_JNI)
#~
#~ include $(CLEAR_VARS)
#~
#~ LOCAL_MODULE_TAGS := optional
#~ LOCAL_SRC_FILES := $(call all-subdir-c-files)
#~ LOCAL_MODULE := libandroint-jni
#~
#~ LOCAL_LDLIBS := -llog
#~
#~ LOCAL_SHARED_LIBRARIES := libcutils
#~
#~ LOCAL_CHECKED_MODULE := build_jni_h
#~ LOCAL_REQUIRED_MODULES := build_jni_h
#~
#~ include $(BUILD_SHARED_LIBRARY)
.PHONY: distclean install_jni_so build_jni_hearder
droid: install_jni_so
############################################
#### create jni h file .
############################################
$(warning DEBUG **** Create JNI heard files.)
include $(CLEAR_VARS)
JNI_LOCAL_PKG_NAME := $(shell cat $(LOCAL_PATH)/AndroidManifest.xml | grep package | sed 's/.*=//g')
JNI_LOCAL_PKG_DIR := $(shell echo $(JNI_LOCAL_PKG_NAME) | sed 's/\./\//g' )
JNI_LOCAL_JAVA_SRC :=
JNI_LOCAL_JAVA_SRC += $(foreach f,$(call all-subdir-java-files), $(addprefix $(LOCAL_PATH)/,$f))
JNI_LOCAL_PATH := $(LOCAL_PATH)
JNI_JAVA_LIB := /home/jeff/Mydroid/android-sdk-linux/platforms/android-15/android.jar
JNI_R_JAVA := $(TARGET_COMMON_OUT_ROOT)/R/$(JNI_LOCAL_PKG_DIR)/R.java
build_jni_hearder: Sample_4
@if [ ! -e $(JNI_LOCAL_PATH)/bin ];then \
mkdir -p $(JNI_LOCAL_PATH)/bin ; \
fi
@if [ ! -e $(JNI_LOCAL_PATH)/bin/.jni_header ];then \
javac -d $(JNI_LOCAL_PATH)/bin -cp $(JNI_JAVA_LIB) $(JNI_R_JAVA) $(JNI_LOCAL_JAVA_SRC) ; \
javah -jni -classpath $(JNI_LOCAL_PATH)/bin -d $(JNI_LOCAL_PATH)/jni/jni_include $(JNI_LOCAL_PKG_NAME).AndroIntActivity ;\
fi
## javac -d ./ -cp /home/jeff/Mydroid/android-sdk-linux/platforms/android-15/android.jar \
## src/com/eps/william/androint/AndroIntActivity.java \
## /home/jeff/Mydroid/TI_Android/rowboat-android/out/target/common/R/com/eps/william/androint/R.java
## javah -jni -classpath ../bin com.eps.william.androint.AndroIntActivity
############################################
#### Jni Library.
############################################
include $(CLEAR_VARS)
export JNI_TC_DIR := $(realpath $(shell dirname $(TARGET_TOOLS_PREFIX)))
export JNI_TC_PREFIX := $(shell basename $(TARGET_TOOLS_PREFIX))
export TARGET_CC := $(JNI_TC_DIR)/$(JNI_TC_PREFIX)gcc
export JNI_COMPILER_FLAGS := $(subst -I ,-I $(shell pwd)/,$(subst -include ,-include $(shell pwd)/,$(TARGET_GLOBAL_CFLAGS))) \
$(foreach f,$(TARGET_C_INCLUDES), $(addprefix -I$(shell pwd)/,$f)) \
$(foreach f,$(TARGET_PROJECT_INCLUDES), $(addprefix -I$(shell pwd)/,$f)) \
$(foreach f,$(JNI_H_INCLUDE), $(addprefix -I$(shell pwd)/,$f)) \
export JNI_LDFLAGS := -L$(shell pwd)/$(TARGET_OUT_STATIC_LIBRARIES) -llog
export JNI_LOCAL_C_FILES := $(call all-subdir-c-files)
export PRODUCT_OUT := $(PRODUCT_OUT)
###################################
install_jni_so: build_jni_hearder \
$(TARGET_CRTBEGIN_DYNAMIC_O) $(TARGET_CRTEND_O) $(TARGET_OUT_STATIC_LIBRARIES)/libm.so \
$(TARGET_OUT_STATIC_LIBRARIES)/libc.so $(TARGET_OUT_STATIC_LIBRARIES)/libdl.so \
$(TARGET_OUT_STATIC_LIBRARIES)/liblog.so
@$(MAKE) -C $(JNI_LOCAL_PATH) -f Makefile.jni local_jni
############################################
#### Clean rules.
############################################
distclean:
@if [ -e $(JNI_LOCAL_PATH)/jni/jni_include ];then \
rm -rf $(JNI_LOCAL_PATH)/jni/jni_include ; \
fi
@echo "Remove temp file \"$(JNI_LOCAL_PATH)/bin/ \" .... "
@if [ -e $(JNI_LOCAL_PATH)/bin ];then \
rm -rf $(JNI_LOCAL_PATH)/bin ;\
fi
@$(MAKE) -C $(JNI_LOCAL_PATH) -f Makefile.jni $@
############################################
因為 Android 的 make rules 太複雜 ,並且支援 make -jN , 所以乾脆獨立出來 build so file . 所以會看到 "@$(MAKE) -C $(JNI_LOCAL_PATH) -f Makefile.jni local_jni " 的字串 , 其中 Makefile.jni 如下:
# Makefile.jni
#
# Copyright 2012 Jeff Hsieh <jeff@instant-jeff.instant>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301, USA.
#
#
DEPEND_FILE := .jni_depend
JNI_SO_NAME := libandroint-jni.so
JNI_LOCAL_OBJ_FILES := $(JNI_LOCAL_C_FILES:.c=.o)
JNI_SO_TARGET := $(addprefix $(shell pwd)/,$(JNI_SO_NAME))
JNI_TARGET_OUT := $(PWD)/$(PRODUCT_OUT)/system/lib/$(JNI_SO_NAME)
.PHONY: local_jni distclean
local_jni: $(DEPEND_FILE) $(JNI_TARGET_OUT)
$(JNI_TARGET_OUT): $(JNI_SO_TARGET)
@echo " Install $(JNI_SO_NAME) ==> $(PRODUCT_OUT)/system/lib"
@cp $(JNI_SO_TARGET) $(PWD)/$(PRODUCT_OUT)/system/lib/
$(JNI_SO_TARGET): $(JNI_LOCAL_OBJ_FILES)
@echo " Building '$@' ... "
@$(TARGET_CC) -shared -Wl,-soname,$(JNI_SO_NAME) -o $@ $(JNI_LOCAL_OBJ_FILES) $(JNI_LDFLAGS)
%.o: %.c
@echo " Compiling '$<' ..."
@$(TARGET_CC) $(JNI_COMPILER_FLAGS) -o $@ -c $<
$(DEPEND_FILE):
@if [ -n "$(JNI_LOCAL_C_FILES)" ]; then \
echo " Generating '$@' ..." ;\
for i in $(JNI_LOCAL_C_FILES) ; do \
j=`echo $$i | sed 's/\.c/.o/g' ` ;\
$(TARGET_CC) $(JNI_COMPILER_FLAGS) -M $$i -MT"./$$j" >> $@ ;\
done ; \
fi
ifeq ($(DEPEND_FILE),$(wildcard $(DEPEND_FILE)))
include $(DEPEND_FILE)
endif
distclean:
@rm -f $(DEPEND_FILE) $(JNI_SO_TARGET) $(JNI_LOCAL_OBJ_FILES)
############################################
沒有留言:
張貼留言