Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.

Copyright [yyyy] [name of copyright owner]
Copyright 2023 Mygod

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
45 changes: 45 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,48 @@ Other features:
* More conveniently refresh the webpage when fullscreen. (During network congestion, Chrome HTTP/3 scheduler retries requests at its own pace. Doing a manual refresh overrides this.)
* Login button is clicked automatically (Discord login only).
* You could make alerts follow location in background.

## Guide for custom build

### Setup instructions

1. If you have not already, generate a signing key with [`keytool`](https://developer.android.com/build/building-cmdline#sign_cmdline).
Using [RSA with a key length of 4096, 8192, or 16384 bits](https://github.com/google/bundletool/blob/0b9149c283e2df73850da670f2130a732639283d/src/main/java/com/android/tools/build/bundletool/commands/AddTransparencyCommand.java#L97) is recommended.
2. Create the following file at `https://mymap.com/.well-known/assetlinks.json` by creating the file in `/path/to/reactmap/public/.well-known/assetlinks.json`:
```json
[
{
"relation": [
"delegate_permission/common.handle_all_urls"
],
"target": {
"namespace": "android_app",
"package_name": "be.mygod.reactmap.com.mymap",
"sha256_cert_fingerprints": [
"insert your sha256 cert fingerprint"
]
}
}
]
```
where the fingerprint can be obtained via `keytool -list -v -keystore /path/to/keystore`.
(If you prefer to using Android Studio to create this file with a wizard, see [here]( https://developer.android.com/studio/write/app-link-indexing#associatesite) for instructions.)
3. (Optional) Make modifications to the source code if you wish.

### Build instructions

Build with [injected properties](https://stackoverflow.com/a/47356720/2245107) (modifying these values as you wish):
```
./gradlew assembleRelease \
-Pandroid.injected.signing.store.file=$KEYFILE \
-Pandroid.injected.signing.store.password=$STORE_PASSWORD \
-Pandroid.injected.signing.key.alias=$KEY_ALIAS \
-Pandroid.injected.signing.key.password=$KEY_PASSWORD \
-Preactmap.defaultHost=mymap.com \
-Preactmap.packageName=be.mygod.reactmap.com.mymap
```

Optionally you can also inject `reactmap.appName`.
An alternative to using `-P` switches is to adding your properties to the `gradle.properties` file in the root directory.

Success! Find your apk in `app/build/outputs/apk/release`.
20 changes: 16 additions & 4 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import com.google.firebase.crashlytics.buildtools.gradle.CrashlyticsExtension

plugins {
alias(libs.plugins.androidApplication)
alias(libs.plugins.firebaseCrashlytics)
alias(libs.plugins.googleServices)
// https://developers.google.com/android/guides/google-services-plugin#processing_the_json_file
// alias(libs.plugins.googleServices)
alias(libs.plugins.kotlinAndroid)
id("kotlin-parcelize")
}
Expand All @@ -11,13 +14,19 @@ android {
compileSdk = 34

defaultConfig {
applicationId = "be.mygod.reactmap"
applicationId = extra["reactmap.packageName"] as String?
minSdk = 26
targetSdk = 34
versionCode = 53
versionName = "0.5.2"
versionCode = 60
versionName = "0.6.0"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"

if (extra.has("reactmap.appName")) resValue("string", "app_name", extra["reactmap.appName"] as String)
extra["reactmap.defaultDomain"]!!.let { defaultDomain ->
manifestPlaceholders["defaultDomain"] = defaultDomain
buildConfigField("String", "DEFAULT_DOMAIN", "\"$defaultDomain\"")
}
}

buildTypes {
Expand All @@ -27,6 +36,9 @@ android {
release {
isMinifyEnabled = true
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
if (!pluginManager.hasPlugin("com.google.gms.google-services")) {
the<CrashlyticsExtension>().mappingFileUploadEnabled = false
}
}
}
buildFeatures.buildConfig = true
Expand Down
44 changes: 28 additions & 16 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

<queries>
<package android:name="com.nianticlabs.pokemongo" />
Expand Down Expand Up @@ -36,14 +36,24 @@

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />

<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />

<data android:scheme="http" />
<data android:scheme="https" />
<data android:host="${defaultDomain}" />
</intent-filter>
</activity>
<receiver
android:name=".follower.BackgroundLocationReceiver"
android:directBootAware="true"
android:enabled="false"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
</intent-filter>
Expand All @@ -52,55 +62,57 @@
<service
android:name="androidx.work.impl.background.systemalarm.SystemAlarmService"
android:directBootAware="true"
tools:replace="android:directBootAware"/>
tools:replace="android:directBootAware" />
<service
android:name="androidx.work.impl.background.systemjob.SystemJobService"
android:directBootAware="true"
tools:replace="android:directBootAware"/>
tools:replace="android:directBootAware" />
<service
android:name="androidx.work.impl.foreground.SystemForegroundService"
android:directBootAware="true"
android:foregroundServiceType="dataSync"
tools:replace="android:directBootAware"
tools:node="merge"/>
tools:node="merge" />

<receiver
android:name="androidx.work.impl.utils.ForceStopRunnable$BroadcastReceiver"
android:directBootAware="true"
tools:replace="android:directBootAware"/>
tools:replace="android:directBootAware" />
<receiver
android:name="androidx.work.impl.background.systemalarm.ConstraintProxy$BatteryChargingProxy"
android:directBootAware="true"
tools:replace="android:directBootAware"/>
tools:replace="android:directBootAware" />
<receiver
android:name="androidx.work.impl.background.systemalarm.ConstraintProxy$BatteryNotLowProxy"
android:directBootAware="true"
tools:replace="android:directBootAware"/>
tools:replace="android:directBootAware" />
<receiver
android:name="androidx.work.impl.background.systemalarm.ConstraintProxy$StorageNotLowProxy"
android:directBootAware="true"
tools:replace="android:directBootAware"/>
tools:replace="android:directBootAware" />
<receiver
android:name="androidx.work.impl.background.systemalarm.ConstraintProxy$NetworkStateProxy"
android:directBootAware="true"
tools:replace="android:directBootAware"/>
tools:replace="android:directBootAware" />
<receiver
android:name="androidx.work.impl.background.systemalarm.RescheduleReceiver"
android:directBootAware="true"
tools:replace="android:directBootAware"/>
tools:replace="android:directBootAware" />
<receiver
android:name="androidx.work.impl.background.systemalarm.ConstraintProxyUpdateReceiver"
android:directBootAware="true"
tools:replace="android:directBootAware"/>
tools:replace="android:directBootAware" />
<receiver
android:name="androidx.work.impl.diagnostics.DiagnosticsReceiver"
android:directBootAware="true"
tools:replace="android:directBootAware"/>
tools:replace="android:directBootAware" />

<provider
android:name="androidx.startup.InitializationProvider"
tools:node="remove"/>
tools:node="remove" />
<provider
android:name="com.google.firebase.provider.FirebaseInitProvider"
tools:node="remove"/>
tools:node="remove" />
</application>

</manifest>
9 changes: 6 additions & 3 deletions app/src/main/java/be/mygod/reactmap/App.kt
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ class App : Application() {
companion object {
private const val PREF_NAME = "reactmap"
const val KEY_ACTIVE_URL = "url.active"
const val URL_DEFAULT = "https://www.reactmap.dev"

lateinit var app: App
}
Expand All @@ -44,7 +43,7 @@ class App : Application() {
val nm by lazy { getSystemService<NotificationManager>()!! }
val userManager by lazy { getSystemService<UserManager>()!! }

val activeUrl get() = pref.getString(KEY_ACTIVE_URL, URL_DEFAULT) ?: URL_DEFAULT
val activeUrl get() = pref.getString(KEY_ACTIVE_URL, null) ?: "https://${BuildConfig.DEFAULT_DOMAIN}"

override fun onCreate() {
super.onCreate()
Expand Down Expand Up @@ -79,13 +78,17 @@ class App : Application() {
NotificationChannel(SiteController.CHANNEL_ID, "Full screen site controls",
NotificationManager.IMPORTANCE_LOW).apply {
lockscreenVisibility = Notification.VISIBILITY_SECRET
setShowBadge(false)
},
NotificationChannel(LocationSetter.CHANNEL_ID, "Background location updating",
NotificationManager.IMPORTANCE_LOW).apply {
lockscreenVisibility = Notification.VISIBILITY_PUBLIC
setShowBadge(false)
},
NotificationChannel(LocationSetter.CHANNEL_ID_SUCCESS, "Background location updated",
NotificationManager.IMPORTANCE_MIN),
NotificationManager.IMPORTANCE_MIN).apply {
setShowBadge(false)
},
NotificationChannel(LocationSetter.CHANNEL_ID_ERROR, "Background location update failed",
NotificationManager.IMPORTANCE_HIGH).apply {
enableLights(true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class ConfigDialogFragment : AlertDialogFragment<ConfigDialogFragment.Arg, Empty
}

override fun AlertDialog.Builder.prepare(listener: DialogInterface.OnClickListener) {
historyUrl = app.pref.getStringSet(KEY_HISTORY_URL, null) ?: setOf(App.URL_DEFAULT)
historyUrl = app.pref.getStringSet(KEY_HISTORY_URL, null) ?: setOf("https://${BuildConfig.DEFAULT_DOMAIN}")
val context = requireContext()
urlEdit = AutoCompleteTextView(context).apply {
isFocusedByDefault = true
Expand Down
24 changes: 17 additions & 7 deletions app/src/main/java/be/mygod/reactmap/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package be.mygod.reactmap
import android.app.AlertDialog
import android.content.DialogInterface
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.view.WindowManager
import android.webkit.WebView
Expand Down Expand Up @@ -35,27 +36,32 @@ class MainActivity : FragmentActivity() {
enableEdgeToEdge()
if (BuildConfig.DEBUG) WebView.setWebContentsDebuggingEnabled(true)
setContentView(R.layout.layout_main)
reactMapFragment()
handleIntent(intent)
if (currentFragment == null) reactMapFragment(null)
if (app.pref.getBoolean(KEY_WELCOME, true)) {
startConfigure(true)
app.pref.edit { putBoolean(KEY_WELCOME, false) }
}
AlertDialogFragment.setResultListener<ConfigDialogFragment, Empty>(this) { which, _ ->
if (which != DialogInterface.BUTTON_POSITIVE) return@setResultListener
currentFragment?.terminate()
reactMapFragment()
reactMapFragment(null)
}
supportFragmentManager.setFragmentResultListener("ReactMapFragment", this) { _, _ ->
reactMapFragment()
reactMapFragment(null)
}
}
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
handleIntent(intent)
}

private var currentFragment: ReactMapFragment? = null
private fun reactMapFragment() = supportFragmentManager.commit {
replace(R.id.content, ReactMapFragment().also { currentFragment = it })
private fun reactMapFragment(overrideUri: Uri?) = supportFragmentManager.commit {
replace(R.id.content, ReactMapFragment(overrideUri).also { currentFragment = it })
}

override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
private fun handleIntent(intent: Intent?) {
when (intent?.action) {
ACTION_CONFIGURE -> startConfigure(false)
ACTION_RESTART_GAME -> AlertDialog.Builder(this).apply {
Expand All @@ -65,6 +71,10 @@ class MainActivity : FragmentActivity() {
setNegativeButton("Samsung") { _, _ -> restartGame("com.nianticlabs.pokemongo.ares") }
setNeutralButton(android.R.string.cancel, null)
}.show()
Intent.ACTION_VIEW -> {
val currentFragment = currentFragment
if (currentFragment == null) reactMapFragment(intent.data) else currentFragment.handleUri(intent.data)
}
}
}
private fun startConfigure(welcome: Boolean) = ConfigDialogFragment().apply {
Expand Down
Loading