Revision a59f38d6
Added by Leszek Koltunski over 2 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