2021年3月4日 星期四

Android Studio - NDK 測試程式(二十二)

Android Studio - NDK 測試程式(二十二):

完成 NDK(Native Development Kit)的安裝和設置,便可以使用編程測試 NDK 功能。首先是要創建一個新的支持 C++ 空項目開始,這樣是相對簡單直接,並且要添加 C++ 庫的話,這個就稍微麻煩一點,需要自行添加相關的幾個文件了,可以參見下面比較這兩種工程之間的不同。

Android Studio + NDK 測試程式

  • 操作系統:Windows 7 64-bit 版本
  • 開發環境:Android Studio 4.0.1 版本
  • Gradle 版本:6.1.1
  • 手機測試版本:API 19
  • 原程式:C:\Development\Development_Android\Android_Project\NDK
  • 程式:C:\Development\Development_Android\Android_Project\NDK
  • NDK 版本:NDK 21.0.6113669 版本 Android

1﹒首先是創建新 Native C++ 項目
Start a new Android Studio project→Native C++→Next→Name=NDK→Next→C++11(可選擇Toolchain / C++11 / C++14 / C++17)→Finish
創建新 Native C++ 項目

2﹒完成創建新 Native C++ 項目後,Android Studio 會自動產生完整的 Jave 呼叫 C++ 的程式,包括 CMakeLists.txt、native-lib.cpp、MainActivity.java 和 active_main.xml 文件,馬上 Run App 便可以測試 NDK。
app / java / MainActivity.java:

package bugworkshop.blogspot.ndk;

 

import androidx.appcompat.app.AppCompatActivity;

 

import android.os.Bundle;

import android.widget.TextView;

 

public class MainActivity extends AppCompatActivity {

 

    // Used to load the 'native-lib' library on application startup.

    static {

        System.loadLibrary("native-lib");

    }

 

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

 

        // Example of a call to a native method

        TextView tv = findViewById(R.id.sample_text);

        tv.setText(stringFromJNI());

    }

 

    /**

     * A native method that is implemented by the 'native-lib' native library,

     * which is packaged with this application.

     */

    public native String stringFromJNI();

}


app / res / layout / active_main.xml:

<?xml version="1.0" encoding="utf-8"?>

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:app="http://schemas.android.com/apk/res-auto"

    xmlns:tools="http://schemas.android.com/tools"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    tools:context=".MainActivity">

 

    <TextView

        android:id="@+id/sample_text"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:text="Hello World!"

        app:layout_constraintBottom_toBottomOf="parent"

        app:layout_constraintLeft_toLeftOf="parent"

        app:layout_constraintRight_toRightOf="parent"

        app:layout_constraintTop_toTopOf="parent" />

 

</androidx.constraintlayout.widget.ConstraintLayout>


app / cpp / native-lib.cpp:

#include <jni.h>

#include <string>

 

extern "C" JNIEXPORT jstring JNICALL

Java_bugworkshop_blogspot_ndk_MainActivity_stringFromJNI(

        JNIEnv* env,

        jobject /* this */) {

    std::string hello = "Hello from C++";

    return env->NewStringUTF(hello.c_str());

}


簡單說明 native-lib.cpp:
  • extern "C":實現 C 和 C++ 的混合程式設計,用於 C++ 代碼調用 C 的函數。
  • JNIEXPORT 和 JNICALL,用於標識函數用途的兩個巨集。
  • jstring,JNI 中的資料類型,對應 Java 中 String 類型,還有 8 種基底資料型別 jbyte、jchar、jshort、jint、jlong、jfloat、jdouble、jboolean,引用資料類型 jintArray、jshortArray、jlongArray 等。
  • 函數命名規則:Java_類全路徑_方法名,這裡的類是那個調用 C 或 C++ 的類,像這裡的Java_bugworkshop_blogspot_ndk_MainActivity_stringFromJNI。 函數至少有兩個參數,第一個參數 :JNIEnv* 是定義任意 native 函數的第一個參數(包括調用 JNI 的 RegisterNatives 函數註冊的函數),指向 JVM 函數表的指標,函數表中的每一個入口指向一個 JNI 函數,每個函數用於訪問 JVM 中特定的資料結構;第二個參數:調用 Java 中 native 方法的實例或 Class 物件,如果這個 native 方法是實例方法,則該參數是 jobject,如果是靜態方法,則是 jclass。
2021年 3月 4日(Thu)天氣報告
氣溫:62.0°F / 17.0°C @ 08:00
風速:每小時 18 公里
相對濕度:百分之 88%
天氣:多雲時陰

沒有留言:

張貼留言