그래프 같은 UI를 만들기 전에 MQTT broker에서 받은 데이터에 따라 알림을 보내는 기능을 먼저 구현해보려고 한다
먼저 알림부터 구현해보자
https://www.youtube.com/watch?v=4BuRMScaaI4
위 블로그와 영상을 참고로 제작
일단 블로그의 코드를 복붙한 다음에 영상을 따라서 알림을 구현했다
//notificationService.java
package com.example.mqtt_test;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.widget.Toast;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
public class notificationService extends Service {
NotificationManager Notifi_M;
ServiceThread thread;
Notification Notifi;
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Notifi_M = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
myServiceHandler handler = new myServiceHandler();
thread = new ServiceThread(handler);
thread.start();
return START_STICKY;
}
//서비스가 종료될 때 할 작업
public void onDestroy() {
thread.stopForever();
thread = null;//쓰레기 값을 만들어서 빠르게 회수하라고 null을 넣어줌.
}
class myServiceHandler extends Handler {
@Override
public void handleMessage(android.os.Message msg) {
Intent intent = new Intent(notificationService.this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(notificationService.this, 0, intent,PendingIntent.FLAG_UPDATE_CURRENT);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
NotificationChannel channel = new NotificationChannel("notify test", "notiName", NotificationManager.IMPORTANCE_DEFAULT);
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(channel);
}
NotificationCompat.Builder builder = new NotificationCompat.Builder(notificationService.this, "notify test");
builder.setContentTitle("알림 테스트")
.setContentText("이것은 알림 테스트입니다.")
.setSmallIcon(R.drawable.ic_alarm_icon)
.setDefaults(Notification.DEFAULT_VIBRATE)
.setContentIntent(pendingIntent)
.setAutoCancel(true);
NotificationManagerCompat managerCompat = NotificationManagerCompat.from(notificationService.this);
managerCompat.notify(1,builder.build());
//Toast.makeText(notificationService.this, "알림 생성", Toast.LENGTH_SHORT).show();
}
};
}
//ServiceThread
package com.example.mqtt_test;
import android.os.Handler;
import android.os.Message;
public class ServiceThread extends Thread{
Handler handler;
boolean isRun = true;
public ServiceThread(Handler handler){
this.handler = handler;
}
public void stopForever(){
synchronized (this) {
this.isRun = false;
}
}
public void run(){
//반복적으로 수행할 작업을 한다.
while(isRun){
handler.sendEmptyMessage(0);//쓰레드에 있는 핸들러에게 메세지를 보냄
try{
Thread.sleep(10000); //10초씩 쉰다.
}catch (Exception e) {}
}
}
}
그리고 conn와 disconn 함수에 Service 시작과 중지를 해놨다
//MainActivity.java
public void conn(View v) //try connecting to MQTT
{
try {
setHost();
Intent intent = new Intent(MainActivity.this, notificationService.class);
startService(intent);
//Toast.makeText(MainActivity.this, "Service start", Toast.LENGTH_SHORT).show();
IMqttToken token = client.connect();
//IMqttToken token = client.connect(options);
token.setActionCallback(new IMqttActionListener() {
@Override
public void onSuccess(IMqttToken asyncActionToken) {
// We are connected
//Log.d(TAG, "onSuccess");
Toast.makeText(MainActivity.this, "connected", Toast.LENGTH_SHORT).show();
setSubscription();
}
@Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
// Something went wrong e.g. connection timeout or firewall problems
//Log.d(TAG, "onFailure");
Toast.makeText(MainActivity.this, "failed to connect", Toast.LENGTH_SHORT).show();
}
});
} catch (MqttException e) {
e.printStackTrace();
}
}
public void disconn(View v) //disconnect MQTT
{
try {
Intent intent = new Intent(MainActivity.this, notificationService.class);
stopService(intent);
//Toast.makeText(MainActivity.this, "Service stop", Toast.LENGTH_SHORT).show();
IMqttToken token = client.disconnect();
token.setActionCallback(new IMqttActionListener() {
@Override
public void onSuccess(IMqttToken asyncActionToken) {
// We are connected
//Log.d(TAG, "onSuccess");
Toast.makeText(MainActivity.this, "disconnected", Toast.LENGTH_SHORT).show();
}
@Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
// Something went wrong e.g. connection timeout or firewall problems
//Log.d(TAG, "onFailure");
Toast.makeText(MainActivity.this, "could not disconnect..", Toast.LENGTH_SHORT).show();
}
});
} catch (MqttException e) {
e.printStackTrace();
}
}

이제 코드를 좀 수정해서 특정값을 받으면 알람이 가도록 해보자
일단 스레드는 나중에...
client.callback에 무지성으로 알림 생성 코드를 떄려박았다
client.setCallback(new MqttCallback() { //setCallback for message arrive
@Override
public void connectionLost(Throwable cause) {
}
@Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
subText.setText(new String(message.getPayload())); //show text on subText
String text = new String(message.toString());
Log.d("valueOf", String.valueOf(message.getPayload()));
Log.d("text", text);
if(text.equals("hello"))
{
Intent intent = new Intent(MainActivity.this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(MainActivity.this, 0, intent,PendingIntent.FLAG_UPDATE_CURRENT);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
NotificationChannel channel = new NotificationChannel("notify test", "notiName", NotificationManager.IMPORTANCE_DEFAULT);
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(channel);
}
NotificationCompat.Builder builder = new NotificationCompat.Builder(MainActivity.this, "notify test");
builder.setContentTitle("알림 테스트")
.setContentText("이것은 알림 테스트입니다.")
.setSmallIcon(R.drawable.ic_alarm_icon)
.setDefaults(Notification.DEFAULT_VIBRATE)
.setContentIntent(pendingIntent)
.setAutoCancel(true);
NotificationManagerCompat managerCompat = NotificationManagerCompat.from(MainActivity.this);
managerCompat.notify(1,builder.build());
Toast.makeText(MainActivity.this, "알림 생성", Toast.LENGTH_SHORT).show();
}
}
@Override
public void deliveryComplete(IMqttDeliveryToken token) {
}
});
hello라는 문자열을 받으면 알림 생성

이제 이걸 Service에서 백그라운드로 동작하게 만들면 된다
Service로 옮기기
원래 코드에서 수정하다가는 대참사가 일어나서 일어날 것 같아서 새로운 프로젝트를 만들어서 진행
mqtt_service라는 이름의 프로젝트 생성
build.gradle은 mqtt_test에서 그대로 복사한 뒤 이름만 바꿔주었다
plugins {
id 'com.android.application'
}
android {
compileSdkVersion 30
buildToolsVersion "30.0.3"
defaultConfig {
applicationId "com.example.mqtt_service"
minSdkVersion 16
targetSdkVersion 30
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
}
}
repositories {
maven {
url "https://repo.eclipse.org/content/repositories/paho-releases/"
}
}
dependencies {
implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.1.0'
implementation 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.1'
implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0'
implementation 'androidx.core:core:1.0.0'
implementation group: 'androidx.legacy', name: 'legacy-support-v4', version: '1.0.0'
implementation 'androidx.appcompat:appcompat:1.3.0'
implementation 'com.google.android.material:material:1.3.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}
그리고 UI는 간단하게 IP와 subTopic만 정할 수 있도록 변경
<?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">
<Button
android:id="@+id/disconnectButton"
android:layout_width="150dp"
android:layout_height="50dp"
android:text="disconnect"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.938"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.571" />
<Button
android:id="@+id/connectButton"
android:layout_width="150dp"
android:layout_height="50dp"
android:text="connect"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.938"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.483" />
<EditText
android:id="@+id/subTopic"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:hint="subTopic"
android:inputType="textPersonName"
android:text="test"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.104"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.567" />
<EditText
android:id="@+id/IP_address"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:hint="IP address"
android:inputType="textPersonName"
android:text="192.168.1.104"
app:layout_constraintBottom_toTopOf="@+id/subTopic"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.104"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.956" />
</androidx.constraintlayout.widget.ConstraintLayout>

MainActivity.java는 입력받은 HOST와 TOPIC을 서비스로 넘겨주고
서비스는 MQTT broker와 연결하여 백그라운드에서 직접 통신을 한다
MainActivity에서 필요한 코드는 입력받은 HOST와 TOPIC을 intent를 통해 서비스로 넘겨주는 것
package com.example.mqtt_service;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
EditText hostNameText;
EditText subTopicText;
Button connButton;
Button disconnButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
hostNameText = (EditText)findViewById(R.id.IP_address);
subTopicText = (EditText)findViewById(R.id.subTopic);
connButton = (Button)findViewById(R.id.connectButton);
disconnButton = (Button)findViewById(R.id.disconnectButton);
connButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
connect();
}
});
disconnButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
disconnect();
}
});
}
String getHost()
{
String _host = hostNameText.getText().toString();
String MQTTHOST = "tcp://"+_host+":1883";
return MQTTHOST;
}
String getSubTopic()
{
String _topic = subTopicText.getText().toString();
return _topic;
}
private void connect()
{
Intent intent = new Intent(MainActivity.this, mqttService.class);
intent.putExtra("HOST", getHost());
intent.putExtra("TOPIC", getSubTopic());
startService(intent);
//Toast.makeText(MainActivity.this, "service Start", Toast.LENGTH_SHORT).show();
}
private void disconnect()
{
Intent intent = new Intent(MainActivity.this, mqttService.class);
stopService(intent);
}
}
서비스는 mqttService라는 이름으로 새로 class를 만들었다
그리고 extends Service를 추가

전체 코드는 아래와 같다
package com.example.mqtt_service;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.Build;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
import org.eclipse.paho.android.service.MqttAndroidClient;
import org.eclipse.paho.client.mqttv3.IMqttActionListener;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.IMqttToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.MqttSecurityException;
public class mqttService extends Service {
String MQTTHOST = "";
String subTopic = "";
MqttAndroidClient client;
//MqttConnectOptions options;
//String USERNAME = "";
//String PASSWORD = "";
@Nullable
@Override
public IBinder onBind(Intent intent)
{
return null;
}
@Override
public void onCreate()
{
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("host", intent.getStringExtra("HOST"));
Log.d("topic", intent.getStringExtra("TOPIC"));
MQTTHOST = intent.getStringExtra("HOST");
subTopic = intent.getStringExtra("TOPIC");
setHost();
connect();
client.setCallback(new MqttCallback() { //setCallback for message arrive
@Override
public void connectionLost(Throwable cause) {
}
@Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
String text = new String(message.toString());
Log.d("valueOf", String.valueOf(message.getPayload()));
Log.d("text", text);
if(text.equals("hello"))
{
Intent intent = new Intent(mqttService.this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(mqttService.this, 0, intent,PendingIntent.FLAG_UPDATE_CURRENT);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
NotificationChannel channel = new NotificationChannel("notify test", "notiName", NotificationManager.IMPORTANCE_DEFAULT);
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(channel);
}
NotificationCompat.Builder builder = new NotificationCompat.Builder(mqttService.this, "notify test");
builder.setContentTitle("알림 테스트")
.setContentText("이것은 알림 테스트입니다.")
.setSmallIcon(R.drawable.ic_alarm_icon)
.setDefaults(Notification.DEFAULT_VIBRATE)
.setContentIntent(pendingIntent)
.setAutoCancel(true);
NotificationManagerCompat managerCompat = NotificationManagerCompat.from(mqttService.this);
managerCompat.notify(0,builder.build());
Toast.makeText(mqttService.this, "알림 생성", Toast.LENGTH_SHORT).show();
}
}
@Override
public void deliveryComplete(IMqttDeliveryToken token) {
}
});
return START_REDELIVER_INTENT;
}
@Override
public void onDestroy() {
disconnect();
super.onDestroy();
}
private void setHost()
{
String clientId = MqttClient.generateClientId();
client = new MqttAndroidClient(this.getApplicationContext(), MQTTHOST, clientId);
//options = new MqttConnectOptions();
//options.setUserName(USERNAME);
//options.setPassword(PASSWORD.toCharArray());
}
private void setSubscription()
{
try
{
client.subscribe(subTopic, 0);
Toast.makeText(mqttService.this, "subscribe "+ subTopic, Toast.LENGTH_SHORT).show();
}
catch(MqttException e)
{
e.printStackTrace();
}
}
private void connect()
{
Log.d("log", "try connection to "+MQTTHOST);
try {
IMqttToken token = client.connect();
token.setActionCallback(new IMqttActionListener()
{
@Override
public void onSuccess(IMqttToken asyncActionToken)
{
Toast.makeText(mqttService.this, "connected", Toast.LENGTH_SHORT).show();
setSubscription();
}
@Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
Toast.makeText(mqttService.this, "failed to connect", Toast.LENGTH_SHORT).show();
Log.d("log", "failed to connect");
}
});
}
catch (MqttException e)
{
e.printStackTrace();
}
}
private void disconnect()
{
try
{
IMqttToken token = client.disconnect();
token.setActionCallback(new IMqttActionListener()
{
@Override
public void onSuccess(IMqttToken asyncActionToken)
{
Toast.makeText(mqttService.this, "disconnected", Toast.LENGTH_SHORT).show();
}
@Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception)
{
Toast.makeText(mqttService.this, "could not disconnect..", Toast.LENGTH_SHORT).show();
}
});
}
catch (MqttException e)
{
e.printStackTrace();
}
}
}
hello를 받으면 알림이 생성된다

그런데 가끔씩 강제종료되었다고 뜬다
이는 Oreo버전부터 background service를 시스템이 종료하는 것 때문인 것 같은데
이왕 이렇게 된거 실행중일 때는 알림이 떠있도록 해보자
Foreground Service
Foreground Service로 백그라운드에서 실행중일 때는 알림이 떠있게 하는 방법이 있다
수정된 코드
package com.example.mqtt_service;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.Build;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
import org.eclipse.paho.android.service.MqttAndroidClient;
import org.eclipse.paho.client.mqttv3.IMqttActionListener;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.IMqttToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.MqttSecurityException;
public class mqttService extends Service {
public static final String CHANNEL_ID = "ForegrounndServiceChannel";
String MQTTHOST = "";
String subTopic = "";
MqttAndroidClient client;
//MqttConnectOptions options;
//String USERNAME = "";
//String PASSWORD = "";
@Nullable
@Override
public IBinder onBind(Intent intent)
{
return null;
}
@Override
public void onCreate()
{
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("host", intent.getStringExtra("HOST"));
Log.d("topic", intent.getStringExtra("TOPIC"));
MQTTHOST = intent.getStringExtra("HOST");
subTopic = intent.getStringExtra("TOPIC");
setHost();
connect();
client.setCallback(new MqttCallback() { //setCallback for message arrive
@Override
public void connectionLost(Throwable cause) {
}
@Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
String text = new String(message.toString());
Log.d("valueOf", String.valueOf(message.getPayload()));
Log.d("text", text);
if(text.equals("hello"))
{
Intent intent = new Intent(mqttService.this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(mqttService.this, 0, intent,PendingIntent.FLAG_UPDATE_CURRENT);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
NotificationChannel channel = new NotificationChannel("notify test", "notiName", NotificationManager.IMPORTANCE_DEFAULT);
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(channel);
}
NotificationCompat.Builder builder = new NotificationCompat.Builder(mqttService.this, "notify test");
builder.setContentTitle("알림 테스트")
.setContentText("이것은 알림 테스트입니다.")
.setSmallIcon(R.drawable.ic_alarm_icon)
.setDefaults(Notification.DEFAULT_VIBRATE)
.setContentIntent(pendingIntent)
.setAutoCancel(true);
NotificationManagerCompat managerCompat = NotificationManagerCompat.from(mqttService.this);
managerCompat.notify(0,builder.build());
Toast.makeText(mqttService.this, "알림 생성", Toast.LENGTH_SHORT).show();
}
}
@Override
public void deliveryComplete(IMqttDeliveryToken token) {
}
});
return START_REDELIVER_INTENT;
}
@Override
public void onDestroy() {
disconnect();
super.onDestroy();
}
private void setHost()
{
String clientId = MqttClient.generateClientId();
client = new MqttAndroidClient(this.getApplicationContext(), MQTTHOST, clientId);
//options = new MqttConnectOptions();
//options.setUserName(USERNAME);
//options.setPassword(PASSWORD.toCharArray());
}
private void setSubscription()
{
try
{
client.subscribe(subTopic, 0);
Toast.makeText(mqttService.this, "subscribe "+ subTopic, Toast.LENGTH_SHORT).show();
}
catch(MqttException e)
{
e.printStackTrace();
}
}
private void connect()
{
Log.d("log", "try connection to "+MQTTHOST);
try {
IMqttToken token = client.connect();
token.setActionCallback(new IMqttActionListener()
{
@Override
public void onSuccess(IMqttToken asyncActionToken)
{
Toast.makeText(mqttService.this, "connected", Toast.LENGTH_SHORT).show();
setSubscription();
createNotificationChannel();
Intent notificationIntent = new Intent(mqttService.this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(mqttService.this, 0, notificationIntent, 0);
Notification notification = new NotificationCompat.Builder(mqttService.this, CHANNEL_ID)
.setContentTitle("mqtt_service")
.setContentText("mqtt service is running on background")
.setSmallIcon(R.mipmap.ic_launcher)
.setContentIntent(pendingIntent)
.build();
startForeground(1, notification);
}
@Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
Toast.makeText(mqttService.this, "failed to connect", Toast.LENGTH_SHORT).show();
Log.d("log", "failed to connect");
}
});
}
catch (MqttException e)
{
e.printStackTrace();
}
}
private void disconnect()
{
try
{
IMqttToken token = client.disconnect();
token.setActionCallback(new IMqttActionListener()
{
@Override
public void onSuccess(IMqttToken asyncActionToken)
{
Toast.makeText(mqttService.this, "disconnected", Toast.LENGTH_SHORT).show();
}
@Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception)
{
Toast.makeText(mqttService.this, "could not disconnect..", Toast.LENGTH_SHORT).show();
}
});
}
catch (MqttException e)
{
e.printStackTrace();
}
}
private void createNotificationChannel()
{
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
NotificationChannel servcieChannel = new NotificationChannel(CHANNEL_ID, "Foreground Service Channel", NotificationManager.IMPORTANCE_NONE);
NotificationManager manager = getSystemService(NotificationManager.class);
assert manager != null;
manager.createNotificationChannel(servcieChannel);
}
}
}
이제 백그라운드에서 실행중임을 알리는 알림과 함께 hello를 받았을 때 뜨는 알림 두개 모두 나온다

마지막으로 알림에서 서비스를 중지할 수 있도록 해보자
중지 버튼 추가
connect함수에 있는 onSuccess에서 foreground service를 생성하는 곳을 수정했다
@Override
public void onSuccess(IMqttToken asyncActionToken)
{
Toast.makeText(mqttService.this, "connected", Toast.LENGTH_SHORT).show();
setSubscription();
createNotificationChannel();
Intent notificationIntent = new Intent(mqttService.this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(mqttService.this, 0, notificationIntent, 0);
Intent stopSelf = new Intent(mqttService.this, mqttService.class);
stopSelf.setAction("STOP");
PendingIntent pStopSelf = PendingIntent.getService(mqttService.this, 0, stopSelf, PendingIntent.FLAG_CANCEL_CURRENT);
Notification notification = new NotificationCompat.Builder(mqttService.this, CHANNEL_ID)
.setContentTitle("mqtt_service")
.setContentText("mqtt service is running on background")
.setSmallIcon(R.mipmap.ic_launcher)
.setContentIntent(pendingIntent)
.addAction(R.drawable.ic_close, getString(R.string.close), pStopSelf)
.build();
startForeground(1, notification);
}
stopSelf라는 intent와 pStopSelf라는 pendingIntent를 각각 생성하고
stopSelf에 "STOP" Action를 설정한다
pStopSelf에 stopSelf를 넣어주고
notification에 addAction를 통해 pStopSelf를 사용하게 한다

흠 근데 close 버튼을 누르니까 앱이 강제종료된다
오류를 확인해보니 getStringExtra가 null이기 때문인듯 하다
이부분을 null이 아닐때만 실행하도록 했다
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(intent.getStringExtra("HOST") != null && intent.getStringExtra("TOPIC") != null)
{
Log.d("host", intent.getStringExtra("HOST"));
Log.d("topic", intent.getStringExtra("TOPIC"));
MQTTHOST = intent.getStringExtra("HOST");
subTopic = intent.getStringExtra("TOPIC");
}
'프로젝트 > SEDP' 카테고리의 다른 글
MQTT 테스트 애플리케이션 제작(2) - subscribe (0) | 2021.07.11 |
---|---|
MQTT 테스트 애플리케이션 제작(1) - publish (2) | 2021.07.11 |
ESP8266 NodeMCU Publish 테스트 (0) | 2021.06.02 |
MQTT broker 테스트 (0) | 2021.05.31 |
SEDP 프로젝트 개요 (0) | 2021.05.22 |