티스토리 뷰

Android

[Android] 비콘(Beacon)

best 2016. 8. 11. 16:11

안드로이드 비콘(Beacon)


비콘은 반경 50 ~ 70m 범위 안에 있는 사용자의 위치를 찾아 메시지 전송, 모바일 결제 등을 가능하게 해주는 모바일 디바이스용 근거리통신 기술이다.

NFC보다 송수신 범위가 길어 O2O 서비스의 핵심 기술로 꼽힌다. 

적은 전력을 사용해 유지 부담이 낮고, 단말기 가격도 저렴하다. 실내에서는 GPS보다 정교한 위치 파악이 가능하다는 장점도 있다.


이러한 비콘을 인식하는 어플리케이션을 만들어보았다.



16(젤리빈) 버전의 프로젝트를 하나 생성한다.


Dependency 추가

Gradle Scripts > build.gradle (Module : app) 파일을 열어 

dependencies 부분에 

compile 'com.estimote:sdk:0.10.4@aar'

를 추가한다. ( 추가 후 Sync now 클릭 )

이것은 비콘전용 라이브러리 중 하나인 estimote 이다.


최초로 실행될때 수행되는 코드

MyApplication 이라는 이름으로 자바 클래스를 생성한다.

public class MyApplication extends Application {

extends Application은 어플리케이션이 설치되고 최초로 실행될 때 수행되는 코드를 의미한다.

앱이 최초로 설치되고 비콘에 접속하게 되면 비콘에게 아이디, Major, Minor를 보낸다.


전체 MyApplication 의 코드

package com.ktds.jmj.mybeaconapplication;

import android.app.ActivityManager;
import android.app.Application;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;

import com.estimote.sdk.Beacon;
import com.estimote.sdk.BeaconManager;
import com.estimote.sdk.Region;

import java.util.List;
import java.util.UUID;

/**
* Application 의 설치가 끝나고 최초로 실행될 때 수정되는 코드
* Created by MinChang Jang on 2016-06-23.
*/
public class MyApplication extends Application {

private BeaconManager beaconManager;

/**
* Application을 설치할 때 실행됨.
*/
@Override
public void onCreate() {
super.onCreate();
beaconManager = new BeaconManager(getApplicationContext());

// Application 설치가 끝나면 Beacon Monitoring Service를 시작한다.
// Application을 종료하더라도 Service가 계속 실행된다.
beaconManager.connect(new BeaconManager.ServiceReadyCallback() {
@Override
public void onServiceReady() {
beaconManager.startMonitoring(new Region(
"monitored region",
UUID.fromString("74278BDA-B644-4520-8F0C-720EAF059935"), // 본인이 연결할 Beacon ID Major / Minor Code를 알아야 한다.
0, 0));
}
});

// Android 단말이 Beacon 의 송신 범위에 들어가거나, 나왔을 때를 체크한다.
beaconManager.setMonitoringListener(new BeaconManager.MonitoringListener() {
@Override
public void onEnteredRegion(Region region, List<Beacon> list) {
// showNotification("들어옴", "비콘 연결됨" + list.get(0).getRssi());
// getApplicationContext().startActivity(new Intent(getApplicationContext(), PopupActivity.class).putExtra("uuid", String.valueOf(list.get(0).getProximityUUID()) ).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
if (!isAlreadyRunActivity() ) {
Intent intent = new Intent(getApplicationContext(), SplashActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("executeType", "beacon");

getApplicationContext().startActivity(intent);
}
else{
showNotification("Penguin", "사용가능한 쿠폰이 있습니다.");
}
}
@Override
public void onExitedRegion(Region region) {
// showNotification("나감", "비콘 연결끊김");
}
});
}

/**
* Notification으로 Beacon 의 신호가 연결되거나 끊겼음을 알림.
* @param title
* @param message
*/
public void showNotification(String title, String message) {
Intent notifyIntent = new Intent(this, CouponActivity.class);
notifyIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);

PendingIntent pendingIntent = PendingIntent.getActivities(this, 0,
new Intent[] { notifyIntent }, PendingIntent.FLAG_UPDATE_CURRENT);

Notification notification = new Notification.Builder(this)
.setSmallIcon(android.R.drawable.ic_dialog_info)
.setContentTitle(title)
.setTicker("[Penguin] 사용가능한 쿠폰이 있습니다.")
.setContentText(message)
.setAutoCancel(true)
.setPriority(Notification.PRIORITY_HIGH)
.setContentIntent(pendingIntent)
.build();

notification.defaults |= Notification.FLAG_AUTO_CANCEL;
notification.defaults |= Notification.DEFAULT_SOUND;

NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(1, notification);
}

private boolean isAlreadyRunActivity() {
ActivityManager activity_manager =
(ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);

List<ActivityManager.RunningTaskInfo> task_Info = activity_manager.getRunningTasks(9999);

String activityName = "";
for(int i = 0; i < task_Info.size(); i++){
activityName = task_Info.get(i).topActivity.getPackageName();

if( activityName.startsWith("com.ktds.jmj.mybeaconapplication")){
return true;
}

}
return false;

}
}


Manifest 추가

방금 생성한 MyApplication을 AndroidManifest에 추가한다.

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

<uses-permission android:name="android.permission.INTERNET" />
<application
android:name=".MyApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<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>


MainActivity 수정


package com.ktds.jmj.mybeaconapplication;

import android.content.DialogInterface;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;

import com.estimote.sdk.Beacon;
import com.estimote.sdk.BeaconManager;
import com.estimote.sdk.Region;
import com.estimote.sdk.SystemRequirementsChecker;

import java.util.List;
import java.util.UUID;

public class MainActivity extends AppCompatActivity {

private BeaconManager beaconManager;
private Region region;

private boolean isConnected;
private TextView tvId;

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

tvId = (TextView) findViewById(R.id.tvId);

beaconManager = new BeaconManager(this);

// add this below:
beaconManager.setRangingListener(new BeaconManager.RangingListener() {
@Override
public void onBeaconsDiscovered(Region region, List<Beacon> list) {
if (!list.isEmpty()) {
Beacon nearestBeacon = list.get(0);
Log.d("Airport", "Nearest places: " + nearestBeacon.getRssi());

// nearestBeacon.getRssi() : 비콘의 수신 강도
tvId.setText(nearestBeacon.getRssi() + "");

if ( !isConnected && nearestBeacon.getRssi() > -70 ) {
isConnected = true;
AlertDialog.Builder dialog = new AlertDialog.Builder(MainActivity.this);
dialog.setTitle("알림")
.setTitle("비콘이 연결되었습니다.")
.setPositiveButton("확인", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {

}
}).create().show();
}
else if( nearestBeacon.getRssi() < -70 ){
Toast.makeText(MainActivity.this, "연결이 끊어졌습니다.", Toast.LENGTH_SHORT).show();
isConnected = false;
}
}
}
});

region = new Region("ranged region",
UUID.fromString("74278BDA-B644-4520-8F0C-720EAF059935"), null, null); // 본인이 연결할 Beacon ID Major / Minor Code를 알아야 한다.
}

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

// 블루투스 권한 승낙 및 블루투스 활성화시키는 코드드
SystemRequirementsChecker.checkWithDefaultDialogs(this);
//
// beaconManager.connect(new BeaconManager.ServiceReadyCallback() {
// @Override
// public void onServiceReady() {
// beaconManager.startRanging(region);
// }
// });
}


@Override
protected void onPause() {
//beaconManager.stopRanging(region);

super.onPause();
}
}


MainActivity에서 

beaconManager.setRangingListener(new BeaconManager.RangingListener() {
@Override
public void onBeaconsDiscovered(Region region, List<Beacon> list) {
if (!list.isEmpty()) {
Beacon nearestBeacon = list.get(0);
Log.d("Airport", "Nearest places: " + nearestBeacon.getRssi());

// nearestBeacon.getRssi() : 비콘의 수신 강도
tvId.setText(nearestBeacon.getRssi() + "");

if ( !isConnected && nearestBeacon.getRssi() > -70 ) {
isConnected = true;
AlertDialog.Builder dialog = new AlertDialog.Builder(MainActivity.this);
dialog.setTitle("알림")
.setTitle("비콘이 연결되었습니다.")
.setPositiveButton("확인", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {

}
}).create().show();
}
else if( nearestBeacon.getRssi() < -70 ){
Toast.makeText(MainActivity.this, "연결이 끊어졌습니다.", Toast.LENGTH_SHORT).show();
isConnected = false;
}
}
}
});

이 부분은 수신 강도에 따라 알림창을 띄우기 위한 코드다.


어플을 실행하고 권한을 허가하면 정상적으로 작동한다.

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/04   »
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
글 보관함