Setup client-side for integration with the wryk/tusky-api prototype.
This commit is contained in:
parent
73a5144741
commit
e282f13fdc
4 changed files with 115 additions and 31 deletions
|
@ -35,6 +35,8 @@ 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.network.TuskyApi;
|
||||
import com.keylesspalace.tusky.util.Log;
|
||||
import com.keylesspalace.tusky.util.OkHttpUtils;
|
||||
import com.keylesspalace.tusky.util.PushNotificationClient;
|
||||
|
||||
|
@ -45,11 +47,17 @@ import okhttp3.Interceptor;
|
|||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.ResponseBody;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
import retrofit2.Retrofit;
|
||||
import retrofit2.converter.gson.GsonConverterFactory;
|
||||
|
||||
public class BaseActivity extends AppCompatActivity {
|
||||
private static final String TAG = "BaseActivity"; // logging tag
|
||||
|
||||
public MastodonAPI mastodonAPI;
|
||||
public TuskyApi tuskyApi;
|
||||
protected PushNotificationClient pushNotificationClient;
|
||||
protected Dispatcher mastodonApiDispatcher;
|
||||
|
||||
|
@ -59,7 +67,8 @@ public class BaseActivity extends AppCompatActivity {
|
|||
|
||||
redirectIfNotLoggedIn();
|
||||
createMastodonAPI();
|
||||
createTuskyAPI();
|
||||
createTuskyApi();
|
||||
createPushNotificationClient();
|
||||
|
||||
/* There isn't presently a way to globally change the theme of a whole application at
|
||||
* runtime, just individual activities. So, each activity has to set its theme before any
|
||||
|
@ -151,9 +160,19 @@ public class BaseActivity extends AppCompatActivity {
|
|||
mastodonAPI = retrofit.create(MastodonAPI.class);
|
||||
}
|
||||
|
||||
protected void createTuskyAPI() {
|
||||
protected void createTuskyApi() {
|
||||
Retrofit retrofit = new Retrofit.Builder()
|
||||
.baseUrl("https://" + getString(R.string.tusky_api_domain))
|
||||
.client(OkHttpUtils.getCompatibleClient())
|
||||
.build();
|
||||
|
||||
tuskyApi = retrofit.create(TuskyApi.class);
|
||||
}
|
||||
|
||||
protected void createPushNotificationClient() {
|
||||
// TODO: Switch to ssl:// when TLS support is added.
|
||||
pushNotificationClient = new PushNotificationClient(getApplicationContext(),
|
||||
getString(R.string.tusky_api_url));
|
||||
"tcp://" + getString(R.string.tusky_api_domain));
|
||||
}
|
||||
|
||||
protected void redirectIfNotLoggedIn() {
|
||||
|
@ -187,10 +206,57 @@ public class BaseActivity extends AppCompatActivity {
|
|||
}
|
||||
|
||||
protected void enablePushNotifications() {
|
||||
pushNotificationClient.subscribeToTopic();
|
||||
Callback<ResponseBody> callback = new Callback<ResponseBody>() {
|
||||
@Override
|
||||
public void onResponse(Call<ResponseBody> call,
|
||||
retrofit2.Response<ResponseBody> response) {
|
||||
if (response.isSuccessful()) {
|
||||
pushNotificationClient.subscribeToTopic(getPushNotificationTopic());
|
||||
} else {
|
||||
onEnablePushNotificationsFailure();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<ResponseBody> call, Throwable t) {
|
||||
onEnablePushNotificationsFailure();
|
||||
}
|
||||
};
|
||||
tuskyApi.register(getBaseUrl(), getAccessToken(), pushNotificationClient.getDeviceToken())
|
||||
.enqueue(callback);
|
||||
}
|
||||
|
||||
private void onEnablePushNotificationsFailure() {
|
||||
Log.e(TAG, "Enabling push notifications failed.");
|
||||
}
|
||||
|
||||
protected void disablePushNotifications() {
|
||||
pushNotificationClient.unsubscribeToTopic();
|
||||
Callback<ResponseBody> callback = new Callback<ResponseBody>() {
|
||||
@Override
|
||||
public void onResponse(Call<ResponseBody> call,
|
||||
retrofit2.Response<ResponseBody> response) {
|
||||
if (response.isSuccessful()) {
|
||||
pushNotificationClient.unsubscribeToTopic(getPushNotificationTopic());
|
||||
} else {
|
||||
onDisablePushNotificationsFailure();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<ResponseBody> call, Throwable t) {
|
||||
onDisablePushNotificationsFailure();
|
||||
}
|
||||
};
|
||||
tuskyApi.unregister(getBaseUrl(), getAccessToken(), pushNotificationClient.getDeviceToken())
|
||||
.enqueue(callback);
|
||||
}
|
||||
|
||||
private void onDisablePushNotificationsFailure() {
|
||||
Log.e(TAG, "Disabling push notifications failed.");
|
||||
}
|
||||
|
||||
private String getPushNotificationTopic() {
|
||||
return String.format("%s/%s/%s", getBaseUrl(), getAccessToken(),
|
||||
pushNotificationClient.getDeviceToken());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,15 +17,14 @@ package com.keylesspalace.tusky.network;
|
|||
|
||||
import okhttp3.ResponseBody;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.http.Field;
|
||||
import retrofit2.http.FormUrlEncoded;
|
||||
import retrofit2.http.POST;
|
||||
|
||||
public interface TuskyAPI {
|
||||
public interface TuskyApi {
|
||||
@FormUrlEncoded
|
||||
@POST("/register")
|
||||
Call<ResponseBody> register(@Field("instance_url") String instanceUrl, @Field("access_token") String accessToken, @Field("device_token") String deviceToken);
|
||||
Call<ResponseBody> register(String instanceUrl, String accessToken, String deviceToken);
|
||||
@FormUrlEncoded
|
||||
@POST("/unregister")
|
||||
Call<ResponseBody> unregister(@Field("instance_url") String instanceUrl, @Field("access_token") String accessToken);
|
||||
Call<ResponseBody> unregister(String instanceUrl, String accessToken, String deviceToken);
|
||||
}
|
|
@ -29,6 +29,7 @@ import org.eclipse.paho.client.mqttv3.MqttMessage;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import okhttp3.Interceptor;
|
||||
import okhttp3.OkHttpClient;
|
||||
|
@ -43,23 +44,37 @@ import static android.content.Context.NOTIFICATION_SERVICE;
|
|||
|
||||
public class PushNotificationClient {
|
||||
private static final String TAG = "PushNotificationClient";
|
||||
private static final String TOPIC = "tusky/notification";
|
||||
private static final int NOTIFY_ID = 666;
|
||||
|
||||
private enum QueuedAction {
|
||||
SUBSCRIBE,
|
||||
UNSUBSCRIBE,
|
||||
DISCONNECT,
|
||||
private static class QueuedAction {
|
||||
enum Type {
|
||||
SUBSCRIBE,
|
||||
UNSUBSCRIBE,
|
||||
DISCONNECT,
|
||||
}
|
||||
|
||||
Type type;
|
||||
String topic;
|
||||
|
||||
QueuedAction(Type type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
QueuedAction(Type type, String topic) {
|
||||
this.type = type;
|
||||
this.topic = topic;
|
||||
}
|
||||
}
|
||||
|
||||
private MqttAndroidClient mqttAndroidClient;
|
||||
private MastodonAPI mastodonApi;
|
||||
private ArrayDeque<QueuedAction> queuedActions;
|
||||
private boolean subscribed;
|
||||
private ArrayList<String> subscribedTopics;
|
||||
|
||||
public PushNotificationClient(final @NonNull Context applicationContext,
|
||||
@NonNull String serverUri) {
|
||||
queuedActions = new ArrayDeque<>();
|
||||
subscribedTopics = new ArrayList<>();
|
||||
|
||||
// Create the MQTT client.
|
||||
String clientId = MqttClient.generateClientId();
|
||||
|
@ -69,8 +84,8 @@ public class PushNotificationClient {
|
|||
public void connectComplete(boolean reconnect, String serverURI) {
|
||||
if (reconnect) {
|
||||
flushQueuedActions();
|
||||
if (subscribed) {
|
||||
subscribeToTopic();
|
||||
for (String topic : subscribedTopics) {
|
||||
subscribeToTopic(topic);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -133,10 +148,10 @@ public class PushNotificationClient {
|
|||
private void flushQueuedActions() {
|
||||
while (!queuedActions.isEmpty()) {
|
||||
QueuedAction action = queuedActions.pop();
|
||||
switch (action) {
|
||||
case SUBSCRIBE: subscribeToTopic(); break;
|
||||
case UNSUBSCRIBE: unsubscribeToTopic(); break;
|
||||
case DISCONNECT: disconnect(); break;
|
||||
switch (action.type) {
|
||||
case SUBSCRIBE: subscribeToTopic(action.topic); break;
|
||||
case UNSUBSCRIBE: unsubscribeToTopic(action.topic); break;
|
||||
case DISCONNECT: disconnect(); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -144,7 +159,7 @@ public class PushNotificationClient {
|
|||
/** Disconnect from the MQTT broker. */
|
||||
public void disconnect() {
|
||||
if (!mqttAndroidClient.isConnected()) {
|
||||
queuedActions.add(QueuedAction.DISCONNECT);
|
||||
queuedActions.add(new QueuedAction(QueuedAction.Type.DISCONNECT));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
|
@ -160,16 +175,16 @@ public class PushNotificationClient {
|
|||
}
|
||||
|
||||
/** Subscribe to the push notification topic. */
|
||||
public void subscribeToTopic() {
|
||||
public void subscribeToTopic(final String topic) {
|
||||
if (!mqttAndroidClient.isConnected()) {
|
||||
queuedActions.add(QueuedAction.SUBSCRIBE);
|
||||
queuedActions.add(new QueuedAction(QueuedAction.Type.SUBSCRIBE, topic));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
mqttAndroidClient.subscribe(TOPIC, 0, null, new IMqttActionListener() {
|
||||
mqttAndroidClient.subscribe(topic, 0, null, new IMqttActionListener() {
|
||||
@Override
|
||||
public void onSuccess(IMqttToken asyncActionToken) {
|
||||
subscribed = true;
|
||||
subscribedTopics.add(topic);
|
||||
onConnectionSuccess();
|
||||
}
|
||||
|
||||
|
@ -186,14 +201,14 @@ public class PushNotificationClient {
|
|||
}
|
||||
|
||||
/** Unsubscribe from the push notification topic. */
|
||||
public void unsubscribeToTopic() {
|
||||
public void unsubscribeToTopic(String topic) {
|
||||
if (!mqttAndroidClient.isConnected()) {
|
||||
queuedActions.add(QueuedAction.UNSUBSCRIBE);
|
||||
queuedActions.add(new QueuedAction(QueuedAction.Type.UNSUBSCRIBE, topic));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
mqttAndroidClient.unsubscribe(TOPIC);
|
||||
subscribed = false;
|
||||
mqttAndroidClient.unsubscribe(topic);
|
||||
subscribedTopics.remove(topic);
|
||||
} catch (MqttException e) {
|
||||
Log.e(TAG, "An exception occurred while unsubscribing." + e.getMessage());
|
||||
onConnectionFailure();
|
||||
|
@ -271,4 +286,8 @@ public class PushNotificationClient {
|
|||
public void clearNotifications(Context context) {
|
||||
((NotificationManager) (context.getSystemService(NOTIFICATION_SERVICE))).cancel(NOTIFY_ID);
|
||||
}
|
||||
|
||||
public String getDeviceToken() {
|
||||
return mqttAndroidClient.getClientId();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<resources>
|
||||
<string name="app_name" translatable="false">Tusky</string>
|
||||
<string name="app_website" translatable="false">https://tusky.keylesspalace.com</string>
|
||||
<string name="tusky_api_url" translatable="false">tcp://tuskyapi.keylesspalace.com</string>
|
||||
<string name="tusky_api_domain" translatable="false">tuskyapi.keylesspalace.com</string>
|
||||
<string name="tusky_api_keystore_password" translatable="false">your_password_here</string>
|
||||
|
||||
<string name="oauth_scheme" translatable="false">oauth2redirect</string>
|
||||
|
|
Loading…
Reference in a new issue