add app-side support for firebase messaging

Works for xw4d variant only so far -- xw4 builds are broken!!!
This commit is contained in:
Eric House 2019-01-24 18:08:36 -08:00
parent 305f45dfc0
commit 6ecfd2f20b
16 changed files with 347 additions and 48 deletions

View file

@ -22,12 +22,12 @@ def CURTAG = "git describe --exact-match".execute().text.trim()
apply plugin: 'com.android.application'
if ( FABRIC_API_KEY && hasProperty('useCrashlytics') ) {
apply plugin: 'io.fabric'
}
if ( FABRIC_API_KEY && hasProperty('useCrashlytics') ) { // rm-for-fdroid
apply plugin: 'io.fabric' // rm-for-fdroid
} // rm-for-fdroid
repositories {
google()
maven { url 'https://maven.fabric.io/public' }
maven { url 'https://maven.fabric.io/public' } // rm-for-fdroid
}
android {
@ -210,9 +210,12 @@ dependencies {
// 2.6.8 is probably as far forward as I can go without upping my
// min-supported SDK version
xw4dImplementation('com.crashlytics.sdk.android:crashlytics:2.6.3@aar') {
transitive = true;
}
xw4dImplementation('com.crashlytics.sdk.android:crashlytics:2.6.3@aar') { // rm-for-fdroid
transitive = true; // rm-for-fdroid
} // rm-for-fdroid
implementation 'com.google.firebase:firebase-messaging:17.3.4' // rm-for-fdroid
implementation 'com.google.firebase:firebase-core:16.0.6' // rm-for-fdroid
}
task mkImages(type: Exec) {
@ -308,3 +311,5 @@ task makeBuildAssets() {
gradle.projectsEvaluated {
build.dependsOn(makeBuildAssets)
}
apply plugin: 'com.google.gms.google-services' // rm-for-fdroid

View file

@ -228,5 +228,11 @@
</intent-filter>
</receiver>
<service android:name="FBMService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
</application>
</manifest>

View file

@ -35,8 +35,8 @@ public class DevID {
private static final String TAG = DevID.class.getSimpleName();
private static final String DEVID_KEY = "DevID.devid_key";
private static final String DEVID_ACK_KEY = "key_relay_regid_ackd";
private static final String GCM_REGVERS_KEY = "key_gcmvers_regid";
private static final String DEVID_ACK_KEY = "key_relay_regid_ackd2";
private static final String FCM_REGVERS_KEY = "key_fcmvers_regid";
private static String s_relayDevID;
private static int s_asInt;
@ -111,10 +111,10 @@ public class DevID {
// DbgUtils.printStack();
}
public static void setGCMDevID( Context context, String devID )
public static void setFCMDevID( Context context, String devID )
{
int curVers = Utils.getAppVersion( context );
DBUtils.setIntFor( context, GCM_REGVERS_KEY, curVers );
DBUtils.setIntFor( context, FCM_REGVERS_KEY, curVers );
DBUtils.setBoolFor( context, DEVID_ACK_KEY, false );
}

View file

@ -28,11 +28,12 @@ import android.os.Handler;
import android.support.v4.app.JobIntentService;
import android.text.TextUtils;
import org.eehouse.android.xw4.FBMService;
import org.eehouse.android.xw4.GameUtils.BackMoveResult;
import org.eehouse.android.xw4.MultiService.DictFetchOwner;
import org.eehouse.android.xw4.MultiService.MultiEvent;
import org.eehouse.android.xw4.jni.CommsAddrRec;
import org.eehouse.android.xw4.jni.CommsAddrRec.CommsConnType;
import org.eehouse.android.xw4.jni.CommsAddrRec;
import org.eehouse.android.xw4.jni.DUtilCtxt.DevIDType;
import org.eehouse.android.xw4.jni.XwJNI;
import org.eehouse.android.xw4.loc.LocUtils;
@ -152,16 +153,16 @@ public class RelayService extends JobIntentService
XWPDEV_GOTINVITE, // test without this!!!
};
public static void gcmConfirmed( Context context, boolean confirmed )
public static void fcmConfirmed( Context context, boolean working )
{
if ( s_gcmWorking != confirmed ) {
Log.i( TAG, "gcmConfirmed(): changing s_gcmWorking to %b",
confirmed );
s_gcmWorking = confirmed;
if ( s_gcmWorking != working ) {
Log.i( TAG, "fcmConfirmed(): changing s_gcmWorking to %b",
working );
s_gcmWorking = working;
}
// If we've gotten a GCM id and haven't registered it, do so!
if ( confirmed && !s_curType.equals( DevIDType.ID_TYPE_ANDROID_GCM ) ) {
if ( working && !s_curType.equals( DevIDType.ID_TYPE_ANDROID_FCM ) ) {
s_regStartTime = 0; // so we're sure to register
devIDChanged();
timerFired( context );
@ -732,7 +733,7 @@ public class RelayService extends JobIntentService
long now = Utils.getCurSeconds();
long interval = now - s_regStartTime;
if ( interval < REG_WAIT_INTERVAL ) {
Log.i( TAG, "registerWithRelay: skipping because only %d "
Log.i( TAG, "registerWithRelay(): skipping because only %d "
+ "seconds since last start", interval );
} else {
String relayID = DevID.getRelayDevID( this );
@ -920,9 +921,9 @@ public class RelayService extends JobIntentService
if ( null != devid && 0 < devid.length() ) {
typ = DevIDType.ID_TYPE_RELAY;
} else {
devid = DevID.getGCMDevID( this );
devid = FBMService.getFCMDevID( this );
if ( null != devid && 0 < devid.length() ) {
typ = DevIDType.ID_TYPE_ANDROID_GCM;
typ = DevIDType.ID_TYPE_ANDROID_FCM;
} else {
devid = "";
typ = DevIDType.ID_TYPE_ANON;
@ -1624,7 +1625,7 @@ public class RelayService extends JobIntentService
private boolean shouldMaintainConnection()
{
boolean result = relayEnabled( this )
&& (!s_gcmWorking || XWPrefs.getIgnoreGCM( this ));
&& (!s_gcmWorking || XWPrefs.getIgnoreFCM( this ));
if ( result ) {
long interval = Utils.getCurSeconds() - m_lastGamePacketReceived;

View file

@ -90,6 +90,7 @@ public class XWApp extends Application implements LifecycleObserver {
UpdateCheckReceiver.restartTimer( this );
RelayService.startService( this );
FBMService.init( this );
WiDirWrapper.init( this );
}

View file

@ -66,14 +66,14 @@ public class XWPrefs {
return getPrefsBoolean( context, R.string.key_enable_nfc_toself, false );
}
public static boolean getIgnoreGCM( Context context )
public static boolean getIgnoreFCM( Context context )
{
return getPrefsBoolean( context, R.string.key_ignore_gcm, false );
return getPrefsBoolean( context, R.string.key_ignore_fcm, false );
}
public static boolean getToastGCM( Context context )
public static boolean getToastFCM( Context context )
{
return getPrefsBoolean( context, R.string.key_show_gcm, false );
return getPrefsBoolean( context, R.string.key_show_fcm, false );
}
public static boolean getSMSToSelfEnabled( Context context )

View file

@ -24,11 +24,12 @@ import android.content.Context;
import android.telephony.PhoneNumberUtils;
import org.eehouse.android.xw4.Assert;
import org.eehouse.android.xw4.XWApp;
import org.eehouse.android.xw4.DBUtils;
import org.eehouse.android.xw4.DevID;
import org.eehouse.android.xw4.R;
import org.eehouse.android.xw4.FBMService;
import org.eehouse.android.xw4.Log;
import org.eehouse.android.xw4.R;
import org.eehouse.android.xw4.XWApp;
import org.eehouse.android.xw4.loc.LocUtils;
public class DUtilCtxt {
@ -40,13 +41,14 @@ public class DUtilCtxt {
m_context = XWApp.getContext();
}
// Possible values for typ[0], these must match enum in xwrelay.sh
// Possible values for typ[0], these must match enum in xwrelay.h
public enum DevIDType { ID_TYPE_NONE
, ID_TYPE_RELAY
, ID_TYPE_LINUX
, ID_TYPE_ANDROID_GCM
, ID_TYPE_ANDROID_OTHER
, ID_TYPE_ANON
, ID_TYPE_RELAY
, ID_TYPE_LINUX
, ID_TYPE_ANDROID_GCM_UNUSED // 3
, ID_TYPE_ANDROID_OTHER
, ID_TYPE_ANON
, ID_TYPE_ANDROID_FCM // 6
}
public String getDevID( /*out*/ byte[] typa )
@ -56,11 +58,11 @@ public class DUtilCtxt {
if ( null != result ) {
typ = DevIDType.ID_TYPE_RELAY;
} else {
result = DevID.getGCMDevID( m_context );
result = FBMService.getFCMDevID( m_context );
if ( result.equals("") ) {
result = null;
} else {
typ = DevIDType.ID_TYPE_ANDROID_GCM;
typ = DevIDType.ID_TYPE_ANDROID_FCM;
}
}
typa[0] = (byte)typ.ordinal();

View file

@ -126,8 +126,8 @@
<string name="key_enable_nfc_toself">key_enable_nfc_toself</string>
<string name="key_enable_sms_toself">key_enable_sms_toself</string>
<string name="key_enable_smsproto">key_enable_smsproto</string>
<string name="key_ignore_gcm">key_ignore_gcm</string>
<string name="key_show_gcm">key_show_gcm</string>
<string name="key_ignore_fcm">key_ignore_fcm</string>
<string name="key_show_fcm">key_show_fcm</string>
<string name="key_nag_intervals">key_nag_intervals</string>
<string name="key_download_path">key_download_path</string>
<string name="key_got_langdict">key_got_langdict</string>

View file

@ -2639,11 +2639,11 @@
devices and I think it\'s rare that people play with more than
two. Let me know if I\'m wrong and I\'ll up the priority.</string>
<string name="ignore_gcm_title">Ignore incoming GCM messages</string>
<string name="ignore_gcm_summary">Mimic life without a google account</string>
<string name="ignore_fcm_title">Ignore incoming FCM messages</string>
<string name="ignore_fcm_summary">Mimic life without a google account</string>
<string name="show_sms_title">Show SMS sends, receives</string>
<string name="show_gcm_title">Show GCM receives</string>
<string name="show_fcm_title">Show FCM receives</string>
<!-- Shown after "resend messages" menuitem chosen -->
<plurals name="resent_msgs_fmt">

View file

@ -393,13 +393,13 @@
<PreferenceScreen android:title="@string/pref_group_relay_title"
android:summary="@string/pref_group_relay_summary"
>
<CheckBoxPreference android:key="@string/key_ignore_gcm"
android:title="@string/ignore_gcm_title"
android:summary="@string/ignore_gcm_summary"
<CheckBoxPreference android:key="@string/key_ignore_fcm"
android:title="@string/ignore_fcm_title"
android:summary="@string/ignore_fcm_summary"
android:defaultValue="false"
/>
<CheckBoxPreference android:key="@string/key_show_gcm"
android:title="@string/show_gcm_title"
<CheckBoxPreference android:key="@string/key_show_fcm"
android:title="@string/show_fcm_title"
android:defaultValue="false"
/>
<org.eehouse.android.xw4.XWEditTextPreference

View file

@ -0,0 +1,169 @@
/* -*- compile-command: "find-and-gradle.sh -PuseCrashlytics insXw4dDeb"; -*- */
/*
* Copyright 2019 by Eric House (xwords@eehouse.org). All rights reserved.
*
* 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 2 of the
* License, or (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.eehouse.android.xw4;
import android.content.Context;
import android.content.Intent;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.iid.InstanceIdResult;
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
import org.json.JSONArray;
import java.util.Map;
public class FBMService extends FirebaseMessagingService {
private static final String TAG = FBMService.class.getSimpleName();
private static final String KEY_FCMID = TAG + "_fcmid";
public static void init( Context context )
{
Log.d( TAG, "init()" );
getTokenAsync( context );
}
@Override
public void onNewToken( String token )
{
Log.d( TAG, "onNewToken(%s)", token);
onGotToken( this, token );
}
@Override
public void onMessageReceived( RemoteMessage message )
{
if ( XWPrefs.getIgnoreFCM( this ) ) {
Log.d( TAG, "onMessageReceived(): ignoring" );
} else {
RelayService.fcmConfirmed( this, true );
Map<String, String> data = message.getData();
Log.d( TAG, "onMessageReceived(data=%s)", data );
boolean toastFCM = XWPrefs.getToastFCM( this );
String value = data.get( "msgs64" );
if ( null != value ) {
String connname = data.get( "connname" );
try {
JSONArray msgs64 = new JSONArray( value );
String[] strs64 = new String[msgs64.length()];
if ( toastFCM ) {
DbgUtils.showf( this, "onMessage(): got %d msgs",
strs64.length );
}
for ( int ii = 0; ii < strs64.length; ++ii ) {
strs64[ii] = msgs64.optString(ii);
}
if ( null == connname ) {
RelayService.processDevMsgs( this, strs64 );
} else {
RelayService.processGameMsgs( this, connname, strs64 );
}
} catch (org.json.JSONException jse ) {
Log.ex( TAG, jse );
Assert.assertFalse( BuildConfig.DEBUG );
}
}
value = data.get( "checkUpdates" );
if ( null != value && Boolean.parseBoolean( value ) ) {
UpdateCheckReceiver.checkVersions( this, true );
}
value = data.get( "getMoves" );
if ( null != value && Boolean.parseBoolean( value ) ) {
RelayService.timerFired( this );
if ( toastFCM ) {
DbgUtils.showf( this, "onMessage(): got 'getMoves'" );
}
}
value = data.get( "msg" );
if ( null != value ) {
String title = data.get( "title" );
if ( null != title ) {
String teaser = data.get( "teaser" );
if ( null == teaser ) {
teaser = value;
}
Intent alertIntent = GamesListDelegate
.makeAlertIntent( this, value );
int code = value.hashCode() ^ title.hashCode();
Utils.postNotification( this, alertIntent, title,
teaser, code );
}
}
}
}
public static String getFCMDevID( Context context )
{
String result = DBUtils.getStringFor( context, KEY_FCMID, null );
if ( null == result ) {
getTokenAsync( context );
}
Log.d( TAG, "getFCMDevID() => %s", result );
return result;
}
private static void getTokenAsync( final Context context )
{
FirebaseInstanceId.getInstance().getInstanceId()
.addOnCompleteListener(new OnCompleteListener<InstanceIdResult>() {
@Override
public void onComplete(Task<InstanceIdResult> task) {
if (!task.isSuccessful()) {
Log.w(TAG, "getInstanceId failed: %s", task.getException());
if ( !XWPrefs.getIgnoreFCM( context ) ) {
RelayService.fcmConfirmed( context, false );
}
} else {
// Get new Instance ID token
String token = task.getResult().getToken();
// Log and toast
Log.d(TAG, "got token!: %s", token );
onGotToken( context, token );
}
}
});
}
private static void onGotToken( Context context, String token )
{
// Don't call this with empty tokens!!!
Assert.assertTrue( token.length() > 0 || !BuildConfig.DEBUG );
DBUtils.setStringFor( context, KEY_FCMID, token );
DevID.setFCMDevID( context, token );
if ( !XWPrefs.getIgnoreFCM( context ) ) {
RelayService.fcmConfirmed( context, true );
}
}
}

View file

@ -0,0 +1,73 @@
{
"project_info": {
"project_number": "801272813571",
"firebase_url": "https://fcmtest-9fe99.firebaseio.com",
"project_id": "fcmtest-9fe99",
"storage_bucket": "fcmtest-9fe99.appspot.com"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:801272813571:android:15f4eb80a9b07720",
"android_client_info": {
"package_name": "com.google.firebase.fiamquickstart"
}
},
"oauth_client": [
{
"client_id": "801272813571-g3lfciu89q8ffb7ahasrce5nj3vsghot.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyCl3lfUITEX0EscF2aeDZY4G-DNL2xeEZ8"
}
],
"services": {
"analytics_service": {
"status": 1
},
"appinvite_service": {
"status": 1,
"other_platform_oauth_client": []
},
"ads_service": {
"status": 2
}
}
},
{
"client_info": {
"mobilesdk_app_id": "1:801272813571:android:8c4ed916336414b2",
"android_client_info": {
"package_name": "org.eehouse.android.xw4dbg"
}
},
"oauth_client": [
{
"client_id": "801272813571-g3lfciu89q8ffb7ahasrce5nj3vsghot.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyCl3lfUITEX0EscF2aeDZY4G-DNL2xeEZ8"
}
],
"services": {
"analytics_service": {
"status": 1
},
"appinvite_service": {
"status": 1,
"other_platform_oauth_client": []
},
"ads_service": {
"status": 2
}
}
}
],
"configuration_version": "1"
}

View file

@ -0,0 +1 @@
../../../../../../xw4/java/org/eehouse/android/xw4/FBMService.java

View file

@ -0,0 +1,39 @@
/* -*- compile-command: "find-and-gradle.sh -PuseCrashlytics insXw4dDeb"; -*- */
/*
* Copyright 2019 by Eric House (xwords@eehouse.org). All rights reserved.
*
* 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 2 of the
* License, or (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.eehouse.android.xw4;
import android.content.Context;
import android.content.Intent;
public class FBMService {
private static final String TAG = FBMService.class.getSimpleName();
private static final String KEY_FCMID = TAG + "_fcmid";
public static void init( Context context )
{
Log.d( TAG, "init()" );
RelayService.fcmConfirmed( context, false );
}
public static String getFCMDevID( Context context )
{
return null;
}
}

View file

@ -4,12 +4,13 @@ buildscript {
repositories {
google()
jcenter()
maven { url 'https://maven.fabric.io/public' }
maven { url 'https://maven.fabric.io/public' } // rm-for-fdroid
}
dependencies {
classpath 'com.android.tools.build:gradle:3.1.2'
classpath 'io.fabric.tools:gradle:1.+'
classpath 'io.fabric.tools:gradle:1.+' // rm-for-fdroid
classpath 'com.google.gms:google-services:4.2.0' // google-services plugin
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}

View file

@ -206,6 +206,7 @@ typedef enum {
,ID_TYPE_ANDROID_GCM
,ID_TYPE_ANDROID_OTHER
,ID_TYPE_ANON /* please assign me one based on nothing */
,ID_TYPE_ANDROID_FCM
,ID_TYPE_NTYPES
} DevIDType;