지난번에 Android에서 OpenCV를 사용하기 위한 SDK 추가작업을 진행 했었는데 실제로 사용법을 익혀 보도록 하겠습니다.

Canny 함수를 이용해서 외각선 검출을 진행하게 되며 결과는 아래와 같습니다.

 

 

대부분 이미지 작업을 하게되기 때문에 OpenCV에서 카메라 제어를 할 수 있도록 작업을 하면 나머지는 간단하게 함수 호출만 해주면 되는데 카메라에서 이미지를 받아오는 설정 부분이 버전마다 조금씩 달라서 Canny() 프로그램 함수는 한줄이면 되는데 환경 설정하는 부분에 시간이 많이 소요 될 가능성도 있습니다.

 

먼저 카메라를 사용 할 수 있도록 권한을 추가합니다.

 

AndroidManifest.xml 

<uses-permission android:name="android.permission.CAMERA" />
<
uses-feature android:name="android.hardware.camera" android:required="false" />
<
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" />

  

 

Activity_main.xml은 내용을 전부 삭제하고 OpenCV 카메라 VIew를 추가해 줍니다. 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
   
xmlns:android="http://schemas.android.com/apk/res/android"
   
xmlns:opencv="http://schemas.android.com/apk/res-auto"
   
xmlns:tools="http://schemas.android.com/tools"
   
android:layout_width="match_parent"
   
android:layout_height="match_parent"
   
android:orientation="vertical"
   
tools:context=".MainActivity">

        <
org.opencv.android.JavaCameraView
           
android:layout_width="match_parent"
           
android:layout_height="match_parent"
           
android:visibility="gone"
           
android:id="@+id/frame_Surface"
           
opencv:show_fps="true"
           
opencv:camera_id="any">

        </
org.opencv.android.JavaCameraView>
</
LinearLayout>

 

 

 

MainActivity.java에 카메라 제어 관련 소스를 추가해 줍니다.

 

Global 변수를 만들어주고 카메라로 부터 Callback을 받아 처리하면 되는 간단한 내용인데 여기서 버전마다 조금씩 다르게 작동을 해서 몇가지 추가적인 작업이 필요할 수도 있습니다.

 

먼저 변수와 callback을 선언 합니다.

private Mat mRgba;
private CameraBridgeViewBase mOpenCvCameraView;
private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
   
@Override
   
public void onManagerConnected(int status) {
       
switch (status) {
           
case LoaderCallbackInterface.SUCCESS: {
                Log.d(
Tag_Log, "OpenCv loaded");
               
mOpenCvCameraView.enableView();
            }
           
break;
           
default:{
               
super.onManagerConnected(status);
            }
           
break;
        }
    }
};

 

 

onCreate()에는 화면구성시 idframe_Surface로 추가한 JavaCameraView를 설정 합니다.

 

mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.frame_Surface);
mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);
mOpenCvCameraView.setCvCameraViewListener(this);
mOpenCvCameraView.setCameraIndex(0);

  

ActivityCvCameraViewListener2를 상속해주고 이와 관련된 OpenCV 카메라 관련 메소드 3개를 Override로 추가합니다.

 

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


    }

   
@Override
   
public void onCameraViewStopped() {
    }

   
@Override
   
public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
       
mRgba = inputFrame.rgba();

       
return mRgba;
    }

 

 

그리고 onCameraFrame()에서 받아온 이미지를 리턴 하면 핸드폰 화면에 이미지가 나오는데 그렇지 않은 경우 아래와 같은 기능을 추가해 줍니다.

 

@Override
protected List<? extends CameraBridgeViewBase> getCameraViewList() {
   
return Collections.singletonList(mOpenCvCameraView);
}

 

 

최신 SDK중 이렇게 getCameraViewList()Override 할 수 있도록 되는 SDK 버전이 있습니다.

 

만약 getCameraViewList()Override로 지원 안되는 SDK 버전이라면

 

Permission에서 함수를 호출 하도록 해야 합니다.

 

@Override
    @TargetApi
(Build.VERSION_CODES.M)
   
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
       
if (requestCode == CAMERA_PERMISSION_REQUEST_CODE && grantResults.length > 0
               
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            onCameraPermissionGranted();
        }
else{
           
       
}
       
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

 

  

protected void onCameraPermissionGranted() {
    List<?
extends CameraBridgeViewBase> cameraViews = getCameraViewList();
   
if (cameraViews == null) {
       
return;
    }
   
for (CameraBridgeViewBase cameraBridgeViewBase: cameraViews) {
       
if (cameraBridgeViewBase != null) {
            cameraBridgeViewBase.setCameraPermissionGranted();
        }
    }
}

 

 

여기까지 왔으면

 

 

 

 

 

이런식으로 화면이 나와야 합니다.

 

 

그럼 Canny 함수 하나를 추가해서 테스트를 진행해 봅니다.

 

@Override
public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
   
mRgba = inputFrame.rgba();

   
if(mRgba == null) {
        Log.d(
Tag_Log, "onCameraFrame error");

    }
   
Mat edges = new Mat();
    Imgproc.Canny(mRgba, edges, 80,200);


   
return edges;
}

 

  

카메라로 가져온 이미지를 OpenCV Canny()함수에 추가해서 작업하는 방법입니다.

python으로도 간단하게 함수만 호출하면 테스트 할 수 있는것과 같이 android java에서도 함수만 호출하면 됩니다.

 

 

이미지가 90도 회전되어 보이는 부분은 AndroidManifest.xml에 설정을 추가하면 되고

MainActivity.java에는 onStart(), onDestroy() 등을 추가해줍니다.

그러면 처음에 보았던 이미지를 확인할 수 있습니다.

 

AndroidManifest.xml 전체 소스 

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
   
package="copycoding.tistory.opencvlib">

    <
uses-permission android:name="android.permission.CAMERA" />
    <
uses-feature android:name="android.hardware.camera" android:required="false" />
    <
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" />

    <
application
       
android:allowBackup="true"
       
android:icon="@mipmap/ic_launcher"
       
android:label="@string/app_name"
       
android:roundIcon="@mipmap/ic_launcher_round"
       
android:supportsRtl="true"
       
android:theme="@style/Theme.OpencvLib">
        <
activity android:name=".MainActivity"
           
android:screenOrientation="landscape"
           
android:configChanges="keyboardHidden|orientation">
            <
intent-filter>
                <
action android:name="android.intent.action.MAIN" />

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

</
manifest>

 

 

 

MainActivity.java 전체 소스입니다. 

package copycoding.tistory.opencvlib;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import android.Manifest;
import android.annotation.TargetApi;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceView;
import android.view.Window;
import android.view.WindowManager;

import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.CameraBridgeViewBase;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.imgproc.Imgproc;

import java.util.Collections;
import java.util.List;

import static android.Manifest.permission.CAMERA;

public class MainActivity extends AppCompatActivity implements CameraBridgeViewBase.CvCameraViewListener2 {

   
private static String Tag_Log = "OpenCV Test : ---------------------";
   
private static final int CAMERA_PERMISSION_REQUEST_CODE = 200;

   
private Mat mRgba;
   
private Mat mGrey;
   
private CameraBridgeViewBase mOpenCvCameraView;
   
private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
       
@Override
       
public void onManagerConnected(int status) {
           
switch (status) {
               
case LoaderCallbackInterface.SUCCESS: {
                    Log.d(
Tag_Log, "OpenCv loaded");
                   
mOpenCvCameraView.enableView();
                }
               
break;
               
default:{
                   
super.onManagerConnected(status);
                }
                
break;
            }
        }
    };


   
@Override
   
protected void onCreate(Bundle savedInstanceState) {
       
super.onCreate(savedInstanceState);

        requestWindowFeature(Window.
FEATURE_NO_TITLE);
        getSupportActionBar().hide();

       
setContentView(R.layout.activity_main);

       
mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.frame_Surface);
       
mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);
       
mOpenCvCameraView.setCvCameraViewListener(this);
       
mOpenCvCameraView.setCameraIndex(0);


   
}

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

   
}

   
@Override
   
public void onCameraViewStopped() {
    }

   
@Override
   
public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
       
mRgba = inputFrame.rgba();
        if(mRgba == null) {
            Log.d(
Tag_Log, "onCameraFrame error");

        }
        Mat edges = new Mat();
        Imgproc.Canny(mRgba, edges, 80,200);


        
return edges;
    }

   
@Override
   
protected void onResume() {
       
super.onResume();
       
if(OpenCVLoader.initDebug()) {
            Log.d(
Tag_Log, "Opencv initialized");
           
mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
        }
else {
            Log.d(
Tag_Log, "Opencv not loaded");
            OpenCVLoader.initAsync(OpenCVLoader.
OPENCV_VERSION, this, mLoaderCallback);
        }
    }

   
@Override
   
protected void onPause() {
       
super.onPause();
       
if(mOpenCvCameraView != null) {
           
mOpenCvCameraView.disableView();
        }
    }

   
@Override
   
protected void onDestroy() {
       
super.onDestroy();
       
if(mOpenCvCameraView != null) {
           
mOpenCvCameraView.disableView();
        }
    }

   
@Override
   
protected void onStart() {
       
super.onStart();

       
boolean havePermission = true;
       
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
           
if (checkSelfPermission(CAMERA) != PackageManager.PERMISSION_GRANTED) {
                requestPermissions(
new String[]{CAMERA}, CAMERA_PERMISSION_REQUEST_CODE);
                havePermission =
false;
            }
        }
       
if (havePermission) {
            onCameraPermissionGranted();
        }
    }

   
protected List<? extends CameraBridgeViewBase> getCameraViewList() {
       
return Collections.singletonList(mOpenCvCameraView);
    }

   
@Override
    @TargetApi
(Build.VERSION_CODES.M)
   
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
       
if (requestCode == CAMERA_PERMISSION_REQUEST_CODE && grantResults.length > 0
               
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            onCameraPermissionGranted();
        }
else{
           
       
}
       
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }


   
protected void onCameraPermissionGranted() {
        List<?
extends CameraBridgeViewBase> cameraViews = getCameraViewList();
       
if (cameraViews == null) {
           
return;
        }
       
for (CameraBridgeViewBase cameraBridgeViewBase: cameraViews) {
           
if (cameraBridgeViewBase != null) {
                cameraBridgeViewBase.setCameraPermissionGranted();
            }
        }
    }

}

 

 

  

이전에 올렸던 OpenCV SDK 설치관련 글을 읽으러 가지 않으려면 아래 gradle을 참고 하세요.

 

plugins {
   
id
'com.android.application'
}

android {
   
compileSdkVersion
29
   
buildToolsVersion "29.0.0"

   
defaultConfig {
       
applicationId
"copycoding.tistory.opencvlib"
       
minSdkVersion 26
       
targetSdkVersion 29
       
versionCode 1
       
versionName "1.0"

       
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
   
}

   
buildTypes {
       
release {
           
minifyEnabled
false
           
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
       
}
    }
   
compileOptions {
       
sourceCompatibility JavaVersion.
VERSION_1_8
       
targetCompatibility JavaVersion.VERSION_1_8
   
}
}

dependencies {

   
implementation
'androidx.appcompat:appcompat:1.3.1'
   
implementation 'com.google.android.material:material:1.4.0'
   
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
   
implementation project(path: ':OpenCV')
    testImplementation
'junit:junit:4.+'
   
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
   
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
}

 

 

 - copy coding -

 

OpenCV를 안드로이드에서 사용하려면 SDK를 이용해야 합니다. OpenCVC++로 되어있어서 설치하는 과정이 복잡했는데 요즘에는 쉽게 사용이 가능합니다. SDKOpenCV에서 제공하고 있는데 안드로이드 버전에 따라 맞는 버전을 선택 해야 하고 저는 최신 버전(현재 OpenCV-4.7.0)으로 테스트 해보려고 하였으나 계속되는 에러로 실패를 하고 다른 버전으로 몇 번을 시도한 후에 적합한 버전을 찾게 되었습니다.

 

안드로이드 버전을 많이 타는것 같습니다.  참고로 제 핸드폰의 Android version 9 입니다. 

OpenCV-4.4.0 버전이 제 핸드폰에는 적합하고 gradle 버전도 맞춰야 하고 dependencies 설정도 적절하게 손을 봐야 합니다.

 

 

아래에 설명되는 글들중 이미지에 버전이 4.7.0로 된 부분이 있다면 4.4.0임을 참고하시기 바랍니다.

처음 캡쳐하고 에러나서 여러번 테스트 하면서 다시 캡쳐를 하지 않았네요.

저는 OpenCV 5개의 버전을 테스트 해서 제가 가지고 있는 핸드폰에 적합한 환경을 설정 했습니다.  핸드폰 버전에 따라 조금씩은 환경 설정에 시간을 소비해야 하지 않을까 생각 됩니다.

 

 

1. SDK 다운로드

 

 

OpenCV SDK를 다운로드 받기 위해 홈페이지에 접속합니다.

 

https://opencv.org/

 

 

 

첫화면의 Library에 마우스를 올려 놓으면 서브메뉴가 나타나고 Releases를 선택합니다.

 

Library > Releases

 

최신 버전순으로 SDK 리스트와 지원하는 운영체제를 볼 수 있습니다.

자신의 핸드폰에 적합하다고 생각되는 버전을 선택합니다.

 

 

 

저는 OpenCV-4.4.0 버전에서 운영체제는 Android를 선택했습니다.

 

opencv-4.4.0-android-sdk.zip  211MB

 

다운로드 받은 파일을 적당한 폴더에서 압축을 풀어줍니다.

 

 

압축을 풀어 준 폴더에 들어가 보면 samples sdk 두개의 폴더가 보입니다.

샘플은 말 그대로 예제 이고 SDK 폴더를 사용합니다.

 

 

2. Android Project 생성

 

안드로이드 스튜디오에 SDK를 적용하여 개발 환경을 구축하기 위해 프로젝트를 하나 생성합니다.

 

 

Empty Activity를 선택하고 [Next] 버튼을 클릭 합니다.

 

 

프로젝트 명을 기입하고 기타 다른 선택도 자신의 환경에 맞게 해 줍니다.

저는 java로 개발하는것을 설명 드립니다.

 

 

3. SDK module 추가

 

이제 여기서 부터가 opencv SDK를 적용하는 부분입니다.

OpenCV를 모듈로 추가합니다.

 

 

메뉴에서 모듈을 import 하기위해

File > New > import Module

순서대로 선택을 하면 module 추가 팝업 창이 나타납니다.

 

 

여기에서 폴더모양 아이콘을 이용하여 다운받은 파일의 압축을 풀어 준 OpenCV sdk 폴더를 선택해줍니다.

 

 

[OK] 버튼을 클릭하면 앞으로 사용할 모듈에 대한 엘리어스 명칭을 입력합니다.

처음에는 폴더명대로 sdk로 되어있는데 이런 이름으로는 구분이 안되겠죠.

 

 

뭐라고 하든 상관은 없지만 혼동을 줄 명칭은 피해서 입력합니다. 대부분 OpenCV 또는 OpenCV4로 입력을 하리라 생각됩니다.

저는 OpenCV로 입력을

:OpenCV

이렇게 했습니다.

 

모듈이 추가되면 프로젝트에 OpenCV가 추가됩니다.

 

 

 

4. OpenCV gradle 수정

 

모듈이 추가되면서 OpenCV 설정gradle도 아래 이름으로 생성됩니다.

build.gradle(Module: OpencvTest.OpenCV)

 

 

 

java로 개발하기 때문에 코틀린 플러그인 오류가 발생 합니다.  sdk에 따라 안나오는 경우도 있습니다.

오류가 발생한 apply plugin: ‘kotlin-android’ 라인을 삭제합니다.

 

 

 

targetSdkVersion 26도 오류가 발생 하는데 29이상 지원이 된다고 하니 29로 변경 합니다.

. 저의 경우는 이렇게 해야 하는거고 개발환경이 다르신 분들은 32또는 33으로 하셔도 됩니다.

나중에 build할때 계속 변경하면서 찾으면 됩니다.

 

apply plugin: 'com.android.library'

def
openCVersionName = "4.4.0"
def
openCVersionCode = ((4 * 100 + 4) * 100 + 0) * 10 + 0

println "OpenCV: " +openCVersionName + " " + project.buildscript.sourceFile

android {
   
compileSdkVersion
29

   
defaultConfig {
       
minSdkVersion
21
       
targetSdkVersion 29

 

수정이 완료 되었습니다.

이제 app gradle 수정을 합니다.

 

build.gradle (Module: OpencvTest.app)

 

android {
   
compileSdkVersion
29
   
buildToolsVersion "29.0.0"

   
defaultConfig {
       
applicationId
"copycoding.tistory.opencvtest"
       
minSdkVersion 26
       
targetSdkVersion 29
       
versionCode 1
        
versionName "1.0"

 
dependencies {

   
implementation
'androidx.appcompat:appcompat:1.3.0'
   
implementation 'com.google.android.material:material:1.4.0'

 

여기도 버전과 dependencies 를 적당하게 수정해 줍니다.

아니면 나중에 build 할때 오류가 발생하면 수정합니다.

수정을 했으면 우측 상단의 [Try Again] 또는 [Sync Now]를 클릭해줍니다.

 

 

5. OpenCVapp에 적용

 

이제 추가된 OpenCV Module app에 적용하는 방법입니다.

 

 

 

안드로이드 스튜디오 상단메뉴에서

File > Project Structure

를 선택 합니다.

 

 

 

현재 제가 사용하고 있는 Android gradle plugin version  Gradle version입니다.

좌측 메뉴에서 Dependencies를 선택해줍니다.

 

 

좀 설명이 복잡할 수 있는데

Dependencies 다음 단계에 있는 Modules에서 맨 아래의 app을 선택합니다.

그리고 다음 단계 Declared Dependencies에서 + 기호를 선택 하면 나타나는 3번째 Module Dependency를 클릭 합니다.

 

Dependencies > app > [+] > Module Dependency

 

그러면 SDK module을 추가할때 이름지은 항목이 나타나는데 OpenCV 또는 OpenCV4등으로 기입한 이름입니다.

 

 

 

저는 OpenCV.로 설정을 하였는데 선택하고 [OK] 버튼을 클릭 합니다.

선택이 완료되면 다시 이전 화면으로 돌아갑니다.

 

 

여기에서 선택을 적용하기 위해 [Apply] 버튼을 먼저 클릭하고 잠시 반영작업이 완료된 후 [OK] 버튼을 클릭합니다. 적용이 완료되면 Apply 버튼이 비활성화 됩니다.

[Apply] > [OK]

 

이제 모든 설정이 완료 되었고 코딩만 진행하면 됩니다.

 

 

6. OpenCV SDK 적용 확인

 

OpenCV sdk가 추가되었는지 간단하게 테스트 해봅니다.

 

MainActivity에 다음과 같은 코드를 추가 합니다.

 

private static String Tag_Log = "OpenCV Test : ";

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

   
if(OpenCVLoader.initDebug()) {
        Log.d(
Tag_Log, "OpenCV Initiallize");
    }
else {
        Log.d(
Tag_Log, "OpenCV Not Initiallize");
    }

}

 

OpenCV SDK가 로드 되는지 확인하는 간단한 코드 입니다.

다른 소스는 전혀 손대지 않아서 if 문만 추가하고 테스트 하면 됩니다.

 

 

Logcat에 설정한 문자가 잘 나오면 성공한것 입니다.

이제 지금까지 학습한 OpenCV관련 소스를 가지고 테스트를 진행하면 됩니다.

 

- copy coding -


구글에서 제공하는 안드로이드 용 지도 앱(단순히 정해준 위치의 지도를 보여주는 기능) 사용하기 예제를 이용하여 테스트 하고 사용 방법을 익혀 봅니다아주 단순하고 간단하게 만들어 볼 수 있습니다. 웹 주소는

https://developers.google.com/maps/documentation/android-sdk/start


이곳으로 여기에 가면 소스를 그대로 복사해서 테스트 해 볼 수 있습니다웹 페이지에 나와있는 순서대로 작업을 해봅니다물론 순서는 편리에 따라 바꾸어도 상관 없습니다.

 

Step 1. Download Android Studio


https://developer.android.com/studio/index.html


android google map sdk


자신의 운영체제에 맞는 패키지를 다운받아 설치 합니다. 현재 3.5버전 이고 다른 버전이라도 설치되어 있으면 패스. 저는 업데이트 했습니다.

 

Step 2. Install the Google Play services SDK


안드로이드 스튜디오 메뉴에서 팝업 창을 열고

Tools > SDK Manager > Appearance & Behavior > System Settings > Android SDK

우측에서 SDK Tools 탭을 선택 합니다.


android google map sdk


Google Play services 를 체크하여 설치 합니다기존에 설치를 했으면 패스.

 

Step 3. Create a Google Maps project


그냥 생각 나는 이름으로 프로젝트를 하나 생성 합니다.

Activityempty를 선택하고 생성 했습니다.


android google map sdk


Package nameAPI 사이트에 등록을 해야 하니 적당하게 입력 합니다저는 copycoding.tistory.mylocation으로 했습니다.


android google map sdk


Step 4. Get a Google Maps API key


구글에서 API를 사용할 수 있는 키를 생성 합니다. 그리고 package name을 이용하여 등록을 합니다.  기존에 생성한 API 키가 있다면 package name만 신규로 등록 합니다키 생성 방법은 검색하면 자세한 설명들이 바글바글 합니다저도 하나 설명한게 있습니다.

[안드로이드] google map 사용을 위한 API 생성(2018.11)


android google map sdk


Step 5. Hello Map! Take a look at the code


이제 프로젝트에 사이트에 있는 소스를 복사해서 붙여 넣기를 합니다사이트에는 두개의 소스가 있습니다.

 

activity_main.xml

<fragment 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"
   
android:id="@+id/map"
   
tools:context=".MapsActivity"
   
android:name="com.google.android.gms.maps.SupportMapFragment" />

 

MainActivity.java

import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;

public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {

   
private GoogleMap mMap;

   
@Override
   
protected void onCreate(Bundle savedInstanceState) {
       
super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_maps);
       
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
        mapFragment.getMapAsync(
this);
    }

   
@Override
   
public void onMapReady(GoogleMap googleMap) {
        mMap = googleMap;

       
// Add a marker in Sydney, Australia, and move the camera.
       
LatLng sydney = new LatLng(-34, 151);
        mMap.addMarker(
new MarkerOptions().position(sydney).title("Marker in Sydney"));
        mMap.moveCamera(
CameraUpdateFactory.newLatLng(sydney));
    }
}

 

이 두가지로만 하면 오류가 발생 합니다.

사이트에 없지만 추가를 해야 하는 항목이 두개 있습니다간단해서 생략 했을 수도 있습니다.


AndroidManifest.xml

<meta-data
   
android:name="com.google.android.geo.API_KEY"
   
android:value="API 키 값" >
</
meta-data>

Step 4에서 생성한 API 키를 입력 합니다.

 

build.gradle(Module: app)

implementation 'com.google.android.gms:play-services-maps:10.2.0'

라이브러리도 추가 해줍니다.

 

Step 6. Connect an Android device


테스트를 진행하기 위해 가상 디바이스를 생성 하거나 실제 핸드폰을 연결 합니다


android google map sdk


Step 7. Build and run your app


이제 프로그램을 실행 하기만 하면 끝 입니다.


android google map sdk


GPS를 이용 하는게 아니라서 방구석 처밖혀 인터넷만 연결되면 테스트가 가능 합니다.

줌 기능을 추가하지 않아 그냥 세계지도를 보는 느낌이네요.

 

전체 소스

 

activity_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">

    <fragment
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"
       
android:id="@+id/map"
       
tools:context=".MapsActivity"
       
android:name="com.google.android.gms.maps.SupportMapFragment" />

</androidx.constraintlayout.widget.ConstraintLayout>

 

 

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
   
package="copycoding.tistory.gpsmap">
    <application
       
android:allowBackup="true"
       
android:icon="@mipmap/ic_launcher"
       
android:label="@string/app_name"
       
android:roundIcon="@mipmap/ic_launcher_round"
       
android:supportsRtl="true"
       
android:theme="@style/AppTheme">

        <meta-data
           
android:name="com.google.android.geo.API_KEY"
           
android:value="API Key "/>
        <activity
android:name=".MainActivity">
            <intent-filter>
                <action
android:name="android.intent.action.MAIN" />

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

</manifest>

 

 

build.gradle(Module: app)

apply plugin: 'com.android.application'

android {
    compileSdkVersion
29
   
buildToolsVersion '29.0.2'
   
defaultConfig {
        applicationId
"copycoding.tistory.gpsmap"
       
minSdkVersion 16
        
targetSdkVersion 29
       
versionCode 1
       
versionName "1.0"
       
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
   
}
    buildTypes {
        release {
           
minifyEnabled false
           
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
       
}
    }
}

dependencies {
    implementation fileTree(
dir: 'libs', include: ['*.jar'])
    implementation
'androidx.appcompat:appcompat:1.1.0'
   
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
   
implementation 'com.google.android.gms:play-services-maps:10.2.0'
   
testImplementation 'junit:junit:4.12'
   
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
   
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}

 

 

 

 

MainActivity.java

package copycoding.tistory.mylocation;

import
androidx.appcompat.app.AppCompatActivity;
import
androidx.fragment.app.FragmentActivity;

import
android.os.Bundle;

import
com.google.android.gms.maps.CameraUpdateFactory;
import
com.google.android.gms.maps.GoogleMap;
import
com.google.android.gms.maps.OnMapReadyCallback;
import
com.google.android.gms.maps.SupportMapFragment;
import
com.google.android.gms.maps.model.LatLng;
import
com.google.android.gms.maps.model.MarkerOptions;

public class
MainActivity extends FragmentActivity implements OnMapReadyCallback {

   
private GoogleMap mMap;

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

       
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.
map);
       
mapFragment.getMapAsync(this);
   
}

   
@Override
   
public void onMapReady(GoogleMap googleMap) {
       
mMap = googleMap;

       
// Add a marker in Sydney, Australia, and move the camera.
       
LatLng sydney = new LatLng(-34, 151);
       
mMap.addMarker(new MarkerOptions().position(sydney).title("Marker in Sydney"));
       
mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney));
   
}
}

 

 - copy coding -


1

+ Recent posts