From e61d7a5629029c78d347f714596c1a5fc0a7347d Mon Sep 17 00:00:00 2001 From: Eric House Date: Tue, 15 Jan 2019 13:56:31 -0800 Subject: [PATCH] remove GCM -- crashes when invoked from server! Once built for SDK 26 the old GCM support code crashes as it's calling startService() from background. Duh! Will have to bring in Firebase's replacement at some point. For now if I'm to release it has to be without GCM. --- xwords4/android/app/build.gradle | 11 +- .../java/org/eehouse/android/xw4/DevID.java | 35 ++-- .../java/org/eehouse/android/xw4/XWApp.java | 1 - .../android/app/src/xw4/AndroidManifest.xml | 26 --- .../eehouse/android/xw4/GCMIntentService.java | 166 ------------------ .../java/org/eehouse/android/xw4/GCMStub.java | 32 ---- .../java/org/eehouse/android/xw4/GCMStub.java | 29 --- .../java/org/eehouse/android/xw4/GCMStub.java | 1 - xwords4/android/libs/gcm.jar | Bin 13662 -> 0 bytes 9 files changed, 19 insertions(+), 282 deletions(-) delete mode 100644 xwords4/android/app/src/xw4/AndroidManifest.xml delete mode 100644 xwords4/android/app/src/xw4/java/org/eehouse/android/xw4/GCMIntentService.java delete mode 100644 xwords4/android/app/src/xw4/java/org/eehouse/android/xw4/GCMStub.java delete mode 100644 xwords4/android/app/src/xw4d/java/org/eehouse/android/xw4/GCMStub.java delete mode 120000 xwords4/android/app/src/xw4fdroid/java/org/eehouse/android/xw4/GCMStub.java delete mode 100644 xwords4/android/libs/gcm.jar diff --git a/xwords4/android/app/build.gradle b/xwords4/android/app/build.gradle index db8699c78..dbc2e49fe 100644 --- a/xwords4/android/app/build.gradle +++ b/xwords4/android/app/build.gradle @@ -2,7 +2,6 @@ def INITIAL_CLIENT_VERS = 8 def VERSION_CODE_BASE = 137 def VERSION_NAME = '4.4.141' def FABRIC_API_KEY = System.getenv("FABRIC_API_KEY") -def GCM_SENDER_ID = System.getenv("GCM_SENDER_ID") def BUILD_INFO_NAME = "build-info.txt" boolean forFDroid = hasProperty('forFDroid') @@ -69,6 +68,7 @@ android { buildConfigField "String", "BUILD_INFO_NAME", "\"${BUILD_INFO_NAME}\"" buildConfigField "boolean", "IS_TAGGED_BUILD", "${CURTAG}" == '' ? "false" : "true" resValue "string", "invite_prefix", "/and/" + buildConfigField "String", "GCM_SENDER_ID", "\"\"" } xw4 { @@ -79,8 +79,6 @@ android { resValue "string", "nbs_port", "3344" buildConfigField "boolean", "WIDIR_ENABLED", "false" buildConfigField "boolean", "RELAYINVITE_SUPPORTED", "false" - - buildConfigField "String", "GCM_SENDER_ID", "\"$GCM_SENDER_ID\"" } xw4fdroid { @@ -91,8 +89,6 @@ android { resValue "string", "nbs_port", "3344" buildConfigField "boolean", "WIDIR_ENABLED", "false" buildConfigField "boolean", "RELAYINVITE_SUPPORTED", "false" - - buildConfigField "String", "GCM_SENDER_ID", "\"\"" } xw4d { dimension "variant" @@ -102,8 +98,6 @@ android { resValue "string", "nbs_port", "3345" buildConfigField "boolean", "WIDIR_ENABLED", "true" buildConfigField "boolean", "RELAYINVITE_SUPPORTED", "true" - - buildConfigField "String", "GCM_SENDER_ID", "\"\"" } // WARNING: "all" breaks things. Seems to be a keyword. Need @@ -205,9 +199,6 @@ ext { } dependencies { - // Look into replacing this with a fetch too PENDING - xw4Implementation files('../libs/gcm.jar') - implementation "com.android.support:support-v4:$SUPPORT_LIB_VERSION" implementation "com.android.support:support-compat:$SUPPORT_LIB_VERSION" diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DevID.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DevID.java index 8a39bac03..57af827cb 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DevID.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DevID.java @@ -120,24 +120,25 @@ public class DevID { public static String getGCMDevID( Context context ) { - int curVers = Utils.getAppVersion( context ); - int storedVers = DBUtils.getIntFor( context, GCM_REGVERS_KEY, 0 ); - // TRANSITIONAL - if ( 0 == storedVers ) { - storedVers = XWPrefs.getPrefsInt( context, - R.string.key_gcmvers_regid, 0 ); - if ( 0 != storedVers ) { - DBUtils.setIntFor( context, GCM_REGVERS_KEY, storedVers ); - } - } + return ""; + // int curVers = Utils.getAppVersion( context ); + // int storedVers = DBUtils.getIntFor( context, GCM_REGVERS_KEY, 0 ); + // // TRANSITIONAL + // if ( 0 == storedVers ) { + // storedVers = XWPrefs.getPrefsInt( context, + // R.string.key_gcmvers_regid, 0 ); + // if ( 0 != storedVers ) { + // DBUtils.setIntFor( context, GCM_REGVERS_KEY, storedVers ); + // } + // } - String result; - if ( 0 != storedVers && storedVers < curVers ) { - result = ""; // Don't trust what registrar has - } else { - result = GCMStub.getRegistrationId( context ); - } - return result; + // String result; + // if ( 0 != storedVers && storedVers < curVers ) { + // result = ""; // Don't trust what registrar has + // } else { + // result = GCMStub.getRegistrationId( context ); + // } + // return result; } public static void clearGCMDevID( Context context ) diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWApp.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWApp.java index 7b4a7e75b..eaf31a49a 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWApp.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWApp.java @@ -90,7 +90,6 @@ public class XWApp extends Application implements LifecycleObserver { UpdateCheckReceiver.restartTimer( this ); RelayService.startService( this ); - GCMIntentService.init( this ); WiDirWrapper.init( this ); } diff --git a/xwords4/android/app/src/xw4/AndroidManifest.xml b/xwords4/android/app/src/xw4/AndroidManifest.xml deleted file mode 100644 index aff0f77bc..000000000 --- a/xwords4/android/app/src/xw4/AndroidManifest.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/xwords4/android/app/src/xw4/java/org/eehouse/android/xw4/GCMIntentService.java b/xwords4/android/app/src/xw4/java/org/eehouse/android/xw4/GCMIntentService.java deleted file mode 100644 index b5f75a606..000000000 --- a/xwords4/android/app/src/xw4/java/org/eehouse/android/xw4/GCMIntentService.java +++ /dev/null @@ -1,166 +0,0 @@ -/* -*- compile-command: "find-and-gradle.sh insXw4Deb"; -*- */ -/* - * Copyright 2012 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.app.Application; -import android.content.Context; -import android.content.Intent; - -import com.google.android.gcm.GCMBaseIntentService; -import com.google.android.gcm.GCMRegistrar; - -import org.json.JSONArray; - - -public class GCMIntentService extends GCMBaseIntentService { - private static final String TAG = GCMIntentService.class.getSimpleName(); - - private Boolean m_toastGCM; - - public GCMIntentService() - { - super( BuildConfig.GCM_SENDER_ID ); - Assert.assertTrue( BuildConfig.GCM_SENDER_ID.length() > 0 ); - } - - @Override - protected void onError( Context context, String error ) - { - Log.d( TAG, "onError(%s)", error ); - } - - @Override - protected void onRegistered( Context context, String regId ) - { - Log.d( TAG, "onRegistered(%s)", regId ); - DevID.setGCMDevID( context, regId ); - notifyRelayService( context, true ); - } - - @Override - protected void onUnregistered( Context context, String regId ) - { - Log.d( TAG, "onUnregistered(%s)", regId ); - DevID.clearGCMDevID( context ); - RelayService.devIDChanged(); - notifyRelayService( context, false ); - } - - @Override - protected void onMessage( Context context, Intent intent ) - { - Log.d( TAG, "onMessage()" ); - - if ( XWPrefs.getIgnoreGCM( context ) ) { - String logMsg = "received GCM but ignoring it"; - Log.d( TAG, logMsg ); - DbgUtils.showf( context, logMsg ); - } else { - boolean toastGCM = XWPrefs.getToastGCM( context ); - - notifyRelayService( context, true ); - - String value = intent.getStringExtra( "checkUpdates" ); - if ( null != value && Boolean.parseBoolean( value ) ) { - UpdateCheckReceiver.checkVersions( context, true ); - } - - value = intent.getStringExtra( "getMoves" ); - if ( null != value && Boolean.parseBoolean( value ) ) { - RelayService.timerFired( context ); - if ( toastGCM ) { - DbgUtils.showf( context, "%s.onMessage(): got 'getMoves'", - TAG ); - } - } - - value = intent.getStringExtra( "msgs64" ); - if ( null != value ) { - String connname = intent.getStringExtra( "connname" ); - try { - JSONArray msgs64 = new JSONArray( value ); - String[] strs64 = new String[msgs64.length()]; - if ( toastGCM ) { - DbgUtils.showf( context, "%s.onMessage(): got %d msgs", - TAG, strs64.length ); - } - - for ( int ii = 0; ii < strs64.length; ++ii ) { - strs64[ii] = msgs64.optString(ii); - } - if ( null == connname ) { - RelayService.processDevMsgs( context, strs64 ); - } else { - RelayService.processGameMsgs( context, connname, strs64 ); - } - } catch (org.json.JSONException jse ) { - Log.ex( TAG, jse ); - Assert.assertFalse( BuildConfig.DEBUG ); - } - } - - value = intent.getStringExtra( "msg" ); - if ( null != value ) { - String title = intent.getStringExtra( "title" ); - if ( null != title ) { - String teaser = intent.getStringExtra( "teaser" ); - if ( null == teaser ) { - teaser = value; - } - Intent alertIntent = GamesListDelegate - .makeAlertIntent( this, value ); - int code = value.hashCode() ^ title.hashCode(); - Utils.postNotification( context, alertIntent, title, - teaser, code ); - } - } - } - } - - public static void init( Application app ) - { - if ( 0 < BuildConfig.GCM_SENDER_ID.length() ) { - int sdkVersion = Integer.valueOf( android.os.Build.VERSION.SDK ); - if ( 8 <= sdkVersion ) { - try { - GCMRegistrar.checkDevice( app ); - // GCMRegistrar.checkManifest( app ); - String regId = DevID.getGCMDevID( app ); - if ( regId.equals("") ) { - GCMRegistrar.register( app, BuildConfig.GCM_SENDER_ID ); - } - } catch ( UnsupportedOperationException uoe ) { - Log.w( TAG, "Device can't do GCM." ); - } catch ( Exception whatever ) { - // funky devices could do anything - Log.ex( TAG, whatever ); - } - } - } - } - - private void notifyRelayService( Context context, boolean working ) - { - if ( !XWPrefs.getIgnoreGCM( context ) ) { - RelayService.gcmConfirmed( context, working ); - } - } -} diff --git a/xwords4/android/app/src/xw4/java/org/eehouse/android/xw4/GCMStub.java b/xwords4/android/app/src/xw4/java/org/eehouse/android/xw4/GCMStub.java deleted file mode 100644 index 1fcc593be..000000000 --- a/xwords4/android/app/src/xw4/java/org/eehouse/android/xw4/GCMStub.java +++ /dev/null @@ -1,32 +0,0 @@ -/* -*- compile-command: "find-and-gradle.sh insXw4Deb"; -*- */ -/* - * Copyright 2010 - 2015 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 com.google.android.gcm.GCMRegistrar; - -class GCMStub { - - public static String getRegistrationId( Context context ) - { - return GCMRegistrar.getRegistrationId( context ); - } -} diff --git a/xwords4/android/app/src/xw4d/java/org/eehouse/android/xw4/GCMStub.java b/xwords4/android/app/src/xw4d/java/org/eehouse/android/xw4/GCMStub.java deleted file mode 100644 index 94e61ed2c..000000000 --- a/xwords4/android/app/src/xw4d/java/org/eehouse/android/xw4/GCMStub.java +++ /dev/null @@ -1,29 +0,0 @@ -/* -*- compile-command: "find-and-gradle.sh insXw4dDeb"; -*- */ -/* - * Copyright 2017 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; - -class GCMStub { - public static String getRegistrationId( Context context ) - { - return ""; - } -} diff --git a/xwords4/android/app/src/xw4fdroid/java/org/eehouse/android/xw4/GCMStub.java b/xwords4/android/app/src/xw4fdroid/java/org/eehouse/android/xw4/GCMStub.java deleted file mode 120000 index d409e129f..000000000 --- a/xwords4/android/app/src/xw4fdroid/java/org/eehouse/android/xw4/GCMStub.java +++ /dev/null @@ -1 +0,0 @@ -../../../../../../xw4d/java/org/eehouse/android/xw4/GCMStub.java \ No newline at end of file diff --git a/xwords4/android/libs/gcm.jar b/xwords4/android/libs/gcm.jar deleted file mode 100644 index ac109a830ebe95e89e1456e23328212ad70576dc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13662 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 K2s`$_e*GU@T3ng{