編輯:關於Android編程
這裡,我將用一個小例子的形式來幫助大家初探JNI的用法,首先,大家要先搭建好NDK環境,請大家先閱讀《Android之——NDK環境搭建》一文。
這個小例子實現的功能就是,通過Android中的java代碼來調用C代碼實現java代碼與C代碼之間的交互。
我們首先在布局文件activity_main.xml中,添加一個按鈕控件,並給按鈕控件設置一個點擊事件,具體代碼如下:
要實現JNI方法的調用,首先要在MainActivity中定義一個本地方法,java中本地方法是以native關鍵字定義的。
具體代碼如下:
public native String helloFromC()
用javah命令生成,h頭文件,前提是要配置好java環境變量,這裡我就不說怎麼配置環境變量了,相信稍微了解java的同學都知道。我們通過cmd命令行進入到MainActivity包所在的目錄。
如下圖:
然後輸入命令
javah -encoding UTF-8 包名.類名其中,-encoding UTF-8是指定生成的.h頭文件的編碼為UTF-8,包名是類所在的包,類名就是包含本地方法的類名,類名不帶有.java後綴。
如下圖:
此時,在當前目錄下會生成一個.h頭文件。
如下圖:
com_lyz_hdk_helloworld_MainActivity.h中生成的代碼如下:
/* DO NOT EDIT THIS FILE - it is machine generated */ #include/* Header for class com_lyz_hdk_helloworld_MainActivity */ #ifndef _Included_com_lyz_hdk_helloworld_MainActivity #define _Included_com_lyz_hdk_helloworld_MainActivity #ifdef __cplusplus extern C { #endif /* * Class: com_lyz_hdk_helloworld_MainActivity * Method: helloFromC * Signature: ()Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_com_lyz_hdk_helloworld_MainActivity_helloFromC (JNIEnv *, jobject); #ifdef __cplusplus } #endif #endif
在Android項目的根目錄新建JNI目錄,將com_lyz_hdk_helloworld_MainActivity.h文件拷貝到jni目錄下,然後新建hello.c文件,引入所需要的庫,
如下所示:
#include在hello.c中實現Java_com_lyz_hdk_helloworld_MainActivity_helloFromC方法,返回相應的字符串#include #include com_lyz_hdk_helloworld_MainActivity.h
具體代碼如下:
JNIEXPORT jstring JNICALL Java_com_lyz_hdk_helloworld_MainActivity_helloFromC(JNIEnv *env , jobject obj){ char *str = hello from c; jstring jstr = (**env).NewStringUTF(env, str); return jstr; }hello.c完整代碼如下:
#include#include #include com_lyz_hdk_helloworld_MainActivity.h JNIEXPORT jstring JNICALL Java_com_lyz_hdk_helloworld_MainActivity_helloFromC(JNIEnv *env , jobject obj){ char *str = hello from c; jstring jstr = (**env).NewStringUTF(env, str); return jstr; }
這個文件是Android實現JNI所必須的文件,而且文件名稱固定為Android.mk不能更改。這個文件裡的內容我們可以到ndk的docs目錄下找到ANDROID-MK.html文件,打開這個文件,找到以下代碼片段,拷貝到Android.mk文件中,注意要每一行不要有空格。
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := hello-jni LOCAL_SRC_FILES := hello-jni.c include $(BUILD_SHARED_LIBRARY)其在文件中的位置如下圖:
其中:
LOCAL_PATH := $(call my-dir):當前文件所存在的目錄
call my-dir 得到當前我的文件的目錄
include $(CLEAR_VARS):配置信息初始化
LOCAL_MODULE := hello-jni:指定編譯完成後的2進制值可執行文件的名稱
LOCAL_SRC_FILES := hello-jni.c:指定你要編譯哪些C的源文件
include $(BUILD_SHARED_LIBRARY):編譯成動態的鏈接庫文件
include $(BUILD_STATIC_LIBRARY):編譯成靜態的鏈接庫文件
我要編譯的文件是hello.c,要生成的so為libhello.so所以我將上面的配置修改為以下代碼:
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := hello LOCAL_SRC_FILES := hello.c include $(BUILD_SHARED_LIBRARY)以上配置也就是Android.mk中的內容了。
如下圖:
這時,我們項目的jni目錄下的文件如下圖所示:
我們打開cygwin,進入到項目的jni目錄下。
如下圖:
執行命令ndk-build
如下圖:
刷新項目工程,會在libs目錄下自動生成一個.so動態鏈接庫,
如下圖:
在MainActivity類中,寫一個靜態代碼塊,用於加載.so動態鏈接庫,注意,這裡我們生成的.so文件是libhello.so,我們在加載這個.so文件的時候,只需要傳入hello即可。
具體代碼實現如下:
//加載靜態代碼塊 static{ System.loadLibrary(hello); }在按鈕的點擊事件中調動本地方法,同時將結果Toast出來。
具體代碼如下:
public void click(View v){ Toast.makeText(this, c代碼的內容是:+helloFromC(), Toast.LENGTH_SHORT).show(); }MainActivity整體代碼如下:
package com.lyz.hdk.helloworld; import android.app.Activity; import android.os.Bundle; import android.view.Menu; import android.view.View; import android.widget.Toast; /** * 主程入口 * @author liuyazhuang * */ public class MainActivity extends Activity { public native String helloFromC(); //加載靜態代碼塊 static{ System.loadLibrary(hello); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } public void click(View v){ Toast.makeText(this, c代碼的內容是:+helloFromC(), Toast.LENGTH_SHORT).show(); } }
本實例中,為了方面,我把一些文字直接寫在了布局文件中和相關的類中,大家在真實的項目中要把這些文字寫在string.xml文件中,在外部引用這些資源,切記,這是作為一個Android程序員最基本的開發常識和規范,我在這裡只是為了方便直接寫在了類和布局文件中。
CollapsingToolbarLayout作用是提供了一個可以折疊的Toolbar,它繼承至FrameLayout,給它設置layout_scrollFlags,它可
大家都知道,Android從3.0版本開始就加入了NavigationBar,主要是為那些沒有實體按鍵的設備提供虛擬按鍵,但是,它始終固定在底部,占用48dp的像素高度,
Android項目:手機安全衛士(16)—— 復雜 ListView1 介紹接著昨天的內容,今天繼續完善應用列表,首先,應用分為系統應用和用戶應用
Android獲得當前系統時間有好幾種方法,本文使用的是System.currentTimeMillis->Date+SimpleDateFormat,我覺得這種方