Integrates with wryk/tusky-api, but only partially working.
Registers to the web-service fine but loses connection when subscribing with the broker.
This commit is contained in:
parent
e282f13fdc
commit
c90c909ca6
@ -31,6 +31,7 @@ import android.view.Menu;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.keylesspalace.tusky.entity.Session;
|
||||
import com.keylesspalace.tusky.json.SpannedTypeAdapter;
|
||||
import com.keylesspalace.tusky.json.StringWithEmoji;
|
||||
import com.keylesspalace.tusky.json.StringWithEmojiTypeAdapter;
|
||||
@ -162,8 +163,9 @@ public class BaseActivity extends AppCompatActivity {
|
||||
|
||||
protected void createTuskyApi() {
|
||||
Retrofit retrofit = new Retrofit.Builder()
|
||||
.baseUrl("https://" + getString(R.string.tusky_api_domain))
|
||||
.baseUrl("http://" + getString(R.string.tusky_api_domain) + ":8080")
|
||||
.client(OkHttpUtils.getCompatibleClient())
|
||||
.addConverterFactory(GsonConverterFactory.create())
|
||||
.build();
|
||||
|
||||
tuskyApi = retrofit.create(TuskyApi.class);
|
||||
@ -172,7 +174,7 @@ public class BaseActivity extends AppCompatActivity {
|
||||
protected void createPushNotificationClient() {
|
||||
// TODO: Switch to ssl:// when TLS support is added.
|
||||
pushNotificationClient = new PushNotificationClient(getApplicationContext(),
|
||||
"tcp://" + getString(R.string.tusky_api_domain));
|
||||
"tcp://" + getString(R.string.tusky_api_domain) + ":8000");
|
||||
}
|
||||
|
||||
protected void redirectIfNotLoggedIn() {
|
||||
@ -212,6 +214,7 @@ public class BaseActivity extends AppCompatActivity {
|
||||
retrofit2.Response<ResponseBody> response) {
|
||||
if (response.isSuccessful()) {
|
||||
pushNotificationClient.subscribeToTopic(getPushNotificationTopic());
|
||||
pushNotificationClient.connect();
|
||||
} else {
|
||||
onEnablePushNotificationsFailure();
|
||||
}
|
||||
@ -222,7 +225,9 @@ public class BaseActivity extends AppCompatActivity {
|
||||
onEnablePushNotificationsFailure();
|
||||
}
|
||||
};
|
||||
tuskyApi.register(getBaseUrl(), getAccessToken(), pushNotificationClient.getDeviceToken())
|
||||
String deviceToken = pushNotificationClient.getDeviceToken();
|
||||
Session session = new Session(getDomain(), getAccessToken(), deviceToken);
|
||||
tuskyApi.register(session)
|
||||
.enqueue(callback);
|
||||
}
|
||||
|
||||
@ -247,7 +252,9 @@ public class BaseActivity extends AppCompatActivity {
|
||||
onDisablePushNotificationsFailure();
|
||||
}
|
||||
};
|
||||
tuskyApi.unregister(getBaseUrl(), getAccessToken(), pushNotificationClient.getDeviceToken())
|
||||
String deviceToken = pushNotificationClient.getDeviceToken();
|
||||
Session session = new Session(getDomain(), getAccessToken(), deviceToken);
|
||||
tuskyApi.unregister(session)
|
||||
.enqueue(callback);
|
||||
}
|
||||
|
||||
@ -256,7 +263,11 @@ public class BaseActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
private String getPushNotificationTopic() {
|
||||
return String.format("%s/%s/%s", getBaseUrl(), getAccessToken(),
|
||||
pushNotificationClient.getDeviceToken());
|
||||
return String.format("%s/%s/#", getDomain(), getAccessToken());
|
||||
}
|
||||
|
||||
private String getDomain() {
|
||||
return getPrivatePreferences()
|
||||
.getString("domain", null);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,28 @@
|
||||
/* Copyright 2017 Andrew Dawson
|
||||
*
|
||||
* This file is a part of Tusky.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
* Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky.entity;
|
||||
|
||||
public class Session {
|
||||
public String instanceUrl;
|
||||
public String accessToken;
|
||||
public String deviceToken;
|
||||
|
||||
public Session(String instanceUrl, String accessToken, String deviceToken) {
|
||||
this.instanceUrl = instanceUrl;
|
||||
this.accessToken = accessToken;
|
||||
this.deviceToken = deviceToken;
|
||||
}
|
||||
}
|
@ -15,16 +15,16 @@
|
||||
|
||||
package com.keylesspalace.tusky.network;
|
||||
|
||||
import com.keylesspalace.tusky.entity.Session;
|
||||
|
||||
import okhttp3.ResponseBody;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.http.FormUrlEncoded;
|
||||
import retrofit2.http.Body;
|
||||
import retrofit2.http.POST;
|
||||
|
||||
public interface TuskyApi {
|
||||
@FormUrlEncoded
|
||||
@POST("/register")
|
||||
Call<ResponseBody> register(String instanceUrl, String accessToken, String deviceToken);
|
||||
@FormUrlEncoded
|
||||
Call<ResponseBody> register(@Body Session session);
|
||||
@POST("/unregister")
|
||||
Call<ResponseBody> unregister(String instanceUrl, String accessToken, String deviceToken);
|
||||
Call<ResponseBody> unregister(@Body Session session);
|
||||
}
|
||||
|
@ -1,257 +0,0 @@
|
||||
package com.keylesspalace.tusky.service;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.Spanned;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.keylesspalace.tusky.R;
|
||||
import com.keylesspalace.tusky.entity.Notification;
|
||||
import com.keylesspalace.tusky.json.SpannedTypeAdapter;
|
||||
import com.keylesspalace.tusky.json.StringWithEmoji;
|
||||
import com.keylesspalace.tusky.json.StringWithEmojiTypeAdapter;
|
||||
import com.keylesspalace.tusky.network.MastodonAPI;
|
||||
import com.keylesspalace.tusky.util.Log;
|
||||
import com.keylesspalace.tusky.util.NotificationMaker;
|
||||
import com.keylesspalace.tusky.util.OkHttpUtils;
|
||||
|
||||
import org.eclipse.paho.android.service.MqttAndroidClient;
|
||||
import org.eclipse.paho.client.mqttv3.DisconnectedBufferOptions;
|
||||
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.MqttCallbackExtended;
|
||||
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
|
||||
import org.eclipse.paho.client.mqttv3.MqttException;
|
||||
import org.eclipse.paho.client.mqttv3.MqttMessage;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
import java.util.UUID;
|
||||
|
||||
import okhttp3.Interceptor;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
import retrofit2.Response;
|
||||
import retrofit2.Retrofit;
|
||||
import retrofit2.converter.gson.GsonConverterFactory;
|
||||
|
||||
public class PushNotificationService extends Service {
|
||||
private class LocalBinder extends Binder {
|
||||
PushNotificationService getService() {
|
||||
return PushNotificationService.this;
|
||||
}
|
||||
}
|
||||
|
||||
private static final String TAG = "PushNotificationService";
|
||||
private static final String CLIENT_NAME = "TuskyMastodonClient";
|
||||
private static final String TOPIC = "tusky/notification";
|
||||
private static final int NOTIFY_ID = 666;
|
||||
|
||||
private final IBinder binder = new LocalBinder();
|
||||
private MqttAndroidClient mqttAndroidClient;
|
||||
private MastodonAPI mastodonApi;
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
|
||||
// Create the MQTT client.
|
||||
String clientId = String.format(Locale.getDefault(), "%s/%s/%s", CLIENT_NAME,
|
||||
System.currentTimeMillis(), UUID.randomUUID().toString());
|
||||
String serverUri = getString(R.string.tusky_api_url);
|
||||
mqttAndroidClient = new MqttAndroidClient(this, serverUri, clientId);
|
||||
mqttAndroidClient.setCallback(new MqttCallbackExtended() {
|
||||
@Override
|
||||
public void connectComplete(boolean reconnect, String serverURI) {
|
||||
if (reconnect) {
|
||||
subscribeToTopic();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connectionLost(Throwable cause) {
|
||||
onConnectionLost();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void messageArrived(String topic, MqttMessage message) throws Exception {
|
||||
onMessageReceived(new String(message.getPayload()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deliveryComplete(IMqttDeliveryToken token) {
|
||||
// This client is read-only, so this is unused.
|
||||
}
|
||||
});
|
||||
|
||||
// Open the MQTT connection.
|
||||
MqttConnectOptions options = new MqttConnectOptions();
|
||||
options.setAutomaticReconnect(true);
|
||||
options.setCleanSession(false);
|
||||
try {
|
||||
mqttAndroidClient.connect(options, null, new IMqttActionListener() {
|
||||
@Override
|
||||
public void onSuccess(IMqttToken asyncActionToken) {
|
||||
DisconnectedBufferOptions options = new DisconnectedBufferOptions();
|
||||
options.setBufferEnabled(true);
|
||||
options.setBufferSize(100);
|
||||
options.setPersistBuffer(false);
|
||||
options.setDeleteOldestMessages(false);
|
||||
mqttAndroidClient.setBufferOpts(options);
|
||||
onConnectionSuccess();
|
||||
subscribeToTopic();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
|
||||
onConnectionFailure();
|
||||
}
|
||||
});
|
||||
} catch (MqttException e) {
|
||||
Log.e(TAG, "An exception occurred while connecting. " + e.getMessage());
|
||||
onConnectionFailure();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
disconnect();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return binder;
|
||||
}
|
||||
|
||||
/** Subscribe to the push notification topic. */
|
||||
public void subscribeToTopic() {
|
||||
try {
|
||||
mqttAndroidClient.subscribe(TOPIC, 0, null, new IMqttActionListener() {
|
||||
@Override
|
||||
public void onSuccess(IMqttToken asyncActionToken) {
|
||||
onConnectionSuccess();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
|
||||
onConnectionFailure();
|
||||
}
|
||||
});
|
||||
} catch (MqttException e) {
|
||||
Log.e(TAG, "An exception occurred while subscribing." + e.getMessage());
|
||||
onConnectionFailure();
|
||||
}
|
||||
}
|
||||
|
||||
/** Unsubscribe from the push notification topic. */
|
||||
public void unsubscribeToTopic() {
|
||||
try {
|
||||
mqttAndroidClient.unsubscribe(TOPIC);
|
||||
} catch (MqttException e) {
|
||||
Log.e(TAG, "An exception occurred while unsubscribing." + e.getMessage());
|
||||
onConnectionFailure();
|
||||
}
|
||||
}
|
||||
|
||||
private void onConnectionSuccess() {
|
||||
|
||||
}
|
||||
|
||||
private void onConnectionFailure() {
|
||||
|
||||
}
|
||||
|
||||
private void onConnectionLost() {
|
||||
|
||||
}
|
||||
|
||||
private void onMessageReceived(String message) {
|
||||
String notificationId = message; // TODO: finalize the form the messages will be received
|
||||
|
||||
Log.d(TAG, "Notification received: " + notificationId);
|
||||
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(
|
||||
getApplicationContext());
|
||||
boolean enabled = preferences.getBoolean("notificationsEnabled", true);
|
||||
if (!enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
createMastodonAPI();
|
||||
|
||||
mastodonApi.notification(notificationId).enqueue(new Callback<Notification>() {
|
||||
@Override
|
||||
public void onResponse(Call<Notification> call, Response<Notification> response) {
|
||||
if (response.isSuccessful()) {
|
||||
NotificationMaker.make(PushNotificationService.this, NOTIFY_ID,
|
||||
response.body());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<Notification> call, Throwable t) {}
|
||||
});
|
||||
}
|
||||
|
||||
/** Disconnect from the MQTT broker. */
|
||||
public void disconnect() {
|
||||
try {
|
||||
mqttAndroidClient.disconnect();
|
||||
} catch (MqttException ex) {
|
||||
Log.e(TAG, "An exception occurred while disconnecting.");
|
||||
onDisconnectFailed();
|
||||
}
|
||||
}
|
||||
|
||||
private void onDisconnectFailed() {
|
||||
|
||||
}
|
||||
|
||||
private void createMastodonAPI() {
|
||||
SharedPreferences preferences = getSharedPreferences(
|
||||
getString(R.string.preferences_file_key), Context.MODE_PRIVATE);
|
||||
final String domain = preferences.getString("domain", null);
|
||||
final String accessToken = preferences.getString("accessToken", null);
|
||||
|
||||
OkHttpClient okHttpClient = OkHttpUtils.getCompatibleClientBuilder()
|
||||
.addInterceptor(new Interceptor() {
|
||||
@Override
|
||||
public okhttp3.Response intercept(Chain chain) throws IOException {
|
||||
Request originalRequest = chain.request();
|
||||
|
||||
Request.Builder builder = originalRequest.newBuilder()
|
||||
.header("Authorization", String.format("Bearer %s", accessToken));
|
||||
|
||||
Request newRequest = builder.build();
|
||||
|
||||
return chain.proceed(newRequest);
|
||||
}
|
||||
})
|
||||
.build();
|
||||
|
||||
Gson gson = new GsonBuilder()
|
||||
.registerTypeAdapter(Spanned.class, new SpannedTypeAdapter())
|
||||
.registerTypeAdapter(StringWithEmoji.class, new StringWithEmojiTypeAdapter())
|
||||
.create();
|
||||
|
||||
Retrofit retrofit = new Retrofit.Builder()
|
||||
.baseUrl("https://" + domain)
|
||||
.client(okHttpClient)
|
||||
.addConverterFactory(GsonConverterFactory.create(gson))
|
||||
.build();
|
||||
|
||||
mastodonApi = retrofit.create(MastodonAPI.class);
|
||||
}
|
||||
}
|
@ -105,8 +105,21 @@ public class PushNotificationClient {
|
||||
// This client is read-only, so this is unused.
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Open the MQTT connection.
|
||||
private void flushQueuedActions() {
|
||||
while (!queuedActions.isEmpty()) {
|
||||
QueuedAction action = queuedActions.pop();
|
||||
switch (action.type) {
|
||||
case SUBSCRIBE: subscribeToTopic(action.topic); break;
|
||||
case UNSUBSCRIBE: unsubscribeToTopic(action.topic); break;
|
||||
case DISCONNECT: disconnect(); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Connect to the MQTT broker. */
|
||||
public void connect() {
|
||||
MqttConnectOptions options = new MqttConnectOptions();
|
||||
options.setAutomaticReconnect(true);
|
||||
options.setCleanSession(false);
|
||||
@ -140,20 +153,21 @@ public class PushNotificationClient {
|
||||
}
|
||||
});
|
||||
} catch (MqttException e) {
|
||||
Log.e(TAG, "An exception occurred while connecting. " + e.getMessage());
|
||||
Log.e(TAG, "An exception occurred while connecpting. " + e.getMessage());
|
||||
onConnectionFailure();
|
||||
}
|
||||
}
|
||||
|
||||
private void flushQueuedActions() {
|
||||
while (!queuedActions.isEmpty()) {
|
||||
QueuedAction action = queuedActions.pop();
|
||||
switch (action.type) {
|
||||
case SUBSCRIBE: subscribeToTopic(action.topic); break;
|
||||
case UNSUBSCRIBE: unsubscribeToTopic(action.topic); break;
|
||||
case DISCONNECT: disconnect(); break;
|
||||
}
|
||||
}
|
||||
private void onConnectionSuccess() {
|
||||
Log.v(TAG, "The connection succeeded.");
|
||||
}
|
||||
|
||||
private void onConnectionFailure() {
|
||||
Log.v(TAG, "The connection failed.");
|
||||
}
|
||||
|
||||
private void onConnectionLost() {
|
||||
Log.v(TAG, "The connection was lost.");
|
||||
}
|
||||
|
||||
/** Disconnect from the MQTT broker. */
|
||||
@ -215,18 +229,6 @@ public class PushNotificationClient {
|
||||
}
|
||||
}
|
||||
|
||||
private void onConnectionSuccess() {
|
||||
Log.v(TAG, "The connection succeeded.");
|
||||
}
|
||||
|
||||
private void onConnectionFailure() {
|
||||
Log.v(TAG, "The connection failed.");
|
||||
}
|
||||
|
||||
private void onConnectionLost() {
|
||||
Log.v(TAG, "The connection was lost.");
|
||||
}
|
||||
|
||||
private void onMessageReceived(final Context context, String message) {
|
||||
String notificationId = message; // TODO: finalize the form the messages will be received
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user