Android Studio 2.2이상 + NDK Library 설정하기 (+openCV 3.1 포함)

 


 

이 포스트에서는 안드이드 스튜디오 2.2 이상 버전 + NDK 라이브러리를 활용하여 C, C++ 네이티브 언어로 앱의 일부를 구현하는 방법을 소개합니다.  구글 검색이 아닌 네이버에서는 관련된 자료가 잘 나와있지 않은 것 같아서, 이 취지를 살려 작성한 것입니다. 추가적으로, 영상처리에서 활용되는 OpenCV 라이브러리를 프로젝트에 포함하여 진행됩니다. (OpenCV를 활용하지 않는 일반 사용자는 이부분을 패스해도 됩니다.) 자바 및 안드로이드 스튜디오 설치 방법은 아래의 링크를 참고해 주시고, 이 프로젝트에서는 안드로이드 스튜디오로 앱을 개발하기 위한 기본 설치는 되어있는 것으로, 그리고 기본적인 안드로이드 스튜디오 프로젝트 구조에 대한 기본적인 이해가 된 것으로 가정합니다.


Java 설치 관련 블로그 : http://t2t2tt.tistory.com/9
Android Studio 설치 관련 블로그 : http://t2t2tt.tistory.com/11

 

 

 

 



이 포스트의 프로젝트는 해당 글 맨 아래   링크로 이동  에서 다운받으실 수 있습니다.


먼저 테스트를 위한 새로운 프로젝트를 생성합니다. 
기존의 NDK 개발을 위해서는 Android.mk, Application.mk 등등.. 여러 파일들을 생성하여 개발해야 했고, 이는 처음 접하는 사용자들에겐.. 너무나 지옥같은 일이었습니다...

 

"하지만"

 

 

안드로이드 스튜디오 2.2 이상 버전에서는 아래 사진과 같이 include C++ support 항목이 새로 생겼는데요, 이를 이용해 어렵지 않게 개발이 가능합니다. 이 옵션에 체크를 하고 프로젝트를 생성합니다.

 

 

 

 

다음으로 나타나는 Customize C++ Support 메뉴에서 표준 C++ 문법을 정하시고, 아래의 체크항목에 모두 체크를 하시고  Finish를 눌러서 프로젝트를 생성합니다. 본 포스팅에서는 C++ Standard 항목을 Toolchain Default로 설정하겠습니다.

 

 

 

프로젝트가 생성되고 아래와같은 에러가 발생할 수 있습니다. 혹시 발생하셨나요?

 

 <C++ support를 선택하지 않았을 때 정상적으로 안드로이드 스튜디오가 빌드가 가능한 경우>에 이 에러가 발생하셨다면, 이 에러는 NDK 라이브러리가 설치되지 않아서 또는 Project에 NDK의 위치가 지정이 되지 않아서 입니다. 먼저 설치가 되어 있지 않은 경우, 상단아이콘의 'SDK manager' 또는 'File → Settings(Ctrl+Alt+S) → Appearence & Behavior → System Settings → Android SDK' 경로를 통해  하단 탭의 SDK Tools 로 이동합니다.

 

 

 

위 항목에서 CMake, LLDB, NDK 세가지 항목중 없는 항목을 체크하고, Apply를 눌러 설치합니다.
저는 그래서, 밑의 Android 개발자 홈페이지에서 NDK를 직접 받아서 저장하였습니다.

 

 

 

 

설치가 모두 완료되고나면 Project Structure 를 열고(Ctrl+Alt+Shift+S) 바로 나타나는 SDK Location에서 NDK의 경로가 지정되었는지를 확인합니다. SDK Tools를 이용해 설치한 경우, 자동으로 나타나고, 저처럼 수동으로 설치하신 경우, 설치하신 경로를 직접 입력하면 Gradle Sync가 이루어지면서 정상적으로 동작이 됨을 알 수 있습니다.

 

 

<설정이 정상적으로 이루어져있는 모습>

 

 

 

 

 

 


 

 

NDK를 활용해 C++ 파일 컴파일 테스트

 

1) 외부 라이브러리를 사용하지 않는 경우

 

이제 NDK를 사용할 기본 과정을 마쳤으므로, 본격적으로 시작 해 볼까요?
먼저 Alt+1을 눌러, 아래와 같이 Android 에서 Project로 뷰를 변경합니다.

 

 

먼저, activity_main.xml 파일을 열어서 다음과 같이 대체합니다.

 

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                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!"
        android:layout_centerInParent="true"/>

    <TextView
        android:id="@+id/sample_text2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        android:layout_centerHorizontal="true"
        android:layout_below="@id/sample_text"/>
    </RelativeLayout>

 

다음으로,  MainActivity를 열어서 다음과 같이 대체합니다. 
작성하실때 패키지명은 본인이 작성한 패키지명으로 반드시 대체하시기 바랍니다.

/*패키지 명은 본인의 패키지명으로 대체해야합니다.*/
package com.example.tigrammer.ndkopencvtest;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    public native String stringFromJNI();
    public native int intFromJNI(int num1, int num2);

    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 = (TextView) findViewById(R.id.sample_text);
        tv.setText(stringFromJNI());

        TextView tv2 = (TextView) findViewById(R.id.sample_text2);
        tv.setText("Result : " + intFromJNI(3,4));
    }
}

 

그 후에 app/src/main/cpp 에 있는 native-lib.cpp 파일이 보이게 됩니다!! 그 파일을 더블클릭해서 열어서 수정해 보겠습니다. 만약, 직접 만든 프로젝트에서 따라하고 계시다면, JNI함수CALL은, 다음과 같이 규칙을 따라야 합니다.

 

JNIEXPORT [j리턴타입] JNICALL
Java_[패키지명1]_[패키지명2]_[...]_[액티비티]_[함수이름] (
    JNIEnv* env, jobject, [인자1],[인자2],[...] ){
}

 

패키지명은 .은 모두 _로 대체해야하며, 액티비티명_함수이름 이 뒤에 붙습니다.
그 후에 인자로 JNIEnv* env, jobject를 필수적으로 작성합니다. jni에서는 void->void, int->jint, double->jdouble... 과같이 표시합니다. MainActivity에서 native함수의 인자가 int라면, 여기선 jint로 입력하는 방법입니다. 이 포스팅에서는 native-lib.cpp을 다음과같이 변경합니다.

#include <jni.h>
#include <string>


extern "C" {
JNIEXPORT jstring JNICALL
Java_com_example_tigrammer_ndkopencvtest_MainActivity_stringFromJNI(
        JNIEnv *env, jobject) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}
JNIEXPORT jint JNICALL
Java_com_example_tigrammer_ndkopencvtest_MainActivity_intFromJNI(
        JNIEnv *env, jobject, jint num1, jint num2) {
    return (num1 * num2);
}

}

 

 이제 앱을 실행시켜보면 아래와 같이 정상적으로 실행이 되는 것을 볼 수가 있습니다.

 

 

 

 

 

만약에 native-lib.cpp 파일이 아닌, 기존 프로젝트의 헤더와 구현파일을 추가하고 싶다면 어떻게 해야 할까요? 저도 처음 공부할 때는 다소 어려움이 많았기에, 도움을 드리고자 합니다. 
먼저, project 뷰 에서 app/src/main/cpp 경로를 타고 가서, 아래와 같이 헤더 및 구현파일을 추가하도록 하겠습니다. 이 포스팅에서는 test.cpp, test.hpp, inner.cpp, inner.hpp 네 개의 파일을 추가하도록 하겠습니다.

 

 

 

아래 체크박스 (Create an associated Header) 를 체크합니다. 확장자는 .cpp / .h 로 하셔도 상관없지만, 전 .cpp / .hpp로 설정을 변경하여 적용했습니다. 적용하시려면 타입을 설정하는 부분 오른쪽에 스패너(?) 아이콘을 클릭하면 변경할 수 있습니다. test.hpp 가 inner.hpp를, native-lib.cpp가 test.hpp를 include 한다고 가정하고 작성하며, native-lib.cpp, test.cpp를 다음과 같이 변경합니다.

//native-lib.cpp
#include 
#include 
#include "test.hpp"


extern "C" {
JNIEXPORT jstring JNICALL
Java_com_example_tigrammer_ndkopencvtest_MainActivity_stringFromJNI(
        JNIEnv *env, jobject) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}
JNIEXPORT jint JNICALL
Java_com_example_tigrammer_ndkopencvtest_MainActivity_intFromJNI(
        JNIEnv *env, jobject, jint num1, jint num2) {
    return getValue(num1, num2);
}

}

//test.cpp
//헤더파일은 각각 맞게 알아서 작성하시면 됩니다.
#include "test.hpp"

int getValue(int num1, int num2){
    return (num1 * num2);
}

}

 

여기까지는 아마 혼자 해보신 분도 있으실겁니다. 새로만드신 .cpp 파일을 아무리 Sync now 를 해도 적용되는거 같지가 않은 문제를 많이들 겪으셨을텐데, 우리는 CMakeList.txt 파일을 열어서 라이브러리로 만들고 라이브러리를 타겟에 링크하도록 하겠습니다. CMakeList.txt를 열고 다음과 같이 대체합니다.
주석을 참고하고, 반드시 주의하여 수정하도록 합니다.

#프로젝트 및 OpenCV 라이브러리 경로를 각각 변수에 저장합니다.
#예시 : set(pathProject C:/Android/Projects/NdkOpencvTest)
set(pathProject C:/[프로젝트경로]/[프로젝트명])
 
cmake_minimum_required(VERSION 3.4.1)
 
set(CMAKE_VERBOSE_MAKEFILE on)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
 
# 다음은 최대최적화 옵션을 직접 지정하는 부분입니다. 필요에 따라 작성하세요.
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3")
 
#다음4줄을 추가합니다.
file(GLOB Library_SOURCES src/main/cpp/*.cpp)
file(GLOB Library_HEADERS src/main/cpp/*.hpp)
add_library(imported-lib SHARED  ${Library_SOURCES} ${Library_HEADERS} )
set_target_properties(imported-lib PROPERTIES LINKER_LANGUAGE CXX)
 
add_library( native-lib
             SHARED
             src/main/cpp/native-lib.cpp )
 
 
#android log
find_library( android-lib android)
 
#미리 빌드된 라이브러리를 찾습니다.
find_library( # Sets the name of the path variable.
              log-lib
 
              # Specifies the name of the NDK library that
              # you want CMake to locate.
              log )
 
# native-lib을 컴파일 하기 위해 필요로 만든 imported-lib를 지정합니다.
target_link_libraries( native-lib #타겟 라이브러리
 
                       #필요한 라이브러리
                       ${log-lib}
                       imported-lib )

 

다음과 같이 수정하고 CMakeList.txt 탭을 닫았다가 다시 열면, 상단에 Sync 안내가 나오게 되고, 이 Sync 버튼을 누르면, 정상 Build가 이루어짐을 확인할 수 있습니다. 이 포스팅에선 4개의 파일을 imported-lib로 생성하였지만, 필요에 따라서 각자 라이브러리로 만들고, target_link_libraries 를 통해서 링크할 수 있습니다. 이 함수에서는 target_link_libraries([타겟 라이브러리]  [필요라이브러리1, 필요라이브러리2, ...]) 와 같은 형식에 주의합니다.
마지막으로, MainActivity의 라이브러리를 로드하는 "static {" 이하 부분을 다음과 같이 교체합니다.
필요로 하는 가장 하위 단계의 라이브러리부터 불러오는 것에 주의해야합니다. 이는 openCV라이브러리를 프로젝트에 포함하는 포스팅 부분에서 다시 강조하겠습니다.

static {
        System.loadLibrary("imported-lib");
        System.loadLibrary("native-lib");
}

 

위 과정을 거쳐서 컴파일 후 실행하면 정상적으로 실행됨을 확인할 수 있습니다 :) 

 

 

 

 

 

2) OpenCV 라이브러리를 사용하는 경우

 

OpenCV 라이브러리는 영상처리에 사용되는 오픈소스 라이브러리입니다. 본 포스팅에서는 OpenCV 3.1Android Pack을 설치하여 진행하겠습니다. 
저는 windows용, ios용, 안드로이드용 3.1,3.0 버전을 각각 설치하고 있기 때문에, 설치한 후 압축을 해제한 폴더를 C:\opencv\경로에 저장해 모아두었습니다.
예를 들어,  Windows 용은 "C:\opencv\opencv-310"에, 안드로이드용은 "C:\opencv\OpenCV-android-sdk_310
" 경로에 저장하였으며, 이 안드로이드용 OpenCV 경로를 이용하여 설명하도록 하겠습니다.

저는 openCV 라이브러리가 제대로 활용되는지를 테스트 하기위해, 카메라 영상을 흑백이미지로 변환하여 보여주는 예제를 작성하였습니다. OpenCV 의 'cvtColor' 함수를 사용할 것입니다. API 23 에서는, 특정 권한을 요구하는 모듈이 추가되어야 하므로, 본 예제를 토대로 작성 해 주시기 바랍니다.
이 예제에서는 앞서 설명한 것 중, 기존 헤더 및 구현파일 여러개가 있는 경우를 기준으로 설명하겠습니다. 먼저, File-New-Import Module을 선택합니다.

 

 

 

 

모듈을 추가하는 창에서 , [Android OpenCV 경로]\sdk\Java 경로를 아래 그림과 같이 지정하면, 모듈 이름이 자동적으로 생성되는 것을 볼 수 있습니다. Next - Finish를 눌러 모듈을 추가합니다.

 

모듈을 추가하게 되면, 다음과 같은 에러 메시지를 볼 수 있습니다. 이는 app.gradle과, openCV 모듈의 gradle이 맞지 않아서 생기는 에러로, 프로젝트 뷰에서 OpenCVLibrary310 디렉토리의  build.gradle을 열고 이를  app의 build.gradle 의 compileSdkVersion, buildToolVersion, minSdkVersion,targetSdkVersion 과 동일하게 바꿔주면 이 에러가 해결됩니다

 

 

다음으로, File - Project Structure(Ctrl + Alt + Shift + S) 를 눌러서, 왼쪽의 app 모듈을 클릭하고, app 모듈의 dependencies를 클릭하여, 오른쪽 상단의 + 를 클릭, module dependency를 클릭하여 openCVLibrary310 라이브러리를 app 에 추가합니다.

 

 

버전을 모두 맞추고 난 후, Gradle Sync를 해주면 openCV 라이브러리를 사용할 수 있게 됩니다.
이제 카메라를 사용할 것이므로, Manifest.xml 을 다음과 같이 수정합니다.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.tigrammer.ndkopencvtest" >
    <uses-permission android:name="android.permission.CAMERA"/>
    <uses-feature android:name="android.hardware.camera" />
    <uses-feature android:name="android.hardware.camera.autofocus" android:required="false"/>
    <uses-feature android:name="android.hardware.camera.front" android:required="false"/>
    <uses-feature android:name="android.hardware.camera.front.autofocus"  android:required="false"/>

    <supports-screens android:resizeable="true"
        android:smallScreens="true"
        android:normalScreens="true"
        android:largeScreens="true"
        android:anyDensity="true" />

    <application
        android:allowBackup="true"
        android:hardwareAccelerated="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity"
            android:screenOrientation="landscape">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

수정이 완료되었으면,  cpp 디렉토리에 process.hpp, process.cpp 파일을 추가하고, native-lib.cpp까지 세 파일을 아래와 같이 작성합니다. 굳이 process.hpp/.cpp 파일을 만든 것은, 여러 프로젝트 파일을 가지고 테스트 해보기 위함입니다.

#ifndef NDKOPENCVTEST_PROCESS_HPP
#define NDKOPENCVTEST_PROCESS_HPP

#include <opencv2/opencv.hpp>
cv::Mat ConvertImage(cv::Mat input);
#endif //NDKOPENCVTEST_PROCESS_HPP


#include "process.hpp"
using namespace cv;

Mat ConvertImage(Mat input){
    Mat output;
    cvtColor(input, output, CV_RGBA2GRAY);
    return output;
}


#include <jni.h>
#include "process.hpp"
using namespace cv;
extern "C"
JNIEXPORT void JNICALL
Java_com_example_tigrammer_ndkopencvtest_MainActivity_GetGrayImage(
        JNIEnv *env, jobject, jlong inputAddr, jlong resultAddr){
    Mat &input = *(Mat*)inputAddr;
    *(Mat*) resultAddr = ConvertImage(input);
}


다음으로, android용 opencv를 설치한 경로에 들어가서, [경로]\sdk\native\libs 폴더를 복사하여, 현재 프로젝트의 src\main에 libs 폴더를 복사하고, 이 폴더의 이름을 'JniLibs'로 변경해 줍니다. 그러면 src\main 에는 cpp, java, JniLibs, res 네 개의 디렉토리가 존재하게 됩니다.

다음으로, CMakeList.txt 파일을 다음과 같이 수정합니다.

#프로젝트 및 OpenCV 라이브러리 경로를 각각 변수에 저장합니다.
# 주의!! : 본인의 프로젝트 경로와, opencv 경로로 수정합니다.
set(pathOpenCv C:/opencv/OpenCV-android-sdk_310)
set(pathProject C:/Android/AndroidStudioProjects/NdkOpencvTest)

cmake_minimum_required(VERSION 3.4.1)

set(CMAKE_VERBOSE_MAKEFILE on)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")

#헤더파일 경로
include_directories(${pathOpenCv}/sdk/native/jni/include)

add_library( lib_opencv SHARED IMPORTED )
set_target_properties(lib_opencv PROPERTIES IMPORTED_LOCATION ${pathProject}/app/src/main/JniLibs/${ANDROID_ABI}/libopencv_java3.so)

file(GLOB Library_SOURCES src/main/cpp/*.cpp)
file(GLOB Library_HEADERS src/main/cpp/*.hpp)

add_library(imported-lib SHARED  ${Library_SOURCES} ${Library_HEADERS} )
set_target_properties(imported-lib PROPERTIES LINKER_LANGUAGE CXX)

add_library( native-lib
             SHARED
             src/main/cpp/native-lib.cpp )


#android log
find_library( android-lib android)

#미리 빌드된 라이브러리를 찾습니다.
find_library( # Sets the name of the path variable.
              log-lib

              # Specifies the name of the NDK library that
              # you want CMake to locate.
              log )

# 타겟 라이브러리를 생성하기 위해 필요한 라이브러리를 명시합니다.
target_link_libraries( imported-lib  #타겟 라이브러리
                       lib_opencv)   #필요한 라이브러리

target_link_libraries( native-lib #타겟 라이브러리

                       #필요한 라이브러리
                       ${log-lib}
                       imported-lib
                       lib_opencv )

 

 여기까지 되셨으면, 마지막으로 activity_main.xml 과 MainActivity.java 파일을 수정하면 됩니다. 아래의 소스코드를 활용하여 수정합니다. 아래의 xml 파일에는 JavaCameraView를 컴포넌트로 가지고 있고,  MainActivity 는 앞서 설명한 권한을 묻는 예제가 포함되어있습니다. 소스코드 분석은 Java에 대한 기본적인 이해를 가지고 계신 분이라면 가능하실 것이라 믿습니다^^;;

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.tigrammer.ndkopencvtest.MainActivity">

    <org.opencv.android.JavaCameraView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/activity_surface_view" />

</RelativeLayout>


package com.example.tigrammer.ndkopencvtest;

import android.Manifest;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.SurfaceView;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Toast;

import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.CameraBridgeViewBase;
import org.opencv.android.JavaCameraView;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;
import org.opencv.core.Mat;

public class MainActivity extends AppCompatActivity implements CameraBridgeViewBase.CvCameraViewListener2{
    static final int REQUEST_CAMERA = 1;
    public JavaCameraView mOpenCvCameraView;
    public Mat mReturnImage;
    private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
        @Override
        public void onManagerConnected(int status) {
            switch (status) {
                case LoaderCallbackInterface.SUCCESS: mOpenCvCameraView.enableView(); break;
                default: super.onManagerConnected(status); break;
            }
        }
    };

    public native void GetGrayImage(long inputAddr, long resultAddr);

    static {
        System.loadLibrary("opencv_java3");
        System.loadLibrary("imported-lib");
        System.loadLibrary("native-lib");
    }

    @Override
    public void onCameraViewStarted(int width, int height) { }

    @Override
    public void onCameraViewStopped() { }

    @Override
    public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
        Mat frame = inputFrame.rgba();
        GetGrayImage(frame.getNativeObjAddr(), mReturnImage.getNativeObjAddr());
        return mReturnImage;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_main);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        mReturnImage = new Mat();
        mOpenCvCameraView = (JavaCameraView) findViewById(R.id.activity_surface_view);
        mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);
        mOpenCvCameraView.setCvCameraViewListener(this);
        mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);

        int permissionCamera = ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.CAMERA);
        if(permissionCamera == PackageManager.PERMISSION_DENIED)
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA);
    }
    @Override
    public void onPause()
    {
        super.onPause();
        if (mOpenCvCameraView != null)
            mOpenCvCameraView.disableView();
        System.gc();
    }


    @Override
    public void onResume(){
        super.onResume();
        if (!OpenCVLoader.initDebug()) {
            OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_1_0, this, mLoaderCallback);
        } else {
            mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
        }
    }

    public void onDestroy() {
        super.onDestroy();
        if (mOpenCvCameraView != null)
            mOpenCvCameraView.disableView();
    }
    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);

        for (int i = 0; i < permissions.length; i++) {
            String permission = permissions[i];
            int grantResult = grantResults[i];
            if (permission.equals(Manifest.permission.CAMERA)) {
                if(grantResult == PackageManager.PERMISSION_GRANTED) {
                    Toast.makeText(MainActivity.this, "Camera Permission Authorized", Toast.LENGTH_SHORT).show();

                    Intent intent = new Intent(this, MainActivity.class);
                    PendingIntent mPendingIntent = PendingIntent.getActivity(this, 123, intent, PendingIntent.FLAG_CANCEL_CURRENT);
                    AlarmManager mgr = (AlarmManager)this.getSystemService(Context.ALARM_SERVICE);
                    mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, mPendingIntent);
                    System.exit(0);
                } else {
                    Toast.makeText(MainActivity.this, "Camera Permission Denied", Toast.LENGTH_SHORT).show();
                }
            }
        }
    }
}

 

해당 MainActivity에서는 static{ 이하에 opencv_java3 라이브러리가 포함되어있으므로 체크하시기 바랍니다. 이 과정까지 하셨으면, 직접 프로젝트를 돌려보겠습니다. 그러면 처음에 권한을 묻고, 승인되면  아래와 같이 어플리케이션이 정상적으로 돌아가는 것을 볼 수 있습니다. 다른 영상처리에 관한 내용은 메일로 문의 해 주시거나, opencv.org 사이트를 참고하시기 바랍니다.

 

 

 실행 결과 화면 (흑백이미지로 출력됨)

 

 프로젝트 소스 : https://github.com/tigapgmr/NdkOpencvTest (클릭)

 


본 포스팅이 도움이 되셨다면 공감을 꾹 눌러주세요!! 

 

 

 Posted By_ Tiga


Posted by Tiga

블로그 이미지
영상처리 & 안드로이드 블로그
Tiga

태그목록

공지사항

Yesterday
Today
Total

달력

 « |  » 2024.5
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31

최근에 올라온 글

최근에 달린 댓글

글 보관함