parent
b211ed0f87
commit
b3ce544bd0
@ -1,55 +0,0 @@ |
|||||||
{ |
|
||||||
"project_info": { |
|
||||||
"project_number": "268851337880", |
|
||||||
"firebase_url": "https://tusky-62772.firebaseio.com", |
|
||||||
"project_id": "tusky-62772", |
|
||||||
"storage_bucket": "tusky-62772.appspot.com" |
|
||||||
}, |
|
||||||
"client": [ |
|
||||||
{ |
|
||||||
"client_info": { |
|
||||||
"mobilesdk_app_id": "1:268851337880:android:fc4111b1d145a00e", |
|
||||||
"android_client_info": { |
|
||||||
"package_name": "com.keylesspalace.tusky" |
|
||||||
} |
|
||||||
}, |
|
||||||
"oauth_client": [ |
|
||||||
{ |
|
||||||
"client_id": "268851337880-eie2ssto2d21bfihn9d1qupcrke8oebf.apps.googleusercontent.com", |
|
||||||
"client_type": 1, |
|
||||||
"android_info": { |
|
||||||
"package_name": "com.keylesspalace.tusky", |
|
||||||
"certificate_hash": "18d196307d6e928e99c2e0bb9818c01c38aff2f9" |
|
||||||
} |
|
||||||
}, |
|
||||||
{ |
|
||||||
"client_id": "268851337880-n19d05m282nirs1fc9kdd5n4of6je4fk.apps.googleusercontent.com", |
|
||||||
"client_type": 3 |
|
||||||
} |
|
||||||
], |
|
||||||
"api_key": [ |
|
||||||
{ |
|
||||||
"current_key": "AIzaSyCbJtSjuk4I3Jy8PdUaO3TaQOXubcOUElo" |
|
||||||
} |
|
||||||
], |
|
||||||
"services": { |
|
||||||
"analytics_service": { |
|
||||||
"status": 1 |
|
||||||
}, |
|
||||||
"appinvite_service": { |
|
||||||
"status": 2, |
|
||||||
"other_platform_oauth_client": [ |
|
||||||
{ |
|
||||||
"client_id": "268851337880-n19d05m282nirs1fc9kdd5n4of6je4fk.apps.googleusercontent.com", |
|
||||||
"client_type": 3 |
|
||||||
} |
|
||||||
] |
|
||||||
}, |
|
||||||
"ads_service": { |
|
||||||
"status": 2 |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
], |
|
||||||
"configuration_version": "1" |
|
||||||
} |
|
@ -1,7 +0,0 @@ |
|||||||
<?xml version="1.0" encoding="utf-8"?> |
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" |
|
||||||
package="com.keylesspalace.tusky"> |
|
||||||
<application> |
|
||||||
<meta-data android:name="firebase_analytics_collection_enabled" android:value="false" /> |
|
||||||
</application> |
|
||||||
</manifest> |
|
@ -1,257 +0,0 @@ |
|||||||
package com.keylesspalace.tusky.util; |
|
||||||
|
|
||||||
import android.app.NotificationManager; |
|
||||||
import android.content.Context; |
|
||||||
import android.support.annotation.NonNull; |
|
||||||
import android.support.v4.util.ArraySet; |
|
||||||
import android.text.Spanned; |
|
||||||
import android.util.Log; |
|
||||||
|
|
||||||
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 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.MqttClient; |
|
||||||
import org.eclipse.paho.client.mqttv3.MqttConnectOptions; |
|
||||||
import org.eclipse.paho.client.mqttv3.MqttException; |
|
||||||
import org.eclipse.paho.client.mqttv3.MqttMessage; |
|
||||||
|
|
||||||
import java.io.InputStream; |
|
||||||
import java.util.ArrayDeque; |
|
||||||
|
|
||||||
import static android.content.Context.NOTIFICATION_SERVICE; |
|
||||||
|
|
||||||
public class PushNotificationClient { |
|
||||||
private static final String TAG = "PushNotificationClient"; |
|
||||||
private static final int NOTIFY_ID = 666; |
|
||||||
|
|
||||||
private static class QueuedAction { |
|
||||||
enum Type { |
|
||||||
SUBSCRIBE, |
|
||||||
UNSUBSCRIBE, |
|
||||||
DISCONNECT, |
|
||||||
} |
|
||||||
|
|
||||||
Type type; |
|
||||||
String topic; |
|
||||||
|
|
||||||
QueuedAction(Type type, String topic) { |
|
||||||
this.type = type; |
|
||||||
this.topic = topic; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private MqttAndroidClient mqttAndroidClient; |
|
||||||
private ArrayDeque<QueuedAction> queuedActions; |
|
||||||
private ArraySet<String> subscribedTopics; |
|
||||||
|
|
||||||
public PushNotificationClient(final @NonNull Context applicationContext, |
|
||||||
@NonNull String serverUri) { |
|
||||||
queuedActions = new ArrayDeque<>(); |
|
||||||
subscribedTopics = new ArraySet<>(); |
|
||||||
|
|
||||||
// Create the MQTT client.
|
|
||||||
String clientId = MqttClient.generateClientId(); |
|
||||||
mqttAndroidClient = new MqttAndroidClient(applicationContext, serverUri, clientId); |
|
||||||
mqttAndroidClient.setCallback(new MqttCallbackExtended() { |
|
||||||
@Override |
|
||||||
public void connectComplete(boolean reconnect, String serverURI) { |
|
||||||
if (reconnect) { |
|
||||||
flushQueuedActions(); |
|
||||||
for (String topic : subscribedTopics) { |
|
||||||
subscribeToTopic(topic); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void connectionLost(Throwable cause) { |
|
||||||
onConnectionLost(); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void messageArrived(String topic, MqttMessage message) throws Exception { |
|
||||||
onMessageReceived(applicationContext, new String(message.getPayload())); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void deliveryComplete(IMqttDeliveryToken token) { |
|
||||||
// This client is read-only, so this is unused.
|
|
||||||
} |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
private void queueAction(QueuedAction.Type type, String topic) { |
|
||||||
// Search queue for duplicates and if one is found, return before it's added to the queue.
|
|
||||||
for (QueuedAction action : queuedActions) { |
|
||||||
if (action.type == type) { |
|
||||||
switch (type) { |
|
||||||
case SUBSCRIBE: |
|
||||||
case UNSUBSCRIBE: |
|
||||||
if (!action.topic.equals(topic)) { |
|
||||||
return; |
|
||||||
} |
|
||||||
break; |
|
||||||
case DISCONNECT: |
|
||||||
return; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
// Add the new unique action.
|
|
||||||
queuedActions.add(new QueuedAction(type, topic)); |
|
||||||
} |
|
||||||
|
|
||||||
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(Context context) { |
|
||||||
MqttConnectOptions options = new MqttConnectOptions(); |
|
||||||
options.setAutomaticReconnect(true); |
|
||||||
options.setCleanSession(false); |
|
||||||
try { |
|
||||||
String password = context.getString(R.string.tusky_api_keystore_password); |
|
||||||
InputStream keystore = context.getResources().openRawResource(R.raw.keystore_tusky_api); |
|
||||||
try { |
|
||||||
options.setSocketFactory(mqttAndroidClient.getSSLSocketFactory(keystore, password)); |
|
||||||
} finally { |
|
||||||
IOUtils.closeQuietly(keystore); |
|
||||||
} |
|
||||||
mqttAndroidClient.connect(options).setActionCallback(new IMqttActionListener() { |
|
||||||
@Override |
|
||||||
public void onSuccess(IMqttToken asyncActionToken) { |
|
||||||
DisconnectedBufferOptions bufferOptions = new DisconnectedBufferOptions(); |
|
||||||
bufferOptions.setBufferEnabled(true); |
|
||||||
bufferOptions.setBufferSize(100); |
|
||||||
bufferOptions.setPersistBuffer(false); |
|
||||||
bufferOptions.setDeleteOldestMessages(false); |
|
||||||
mqttAndroidClient.setBufferOpts(bufferOptions); |
|
||||||
onConnectionSuccess(); |
|
||||||
flushQueuedActions(); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void onFailure(IMqttToken asyncActionToken, Throwable exception) { |
|
||||||
Log.e(TAG, "An exception occurred while connecting. " + exception.getMessage() |
|
||||||
+ " " + exception.getCause()); |
|
||||||
onConnectionFailure(); |
|
||||||
} |
|
||||||
}); |
|
||||||
} catch (MqttException e) { |
|
||||||
Log.e(TAG, "An exception occurred while connecpting. " + e.getMessage()); |
|
||||||
onConnectionFailure(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
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. */ |
|
||||||
public void disconnect() { |
|
||||||
if (!mqttAndroidClient.isConnected()) { |
|
||||||
queueAction(QueuedAction.Type.DISCONNECT, null); |
|
||||||
return; |
|
||||||
} |
|
||||||
try { |
|
||||||
mqttAndroidClient.disconnect(); |
|
||||||
} catch (MqttException ex) { |
|
||||||
Log.e(TAG, "An exception occurred while disconnecting."); |
|
||||||
onDisconnectFailed(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private void onDisconnectFailed() { |
|
||||||
Log.v(TAG, "Failed while disconnecting from the broker."); |
|
||||||
} |
|
||||||
|
|
||||||
/** Subscribe to the push notification topic. */ |
|
||||||
public void subscribeToTopic(final String topic) { |
|
||||||
if (!mqttAndroidClient.isConnected()) { |
|
||||||
queueAction(QueuedAction.Type.SUBSCRIBE, topic); |
|
||||||
return; |
|
||||||
} |
|
||||||
if (subscribedTopics.contains(topic)) { |
|
||||||
return; |
|
||||||
} |
|
||||||
try { |
|
||||||
mqttAndroidClient.subscribe(topic, 0, null, new IMqttActionListener() { |
|
||||||
@Override |
|
||||||
public void onSuccess(IMqttToken asyncActionToken) { |
|
||||||
subscribedTopics.add(topic); |
|
||||||
onConnectionSuccess(); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void onFailure(IMqttToken asyncActionToken, Throwable exception) { |
|
||||||
Log.e(TAG, "An exception occurred while subscribing." + exception.getMessage()); |
|
||||||
onConnectionFailure(); |
|
||||||
} |
|
||||||
}); |
|
||||||
} catch (MqttException e) { |
|
||||||
Log.e(TAG, "An exception occurred while subscribing." + e.getMessage()); |
|
||||||
onConnectionFailure(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** Unsubscribe from the push notification topic. */ |
|
||||||
public void unsubscribeToTopic(String topic) { |
|
||||||
if (!mqttAndroidClient.isConnected()) { |
|
||||||
queueAction(QueuedAction.Type.UNSUBSCRIBE, topic); |
|
||||||
return; |
|
||||||
} |
|
||||||
try { |
|
||||||
mqttAndroidClient.unsubscribe(topic); |
|
||||||
subscribedTopics.remove(topic); |
|
||||||
} catch (MqttException e) { |
|
||||||
Log.e(TAG, "An exception occurred while unsubscribing." + e.getMessage()); |
|
||||||
onConnectionFailure(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private void onMessageReceived(final Context context, String message) { |
|
||||||
Log.v(TAG, "Notification received: " + message); |
|
||||||
|
|
||||||
Gson gson = new GsonBuilder() |
|
||||||
.registerTypeAdapter(Spanned.class, new SpannedTypeAdapter()) |
|
||||||
.registerTypeAdapter(StringWithEmoji.class, new StringWithEmojiTypeAdapter()) |
|
||||||
.create(); |
|
||||||
Notification notification = gson.fromJson(message, Notification.class); |
|
||||||
|
|
||||||
NotificationMaker.make(context, NOTIFY_ID, notification); |
|
||||||
} |
|
||||||
|
|
||||||
public void clearNotifications(Context context) { |
|
||||||
((NotificationManager) (context.getSystemService(NOTIFICATION_SERVICE))).cancel(NOTIFY_ID); |
|
||||||
} |
|
||||||
|
|
||||||
public String getDeviceToken() { |
|
||||||
return mqttAndroidClient.getClientId(); |
|
||||||
} |
|
||||||
} |
|
Loading…
Reference in new issue