1. 程式人生 > >Android Studio Jni開發(二)實現Native呼叫java方法和Native呼叫Android API

Android Studio Jni開發(二)實現Native呼叫java方法和Native呼叫Android API

這一篇主要內容是Native呼叫java方法和Native呼叫Android API,以及External Tools快速生成.h檔案,依然是使用NDK方式編譯,如果是複製貼上黨,建議跟本文用一樣的工程名,本文後面會提供demo連結


一、建立工程

1.建立名為Jnitest01的工程


2.點選Next 選擇API等級,我選擇的是26,Activity選擇Empty Activity,一路next後點擊Finish建立工程

二、建立Myjni類並編寫load與Native介面

1.建立Myjni類


填寫類名並點選OK


2.為Myjni類新增程式碼


程式碼:

public class 
Myjni { private Context lContext; static { System.loadLibrary("Myjni"); } public Myjni(Context context){ this.lContext = context; } public void MyToast(String s) { Toast.makeText(lContext, s, Toast.LENGTH_SHORT).show(); } //native public native void
MyjniToast(String s); //native public static native void NativeToast(Context context, String s); //native public static native String NativeString(); }

三、配置External tools快速生成.h標頭檔案

1.開啟External對話方塊

在選單欄找到 File->Settings..->


然後找到 Tools->External tools點選新增Tool按鈕


2.設定tool資訊


不願意新增巨集照抄即可,需要注意的是Android SDK 的JAR包路徑要根據自己的路徑修改以下

Name:Javah

Description:Javah

Program:$JDKPath$\bin\javah

Parameters:-d jni -classpath D:\Android\android-sdk\platforms\android-19\\android.jar;$OutputPath$ $FileClass$

這裡需要特別注意一下  D:\Android\android-sdk\platforms\android-19\\android.jar    這個SDK包的位置請根據自己的機器環境填寫 否則會發生錯誤)

Working directory:$ProjectFileDir$

設定完畢點選OK即可

3. Make Project生成class檔案


點選Make Project後會在工程路徑  \app\build\intermediates\classes\debug\com\example\file\jnitest01 中生成出class檔案,

下面生成標頭檔案需要class檔案

4.使用tool生成標頭檔案


點選 javah 後會開始自動生成,生成成功會提示處理完成 錯誤為0個


由於巨集設定的工作目錄在工程的根目錄,所以標頭檔案會生成在工程根目錄下面的jni資料夾中,

比如的我工程目錄在 D:\AndroidStudioProjects\Jnitest01 ,那麼在標頭檔案會生成在 D:\AndroidStudioProjects\Jnitest01\jni 中

四、編寫native程式碼

1.在Java目錄下新建Jni資料夾


2.把上面生成的com_example_file_test01_Myjni.h 移動到新建的jni目錄下

3.在jni目錄下新建一個cpp檔名為Myjni.cpp


點選OK建立即可

4.為新建的Myjni.cpp編寫native程式碼

由於程式碼有點長就不截圖了,直接上程式碼

// Created by file on 2017/10/24.
#include 
#include 

#define  LOG_TAG    "native-dev"
#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGE(...)  __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
#define LOGI(...)  __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)


JNIEXPORT void JNICALL Java_com_example_file_jnitest01_Myjni_MyjniToast
(JNIEnv* env, jobject job, jstring jStr)
{
    jclass myjniclass = NULL;
    jmethodID mid = NULL;
    const char* pNativeStr = NULL;
    jstring szOut = NULL;

    LOGI("MyjniToast---FindClass");
    myjniclass = env->FindClass("com/example/file/jnitest01/Myjni");
    if(myjniclass == NULL) {
        return;
    }
    mid = env->GetMethodID(myjniclass,"MyToast","(Ljava/lang/String;)V");
    if(mid == NULL) {
        return;
    }
    //jstring 轉 char* 需要開記憶體所以下面必須使用ReleaseStringUTFChars釋放  防止洩露
    pNativeStr = env->GetStringUTFChars(jStr, 0);
    if(pNativeStr == NULL) {
        return;
    }
    //重新生成一個jstring  也需要釋放一下szOut
    szOut = env->NewStringUTF(pNativeStr);
    if(szOut == NULL) {
        return;
    }
    //呼叫Myjni.MyToast 方法
    env->CallVoidMethod(job, mid, szOut);
    //釋放pNativeStr char*指標
    env->ReleaseStringUTFChars(jStr, pNativeStr);
    //釋放szOut
    env->DeleteLocalRef(szOut);
}

JNIEXPORT void JNICALL Java_com_example_file_jnitest01_Myjni_NativeToast
(JNIEnv* env, jclass jc, jobject context, jstring jStr)
{
    jclass tclass = NULL;
    jmethodID mID = NULL;
    jobject job = NULL;
    jmethodID showId = NULL;

    tclass = env->FindClass("android/widget/Toast");
    if(tclass == NULL) {
        return;
    }
    //獲取makeText方法ID
    mID = env->GetStaticMethodID(tclass,"makeText","(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;");
    if(mID == NULL) {
        return;
    }
    //呼叫makeText  第5個引數是makeText的duration
    job = env->CallStaticObjectMethod(tclass, mID, context, jStr , 0);
    if(job == NULL) {
        return;
    }
    showId = env->GetMethodID(tclass,"show","()V");
    if(showId == NULL) {
        return;
    }
    env->CallVoidMethod(job, showId, context, jStr);
}

JNIEXPORT jstring JNICALL Java_com_example_file_jnitest01_Myjni_NativeString
(JNIEnv* env, jclass)
{
    return env->NewStringUTF("NativeString");
}

5.建立Android.mk檔案



程式碼如下:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_CPP_EXTENSION := cpp
LOCAL_MODULE    := Myjni
LOCAL_SRC_FILES := Myjni.cpp
LOCAL_LDLIBS := -llog
include $(BUILD_SHARED_LIBRARY)

6.建立Application.mk



程式碼如下:

APP_ABI := all
APP_STL := stlport_static
APP_OPIM := debug

7.修改Build.gradle  進行編譯

Build.gradle:


ndk{
    moduleName "myjni"                              //so檔名
}


externalNativeBuild {
    ndkBuild {
        path "src/main/jni/android.mk"
}
}

6.修改完成點選 Build->Build APK ,提示編譯成功的話就可以新增呼叫Native方法的程式碼了

五、為Activity新增兩個測試按鈕

1.新增兩個測試按鈕


2.為按鈕添加回調方法


3.在 MainActivity中實現回撥方法並呼叫Native方法


程式碼:

public void button_MyjniToast(View view) {

    jni.MyjniToast("Myjni.MyjniToast->Myjni->MyToast");
}


public void button_NativeToast(View view) {
    jni.NativeToast(this, "Myjni.NativeToast->android.widget.Toast");
}

六、Build APK 測試吧

相關推薦

Android Studio Jni開發實現Native呼叫java方法Native呼叫Android API

這一篇主要內容是Native呼叫java方法和Native呼叫Android API,以及External Tools快速生成.h檔案,依然是使用NDK方式編譯,如果是複製貼上黨,建議跟本文用一樣的工程名,本文後面會提供demo連結 一、建立工程 1.建立名為Jnites

一步一步學習Android TV/盒子開發

TV、機頂盒開發除錯不能像手機一樣通過USB線連線除錯,可通過ADB連線除錯 連線電視 adb connect 10.74.84.199 1 2 連線後就可以開始開發除錯了! 斷開連線 // 斷開某個裝置 adb disconnect 10.74.84

Android Studio專案打包常見錯誤:Execution failed for task ':app:mergeReleaseResources'等等

    Generate Signed APK: Errors while building APK. You can find the errors in the 'Messages' view. 錯誤1: AAPT: libpng error: Not

android介面設計筆記實現頂部底部二級導航欄

下載demo:https://github.com/linliangliang/BottomNavagationBar 二級導航欄的實現是在之前學習導航欄的兩種實現方式的基礎上實現的。 1、https://blog.csdn.net/qq_25066049/article/details/8

Android OpenGL ES 開發— 繪製三角形

        在前一篇部落格我們知道了Android中OpenGL ES是什麼,然後知道了怎麼搭建一個OpenGL ES的執行環境,現在我們就來開始繪製我們自己想要的圖形了(繪製圖片會在後面講解,因為繪製圖形是繪製圖片的基礎),我們最先開始繪製一個三角形

Android studio 混合程式設計

Android studio 混合程式設計(一)裡面講的是直接載入了百度的首頁,現在繼續講如何加入自己的Html 5 頁面。 一、首先匯入Html 5 專案檔案 選擇 app\src\main 選單,右鍵選擇New->Folder->Assets

Android藍芽開發 BLE4.0低功耗藍芽

一、BLE4.0低功耗藍芽 Bluetooth Low Energy,藍芽低功耗,是從藍芽4.0開始支援的技術。相較傳統藍芽,傳輸速度更快、覆蓋範圍廣、安全性高、延時短、耗電低等特點。 二、關鍵術語 1.GATT(通用屬性配置):通用屬性配置檔案,用於ble鏈路上傳送和接

Android微信開發:程式碼分析

package com.example.teststudyshare.wxapi; import java.io.ObjectOutputStream.PutField; import android.R; import android.app.Activity; import android.content

Android NDK 開發JNI 傳遞引數返回值

前言 我們在使用 JNI 時最常問到的是 JAVA 和 C/C++之間如何傳遞資料,以及資料型別之間如何 互相對映。我們從整數等基本型別和陣列、字串等普通的物件型別開始講述。至於如何傳遞任意物件,將在後面會更新。 正文 繼JNI簡介及呼叫流程這

Android Design Support Library用NavigationView實現抽屜菜單界面

mpi tar bar board contex != print 滑動 頭部 NavigationView在MD設計中很重要,之前Google也提出了使用DrawerLayout來實現導航抽屜。這次,在Android Design Support Li

android的百度地圖開發 定位

頻率 update 殺死 一次 ddr animate 語義 pri des 參考:http://blog.csdn.net/mr_wzc/article/details/51590485 第一步,初始化LocationClient類 //獲取地圖控件引用

嵌入式核心及驅動開發之學習筆記 實現應用控制驅動

Linux系統根據驅動程式實現的模型框架將裝置驅動分成字元裝置驅動、塊裝置驅動、網路裝置驅動三大類。這裡簡單理解一下概念 字元裝置:裝置按位元組流處理資料,通常用的串列埠裝置、鍵盤裝置都是這種。 塊裝置:裝置按塊單位對資料處理,通常是儲存裝置。 網路裝置:顧名思義,建立在soc

手把手教你如何在Android下進行JNI開發入門

在進行Android開發的過程中,我們必定會遇到視訊影象處理、高強度密集運算、特殊演算法等場景,這時我們就不得不需要去接觸一些C/C++程式碼,進行JNI開發。下面我將從Android.mk和CMake這兩種方式教大家如何進行開發。文章結尾將給出演示的專案程式碼,如果你能耐心地仔細看完,相信你一定能掌握

iOS藍芽開發在裝置端實現Central角色

若想在裝置上實現Central角色的功能,主要有以下步驟: 2.搜尋周圍廣播的裝置 3.與一個外設進行連線,並探索外設提供的服務 4.向外設傳送讀寫characteristic的請求,如果有需要訂閱characteristic值得更新,來跟蹤資料的變化。 myCe

SpringBoot實現Java高併發秒殺系統之Service層開發

繼上一篇文章:SpringBoot實現Java高併發秒殺系統之DAO層開發 我們建立了SpringBoot專案並熟悉了秒殺系統的表設計,下面我們將講解一下秒殺系統的核心部分:Service業務層的開發。 Service層又稱為業務層,在Spring階段主要是由@

小KING教你做android專案---實現登陸頁面並跳轉簡單的註冊頁面

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_par

Android開發SQLite視覺化工具SQLiteStudio的用法

一、SQLiteStudio下載地址:  http://www.pc6.com/softview/SoftView_86552.html#download二、SQLiteStudio使用教程第一步:建庫    開啟SQLite Studio,點選“新增資料庫”按鈕第二步:資料

android介面設計筆記底部導航欄的兩種實現方式

demo:https://github.com/linliangliang/BottomNavagationBar android底部導航欄的實現方式比較多,今天學習其中兩種方式: 一、使用tabLayout+Fragment實現。 二、使用BottomNavagationBar實現。 第一

Android 百萬級視訊應用開發

在完成可之前的思考之後,我感覺我也是絞盡腦汁了。 7月25號的時候出了效果圖,和切圖,我26號下午完成了整個軟體的頁面搭建。歷史8.5小時26個頁面。但是我想我應該可以做的更好,因為,我的封裝做的還不徹底,既然複用那麼複用率就應該達到100%!既然封裝,那麼就

Android Design Support Library用NavigationView實現抽屜選單介面

NavigationView在MD設計中非常重要,之前Google也提出了使用DrawerLayout來實現導航抽屜。這次,在Android Design Support Library中,Google提供了NavigationView來實現導航選單介面。