Revision a59f38d6
Added by Leszek Koltunski over 3 years ago
| build.gradle | ||
|---|---|---|
| 37 | 37 |
api project(':distorted-objectlib')
|
| 38 | 38 |
api project(':distorted-flags')
|
| 39 | 39 |
|
| 40 |
implementation 'com.google.firebase:firebase-analytics:21.0.0' |
|
| 41 |
implementation 'com.google.firebase:firebase-crashlytics:18.2.11' |
|
| 40 |
implementation platform('com.google.firebase:firebase-bom:30.2.0')
|
|
| 41 |
implementation 'com.google.firebase:firebase-messaging' |
|
| 42 |
implementation 'com.google.firebase:firebase-analytics' |
|
| 43 |
implementation 'com.google.firebase:firebase-crashlytics' |
|
| 44 |
implementation 'com.google.firebase:firebase-inappmessaging-display' |
|
| 42 | 45 |
implementation 'com.google.android.play:core:1.10.3' |
| 43 | 46 |
implementation 'androidx.appcompat:appcompat:1.4.2' |
| 47 |
implementation "androidx.work:work-runtime:2.7.1" |
|
| 44 | 48 |
implementation 'com.google.android.material:material:1.6.1' |
| 45 | 49 |
implementation project(path: ':distorted-puzzle-jsons') |
| 46 | 50 |
implementation project(path: ':distorted-puzzle-dmesh') |
| src/main/AndroidManifest.xml | ||
|---|---|---|
| 32 | 32 |
<activity android:name="org.distorted.config.ConfigActivity" android:exported="false" android:screenOrientation="portrait"/> |
| 33 | 33 |
<activity android:name="org.distorted.bandaged.BandagedCreatorActivity" android:exported="false" android:screenOrientation="portrait"/> |
| 34 | 34 |
<activity android:name="org.distorted.bandaged.BandagedPlayActivity" android:exported="false" android:screenOrientation="portrait"/> |
| 35 |
|
|
| 36 |
<service |
|
| 37 |
android:name="org.distorted.messaging.RubikMessagingService" |
|
| 38 |
android:exported="false"> |
|
| 39 |
<intent-filter> |
|
| 40 |
<action android:name="com.google.firebase.MESSAGING_EVENT" /> |
|
| 41 |
</intent-filter> |
|
| 42 |
</service> |
|
| 35 | 43 |
</application> |
| 36 | 44 |
</manifest> |
| src/main/java/org/distorted/external/RubikNetwork.java | ||
|---|---|---|
| 116 | 116 |
"%f8", "%f9", "%fa", "%fb", "%fc", "%fd", "%fe", "%ff" |
| 117 | 117 |
}; |
| 118 | 118 |
|
| 119 |
private static final String SERVER="https://distorted.org/magic/cgi-bin/"; |
|
| 120 |
|
|
| 119 | 121 |
private static String[][][] mCountry; |
| 120 | 122 |
private static String[][][] mName; |
| 121 | 123 |
private static float[][][] mTime; |
| ... | ... | |
| 440 | 442 |
private String constructSuspiciousURL(String suspURL) |
| 441 | 443 |
{
|
| 442 | 444 |
RubikScores scores = RubikScores.getInstance(); |
| 443 |
int deviceID= scores.getDeviceID(); |
|
| 444 |
String suspicious = URLencode(suspURL); |
|
| 445 |
int deviceID = scores.getDeviceID();
|
|
| 446 |
String suspicious = URLencode(suspURL);
|
|
| 445 | 447 |
|
| 446 |
String url="https://distorted.org/magic/cgi-bin/suspicious.cgi";
|
|
| 447 |
url += "?i="+deviceID+"&d="+suspicious;
|
|
| 448 |
return SERVER+"suspicious.cgi?i="+deviceID+"&d="+suspicious;
|
|
| 449 |
}
|
|
| 448 | 450 |
|
| 449 |
return url; |
|
| 451 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 452 |
|
|
| 453 |
private String constructTokenURL(String token) |
|
| 454 |
{
|
|
| 455 |
RubikScores scores = RubikScores.getInstance(); |
|
| 456 |
String name = URLencode(scores.getName()); |
|
| 457 |
int deviceID= scores.getDeviceID(); |
|
| 458 |
String country = scores.getCountry(); |
|
| 459 |
String version = mVersion==null ? "null" : mVersion; |
|
| 460 |
String tkn = URLencode(token); |
|
| 461 |
|
|
| 462 |
return SERVER+"token.cgi?n="+name+"&i="+deviceID+"&e="+version+"&c="+country+"&t="+tkn; |
|
| 450 | 463 |
} |
| 451 | 464 |
|
| 452 | 465 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| ... | ... | |
| 466 | 479 |
renderer = URLencode(renderer); |
| 467 | 480 |
version = URLencode(version); |
| 468 | 481 |
|
| 469 |
String url="https://distorted.org/magic/cgi-bin/debugs.cgi";
|
|
| 482 |
String url=SERVER+"debugs.cgi";
|
|
| 470 | 483 |
url += "?n="+name+"&r="+numRuns+"&p="+numPlay+"&c="+country+"&e="+mVersion+"d"; |
| 471 | 484 |
url += "&d="+renderer+"&v="+version+"&a="+objectAPI+"&b="+tutorialAPI; |
| 472 | 485 |
|
| ... | ... | |
| 483 | 496 |
int numPlay = scores.getNumPlays(); |
| 484 | 497 |
String country = scores.getCountry(); |
| 485 | 498 |
|
| 486 |
String url="https://distorted.org/magic/cgi-bin/download.cgi"; |
|
| 487 |
url += "?n="+name+"&r="+numRuns+"&p="+numPlay+"&c="+country+"&e="+mVersion; |
|
| 488 |
|
|
| 489 |
return url; |
|
| 499 |
return SERVER+"download.cgi?n="+name+"&r="+numRuns+"&p="+numPlay+"&c="+country+"&e="+mVersion; |
|
| 490 | 500 |
} |
| 491 | 501 |
|
| 492 | 502 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| ... | ... | |
| 511 | 521 |
renderer = parseRenderer(type,renderer); |
| 512 | 522 |
version = parseVersion(type,version); |
| 513 | 523 |
|
| 514 |
String url1="https://distorted.org/magic/cgi-bin/submit.cgi";
|
|
| 524 |
String url1=SERVER+"submit.cgi";
|
|
| 515 | 525 |
String url2 = "n="+name+"&v="+veri+"&r="+numRuns+"&p="+numPlay+"&i="+deviceID+"&e="+mVersion; |
| 516 | 526 |
url2 += "&d="+renderer+"&s="+version+reclist+"&c="+country+"&f="+epoch; |
| 517 | 527 |
String hash = computeHash( url2, salt.getBytes() ); |
| ... | ... | |
| 670 | 680 |
} |
| 671 | 681 |
} |
| 672 | 682 |
|
| 683 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 684 |
|
|
| 685 |
private void tokenThread(String token) |
|
| 686 |
{
|
|
| 687 |
String url = constructTokenURL(token); |
|
| 688 |
|
|
| 689 |
try |
|
| 690 |
{
|
|
| 691 |
java.net.URL connectURL = new URL(url); |
|
| 692 |
HttpURLConnection conn = (HttpURLConnection)connectURL.openConnection(); |
|
| 693 |
|
|
| 694 |
conn.setDoInput(true); |
|
| 695 |
conn.setDoOutput(true); |
|
| 696 |
conn.setUseCaches(false); |
|
| 697 |
conn.setRequestMethod("GET");
|
|
| 698 |
conn.connect(); |
|
| 699 |
conn.getOutputStream().flush(); |
|
| 700 |
conn.getInputStream(); |
|
| 701 |
conn.disconnect(); |
|
| 702 |
} |
|
| 703 |
catch( final Exception e ) |
|
| 704 |
{
|
|
| 705 |
// ignore |
|
| 706 |
} |
|
| 707 |
} |
|
| 708 |
|
|
| 673 | 709 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| 674 | 710 |
|
| 675 | 711 |
private Bitmap downloadIcon(String url) |
| ... | ... | |
| 900 | 936 |
thread.start(); |
| 901 | 937 |
} |
| 902 | 938 |
|
| 939 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 940 |
|
|
| 941 |
public void token(final String token) |
|
| 942 |
{
|
|
| 943 |
initializeStatics(); |
|
| 944 |
|
|
| 945 |
Thread thread = new Thread() |
|
| 946 |
{
|
|
| 947 |
public void run() |
|
| 948 |
{
|
|
| 949 |
tokenThread(token); |
|
| 950 |
} |
|
| 951 |
}; |
|
| 952 |
|
|
| 953 |
thread.start(); |
|
| 954 |
} |
|
| 955 |
|
|
| 903 | 956 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| 904 | 957 |
// Yes it can happen that the second Updatee registers before we sent an update to the first one |
| 905 | 958 |
// and, as a result, the update never gets sent to the first one. This is not a problem (now, when |
| src/main/java/org/distorted/main/RubikActivity.java | ||
|---|---|---|
| 41 | 41 |
import androidx.appcompat.app.AppCompatActivity; |
| 42 | 42 |
|
| 43 | 43 |
import com.google.firebase.analytics.FirebaseAnalytics; |
| 44 |
import com.google.firebase.inappmessaging.FirebaseInAppMessaging; |
|
| 44 | 45 |
|
| 45 | 46 |
import org.distorted.config.ConfigActivity; |
| 46 | 47 |
import org.distorted.bandaged.BandagedCreatorActivity; |
| 47 | 48 |
import org.distorted.library.main.DistortedLibrary; |
| 48 | 49 |
|
| 50 |
import org.distorted.messaging.RubikInAppMessanging; |
|
| 49 | 51 |
import org.distorted.objectlib.main.ObjectControl; |
| 50 | 52 |
import org.distorted.objectlib.main.TwistyObject; |
| 51 | 53 |
import org.distorted.objectlib.effects.BaseEffect; |
| ... | ... | |
| 134 | 136 |
hideNavigationBar(); |
| 135 | 137 |
cutoutHack(); |
| 136 | 138 |
computeBarHeights(); |
| 139 |
|
|
| 140 |
RubikInAppMessanging listener = new RubikInAppMessanging(); |
|
| 141 |
FirebaseInAppMessaging.getInstance().addClickListener(listener); |
|
| 137 | 142 |
} |
| 138 | 143 |
|
| 139 | 144 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| src/main/java/org/distorted/messaging/RubikInAppMessanging.java | ||
|---|---|---|
| 1 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 2 |
// Copyright 2022 Leszek Koltunski // |
|
| 3 |
// // |
|
| 4 |
// This file is part of Magic Cube. // |
|
| 5 |
// // |
|
| 6 |
// Magic Cube is free software: you can redistribute it and/or modify // |
|
| 7 |
// it under the terms of the GNU General Public License as published by // |
|
| 8 |
// the Free Software Foundation, either version 2 of the License, or // |
|
| 9 |
// (at your option) any later version. // |
|
| 10 |
// // |
|
| 11 |
// Magic Cube is distributed in the hope that it will be useful, // |
|
| 12 |
// but WITHOUT ANY WARRANTY; without even the implied warranty of // |
|
| 13 |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // |
|
| 14 |
// GNU General Public License for more details. // |
|
| 15 |
// // |
|
| 16 |
// You should have received a copy of the GNU General Public License // |
|
| 17 |
// along with Magic Cube. If not, see <http://www.gnu.org/licenses/>. // |
|
| 18 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 19 |
|
|
| 20 |
package org.distorted.messaging; |
|
| 21 |
|
|
| 22 |
import com.google.firebase.inappmessaging.FirebaseInAppMessagingClickListener; |
|
| 23 |
import com.google.firebase.inappmessaging.model.Action; |
|
| 24 |
import com.google.firebase.inappmessaging.model.CampaignMetadata; |
|
| 25 |
import com.google.firebase.inappmessaging.model.InAppMessage; |
|
| 26 |
|
|
| 27 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 28 |
|
|
| 29 |
public class RubikInAppMessanging implements FirebaseInAppMessagingClickListener |
|
| 30 |
{
|
|
| 31 |
@Override |
|
| 32 |
public void messageClicked(InAppMessage inAppMessage, Action action) |
|
| 33 |
{
|
|
| 34 |
// Determine which URL the user clicked |
|
| 35 |
String url = action.getActionUrl(); |
|
| 36 |
|
|
| 37 |
android.util.Log.e("D", "In App Messaging: url="+url);
|
|
| 38 |
|
|
| 39 |
// Get general information about the campaign |
|
| 40 |
CampaignMetadata metadata = inAppMessage.getCampaignMetadata(); |
|
| 41 |
|
|
| 42 |
if( metadata!=null ) |
|
| 43 |
{
|
|
| 44 |
String id = metadata.getCampaignId(); |
|
| 45 |
String name = metadata.getCampaignName(); |
|
| 46 |
boolean test = metadata.getIsTestMessage(); |
|
| 47 |
android.util.Log.e("D", "In App Messaging: id="+id+" name="+name+" test="+test);
|
|
| 48 |
} |
|
| 49 |
|
|
| 50 |
} |
|
| 51 |
} |
|
| src/main/java/org/distorted/messaging/RubikMessagingService.java | ||
|---|---|---|
| 1 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 2 |
// Copyright 2022 Leszek Koltunski // |
|
| 3 |
// // |
|
| 4 |
// This file is part of Magic Cube. // |
|
| 5 |
// // |
|
| 6 |
// Magic Cube is free software: you can redistribute it and/or modify // |
|
| 7 |
// it under the terms of the GNU General Public License as published by // |
|
| 8 |
// the Free Software Foundation, either version 2 of the License, or // |
|
| 9 |
// (at your option) any later version. // |
|
| 10 |
// // |
|
| 11 |
// Magic Cube is distributed in the hope that it will be useful, // |
|
| 12 |
// but WITHOUT ANY WARRANTY; without even the implied warranty of // |
|
| 13 |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // |
|
| 14 |
// GNU General Public License for more details. // |
|
| 15 |
// // |
|
| 16 |
// You should have received a copy of the GNU General Public License // |
|
| 17 |
// along with Magic Cube. If not, see <http://www.gnu.org/licenses/>. // |
|
| 18 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 19 |
|
|
| 20 |
package org.distorted.messaging; |
|
| 21 |
|
|
| 22 |
import android.content.Context; |
|
| 23 |
import android.util.Log; |
|
| 24 |
|
|
| 25 |
import androidx.annotation.NonNull; |
|
| 26 |
|
|
| 27 |
import androidx.work.OneTimeWorkRequest; |
|
| 28 |
import androidx.work.WorkManager; |
|
| 29 |
import androidx.work.Worker; |
|
| 30 |
import androidx.work.WorkerParameters; |
|
| 31 |
|
|
| 32 |
import com.google.firebase.messaging.FirebaseMessagingService; |
|
| 33 |
import com.google.firebase.messaging.RemoteMessage; |
|
| 34 |
|
|
| 35 |
import org.distorted.external.RubikNetwork; |
|
| 36 |
|
|
| 37 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 38 |
|
|
| 39 |
public class RubikMessagingService extends FirebaseMessagingService |
|
| 40 |
{
|
|
| 41 |
private static final String TAG = "RubikMessagingService"; |
|
| 42 |
|
|
| 43 |
public static class RubikWorker extends Worker |
|
| 44 |
{
|
|
| 45 |
public RubikWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) |
|
| 46 |
{
|
|
| 47 |
super(context, workerParams); |
|
| 48 |
} |
|
| 49 |
|
|
| 50 |
@NonNull |
|
| 51 |
@Override |
|
| 52 |
public Result doWork() |
|
| 53 |
{
|
|
| 54 |
return Result.success(); |
|
| 55 |
} |
|
| 56 |
} |
|
| 57 |
|
|
| 58 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 59 |
|
|
| 60 |
@Override |
|
| 61 |
public void onMessageReceived(RemoteMessage remoteMessage) |
|
| 62 |
{
|
|
| 63 |
Log.e(TAG, "From: " + remoteMessage.getFrom()); |
|
| 64 |
|
|
| 65 |
if (remoteMessage.getData().size() > 0) |
|
| 66 |
{
|
|
| 67 |
Log.e(TAG, "Message data payload: " + remoteMessage.getData()); |
|
| 68 |
|
|
| 69 |
if (/* Check if data needs to be processed by long running job */ true) |
|
| 70 |
{
|
|
| 71 |
scheduleJob(); |
|
| 72 |
} |
|
| 73 |
else |
|
| 74 |
{
|
|
| 75 |
handleNow(); |
|
| 76 |
} |
|
| 77 |
} |
|
| 78 |
|
|
| 79 |
if (remoteMessage.getNotification() != null) |
|
| 80 |
{
|
|
| 81 |
Log.e(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody()); |
|
| 82 |
} |
|
| 83 |
} |
|
| 84 |
|
|
| 85 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 86 |
|
|
| 87 |
@Override |
|
| 88 |
public void onNewToken(@NonNull String token) |
|
| 89 |
{
|
|
| 90 |
RubikNetwork network = RubikNetwork.getInstance(); |
|
| 91 |
network.token(token); |
|
| 92 |
} |
|
| 93 |
|
|
| 94 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 95 |
|
|
| 96 |
private void scheduleJob() |
|
| 97 |
{
|
|
| 98 |
OneTimeWorkRequest work = new OneTimeWorkRequest.Builder(RubikWorker.class).build(); |
|
| 99 |
WorkManager.getInstance(this).beginWith(work).enqueue(); |
|
| 100 |
} |
|
| 101 |
|
|
| 102 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 103 |
|
|
| 104 |
private void handleNow() |
|
| 105 |
{
|
|
| 106 |
|
|
| 107 |
} |
|
| 108 |
} |
|
| src/main/java/org/distorted/solvers/cube3/SolverCoordCube.java | ||
|---|---|---|
| 36 | 36 |
static final short N_URtoUL = 1320; // 12!/(12-3)! permutation of UR,UF,UL edges |
| 37 | 37 |
static final short N_UBtoDF = 1320; // 12!/(12-3)! permutation of UB,DR,DF edges |
| 38 | 38 |
static final short N_URtoDF = 20160; // 8!/(8-6)! permutation of UR,UF,UL,UB,DR,DF edges in phase2 |
| 39 |
static final int N_URFtoDLB = 40320; // 8! permutations of the corners |
|
| 40 |
static final int N_URtoBR = 479001600;// 8! permutations of the corners |
|
| 41 | 39 |
static final short N_MOVE = 18; |
| 42 | 40 |
|
| 43 | 41 |
// All coordinates are 0 for a solved cube except for UBtoDF, which is 114 |
Also available in: Unified diff
Add Firebase Cloud Messaging and Firebase In-App Messaging