Android

[Native C++] 응용1. Assets을 이용한 aar 만들기 (3)

별빛의온기 2022. 10. 30. 17:28
반응형

 

Assets 폴더의 자산을 활용할수 있도록 Class를 변경하도록 합니다.

 

1. 다음과 같이 클래스에 소스를 추가합니다.

import android.content.Context;
import android.content.res.AssetManager;

public class Sample {
    // Used to load the 'native-lib' library on application startup.
    static {
        System.loadLibrary("native-lib");
    }

      //기본 생성자.
    public Sample(){
    }
    // 생성자 추가, 라이브러리에서 Assets에 접근하기 위함.
    public Sample(Context context){
        jni_ReadAssetManager(context.getAssets());
    }

    // 테스트 메소드 추가
    public int getSampleData(int[] n1, int[] n2, float[] ratio) {
        return jni_getSampleData(n1, n2, ratio);
    }
    
    public String stringFromJNI() {
        return jni_stringFromJNI();
    }

    public String getVersion() {
        return jni_getVersion();
    }

    public int getSampleSumData(int n1, int n2) {
        return jni_getSampleSumData(n1, n2);
    }


    /**
     * A native method that is implemented by the 'native-lib' native library,
     * which is packaged with this application.
     */
    private native String jni_stringFromJNI();
    private native String jni_getVersion();
    private native int jni_getSampleSumData(int n1, int n2);

    //Asset 관련 메소드 추가.
    private native void jni_ReadAssetManager( AssetManager assetManager );
    // 테스트 메소드 추가
    private native int jni_getSampleData( int[] n1, int[] n2, float[] ratio );
}
 

2. native-lib.cpp도 그에 맞게 수정합니다.

//추가
#include <android/asset_manager.h>
#include <android/asset_manager_jni.h>
#include "android_fopen.h"

..
.
..
.

//Assets 관련 함수 추가
extern "C"
JNIEXPORT void JNICALL
Java_com_hsk_sample_Sample_jni_1ReadAssetManager(JNIEnv *env, jobject thiz, jobject asset_manager) {
    // TODO: implement jni_ReadAssetManager()
    AAssetManager* mgr = AAssetManager_fromJava(env, asset_manager);
    android_fopen_set_asset_manager(mgr);
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_hsk_sample_Sample_jni_1getSampleData(JNIEnv *env, jobject thiz,
                                                jintArray n1,
                                                jintArray n2,
                                                jfloatArray ratio) {
    // TODO: implement jni_getSampleData()
    jint ret;
    jint *p_n1 = env->GetIntArrayElements(n1, NULL);
    jint *p_n2 = env->GetIntArrayElements(n2, NULL);
    jfloat *p_ratio = env->GetFloatArrayElements(ratio, NULL);

    ret = getSampleData(p_n1, p_n2, p_ratio);

    env->ReleaseIntArrayElements(n1, p_n1, 0);
    env->ReleaseIntArrayElements(n2, p_n2, 0);
    env->ReleaseFloatArrayElements(ratio, p_ratio, 0);

    return ret;
}
 

3. sample.cpp와 sample.h에 getSampleData 함수를 추가합니다

//sample.h
..
.
//추가
int getSampleData(int* p_n1, int* p_n2, float* p_ratio);
..
.
 
//sample.cpp

#include "android_fopen.h"
#include <cstring>
#include <stdlib.h>
#include <src.h>

..
생략
..



int getSampleData(int* p_n1, int* p_n2, float* p_ratio){
    FILE *fp;
    int ret = 0;
    char line[200], namestr[100], valstr[100];

    fp = assets_fopen("data.txt", "rb"); //Assets 자산 경로 입력 및 모드 입력

    if( fp == NULL){
        ret = 1;
    }else{

        while(fgets(line, 200, fp)){
            if (sscanf(line, "%s %s", namestr, valstr) < 2)
                continue;

            if (!strcmp(namestr, "#num1"))
                *p_n1 = atoi(valstr);
            else if (!strcmp(namestr, "#num2"))
                *p_n2 = atoi(valstr);
            else if (!strcmp(namestr, "#ratio"))
                *p_ratio = atof(valstr);
        }
        fclose(fp);
    }
    return ret;
}
 

4. CMakeLists에 target_link_libbraries에 android를 추가합니다

 

target_link_libraries( # Specifies the target library.
                       Sample-lib
                       android   #추가
                       # Links the target library to the log library
                       # included in the NDK.
                       ${log-lib} )
 

5. 마지막으로 MainActivity를 수정합니다

public class MainActivity extends AppCompatActivity {

    //추가
    Sample sample;
    int[] n1, n2;
    float[] ratio;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

		//수정
        sample = new Sample(this);

        n1 = new int[1];
        n2 = new int[1];
        ratio = new float[1];

        sample.getSampleData(n1,n2,ratio);
        
        Log.d("result : " , String.format( "sum : %d , ratio : %f", sample.getSampleSumData(n1[0], n2[0]), ratio[0]));
       
    }
}
 

6. app모듈의 bulid.gradle이 어플리케이션으로 설정되어있는지 확인하고 libraryVariamts.all이 설정되어 있으면 주석처리합니다. 또한 manifast 파일도 액티비티를 활성화 한 후 동기화합니다.

 

 

7. 이후 빌드하여 스마트폰에서 동작시켜보면 다음과 같은 결과를 얻습니다.

 

 

 

txt 파일에서 데이터를 가져왔음을 확인 할 수 있습니다.

반응형