aboutsummaryrefslogtreecommitdiffstats
path: root/src/playstore
diff options
context:
space:
mode:
authorChristian Schneppe <christian.schneppe@pix-art.de>2019-11-02 15:44:31 +0100
committerChristian Schneppe <christian.schneppe@pix-art.de>2019-11-02 15:44:31 +0100
commit7bb48465e21a8468a5a9ed61b81989903c8b36a4 (patch)
treee2c3819e36c108f55722c4d62300a3fded6fdfdd /src/playstore
parent6e386a8701190aad9e5adfa83c48ef9ea1582f1e (diff)
rename build flavors
Diffstat (limited to 'src/playstore')
-rw-r--r--src/playstore/AndroidManifest.xml32
-rw-r--r--src/playstore/java/de/pixart/messenger/services/EmojiService.java53
-rw-r--r--src/playstore/java/de/pixart/messenger/services/MaintenanceReceiver.java38
-rw-r--r--src/playstore/java/de/pixart/messenger/services/PushManagementService.java194
-rw-r--r--src/playstore/java/de/pixart/messenger/services/PushMessageReceiver.java39
-rw-r--r--src/playstore/java/de/pixart/messenger/ui/widget/EmojiWrapperEditText.java17
6 files changed, 373 insertions, 0 deletions
diff --git a/src/playstore/AndroidManifest.xml b/src/playstore/AndroidManifest.xml
new file mode 100644
index 000000000..a54f8bee1
--- /dev/null
+++ b/src/playstore/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ package="de.pixart.messenger">
+
+ <application tools:ignore="GoogleAppIndexingWarning">
+
+ <meta-data
+ android:name="firebase_analytics_collection_deactivated"
+ android:value="true" />
+ <meta-data
+ android:name="google_analytics_adid_collection_enabled"
+ android:value="false" />
+
+ <receiver
+ android:name=".services.MaintenanceReceiver"
+ android:exported="true"
+ android:permission="android.permission.CHANGE_CONFIGURATION">
+ <intent-filter>
+ <action android:name="de.pixart.messenger.RENEW_INSTANCE_ID" />
+ </intent-filter>
+ </receiver>
+
+ <service
+ android:name=".services.PushMessageReceiver"
+ android:exported="false">
+ <intent-filter>
+ <action android:name="com.google.firebase.MESSAGING_EVENT" />
+ </intent-filter>
+ </service>
+ </application>
+</manifest>
diff --git a/src/playstore/java/de/pixart/messenger/services/EmojiService.java b/src/playstore/java/de/pixart/messenger/services/EmojiService.java
new file mode 100644
index 000000000..0e5bfadd0
--- /dev/null
+++ b/src/playstore/java/de/pixart/messenger/services/EmojiService.java
@@ -0,0 +1,53 @@
+package de.pixart.messenger.services;
+
+import android.content.Context;
+import android.os.Build;
+import android.util.Log;
+
+import androidx.core.provider.FontRequest;
+import androidx.emoji.text.EmojiCompat;
+import androidx.emoji.text.FontRequestEmojiCompatConfig;
+
+import de.pixart.messenger.Config;
+import de.pixart.messenger.R;
+
+public class EmojiService {
+
+ private final EmojiCompat.InitCallback initCallback = new EmojiCompat.InitCallback() {
+ @Override
+ public void onInitialized() {
+ super.onInitialized();
+ Log.d(Config.LOGTAG, "EmojiService succeeded in loading fonts");
+
+ }
+
+ @Override
+ public void onFailed(Throwable throwable) {
+ super.onFailed(throwable);
+ Log.d(Config.LOGTAG, "EmojiService failed to load fonts", throwable);
+ }
+ };
+
+ private final Context context;
+
+ public EmojiService(Context context) {
+ this.context = context;
+ }
+
+ public void init(boolean useBundledEmoji) {
+ final FontRequest fontRequest = new FontRequest(
+ "com.google.android.gms.fonts",
+ "com.google.android.gms",
+ "Noto Color Emoji Compat",
+ R.array.font_certs);
+ FontRequestEmojiCompatConfig fontRequestEmojiCompatConfig = new FontRequestEmojiCompatConfig(context, fontRequest);
+ fontRequestEmojiCompatConfig.registerInitCallback(initCallback);
+ //On recent Androids we assume to have the latest emojis
+ //there are some annoying bugs with emoji compat that make it a safer choice not to use it when possible
+ // a) when using the ondemand emoji font (play store) flags don’t work
+ // b) the text preview has annoying glitches when the cut of text contains emojis (the emoji will be half visible)
+ // c) can trigger a hardware rendering bug https://issuetracker.google.com/issues/67102093
+ fontRequestEmojiCompatConfig.setReplaceAll(useBundledEmoji && Build.VERSION.SDK_INT < Build.VERSION_CODES.O);
+ EmojiCompat.init(fontRequestEmojiCompatConfig);
+ }
+} \ No newline at end of file
diff --git a/src/playstore/java/de/pixart/messenger/services/MaintenanceReceiver.java b/src/playstore/java/de/pixart/messenger/services/MaintenanceReceiver.java
new file mode 100644
index 000000000..31ed95a88
--- /dev/null
+++ b/src/playstore/java/de/pixart/messenger/services/MaintenanceReceiver.java
@@ -0,0 +1,38 @@
+package de.pixart.messenger.services;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.util.Log;
+
+import com.google.firebase.iid.FirebaseInstanceId;
+
+import java.io.IOException;
+
+import de.pixart.messenger.Config;
+import de.pixart.messenger.utils.Compatibility;
+
+public class MaintenanceReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ Log.d(Config.LOGTAG, "received intent in maintenance receiver");
+ if ("de.pixart.messenger.RENEW_INSTANCE_ID".equals(intent.getAction())) {
+ renewInstanceToken(context);
+
+ }
+ }
+
+ private void renewInstanceToken(final Context context) {
+ new Thread(() -> {
+ try {
+ FirebaseInstanceId.getInstance().deleteInstanceId();
+ final Intent intent = new Intent(context, XmppConnectionService.class);
+ intent.setAction(XmppConnectionService.ACTION_FCM_TOKEN_REFRESH);
+ Compatibility.startService(context, intent);
+ } catch (IOException e) {
+ Log.d(Config.LOGTAG, "unable to renew instance token", e);
+ }
+ }).start();
+
+ }
+} \ No newline at end of file
diff --git a/src/playstore/java/de/pixart/messenger/services/PushManagementService.java b/src/playstore/java/de/pixart/messenger/services/PushManagementService.java
new file mode 100644
index 000000000..a7054cf2f
--- /dev/null
+++ b/src/playstore/java/de/pixart/messenger/services/PushManagementService.java
@@ -0,0 +1,194 @@
+package de.pixart.messenger.services;
+
+import android.util.Log;
+
+import com.google.android.gms.common.ConnectionResult;
+import com.google.android.gms.common.GoogleApiAvailability;
+import com.google.firebase.iid.FirebaseInstanceId;
+import com.google.firebase.iid.InstanceIdResult;
+
+import de.pixart.messenger.Config;
+import de.pixart.messenger.R;
+import de.pixart.messenger.entities.Account;
+import de.pixart.messenger.entities.Conversation;
+import de.pixart.messenger.utils.Namespace;
+import de.pixart.messenger.utils.PhoneHelper;
+import de.pixart.messenger.xml.Element;
+import de.pixart.messenger.xmpp.XmppConnection;
+import de.pixart.messenger.xmpp.forms.Data;
+import de.pixart.messenger.xmpp.stanzas.IqPacket;
+import rocks.xmpp.addr.Jid;
+
+public class PushManagementService {
+
+ protected final XmppConnectionService mXmppConnectionService;
+
+ PushManagementService(XmppConnectionService service) {
+ this.mXmppConnectionService = service;
+ }
+
+ private static Data findResponseData(IqPacket response) {
+ final Element command = response.findChild("command", Namespace.COMMANDS);
+ final Element x = command == null ? null : command.findChild("x", Namespace.DATA);
+ return x == null ? null : Data.parse(x);
+ }
+
+ private Jid getAppServer() {
+ return Jid.of(mXmppConnectionService.getString(R.string.app_server));
+ }
+
+ void registerPushTokenOnServer(final Account account) {
+ Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": has push support");
+ retrieveFcmInstanceToken(token -> {
+ final String androidId = PhoneHelper.getAndroidId(mXmppConnectionService);
+ final IqPacket packet = mXmppConnectionService.getIqGenerator().pushTokenToAppServer(getAppServer(), token, androidId);
+ mXmppConnectionService.sendIqPacket(account, packet, (a, response) -> {
+ final Data data = findResponseData(response);
+ if (response.getType() == IqPacket.TYPE.RESULT && data != null) {
+ try {
+ String node = data.getValue("node");
+ String secret = data.getValue("secret");
+ Jid jid = Jid.of(data.getValue("jid"));
+ if (node != null && secret != null) {
+ enablePushOnServer(a, jid, node, secret);
+ }
+ } catch (IllegalArgumentException e) {
+ e.printStackTrace();
+ }
+ } else {
+ Log.d(Config.LOGTAG, a.getJid().asBareJid() + ": invalid response from app server");
+ }
+ });
+ });
+ }
+
+ public void unregisterChannel(final Account account, final String channel) {
+ final String androidId = PhoneHelper.getAndroidId(mXmppConnectionService);
+ final Jid appServer = getAppServer();
+ final IqPacket packet = mXmppConnectionService.getIqGenerator().unregisterChannelOnAppServer(appServer, androidId, channel);
+ mXmppConnectionService.sendIqPacket(account, packet, (a, response) -> {
+ if (response.getType() == IqPacket.TYPE.RESULT) {
+ Log.d(Config.LOGTAG, a.getJid().asBareJid() + ": successfully unregistered channel");
+ } else if (response.getType() == IqPacket.TYPE.ERROR) {
+ Log.d(Config.LOGTAG, a.getJid().asBareJid() + ": unable to unregister channel with hash " + channel);
+ }
+ });
+ }
+
+ void registerPushTokenOnServer(final Conversation conversation) {
+ Log.d(Config.LOGTAG, conversation.getAccount().getJid().asBareJid() + ": room " + conversation.getJid().asBareJid() + " has push support");
+ retrieveFcmInstanceToken(token -> {
+ final Jid muc = conversation.getJid().asBareJid();
+ final String androidId = PhoneHelper.getAndroidId(mXmppConnectionService);
+ final IqPacket packet = mXmppConnectionService.getIqGenerator().pushTokenToAppServer(getAppServer(), token, androidId, muc);
+ packet.setTo(muc);
+ mXmppConnectionService.sendIqPacket(conversation.getAccount(), packet, (a, response) -> {
+ final Data data = findResponseData(response);
+ if (response.getType() == IqPacket.TYPE.RESULT && data != null) {
+ try {
+ final String node = data.getValue("node");
+ final String secret = data.getValue("secret");
+ final Jid jid = Jid.of(data.getValue("jid"));
+ if (node != null && secret != null) {
+ enablePushOnServer(conversation, jid, node, secret);
+ }
+ } catch (IllegalArgumentException e) {
+ e.printStackTrace();
+ }
+ } else {
+ Log.d(Config.LOGTAG, a.getJid().asBareJid() + ": invalid response from app server");
+ }
+ });
+ });
+ }
+
+ private void enablePushOnServer(final Account account, final Jid appServer, final String node, final String secret) {
+ final IqPacket enable = mXmppConnectionService.getIqGenerator().enablePush(appServer, node, secret);
+ mXmppConnectionService.sendIqPacket(account, enable, (a, p) -> {
+ if (p.getType() == IqPacket.TYPE.RESULT) {
+ Log.d(Config.LOGTAG, a.getJid().asBareJid() + ": successfully enabled push on server");
+ } else if (p.getType() == IqPacket.TYPE.ERROR) {
+ Log.d(Config.LOGTAG, a.getJid().asBareJid() + ": enabling push on server failed");
+ }
+ });
+ }
+
+ private void enablePushOnServer(final Conversation conversation, final Jid appServer, final String node, final String secret) {
+ final Jid muc = conversation.getJid().asBareJid();
+ final IqPacket enable = mXmppConnectionService.getIqGenerator().enablePush(appServer, node, secret);
+ enable.setTo(muc);
+ mXmppConnectionService.sendIqPacket(conversation.getAccount(), enable, (a, p) -> {
+ if (p.getType() == IqPacket.TYPE.RESULT) {
+ Log.d(Config.LOGTAG, a.getJid().asBareJid() + ": successfully enabled push on " + muc);
+ if (conversation.setAttribute(Conversation.ATTRIBUTE_ALWAYS_NOTIFY, node)) {
+ mXmppConnectionService.updateConversation(conversation);
+ }
+ } else if (p.getType() == IqPacket.TYPE.ERROR) {
+ Log.d(Config.LOGTAG, a.getJid().asBareJid() + ": enabling push on " + muc + " failed");
+ }
+ });
+ }
+
+ public void disablePushOnServer(final Conversation conversation) {
+ final Jid muc = conversation.getJid().asBareJid();
+ final String node = conversation.getAttribute(Conversation.ATTRIBUTE_PUSH_NODE);
+ if (node != null) {
+ final IqPacket disable = mXmppConnectionService.getIqGenerator().disablePush(getAppServer(), node);
+ disable.setTo(muc);
+ mXmppConnectionService.sendIqPacket(conversation.getAccount(), disable, (account, response) -> {
+ if (response.getType() == IqPacket.TYPE.ERROR) {
+ Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": unable to disable push for room " + muc);
+ }
+ });
+ } else {
+ Log.d(Config.LOGTAG, conversation.getAccount().getJid().asBareJid() + ": room " + muc + " has no stored node. unable to disable push");
+ }
+ }
+
+ private void retrieveFcmInstanceToken(final OnGcmInstanceTokenRetrieved instanceTokenRetrieved) {
+ final FirebaseInstanceId firebaseInstanceId;
+ try {
+ firebaseInstanceId = FirebaseInstanceId.getInstance();
+ } catch (IllegalStateException e) {
+ Log.d(Config.LOGTAG, "unable to get firebase instance token ", e);
+ return;
+ }
+ firebaseInstanceId.getInstanceId().addOnCompleteListener(task -> {
+ if (!task.isSuccessful()) {
+ Log.d(Config.LOGTAG, "unable to get Firebase instance token", task.getException());
+ }
+ final InstanceIdResult result;
+ try {
+ result = task.getResult();
+ } catch (Exception e) {
+ Log.d(Config.LOGTAG, "unable to get Firebase instance token due to bug in library ", e);
+ return;
+ }
+ if (result != null) {
+ instanceTokenRetrieved.onGcmInstanceTokenRetrieved(result.getToken());
+ }
+ });
+
+ }
+
+
+ public boolean available(Account account) {
+ final XmppConnection connection = account.getXmppConnection();
+ return connection != null
+ && connection.getFeatures().sm()
+ && connection.getFeatures().push()
+ && playServicesAvailable();
+ }
+
+ private boolean playServicesAvailable() {
+ return GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(mXmppConnectionService) == ConnectionResult.SUCCESS;
+ }
+
+ public boolean isStub() {
+ return false;
+ }
+
+ interface OnGcmInstanceTokenRetrieved {
+ void onGcmInstanceTokenRetrieved(String token);
+ }
+} \ No newline at end of file
diff --git a/src/playstore/java/de/pixart/messenger/services/PushMessageReceiver.java b/src/playstore/java/de/pixart/messenger/services/PushMessageReceiver.java
new file mode 100644
index 000000000..c6d9b96be
--- /dev/null
+++ b/src/playstore/java/de/pixart/messenger/services/PushMessageReceiver.java
@@ -0,0 +1,39 @@
+package de.pixart.messenger.services;
+
+import android.content.Intent;
+import android.util.Log;
+
+import com.google.firebase.messaging.FirebaseMessagingService;
+import com.google.firebase.messaging.RemoteMessage;
+
+import java.util.Map;
+
+import de.pixart.messenger.Config;
+import de.pixart.messenger.utils.Compatibility;
+
+public class PushMessageReceiver extends FirebaseMessagingService {
+
+ @Override
+ public void onMessageReceived(RemoteMessage message) {
+ if (!EventReceiver.hasEnabledAccounts(this)) {
+ Log.d(Config.LOGTAG, "PushMessageReceiver ignored message because no accounts are enabled");
+ return;
+ }
+ final Map<String, String> data = message.getData();
+ final Intent intent = new Intent(this, XmppConnectionService.class);
+ intent.setAction(XmppConnectionService.ACTION_FCM_MESSAGE_RECEIVED);
+ intent.putExtra("account", data.get("account"));
+ Compatibility.startService(this, intent);
+ }
+
+ @Override
+ public void onNewToken(String token) {
+ if (!EventReceiver.hasEnabledAccounts(this)) {
+ Log.d(Config.LOGTAG, "PushMessageReceiver ignored new token because no accounts are enabled");
+ return;
+ }
+ final Intent intent = new Intent(this, XmppConnectionService.class);
+ intent.setAction(XmppConnectionService.ACTION_FCM_TOKEN_REFRESH);
+ Compatibility.startService(this, intent);
+ }
+} \ No newline at end of file
diff --git a/src/playstore/java/de/pixart/messenger/ui/widget/EmojiWrapperEditText.java b/src/playstore/java/de/pixart/messenger/ui/widget/EmojiWrapperEditText.java
new file mode 100644
index 000000000..662669fa3
--- /dev/null
+++ b/src/playstore/java/de/pixart/messenger/ui/widget/EmojiWrapperEditText.java
@@ -0,0 +1,17 @@
+package de.pixart.messenger.ui.widget;
+
+import android.content.Context;
+import android.util.AttributeSet;
+
+import androidx.appcompat.widget.AppCompatEditText;
+
+public class EmojiWrapperEditText extends AppCompatEditText {
+
+ public EmojiWrapperEditText(Context context) {
+ super(context);
+ }
+
+ public EmojiWrapperEditText(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+} \ No newline at end of file