├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── omkarmoghe │ │ │ └── pokemap │ │ │ ├── controllers │ │ │ ├── MarkerRefreshController.java │ │ │ ├── app_preferences │ │ │ │ ├── PokemapAppPreferences.java │ │ │ │ └── PokemapSharedPreferences.java │ │ │ ├── map │ │ │ │ └── LocationManager.java │ │ │ ├── net │ │ │ │ ├── GoogleManager.java │ │ │ │ ├── GoogleService.java │ │ │ │ ├── NetworkRequestLoggingInterceptor.java │ │ │ │ ├── NianticManager.java │ │ │ │ └── NianticService.java │ │ │ └── service │ │ │ │ └── PokemonNotificationService.java │ │ │ ├── helpers │ │ │ ├── MapHelper.java │ │ │ └── RemoteImageLoader.java │ │ │ ├── models │ │ │ ├── events │ │ │ │ ├── CatchablePokemonEvent.java │ │ │ │ ├── ClearMapEvent.java │ │ │ │ ├── GymsEvent.java │ │ │ │ ├── IEvent.java │ │ │ │ ├── InternalExceptionEvent.java │ │ │ │ ├── LoginEventResult.java │ │ │ │ ├── LurePokemonEvent.java │ │ │ │ ├── MarkerExpired.java │ │ │ │ ├── MarkerUpdate.java │ │ │ │ ├── PokestopsEvent.java │ │ │ │ ├── SearchInPosition.java │ │ │ │ └── ServerUnreachableEvent.java │ │ │ ├── login │ │ │ │ ├── GoogleLoginInfo.java │ │ │ │ ├── LoginInfo.java │ │ │ │ └── PtcLoginInfo.java │ │ │ └── map │ │ │ │ ├── GymMarkerExtended.java │ │ │ │ ├── PokemonMarkerExtended.java │ │ │ │ └── PokestopMarkerExtended.java │ │ │ ├── util │ │ │ └── PokemonIdUtils.java │ │ │ └── views │ │ │ ├── BaseActivity.java │ │ │ ├── GoogleAuthActivity.java │ │ │ ├── LoginActivity.java │ │ │ ├── MainActivity.java │ │ │ ├── map │ │ │ └── MapWrapperFragment.java │ │ │ └── settings │ │ │ ├── PokemonToShowAdapter.java │ │ │ ├── PokemonToShowPreference.java │ │ │ ├── SettingsActivity.java │ │ │ ├── SettingsFragment.java │ │ │ └── ThemeActivity.java │ └── res │ │ ├── drawable-hdpi │ │ ├── ic_favorite_white_24dp.png │ │ ├── ic_list_white_24dp.png │ │ ├── ic_map_white_24dp.png │ │ └── ic_my_location_white_24dp.png │ │ ├── drawable-mdpi │ │ ├── ic_favorite_white_24dp.png │ │ ├── ic_list_white_24dp.png │ │ ├── ic_map_white_24dp.png │ │ └── ic_my_location_white_24dp.png │ │ ├── drawable-xhdpi │ │ ├── ic_favorite_white_24dp.png │ │ ├── ic_list_white_24dp.png │ │ ├── ic_map_white_24dp.png │ │ └── ic_my_location_white_24dp.png │ │ ├── drawable-xxhdpi │ │ ├── ic_favorite_white_24dp.png │ │ ├── ic_list_white_24dp.png │ │ ├── ic_map_white_24dp.png │ │ └── ic_my_location_white_24dp.png │ │ ├── drawable-xxxhdpi │ │ ├── ic_favorite_white_24dp.png │ │ ├── ic_list_white_24dp.png │ │ ├── ic_map_white_24dp.png │ │ └── ic_my_location_white_24dp.png │ │ ├── drawable │ │ ├── ic_arrow_back_white.xml │ │ ├── ic_cancel_white_24px.xml │ │ ├── ic_close_white_24dp.xml │ │ └── ic_gps_fixed_white_24px.xml │ │ ├── layout │ │ ├── activity_google_auth.xml │ │ ├── activity_login.xml │ │ ├── activity_main.xml │ │ ├── activity_settings.xml │ │ ├── activity_theme.xml │ │ ├── fragment_map_wrapper.xml │ │ ├── item_pokemon_to_show_preference.xml │ │ ├── request_credentials_dialog.xml │ │ └── toolbar.xml │ │ ├── menu │ │ └── menu_main.xml │ │ ├── values-de │ │ └── pokemon.xml │ │ ├── values-fr │ │ └── pokemon.xml │ │ ├── values-ja │ │ └── pokemon.xml │ │ ├── values-nl │ │ ├── pokemon.xml │ │ └── strings.xml │ │ ├── values-v21 │ │ └── styles.xml │ │ ├── values-w820dp │ │ └── dimens.xml │ │ ├── values │ │ ├── arrays.xml │ │ ├── colors.xml │ │ ├── config.xml │ │ ├── dimens.xml │ │ ├── pokemon.xml │ │ ├── strings.xml │ │ └── styles.xml │ │ └── xml │ │ └── preferences.xml │ └── test │ └── java │ └── com │ └── omkarmoghe │ └── pokemap │ └── controllers │ └── app_preferences │ └── PokemapSharedPreferencesTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── strings.xml /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.gitignore.io 2 | 3 | ### Android ### 4 | 5 | # Files for the Dalvik VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # Generated files 12 | bin/ 13 | gen/ 14 | 15 | # Gradle files 16 | .gradle/ 17 | build/ 18 | $ANDROID_SDK/ 19 | 20 | # Local configuration file (sdk path, etc) 21 | local.properties 22 | 23 | # Proguard folder generated by Eclipse 24 | proguard/ 25 | 26 | # Log Files 27 | *.log 28 | 29 | 30 | ### Intellij ### 31 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm 32 | 33 | *.iml 34 | 35 | ## Directory-based project format: 36 | .idea/ 37 | # if you remove the above rule, at least ignore the following: 38 | 39 | # User-specific stuff: 40 | # .idea/workspace.xml 41 | # .idea/tasks.xml 42 | # .idea/dictionaries 43 | 44 | # Sensitive or high-churn files: 45 | # .idea/dataSources.ids 46 | # .idea/dataSources.xml 47 | # .idea/sqlDataSources.xml 48 | # .idea/dynamic.xml 49 | # .idea/uiDesigner.xml 50 | 51 | # Gradle: 52 | # .idea/gradle.xml 53 | # .idea/libraries 54 | 55 | # Mongo Explorer plugin: 56 | # .idea/mongoSettings.xml 57 | 58 | ## File-based project format: 59 | *.ipr 60 | *.iws 61 | 62 | ## Plugin-specific files: 63 | 64 | # IntelliJ 65 | out/ 66 | 67 | # mpeltonen/sbt-idea plugin 68 | .idea_modules/ 69 | 70 | # JIRA plugin 71 | atlassian-ide-plugin.xml 72 | 73 | # Crashlytics plugin (for Android Studio and IntelliJ) 74 | com_crashlytics_export_strings.xml 75 | 76 | # Ignore Gradle GUI config 77 | gradle-app.setting 78 | 79 | # Mobile Tools for Java (J2ME) 80 | .mtj.tmp/ 81 | 82 | # Package Files # 83 | *.war 84 | *.ear 85 | 86 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 87 | hs_err_pid* 88 | 89 | *.DS_Store 90 | gradle.properties 91 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: android 2 | jdk: 3 | - oraclejdk8 4 | android: 5 | components: 6 | - platform-tools 7 | - tools 8 | - build-tools-24.0.1 9 | - android-24 10 | - extra-google-google_play_services 11 | - extra-android-m2repository 12 | - extra-google-m2repository 13 | licenses: 14 | - android-sdk-license-.+ 15 | - google-gdk-license-.+ 16 | before_script: 17 | - chmod +x gradlew 18 | script: 19 | - "./gradlew build -PversionCode=$TRAVIS_BUILD_NUMBER" 20 | before_deploy: 21 | - git config --global user.email "builds@travis-ci.com" 22 | - git config --global user.name "Travis CI" 23 | - export GIT_TAG=$TRAVIS_BRANCH-rev$TRAVIS_BUILD_NUMBER 24 | - git tag $GIT_TAG -a -m "Pokemap development build $TRAVIS_BUILD_NUMBER" 25 | - git push -q https://$GH_TOKEN:x-oauth-basic@github.com/$TRAVIS_REPO_SLUG --tags 26 | - ls -R 27 | deploy: 28 | skip_cleanup: true 29 | provider: releases 30 | prerelease: true 31 | api_key: 32 | secure: OQHzpHLLrxjZZ/vgSmi8sv8xYTW4ddHENSi37IEQMZC0uQig0sdUDgunadS9rMq7/Wf3lvJsYIItBHLLteVcUJC1opo7RqDEBBho3xnSPPW89f3c2j9LC43FFOgTmgr9obf9nC3fdZb/icpK+eK+jlrQ7FO3S+OkbeK+UuduqpzOn79pE1TN8IIQ6fsdJyGektEBsuHJ/bEYNnc++KAgkfVHqS8JWMoTtwo61H2Bn/rtgrQBVEiijpuzZ6W3/klFP9FjETlGcXGiFgCT0jR+QrNC4RtveEit7MyUc8pEyBxwt+5GW6dzA+pgX1jEqHIdlY28Zc04743fP93iXhGSHxXRw9+F9JcY3qLToLGPDemnLY2PbAQN+/07SrO9OAczDjCSEfBoObaVbwHal6/GSimcrA+K3lWpnbDTrer5IZnEq9UPEYEtf5yF0PpCkQlFkfxzJSyla2+ER3uSb/azBvWUz8R93dDA101HAyurqLSa3QwfVGw+M+YN5C8C/jLAgfZRfEKGrtogX8GHG3ioXKUpbjKfX+vwXemvK//6M1zdRUhpxt69a1dTR9hx3mpt8eYmfDCioCP40ZWFrfb8nmacsCqUAn2stV1i2r2yrn9JsUnaM9qVco8ztrXo9SN7cdIFFx8Je5ZKUp6Vxyg0vQjPKNrauueWngRcjdzpcD4= 33 | file: $TRAVIS_BUILD_DIR/app/build/outputs/apk/app-debug.apk 34 | on: 35 | tags: false 36 | repo: omkarmoghe/Pokemap 37 | branch: dev 38 | branches: 39 | except: 40 | - "/^*-rev[0-9]/" 41 | notifications: 42 | email: false 43 | env: 44 | global: 45 | secure: Q8ujMb2AcMsN4x6Z92K5U2zSkhDI9C2yRzfN/8CHZBqt4Wr0bNMeMWA8LuwSzGAqrJFkwjI76M7WGqCcQmM6sCakAS3zD/GwK6vJ96fN537lGF8zhJv9+qk1hYCrK/LSBwY2m+RJGwLRh0da5V5aD23r/oiNdH9Bo8fcWsN/SpGD4CHI2Q3F9nIvMBB3FMnrZRUC3hEzNFdTpdoYGxUiSOFs3uAKYHKJWc8tJ1AQfd58f8Uf2TQ5LBlBk8I2kUieU8RaRweuFwVBPwLa0rJzuIlmhBUJrZxIC/evxRnBYjEITwbYCixymj8JicHT9JgPkvRJJkhbjX+H7AX+xjjXKQgqDgSye5dTDFqfkjgdgnpAoCbXhzl8JXKPB/cDsiMuJGE2Az9asZN7EgvPDz7/NpqKc3nhzLkcNy8EWo0K28HPqLw2IZdST9ivrh3uUG+ry2GkXv8j4+4YP9VYJ3hz3OtLZXGXXnfqDr+ruOIKZez36gUH4HmrgssZCUa8O1kZq+geiMzqBq2NfR+QZ5NK+2zpNtT5jANma4hrpEJaeHC5m2l62HKlzMGTCmmitHkmOk2zuI/2xUW63K7bIqY5ioHA5H07RoDB79O6sHJuVMsZL/5vq+lMEzBxEvsW+KA8XtQZuk1Xktv4Fkgf41UGymeT+hqUbmxPCuKbPlIg2VA= 46 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Pokemap [![Download](https://img.shields.io/badge/download-latest-brightgreen.svg?style=flat-square)](https://github.com/omkarmoghe/Pokemap/releases) 2 | 3 | 4 | #[Our website is now live](http://pokemapgo.xyz/) 5 | 6 | 7 | 8 | Join our Discord server ![Pokemap Discord](https://discordapp.com/api/guilds/258391846143787009/widget.png) 9 | 10 | 11 | 12 | 13 | # IMPORTANT UPDATE (PLEASE READ) 8/7/16 14 | 15 | First off, we want to thank the entire community for the crazy support and excitement you have shown about our project. We have some important news and updates concerning the state of this project. 16 | 17 | Unforunately, we have noticed an increasing number of apps using our codebase to create bots or charge users for the services we aim to provide for free. While we encourage the community to use our code and play with the app, such uses undermine the progress of our app by [motiviating Niantic to change their APIs](https://github.com/omkarmoghe/Pokemap/issues/383) and ultimately hinder further development of this project. For these reasons our dev team has made the following decisions regarding our source code: 18 | 19 | 1. Further development of Pokemap will continue in a private repo. The source code here will be left as legacy. 20 | 2. Signed APKs will be periodically uploaded to [releases](https://github.com/omkarmoghe/Pokemap/releases). 21 | 3. The translations will be kept open source and we will accept pull requests for languages. 22 | 4. No other pull requests will be merged to this repo. 23 | 5. Issues will be tracked and used to add features and fix bugs with the APK releases. 24 | 25 | If you are interested in contributing to the project, reach out to one of the contributors! 26 | 27 | Thanks for all your support! 28 | 29 | :heart:, 30 | The Pokemap Dev Team 31 | 32 | --- 33 | 34 | [Can't log in? Check the PTC login status.](http://ispokemongodownornot.com/) 35 | 36 | A native Android client built with https://github.com/AHAAAAAAA/PokemonGo-Map 37 | 38 | screenshots from @linkout @mike @z14942744 @kyr0 @rancor 39 | 40 | ### **Slack invites are now restricted to contributors only. Please comment your email when you submit a PR and we will send you an invite.** 41 | 42 | # [RTFM](https://github.com/omkarmoghe/Pokemap/wiki) 43 | Please read the f***ing manual before opening an issue. :heart: 44 | 45 | [Contribute to the documentation!](https://github.com/omkarmoghe/Pokemap/issues/17) 46 | 47 | ## [Building] (https://github.com/omkarmoghe/Pokemap/wiki/Building) 48 | Make sure you use the latest [android studio version 2.2 (canary builds)] (http://tools.android.com/download/studio/canary/latest) and have installed the latest versions of the build tools and support libraries in order to successfully compile and run the project. 49 | 50 | # Contributing 51 | All PRs should go to the `dev` branch. `master` will be updated periodically with stable* releases. 52 | 53 | Please read this to understand how this all works: https://www.reddit.com/r/pokemongodev/comments/4svl1o/guide_to_pokemon_go_server_responses/ 54 | 55 | ## Translations 56 | If you are contributing a PR related to language translations, please have other members of the community :thumbsup: your change. 57 | 58 | ## Reporting Bugs 59 | Please include a screenshot and instructions on how to recreate the bug you are reporting. If you have any LogCat stack traces, etc. please include those as well. **Use the search bar to make sure you are not creating duplicate issues. If your bug has already been reported, feel free to comment with additional info.** 60 | 61 | # [Official Website] (http://pokemapgo.xyz/) 62 | From the main repo: 63 | > Live visualization of all pokemon (with option to show gyms and pokestops) in your area. This is a proof of concept that we can load all nearby pokemon given a location. Currently runs on a Flask server displaying a Google Map with markers on it. 64 | > 65 | > Using this software is against the ToS and can get you banned. Use at your own risk. 66 | > 67 | > Building off [Mila432](https://github.com/Mila432/Pokemon_Go_API)'s PokemonGo API, [tejado's additions](https://github.com/tejado/pokemongo-api-demo), [leegao's additions](https://github.com/leegao/pokemongo-api-demo/tree/simulation) and [Flask-GoogleMaps](https://github.com/rochacbruno/Flask-GoogleMaps). 68 | > 69 | > For instructions, please refer to [the wiki](https://github.com/AHAAAAAAA/PokemonGo-Map/wiki) 70 | 71 | ## iOS Version 72 | There is an [iOS port](https://github.com/istornz/iPokeGo) in the works. All iOS related prs and issues please refer to this [repo](https://github.com/istornz/iPokeGo). 73 | 74 | --- 75 | :pineapple: 76 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'android-apt' 3 | apply plugin: 'com.getkeepsafe.dexcount' 4 | 5 | def getVersionCode = { -> 6 | def code = project.hasProperty('versionCode') ? versionCode.toInteger() : 1 7 | return code 8 | } 9 | android { 10 | compileSdkVersion 24 11 | buildToolsVersion "24.0.1" 12 | defaultConfig { 13 | applicationId "com.omkarmoghe.pokemap" 14 | minSdkVersion 17 15 | targetSdkVersion 24 16 | multiDexEnabled true 17 | versionCode getVersionCode() 18 | versionName "1.0" 19 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 20 | } 21 | buildTypes { 22 | debug { 23 | minifyEnabled true 24 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 25 | } 26 | release { 27 | minifyEnabled true 28 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 29 | } 30 | } 31 | lintOptions { 32 | abortOnError false 33 | } 34 | testOptions { 35 | unitTests.returnDefaultValues = true 36 | } 37 | } 38 | 39 | //https://jitpack.io/#Grover-c13/PokeGOAPI-Java/4f5b715380 40 | dependencies { 41 | compile fileTree(dir: 'libs', include: ['*.jar']) 42 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 43 | exclude group: 'com.android.support', module: 'support-annotations' 44 | }) 45 | 46 | //Android Support Library 47 | compile 'com.android.support:appcompat-v7:24.0.0' 48 | compile 'com.android.support:design:24.0.0' 49 | compile 'com.android.support:support-v4:24.0.0' 50 | compile 'com.android.support:cardview-v7:24.0.0' 51 | //Google Play Services 52 | compile 'com.google.android.gms:play-services-maps:9.2.1' 53 | compile 'com.google.android.gms:play-services-location:9.2.1' 54 | 55 | //Pokemon Go API 56 | compile 'com.github.Grover-c13:PokeGOAPI-Java:2e14fab7f0' 57 | 58 | //Image handler 59 | compile 'com.github.bumptech.glide:glide:3.7.0' 60 | 61 | //Network 62 | compile 'com.github.franmontiel:PersistentCookieJar:v0.9.3' 63 | compile 'com.squareup.retrofit2:retrofit:2.0.0' 64 | compile 'com.squareup.retrofit2:converter-gson:2.0.0' 65 | compile 'org.greenrobot:eventbus:3.0.0' 66 | testCompile 'junit:junit:4.12' 67 | testCompile 'org.mockito:mockito-core:1.10.19' 68 | testCompile 'org.powermock:powermock-module-junit4:1.6.5' 69 | testCompile 'org.powermock:powermock-api-mockito:1.6.5' 70 | 71 | } 72 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in C:\Users\Omkar Moghe\android-sdks/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | 19 | -printseeds build/seed.txt 20 | -printusage build/usuage.txt 21 | 22 | -dontobfuscate 23 | -dontusemixedcaseclassnames 24 | -dontskipnonpubliclibraryclasses 25 | -dontskipnonpubliclibraryclassmembers 26 | -dontpreverify 27 | -optimizationpasses 5 28 | 29 | -keepattributes Signature, InnerClasses, EnclosingMethod, *Annotation* 30 | 31 | ##### 32 | # Something to do with Okio.Http 33 | ##### 34 | -dontwarn java.nio.file.Files 35 | -dontwarn java.nio.file.Path 36 | -dontwarn java.nio.file.OpenOption 37 | -dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement 38 | -keep, includedescriptorclasses class sun.misc.Unsafe { *; } 39 | 40 | 41 | ###### 42 | # Support Stream 43 | ###### 44 | #-dontwarn java.lang.invoke.** 45 | -dontwarn sun.misc.Unsafe 46 | -dontwarn java.lang.** 47 | 48 | ###### 49 | # App Compat, Design Support Libraries 50 | ###### 51 | -keep, includedescriptorclasses public class android.support.v7.widget.** { *; } 52 | -keep public class android.support.v7.internal.widget.** { *; } 53 | -keep public class android.support.v7.internal.view.menu.** { *; } 54 | -dontwarn android.support.design.** 55 | -keep, includedescriptorclasses class android.support.design.** { *; } 56 | -keep interface android.support.design.** { *; } 57 | -keep, includedescriptorclasses public class android.support.design.R$* { *; } 58 | 59 | 60 | ##### 61 | # Protocol Buffers 62 | ##### 63 | -keep class com.google.protobuf.** { *; } 64 | -dontwarn com.google.** 65 | -keep class * extends com.google.protobuf.GeneratedMessage { *; } 66 | -keepclassmembernames class * extends com.google.protobuf.GeneratedMessage { *; } 67 | 68 | 69 | -keep class java8.** 70 | -dontwarn java8.** 71 | 72 | -keep, includedescriptorclasses public class POGOSProtos.**{ *; } 73 | -keep, includedescriptorclasses public class com.omkarmoghe.**{ *; } 74 | 75 | ###### 76 | # Google maps animations 77 | ###### 78 | -keep, includedescriptorclasses public class com.google.android.gms.maps.model.** {*;} 79 | 80 | 81 | #-ignorewarnings -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 16 | 19 | 20 | 23 | 27 | 28 | 30 | 31 | 35 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 49 | 52 | 53 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /app/src/main/java/com/omkarmoghe/pokemap/controllers/MarkerRefreshController.java: -------------------------------------------------------------------------------- 1 | package com.omkarmoghe.pokemap.controllers; 2 | 3 | import android.os.CountDownTimer; 4 | import android.os.Handler; 5 | import android.os.HandlerThread; 6 | import android.os.Message; 7 | import android.util.Log; 8 | 9 | import com.omkarmoghe.pokemap.models.events.MarkerExpired; 10 | import com.omkarmoghe.pokemap.models.events.MarkerUpdate; 11 | import com.omkarmoghe.pokemap.models.map.PokemonMarkerExtended; 12 | 13 | import org.greenrobot.eventbus.EventBus; 14 | 15 | import java.sql.Time; 16 | 17 | /** 18 | * Created by Rohan on 26-07-2016. 19 | */ 20 | 21 | 22 | public class MarkerRefreshController { 23 | 24 | final private String TAG = MarkerRefreshController.class.getName(); 25 | 26 | private static final int DEFAULT_UPDATE_INTERVAL = 1000;//1 seconds : heartbeat 27 | private static final int MARKER_EXPIRED = 1; 28 | 29 | private Handler mHandler; 30 | private CountDownTimer mTimer; 31 | 32 | private static MarkerRefreshController mInstance; 33 | 34 | private MarkerRefreshController() { 35 | Handler.Callback callback = new Handler.Callback() { 36 | @Override 37 | public boolean handleMessage(Message message) { 38 | switch (message.what) { 39 | case MARKER_EXPIRED: 40 | //If Marker Expired 41 | if (message.obj instanceof PokemonMarkerExtended) { 42 | EventBus.getDefault().post(new MarkerExpired((PokemonMarkerExtended) message.obj)); 43 | return true; 44 | } 45 | break; 46 | } 47 | return false; 48 | } 49 | }; 50 | mHandler = new Handler(callback); 51 | } 52 | 53 | /* 54 | * Singleton getter 55 | */ 56 | public static MarkerRefreshController getInstance() { 57 | if (mInstance == null) { 58 | mInstance = new MarkerRefreshController(); 59 | } 60 | return mInstance; 61 | } 62 | 63 | 64 | /** 65 | * Cleanup Messages and cancels the timer if it is running. 66 | */ 67 | public void clear() { 68 | if(mTimer != null){ 69 | mTimer.cancel(); 70 | mTimer = null; 71 | } 72 | mHandler.removeMessages(MARKER_EXPIRED); 73 | 74 | } 75 | 76 | public void startTimer(long duration){ 77 | if(mTimer != null){ 78 | mTimer.cancel(); 79 | } 80 | 81 | if(duration <= 0) { 82 | return; 83 | } 84 | 85 | final MarkerUpdate event = new MarkerUpdate(); 86 | mTimer = new CountDownTimer(duration, DEFAULT_UPDATE_INTERVAL) { 87 | @Override 88 | public void onTick(long l) { 89 | EventBus.getDefault().post(event); 90 | } 91 | 92 | @Override 93 | public void onFinish() { 94 | mTimer = null; 95 | EventBus.getDefault().post(event); 96 | } 97 | }; 98 | mTimer.start(); 99 | } 100 | 101 | public void stopTimer(){ 102 | if(mTimer != null){ 103 | mTimer.cancel(); 104 | mTimer = null; 105 | } 106 | } 107 | 108 | public void clearMessages(){ 109 | mHandler.removeMessages(MARKER_EXPIRED); 110 | } 111 | 112 | public void postMarker(PokemonMarkerExtended markerData){ 113 | long time = markerData.getCatchablePokemon().getExpirationTimestampMs() - System.currentTimeMillis(); 114 | if(time > 0) { 115 | Message message = mHandler.obtainMessage(MARKER_EXPIRED, markerData); 116 | mHandler.sendMessageDelayed(message, time); 117 | } 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /app/src/main/java/com/omkarmoghe/pokemap/controllers/app_preferences/PokemapAppPreferences.java: -------------------------------------------------------------------------------- 1 | package com.omkarmoghe.pokemap.controllers.app_preferences; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import com.omkarmoghe.pokemap.models.login.LoginInfo; 6 | 7 | import java.util.List; 8 | import java.util.Set; 9 | 10 | import POGOProtos.Enums.PokemonIdOuterClass; 11 | 12 | /** 13 | * A contract which defines a user's app preferences 14 | */ 15 | public interface PokemapAppPreferences { 16 | 17 | LoginInfo getLoginInfo(); 18 | 19 | void setLoginInfo(LoginInfo loginInfo); 20 | 21 | boolean isLoggedIn(); 22 | 23 | boolean getShowScannedPlaces(); 24 | boolean getShowPokestops(); 25 | boolean getShowGyms(); 26 | boolean getShowLuredPokemon(); 27 | int getSteps(); 28 | 29 | void clearLoginCredentials(); 30 | /** 31 | * 32 | * @param isEnabled Sets if the background service is enabled. 33 | */ 34 | void setServiceState(@NonNull boolean isEnabled); 35 | 36 | /** 37 | * 38 | * @return Returns service state as set in preffs 39 | */ 40 | boolean isServiceEnabled(); 41 | 42 | int getServiceRefreshRate(); 43 | 44 | /** 45 | * @return a set of pokemonIDs which can be shown according to the preferences. 46 | */ 47 | Set getShowablePokemonIDs(); 48 | 49 | void setShowablePokemonIDs(Set pokemonIDs); 50 | 51 | void setShowMapSuggestion(boolean showMapSuggestion); 52 | 53 | boolean getShowMapSuggestion(); 54 | } 55 | -------------------------------------------------------------------------------- /app/src/main/java/com/omkarmoghe/pokemap/controllers/app_preferences/PokemapSharedPreferences.java: -------------------------------------------------------------------------------- 1 | package com.omkarmoghe.pokemap.controllers.app_preferences; 2 | 3 | import android.content.Context; 4 | import android.content.SharedPreferences; 5 | import android.preference.PreferenceManager; 6 | import android.support.annotation.NonNull; 7 | import android.text.TextUtils; 8 | import android.util.ArraySet; 9 | import android.util.Log; 10 | 11 | import com.omkarmoghe.pokemap.models.login.GoogleLoginInfo; 12 | import com.omkarmoghe.pokemap.models.login.LoginInfo; 13 | import com.omkarmoghe.pokemap.models.login.PtcLoginInfo; 14 | import com.pokegoapi.api.pokemon.Pokemon; 15 | 16 | import java.util.Arrays; 17 | import java.util.HashSet; 18 | import java.util.Set; 19 | 20 | import java.util.HashSet; 21 | import java.util.Set; 22 | 23 | import POGOProtos.Enums.PokemonIdOuterClass; 24 | 25 | /** 26 | * Provide convenience methods to access shared preferences 27 | */ 28 | 29 | public final class PokemapSharedPreferences implements PokemapAppPreferences { 30 | private static final String TAG = "PokemapSharedPreference"; 31 | 32 | private static final String PTC_INFO_KEY = "PTCKey"; 33 | private static final String GOOGLE_INFO_KEY = "GoogleKey"; 34 | private static final String SHOW_SCANNED_PLACES = "scanned_checkbox"; 35 | private static final String SHOW_POKESTOPS = "pokestops_checkbox"; 36 | private static final String SHOW_GYMS = "gyms_checkbox"; 37 | private static final String SHOW_LURED = "lured_checkbox"; 38 | private static final String SERVICE_KEY = "background_poke_service"; 39 | private static final String SERVICE_REFRESH_KEY = "service_refresh_rate"; 40 | private static final String POKEMONS_TO_SHOW = "pokemons_to_show"; 41 | private static final String STEPS = "search_steps"; 42 | private static final String SHOW_MAP_SUGGESTION = "show_map_suggestion"; 43 | 44 | private static final String INFO_TOKEN = "token="; 45 | private static final String INFO_REFRESH = "refresh="; 46 | private static final String INFO_USERNAME = "username="; 47 | private static final String INFO_PASSWORD = "password="; 48 | 49 | private final SharedPreferences sharedPreferences; 50 | 51 | public PokemapSharedPreferences(@NonNull Context context) { 52 | sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context); 53 | } 54 | 55 | @Override 56 | public LoginInfo getLoginInfo() { 57 | 58 | if(sharedPreferences.contains(PTC_INFO_KEY)){ 59 | Set ptcInfo = sharedPreferences.getStringSet(PTC_INFO_KEY, null); 60 | if(ptcInfo != null && !ptcInfo.isEmpty()) { 61 | String[] info = ptcInfo.toArray(new String[3]); 62 | 63 | String token = null; 64 | String username = null; 65 | String password = null; 66 | 67 | for (String s :info) { 68 | if(!TextUtils.isEmpty(s)) { 69 | if (s.contains(INFO_TOKEN)) { 70 | token = getStoredString(s); 71 | continue; 72 | } 73 | if (s.contains(INFO_USERNAME)) { 74 | username = getStoredString(s); 75 | continue; 76 | } 77 | if (s.contains(INFO_PASSWORD)) { 78 | password = getStoredString(s); 79 | } 80 | } 81 | } 82 | return new PtcLoginInfo(token, username, password); 83 | } 84 | } 85 | 86 | if(sharedPreferences.contains(GOOGLE_INFO_KEY)) { 87 | Set googleInfo = sharedPreferences.getStringSet(GOOGLE_INFO_KEY, null); 88 | if (googleInfo != null) { 89 | String[] info = googleInfo.toArray(new String[2]); 90 | 91 | String token = null; 92 | String refresh = null; 93 | 94 | for (String s :info) { 95 | if(!TextUtils.isEmpty(s)) { 96 | if (s.contains(INFO_TOKEN)) { 97 | token = getStoredString(s); 98 | continue; 99 | } 100 | if (s.contains(INFO_PASSWORD)) { 101 | refresh = getStoredString(s); 102 | } 103 | } 104 | } 105 | 106 | return new GoogleLoginInfo(token, refresh); 107 | } 108 | } 109 | 110 | return null; 111 | } 112 | 113 | @Override 114 | public void setLoginInfo(LoginInfo loginInfo) { 115 | Log.d(TAG, "setLoginInfo: LoginInfo = " + loginInfo); 116 | 117 | clearLoginCredentials(); 118 | 119 | if(loginInfo instanceof PtcLoginInfo){ 120 | Set info = new HashSet<>(); 121 | PtcLoginInfo ptc = (PtcLoginInfo) loginInfo; 122 | info.add(INFO_TOKEN + ptc.getToken()); 123 | info.add(INFO_USERNAME + ptc.getUsername()); 124 | info.add(INFO_PASSWORD + ptc.getPassword()); 125 | sharedPreferences.edit().putStringSet(PTC_INFO_KEY, info).apply(); 126 | } 127 | 128 | if(loginInfo instanceof GoogleLoginInfo){ 129 | Set info = new HashSet<>(); 130 | GoogleLoginInfo google = (GoogleLoginInfo) loginInfo; 131 | info.add(INFO_TOKEN + google.getToken()); 132 | info.add(INFO_REFRESH + google.getRefreshToken()); 133 | Log.d(TAG, "setLoginInfo: Googleinfo = " + info); 134 | sharedPreferences.edit().putStringSet(GOOGLE_INFO_KEY, info).apply(); 135 | } 136 | } 137 | 138 | private String getStoredString(String value){ 139 | if (value == null) return null; 140 | String[] parts = value.split("="); 141 | 142 | return (parts.length > 1) ? parts[1] : null; 143 | } 144 | 145 | @Override 146 | public boolean isLoggedIn() { 147 | return sharedPreferences.contains(PTC_INFO_KEY) || sharedPreferences.contains(GOOGLE_INFO_KEY); 148 | } 149 | 150 | @Override 151 | public void clearLoginCredentials() { 152 | 153 | sharedPreferences.edit().remove(GOOGLE_INFO_KEY).apply(); 154 | sharedPreferences.edit().remove(PTC_INFO_KEY).apply(); 155 | } 156 | 157 | @Override 158 | public boolean getShowScannedPlaces() { 159 | return sharedPreferences.getBoolean(SHOW_SCANNED_PLACES, false); 160 | } 161 | 162 | @Override 163 | public boolean getShowPokestops() { 164 | return sharedPreferences.getBoolean(SHOW_POKESTOPS, false); 165 | } 166 | 167 | @Override 168 | public int getSteps() { 169 | return Integer.parseInt(sharedPreferences.getString(STEPS, "3")); 170 | } 171 | 172 | @Override 173 | public boolean getShowGyms() { 174 | return sharedPreferences.getBoolean(SHOW_GYMS, false); 175 | } 176 | 177 | @Override 178 | public boolean getShowLuredPokemon() { 179 | return sharedPreferences.getBoolean(SHOW_LURED, true); 180 | } 181 | 182 | public Set getShowablePokemonIDs() { 183 | Set showablePokemonStringIDs = sharedPreferences.getStringSet(POKEMONS_TO_SHOW, null); 184 | if(showablePokemonStringIDs == null) { 185 | //Provides the filter with all available pokemon if no filter is set. 186 | showablePokemonStringIDs = new HashSet<>(); 187 | for (PokemonIdOuterClass.PokemonId pokemonId : PokemonIdOuterClass.PokemonId.values()) { 188 | if(pokemonId != PokemonIdOuterClass.PokemonId.UNRECOGNIZED) { 189 | showablePokemonStringIDs.add(String.valueOf(pokemonId.getNumber())); 190 | } 191 | } 192 | } 193 | Set showablePokemonIDs = new HashSet<>(); 194 | for (String stringId : showablePokemonStringIDs) { 195 | showablePokemonIDs.add(PokemonIdOuterClass.PokemonId.forNumber(Integer.valueOf(stringId))); 196 | } 197 | return showablePokemonIDs; 198 | } 199 | 200 | public void setShowablePokemonIDs(Set ids) { 201 | Set showablePokemonStringIDs = new HashSet<>(); 202 | for (PokemonIdOuterClass.PokemonId pokemonId : ids) { 203 | showablePokemonStringIDs.add(String.valueOf(pokemonId.getNumber())); 204 | } 205 | sharedPreferences.edit().putStringSet(POKEMONS_TO_SHOW, showablePokemonStringIDs).apply(); 206 | } 207 | 208 | @Override 209 | public void setShowMapSuggestion(boolean showMapSuggestion) { 210 | sharedPreferences.edit().putBoolean(SHOW_MAP_SUGGESTION, showMapSuggestion).apply(); 211 | } 212 | 213 | @Override 214 | public boolean getShowMapSuggestion() { 215 | return sharedPreferences.getBoolean(SHOW_MAP_SUGGESTION, true); 216 | } 217 | 218 | @Override 219 | public void setServiceState(@NonNull boolean isEnabled) { 220 | sharedPreferences.edit().putBoolean(SERVICE_KEY, isEnabled).apply(); 221 | } 222 | 223 | @Override 224 | public boolean isServiceEnabled() { 225 | return sharedPreferences.getBoolean(SERVICE_KEY, false); 226 | } 227 | 228 | @Override 229 | public int getServiceRefreshRate() { 230 | return Integer.valueOf(sharedPreferences.getString(SERVICE_REFRESH_KEY, "60")); 231 | } 232 | } 233 | -------------------------------------------------------------------------------- /app/src/main/java/com/omkarmoghe/pokemap/controllers/map/LocationManager.java: -------------------------------------------------------------------------------- 1 | package com.omkarmoghe.pokemap.controllers.map; 2 | 3 | import android.Manifest; 4 | import android.app.Activity; 5 | import android.content.Context; 6 | import android.content.pm.PackageManager; 7 | import android.location.Location; 8 | import android.os.Bundle; 9 | import android.support.annotation.NonNull; 10 | import android.support.annotation.Nullable; 11 | import android.support.v4.app.ActivityCompat; 12 | import android.util.Log; 13 | 14 | import com.google.android.gms.common.ConnectionResult; 15 | import com.google.android.gms.common.api.GoogleApiClient; 16 | import com.google.android.gms.location.LocationListener; 17 | import com.google.android.gms.location.LocationRequest; 18 | import com.google.android.gms.location.LocationServices; 19 | import com.google.android.gms.maps.model.LatLng; 20 | 21 | import java.util.ArrayList; 22 | import java.util.List; 23 | 24 | /** 25 | * Created by vanshilshah on 19/07/16. 26 | */ 27 | public class LocationManager { 28 | 29 | private static final String TAG = "LocationManager"; 30 | private List listeners; 31 | 32 | GoogleApiClient mGoogleApiClient; 33 | 34 | private static LocationManager instance; 35 | public boolean pingLocation = false; 36 | 37 | Location location; 38 | 39 | public static LocationManager getInstance(Context context) { 40 | if (instance == null) { 41 | instance = new LocationManager(context); 42 | } 43 | 44 | return instance; 45 | } 46 | private LocationManager(final Context context) { 47 | final LocationListener locationListener = new LocationListener() { 48 | @Override 49 | public void onLocationChanged(Location newLocation) { 50 | location = newLocation; 51 | Log.d(TAG, "User location found: " + location.getLatitude() + ", " + location.getLongitude()); 52 | notifyLocationChanged(location); 53 | } 54 | }; 55 | if (mGoogleApiClient == null) { 56 | mGoogleApiClient = new GoogleApiClient.Builder(context) 57 | .addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() { 58 | @Override 59 | public void onConnected(@Nullable Bundle bundle) { 60 | LocationRequest mLocationRequest = new LocationRequest(); 61 | mLocationRequest.setInterval(10000); 62 | mLocationRequest.setFastestInterval(5000); 63 | mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); 64 | 65 | if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { 66 | if (context instanceof Activity) { 67 | ActivityCompat.requestPermissions((Activity) context, new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, 0); 68 | 69 | } 70 | return; 71 | } 72 | 73 | LocationServices.FusedLocationApi.requestLocationUpdates( 74 | mGoogleApiClient, mLocationRequest, locationListener); 75 | 76 | } 77 | 78 | @Override 79 | public void onConnectionSuspended(int i) { 80 | Log.e(TAG, "Failed to fetch user location. Connection suspended, code: " + i); 81 | notifyLocationFetchFailed(null); 82 | } 83 | }) 84 | .addOnConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() { 85 | @Override 86 | public void onConnectionFailed(@NonNull ConnectionResult connectionResult) { 87 | Log.e(TAG, "Failed to fetch user location. Connection result: " + connectionResult.getErrorMessage()); 88 | notifyLocationFetchFailed(connectionResult); 89 | } 90 | }) 91 | .addApi(LocationServices.API) 92 | .build(); 93 | } 94 | listeners = new ArrayList<>(); 95 | } 96 | 97 | public LatLng getLocation(){ 98 | //Don't getLatitude without checking if location is not null... it will throw sys err... 99 | if(location != null){ 100 | return new LatLng(location.getLatitude(), location.getLongitude()); 101 | } else { 102 | notifyLocationFetchFailed(null); 103 | } 104 | return null; 105 | } 106 | 107 | public void onResume(){ 108 | 109 | if (mGoogleApiClient != null) { 110 | mGoogleApiClient.connect(); 111 | } 112 | } 113 | 114 | public void onPause(){ 115 | 116 | if (mGoogleApiClient != null) { 117 | mGoogleApiClient.disconnect(); 118 | } 119 | } 120 | 121 | public void unregister(Listener listener){ 122 | if(listeners != null && listeners.indexOf(listener) != -1){ 123 | listeners.remove(listener); 124 | } 125 | } 126 | public void register(Listener listener){ 127 | if(listeners != null && listeners.indexOf(listener) == -1){ 128 | listeners.add(listener); 129 | } 130 | } 131 | 132 | private void notifyLocationFetchFailed(@Nullable ConnectionResult connectionResult) { 133 | 134 | if (listeners != null) { 135 | 136 | for (Listener listener : listeners) { 137 | listener.onLocationFetchFailed(connectionResult); 138 | } 139 | } 140 | } 141 | 142 | private void notifyLocationChanged(Location location){ 143 | 144 | if (listeners != null) { 145 | for (Listener listener : listeners) { 146 | listener.onLocationChanged(location); 147 | } 148 | } 149 | 150 | } 151 | 152 | public interface Listener { 153 | void onLocationChanged(Location location); 154 | void onLocationFetchFailed(@Nullable ConnectionResult connectionResult); 155 | } 156 | 157 | 158 | } 159 | -------------------------------------------------------------------------------- /app/src/main/java/com/omkarmoghe/pokemap/controllers/net/GoogleManager.java: -------------------------------------------------------------------------------- 1 | package com.omkarmoghe.pokemap.controllers.net; 2 | 3 | import android.util.Log; 4 | 5 | import okhttp3.FormBody; 6 | import okhttp3.HttpUrl; 7 | import okhttp3.OkHttpClient; 8 | import okhttp3.RequestBody; 9 | import retrofit2.Call; 10 | import retrofit2.Callback; 11 | import retrofit2.Response; 12 | import retrofit2.Retrofit; 13 | import retrofit2.converter.gson.GsonConverterFactory; 14 | 15 | /** 16 | * Created by chris on 7/21/2016. 17 | */ 18 | public class GoogleManager { 19 | private static final String TAG = "GoogleManager"; 20 | 21 | private static GoogleManager ourInstance = new GoogleManager(); 22 | 23 | private static final String BASE_URL = "https://www.google.com"; 24 | private static final String SECRET = "NCjF1TLi2CcY6t5mt0ZveuL7"; 25 | public static final String CLIENT_ID = "848232511240-73ri3t7plvk96pj4f85uj8otdat2alem.apps.googleusercontent.com"; 26 | private static final String OAUTH_TOKEN_ENDPOINT = "https://www.googleapis.com/oauth2/v4/token"; 27 | public static final String OAUTH_ENDPOINT = "https://accounts.google.com/o/oauth2/v2/auth"; 28 | // private static final String OAUTH_ENDPOINT = "https://accounts.google.com/o/oauth2/device/code"; 29 | 30 | private final OkHttpClient mClient; 31 | private final GoogleService mGoogleService; 32 | 33 | public static GoogleManager getInstance() { 34 | return ourInstance; 35 | } 36 | 37 | private GoogleManager() { 38 | mClient = new OkHttpClient.Builder() 39 | .addInterceptor(new NetworkRequestLoggingInterceptor()) 40 | .followRedirects(false) 41 | .followSslRedirects(false) 42 | .build(); 43 | 44 | mGoogleService = new Retrofit.Builder() 45 | .baseUrl(BASE_URL) 46 | .addConverterFactory(GsonConverterFactory.create()) 47 | .client(mClient) 48 | .build() 49 | .create(GoogleService.class); 50 | } 51 | 52 | @Deprecated 53 | @SuppressWarnings({"deprecation","unused"}) 54 | public void authUser(final LoginListener listener) { 55 | HttpUrl url = HttpUrl.parse(OAUTH_ENDPOINT).newBuilder() 56 | .addQueryParameter("client_id", CLIENT_ID) 57 | .addQueryParameter("scope", "openid email https://www.googleapis.com/auth/userinfo.email") 58 | .addQueryParameter("response_type","code") 59 | .addQueryParameter("redirect_uri","http://127.0.0.1:9004") 60 | .build(); 61 | 62 | Callback googleCallback = new Callback() { 63 | @Override 64 | public void onResponse(Call call, Response response) { 65 | GoogleService.AuthRequest body = response.body(); 66 | 67 | if (body != null) { 68 | listener.authRequested(body); 69 | } else { 70 | Log.e(TAG, "Google login failed while authenticating. response.body() is null."); 71 | listener.authFailed("Google login failed while authenticating"); 72 | } 73 | } 74 | 75 | @Override 76 | public void onFailure(Call call, Throwable t) { 77 | t.printStackTrace(); 78 | Log.e(TAG, "Google authentication failed when calling authUser(). googleCallback's onFailure() threw: " + t.getMessage()); 79 | listener.authFailed("Failed on getting the information for the user auth"); 80 | } 81 | }; 82 | 83 | if (mGoogleService != null) { 84 | Call call = mGoogleService.requestAuth(url.toString()); 85 | call.enqueue(googleCallback); 86 | } 87 | } 88 | 89 | public void requestToken(String deviceCode, final LoginListener listener){ 90 | HttpUrl url = HttpUrl.parse(OAUTH_TOKEN_ENDPOINT).newBuilder() 91 | // .addQueryParameter("client_id", CLIENT_ID) 92 | // .addQueryParameter("client_secret", SECRET) 93 | // .addQueryParameter("code", deviceCode) 94 | // .addQueryParameter("grant_type", "http://oauth.net/grant_type/device/1.0") 95 | // .addQueryParameter("scope", "openid email https://www.googleapis.com/auth/userinfo.email") 96 | .build(); 97 | 98 | RequestBody body = new FormBody.Builder() 99 | .add("code", deviceCode) 100 | .add("client_id", CLIENT_ID) 101 | .add("client_secret", SECRET) 102 | .add("redirect_uri", "http://127.0.0.1:8080") 103 | .add("grant_type", "authorization_code") 104 | .build(); 105 | 106 | Callback googleCallback = new Callback() { 107 | @Override 108 | public void onResponse(Call call, Response response) { 109 | 110 | if (response.body() != null) { 111 | listener.authSuccessful(response.body().getIdToken(), response.body().getRefreshToken()); 112 | } else { 113 | Log.e(TAG, "Google login failed while fetching token. response.body() is null."); 114 | listener.authFailed("Google login failed while authenticating. Token missing."); 115 | } 116 | } 117 | 118 | @Override 119 | public void onFailure(Call call, Throwable t) { 120 | t.printStackTrace(); 121 | Log.e(TAG, "Google authentication failed while fetching request token using requestToken(). googleCallback's onFailure() threw: " + t.getMessage()); 122 | listener.authFailed("Failed on requesting the id token"); 123 | } 124 | }; 125 | 126 | if (mGoogleService != null) { 127 | Call call = mGoogleService.requestToken(url.toString(), body); 128 | call.enqueue(googleCallback); 129 | } 130 | } 131 | 132 | public void refreshToken(String refreshToken, final RefreshListener listener) { 133 | HttpUrl url = HttpUrl.parse(OAUTH_TOKEN_ENDPOINT).newBuilder() 134 | .addQueryParameter("client_id", CLIENT_ID) 135 | .addQueryParameter("client_secret", SECRET) 136 | .addQueryParameter("refresh_token", refreshToken) 137 | .addQueryParameter("grant_type", "refresh_token") 138 | .build(); 139 | 140 | 141 | Callback googleCallback = new Callback() { 142 | @Override 143 | public void onResponse(Call call, Response response) { 144 | if(response != null && response.body() != null) { 145 | listener.refreshSuccessful(response.body().getIdToken(), response.body().getRefreshToken()); 146 | }else { 147 | listener.refreshFailed("Failed on requesting the id token"); 148 | } 149 | } 150 | 151 | @Override 152 | public void onFailure(Call call, Throwable t) { 153 | t.printStackTrace(); 154 | listener.refreshFailed("Failed on requesting the id token"); 155 | } 156 | }; 157 | 158 | if (mGoogleService != null) { 159 | Call call = mGoogleService.requestToken(url.toString()); 160 | call.enqueue(googleCallback); 161 | } 162 | } 163 | 164 | public interface LoginListener { 165 | void authSuccessful(String authToken, String refreshToken); 166 | void authFailed(String message); 167 | @Deprecated 168 | void authRequested(GoogleService.AuthRequest body); 169 | } 170 | 171 | public interface RefreshListener { 172 | void refreshSuccessful(String authToken, String refreshToken); 173 | void refreshFailed(String message); 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /app/src/main/java/com/omkarmoghe/pokemap/controllers/net/GoogleService.java: -------------------------------------------------------------------------------- 1 | package com.omkarmoghe.pokemap.controllers.net; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | import okhttp3.RequestBody; 6 | import okhttp3.ResponseBody; 7 | import retrofit2.Call; 8 | import retrofit2.http.Body; 9 | import retrofit2.http.POST; 10 | import retrofit2.http.Url; 11 | 12 | /** 13 | * Created by chris on 7/21/2016. 14 | */ 15 | 16 | public interface GoogleService { 17 | @Deprecated 18 | @POST 19 | Call requestAuth(@Url String url); 20 | 21 | @POST 22 | Call requestToken(@Url String url, @Body RequestBody body); 23 | 24 | @POST 25 | Call requestToken(@Url String url); 26 | 27 | @Deprecated 28 | class AuthRequest{ 29 | @SerializedName("device_code") 30 | String deviceCode; 31 | @SerializedName("user_code") 32 | String userCode; 33 | @SerializedName("verification_url") 34 | String verificationUrl; 35 | @SerializedName("expires_in") 36 | int expiresIn; 37 | @SerializedName("interval") 38 | int interval; 39 | 40 | public AuthRequest(){ 41 | } 42 | 43 | public String getDeviceCode() { 44 | return deviceCode; 45 | } 46 | 47 | public String getUserCode() { 48 | return userCode; 49 | } 50 | 51 | public String getVerificationUrl() { 52 | return verificationUrl; 53 | } 54 | 55 | public int getExpiresIn() { 56 | return expiresIn; 57 | } 58 | 59 | public int getInterval() { 60 | return interval; 61 | } 62 | } 63 | 64 | class TokenResponse { 65 | @SerializedName("access_token") 66 | private String accessToken; 67 | @SerializedName("token_type") 68 | private String tokenType; 69 | @SerializedName("expires_in") 70 | private int expiresIn; 71 | @SerializedName("refresh_token") 72 | private String refreshToken; 73 | @SerializedName("id_token") 74 | private String idToken; 75 | 76 | public TokenResponse() { 77 | } 78 | 79 | public String getAccessToken() { 80 | return accessToken; 81 | } 82 | 83 | public String getTokenType() { 84 | return tokenType; 85 | } 86 | 87 | public int getExpiresIn() { 88 | return expiresIn; 89 | } 90 | 91 | public String getRefreshToken() { 92 | return refreshToken; 93 | } 94 | 95 | public String getIdToken() { 96 | return idToken; 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /app/src/main/java/com/omkarmoghe/pokemap/controllers/net/NetworkRequestLoggingInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.omkarmoghe.pokemap.controllers.net; 2 | 3 | /** 4 | * Created by vanshilshah on 20/07/16. 5 | */ 6 | 7 | import android.util.Log; 8 | 9 | import java.io.IOException; 10 | import java.text.MessageFormat; 11 | 12 | import okhttp3.HttpUrl; 13 | import okhttp3.Interceptor; 14 | import okhttp3.Request; 15 | import okhttp3.Response; 16 | import okhttp3.ResponseBody; 17 | import okio.Buffer; 18 | 19 | public class NetworkRequestLoggingInterceptor implements Interceptor { 20 | 21 | private final String TAG = "NetworkRequest"; 22 | 23 | private final String REQUEST_SEND_LOG = "Sending {0} request.\nURL: {1}\nConnection: {2}\nHeaders:\n{3}\n"; 24 | private final String REQUEST_BODY_LOG = "Request body:\n{0}\n"; 25 | private final String RESPONSE_RECEIVE_LOG = "Received response in {0} ms.\nURL: {1}. \nHeaders:\n{2}\n"; 26 | private final String RESPONSE_BODY_LOG = "Response body:\n{0}\n"; 27 | 28 | private String sanitize(HttpUrl url) { 29 | return url.toString().replaceAll("username=[^&]+","username=++++++").replaceAll("password=[^&]+","password=++++++"); 30 | } 31 | 32 | 33 | @Override 34 | public Response intercept(Interceptor.Chain chain) throws IOException { 35 | final Request request = chain.request(); 36 | 37 | // Log request 38 | Log.d(TAG, MessageFormat.format(REQUEST_SEND_LOG, request.method(), sanitize(request.url()), chain.connection(), request.headers())); 39 | if(request.method().compareToIgnoreCase("post") == 0) 40 | Log.d(TAG, MessageFormat.format(REQUEST_BODY_LOG, convertRequestBodyToString(request))); 41 | 42 | final long requestStart = System.currentTimeMillis(); 43 | final Response response = chain.proceed(request); 44 | final long requestEnd = System.currentTimeMillis(); 45 | final long responseTime = requestEnd - requestStart; 46 | 47 | // Log response 48 | Log.d(TAG, MessageFormat.format(RESPONSE_RECEIVE_LOG, responseTime, sanitize(response.request().url()), response.headers())); 49 | final String responseBodyString = response.body().string(); 50 | if(responseBodyString.length() > 0) 51 | Log.d(TAG, MessageFormat.format(RESPONSE_BODY_LOG, responseBodyString.trim())); 52 | 53 | return response.newBuilder().body(ResponseBody.create(response.body().contentType(), responseBodyString)).build(); 54 | 55 | } 56 | 57 | private String convertRequestBodyToString(final Request request) { 58 | try { 59 | final Request copy = request.newBuilder().build(); 60 | final Buffer buffer = new Buffer(); 61 | copy.body().writeTo(buffer); 62 | return buffer.readUtf8(); 63 | } catch (final IOException e) { 64 | e.printStackTrace(); 65 | Log.e(TAG, "Failed to convert request body to string via convertRequestBodyToString(). Raised: " + e.getMessage()); 66 | return null; 67 | } 68 | } 69 | } -------------------------------------------------------------------------------- /app/src/main/java/com/omkarmoghe/pokemap/controllers/net/NianticService.java: -------------------------------------------------------------------------------- 1 | package com.omkarmoghe.pokemap.controllers.net; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | import okhttp3.ResponseBody; 6 | import retrofit2.Call; 7 | import retrofit2.http.GET; 8 | import retrofit2.http.Headers; 9 | import retrofit2.http.POST; 10 | import retrofit2.http.Url; 11 | 12 | /** 13 | * Created by vanshilshah on 20/07/16. 14 | */ 15 | public interface NianticService { 16 | @Headers("User-Agent: Niantic") 17 | @GET("login?service=https://sso.pokemon.com/sso/oauth2.0/callbackAuthorize") 18 | Call getLoginValues(); 19 | 20 | @Headers("User-Agent: Niantic") 21 | @POST 22 | Call login(@Url String url); 23 | 24 | 25 | @Headers("User-Agent: Niantic") 26 | @POST 27 | Call requestToken(@Url String url); 28 | 29 | class LoginValues { 30 | private String lt; 31 | private String execution; 32 | 33 | public LoginValues(){ 34 | } 35 | 36 | public String getLt() { 37 | return lt; 38 | } 39 | public String getExecution() { 40 | return execution; 41 | } 42 | } 43 | 44 | class LoginResponse{ 45 | public LoginResponse(){ 46 | } 47 | } 48 | 49 | class LoginError{ 50 | private String[] errors; 51 | } 52 | } 53 | 54 | -------------------------------------------------------------------------------- /app/src/main/java/com/omkarmoghe/pokemap/controllers/service/PokemonNotificationService.java: -------------------------------------------------------------------------------- 1 | package com.omkarmoghe.pokemap.controllers.service; 2 | 3 | import android.app.NotificationManager; 4 | import android.app.PendingIntent; 5 | import android.app.Service; 6 | import android.content.BroadcastReceiver; 7 | import android.content.Context; 8 | import android.content.Intent; 9 | import android.content.IntentFilter; 10 | import android.location.Location; 11 | import android.os.IBinder; 12 | import android.support.v4.app.NotificationCompat; 13 | import android.util.Log; 14 | 15 | import com.google.android.gms.maps.model.LatLng; 16 | import com.omkarmoghe.pokemap.R; 17 | import com.omkarmoghe.pokemap.controllers.app_preferences.PokemapSharedPreferences; 18 | import com.omkarmoghe.pokemap.controllers.map.LocationManager; 19 | import com.omkarmoghe.pokemap.controllers.net.NianticManager; 20 | import com.omkarmoghe.pokemap.models.events.CatchablePokemonEvent; 21 | import com.omkarmoghe.pokemap.util.PokemonIdUtils; 22 | import com.omkarmoghe.pokemap.views.MainActivity; 23 | import com.pokegoapi.api.map.pokemon.CatchablePokemon; 24 | 25 | import org.greenrobot.eventbus.EventBus; 26 | import org.greenrobot.eventbus.Subscribe; 27 | 28 | import java.util.List; 29 | import java.util.Set; 30 | import java.util.concurrent.TimeUnit; 31 | 32 | import POGOProtos.Enums.PokemonIdOuterClass; 33 | 34 | 35 | public class PokemonNotificationService extends Service{ 36 | 37 | private static final String TAG = "NotificationService"; 38 | 39 | private static final int notificationId = 2423235; 40 | private static final String ACTION_STOP_SELF = "com.omkarmoghe.pokemap.STOP_SERVICE"; 41 | 42 | public static boolean isRunning = false; 43 | 44 | private UpdateRunnable updateRunnable; 45 | private Thread workThread; 46 | private LocationManager locationManager; 47 | private NianticManager nianticManager; 48 | private NotificationCompat.Builder builder; 49 | private PokemapSharedPreferences preffs; 50 | 51 | 52 | public PokemonNotificationService() { 53 | } 54 | 55 | @Override 56 | public IBinder onBind(Intent intent) { 57 | throw new UnsupportedOperationException("Not yet implemented"); 58 | } 59 | 60 | @Override 61 | public void onCreate() { 62 | 63 | EventBus.getDefault().register(this); 64 | createNotification(); 65 | 66 | preffs = new PokemapSharedPreferences(this); 67 | 68 | locationManager = LocationManager.getInstance(this); 69 | nianticManager = NianticManager.getInstance(); 70 | 71 | updateRunnable = new UpdateRunnable(preffs.getServiceRefreshRate() * 1000); 72 | workThread = new Thread(updateRunnable); 73 | 74 | initBroadcastReciever(); 75 | workThread.start(); 76 | locationManager.onResume(); 77 | 78 | isRunning = true; 79 | } 80 | 81 | /** 82 | * This sets up the broadcast reciever. 83 | */ 84 | private void initBroadcastReciever() { 85 | IntentFilter intentFilter = new IntentFilter(); 86 | intentFilter.addAction(ACTION_STOP_SELF); 87 | registerReceiver(mBroadcastReciever,intentFilter); 88 | } 89 | 90 | @Override 91 | public void onDestroy() { 92 | cancelNotification(); 93 | updateRunnable.stop(); 94 | EventBus.getDefault().unregister(this); 95 | unregisterReceiver(mBroadcastReciever); 96 | isRunning = false; 97 | } 98 | 99 | @Override 100 | public int onStartCommand(Intent intent, int flags, int startId) { 101 | return START_NOT_STICKY; 102 | } 103 | 104 | private void createNotification(){ 105 | builder = new NotificationCompat.Builder(getApplication()) 106 | .setSmallIcon(R.drawable.ic_gps_fixed_white_24px) 107 | .setContentTitle(getString(R.string.notification_service_title)) 108 | .setContentText(getString(R.string.notification_service_scanning)).setOngoing(true); 109 | 110 | Intent i = new Intent(this, MainActivity.class); 111 | i.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); 112 | 113 | PendingIntent pi = PendingIntent.getActivity(this,0,i,PendingIntent.FLAG_CANCEL_CURRENT); 114 | 115 | NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); 116 | 117 | builder.setContentIntent(pi); 118 | 119 | Intent stopService = new Intent(); 120 | stopService.setAction(ACTION_STOP_SELF); 121 | 122 | PendingIntent piStopService = PendingIntent.getBroadcast(this,0,stopService,0); 123 | builder.addAction(R.drawable.ic_cancel_white_24px, getString(R.string.notification_service_stop), piStopService); 124 | 125 | Intent pokemonGoIntent = getPackageManager().getLaunchIntentForPackage("com.nianticlabs.pokemongo"); 126 | if (pokemonGoIntent != null) { // make sure we will be able to launch Pokémon GO 127 | PendingIntent pokemonGoPendingIntent = PendingIntent.getActivity(this, 1, pokemonGoIntent, 0); 128 | builder.addAction(R.drawable.ic_pokeball, getString(R.string.notification_service_launch_pokemon_go), pokemonGoPendingIntent); 129 | } 130 | 131 | nm.notify(notificationId,builder.build()); 132 | } 133 | 134 | private void cancelNotification(){ 135 | NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); 136 | nm.cancel(notificationId); 137 | } 138 | 139 | @Subscribe 140 | public void onEvent(CatchablePokemonEvent event) { 141 | List catchablePokemon = event.getCatchablePokemon(); 142 | 143 | LatLng location = locationManager.getLocation(); 144 | Location myLoc = new Location(""); 145 | myLoc.setLatitude(location.latitude); 146 | myLoc.setLongitude(location.longitude); 147 | builder.setContentText(getString(R.string.notification_service_pokemon_near,catchablePokemon.size())); 148 | builder.setStyle(null); 149 | 150 | if(!catchablePokemon.isEmpty()){ 151 | NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle(); 152 | inboxStyle.setBigContentTitle(getString(R.string.notification_service_pokemon_in_area, catchablePokemon.size())); 153 | Set showablePokemonIDs = preffs.getShowablePokemonIDs(); 154 | 155 | for(CatchablePokemon cp : catchablePokemon){ 156 | //Only show the notification if the Pokemon is in the preference list 157 | if(showablePokemonIDs.contains(cp.getPokemonId())) { 158 | Location pokeLocation = new Location(""); 159 | pokeLocation.setLatitude(cp.getLatitude()); 160 | pokeLocation.setLongitude(cp.getLongitude()); 161 | long remainingTime = cp.getExpirationTimestampMs() - System.currentTimeMillis(); 162 | 163 | String pokeName = PokemonIdUtils.getLocalePokemonName(getApplicationContext(),cp.getPokemonId().name()); 164 | long remTime = TimeUnit.MILLISECONDS.toMinutes(remainingTime); 165 | int dist = (int)Math.ceil(pokeLocation.distanceTo(myLoc)); 166 | 167 | inboxStyle.addLine(getString(R.string.notification_service_inbox_line, pokeName, remTime,dist)); 168 | } 169 | } 170 | 171 | builder.setStyle(inboxStyle); 172 | } 173 | 174 | NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); 175 | nm.notify(notificationId,builder.build()); 176 | } 177 | 178 | private final class UpdateRunnable implements Runnable{ 179 | private long refreshRate = preffs.getServiceRefreshRate() * 1000; 180 | private boolean isRunning = true; 181 | 182 | public UpdateRunnable(int refreshRate){ 183 | this.refreshRate = refreshRate; 184 | } 185 | 186 | @Override 187 | public void run() { 188 | 189 | try { 190 | 191 | // initial wait (fFor a reason! Do NOT remove because of cyclic sleep!) 192 | Thread.sleep(refreshRate); 193 | 194 | while (isRunning) { 195 | 196 | LatLng currentLocation = locationManager.getLocation(); 197 | 198 | if (currentLocation != null){ 199 | nianticManager.getCatchablePokemon(currentLocation.latitude,currentLocation.longitude,0); 200 | } else { 201 | locationManager = LocationManager.getInstance(PokemonNotificationService.this); 202 | } 203 | 204 | // cyclic sleep 205 | Thread.sleep(refreshRate); 206 | 207 | } 208 | } catch (InterruptedException | NullPointerException e) { 209 | e.printStackTrace(); 210 | Log.e(TAG, "Failed updating. UpdateRunnable.run() raised: " + e.getMessage()); 211 | } 212 | } 213 | 214 | public void stop(){ 215 | isRunning = false; 216 | } 217 | } 218 | 219 | private BroadcastReceiver mBroadcastReciever = new BroadcastReceiver() { 220 | @Override 221 | public void onReceive(Context context, Intent intent) { 222 | stopSelf(); 223 | locationManager.onPause(); 224 | } 225 | }; 226 | 227 | public static boolean isRunning() { 228 | return isRunning; 229 | } 230 | } 231 | -------------------------------------------------------------------------------- /app/src/main/java/com/omkarmoghe/pokemap/helpers/MapHelper.java: -------------------------------------------------------------------------------- 1 | package com.omkarmoghe.pokemap.helpers; 2 | 3 | import com.google.android.gms.maps.model.LatLng; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | /** 9 | * Created by localuser on 7/25/2016. 10 | */ 11 | public class MapHelper { 12 | private static final String TAG = "MapHelper"; 13 | 14 | //Radius of the Earth in km 15 | public static final double EARTH = 6371; 16 | 17 | // Layers 18 | public static final float LAYER_MY_SEARCH = 0; 19 | public static final float LAYER_SCANNED_LOCATIONS = 50; 20 | public static final float LAYER_POKESTOPS = 100; 21 | public static final float LAYER_GYMS = 150; 22 | public static final float LAYER_POKEMONS = 200; 23 | 24 | public static final int SCAN_RADIUS = 70; 25 | private static final double DISTANCE_BETWEEN_CIRCLES = 121; 26 | 27 | /** 28 | * Returns the distance from 'this' point to destination point (using haversine formula). 29 | * 30 | * @return Distance between this point and destination point, in same units as radius. 31 | */ 32 | public static double distance(LatLng pointA, LatLng pointB){ 33 | //Getting the coordinates and converting them to radians 34 | double lat = Math.toRadians(pointA.latitude); 35 | double lat2 = Math.toRadians(pointB.latitude); 36 | 37 | //Getting the differences between the Lat and Long coordinates and 38 | //converting them to radians 39 | double difLat = Math.toRadians(pointB.latitude - pointA.latitude); 40 | double difLong = Math.toRadians(pointB.longitude - pointA.longitude); 41 | 42 | //Calculating the Haversine formula - a 43 | double a = (Math.pow(Math.sin(difLat/2), 2)) + 44 | (Math.cos(lat) * Math.cos(lat2) * Math.pow(Math.sin(difLong/2), 2)); 45 | 46 | //Calculating the Haversine formula - c 47 | double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 48 | 49 | //Calculating the distance using c and the radius of the earth 50 | return EARTH * c; 51 | } 52 | 53 | /** 54 | * Returns the destination point from the starting point point having travelled the given distance on the 55 | * given initial bearing (bearing normally varies around path followed). 56 | * @param point - original location in the map to translate 57 | * @param distance - the distance between the current point and the new point 58 | * @param bearing - the bearing of the object moving (clockwise from north) in degrees (0-360) 59 | * @return An ArcGIS Point class storing the the Latitude and Longitude in decimal degrees. 60 | * The x coordinate is the Longitude, the y coordinate is the Latitude 61 | */ 62 | public static LatLng translatePoint(LatLng point, double distance, double bearing){ 63 | distance = distance/1000d; 64 | 65 | //converts the Latitude, Longitude and bearings into radians 66 | double lat = Math.toRadians(point.latitude); 67 | double lng = Math.toRadians(point.longitude); 68 | bearing = Math.toRadians(bearing); 69 | 70 | //Give the distance and the first Latitude, computes the second latitude 71 | double Lat2 = Math.asin( (Math.sin(lat)*Math.cos(distance/EARTH)) + 72 | (Math.cos(lat)*Math.sin(distance/EARTH)*Math.cos(bearing)) ); 73 | 74 | //Give the distance and the first longitude, computes the second longitude 75 | double Long2 = lng + Math.atan2(Math.sin(bearing)*Math.sin(distance/EARTH)*Math.cos(lat), 76 | Math.cos(distance/EARTH)- (Math.sin(lat)*Math.sin(Lat2)) ); 77 | 78 | //Converting the new Latitude and Longitude from radians to degrees 79 | Lat2 = Math.toDegrees(Lat2); 80 | Long2 = Math.toDegrees(Long2); 81 | 82 | //Creates a point object to return back. X is the longitude, Y is the Latitude 83 | return new LatLng(Lat2, Long2); 84 | } 85 | 86 | 87 | public static List getSearchArea(int steps, LatLng center){ 88 | 89 | List searchArea = new ArrayList<>(); 90 | searchArea.add(center); 91 | 92 | int count = 0; 93 | for (int i = 2; i <= steps; i++) { 94 | 95 | LatLng prev = searchArea.get(searchArea.size() - (1 + count)); 96 | LatLng next = MapHelper.translatePoint(prev, MapHelper.DISTANCE_BETWEEN_CIRCLES, 0.0); 97 | searchArea.add(next); 98 | 99 | // go east 100 | for (int j = 0; j < i - 1; j ++) { 101 | prev = searchArea.get(searchArea.size() - 1); 102 | next = MapHelper.translatePoint(prev, MapHelper.DISTANCE_BETWEEN_CIRCLES, 120.0); 103 | searchArea.add(next); 104 | } 105 | 106 | // go due south 107 | for (int j = 0; j < i - 1; j ++) { 108 | prev = searchArea.get(searchArea.size() - 1); 109 | next = MapHelper.translatePoint(prev, MapHelper.DISTANCE_BETWEEN_CIRCLES, 180.0); 110 | searchArea.add(next); 111 | } 112 | // go south-west 113 | for (int j = 0; j < i - 1 ; j ++) { 114 | prev = searchArea.get(searchArea.size() - 1); 115 | next = MapHelper.translatePoint(prev, MapHelper.DISTANCE_BETWEEN_CIRCLES, 240.0); 116 | searchArea.add(next); 117 | } 118 | // go north-west 119 | for (int j = 0; j < i - 1; j ++) { 120 | prev = searchArea.get(searchArea.size() - 1); 121 | next = MapHelper.translatePoint(prev, MapHelper.DISTANCE_BETWEEN_CIRCLES, 300.0); 122 | searchArea.add(next); 123 | } 124 | // go due north 125 | for (int j = 0; j < i - 1; j ++) { 126 | prev = searchArea.get(searchArea.size() - 1); 127 | next = MapHelper.translatePoint(prev, MapHelper.DISTANCE_BETWEEN_CIRCLES, 0.0); 128 | searchArea.add(next); 129 | } 130 | // go north-east 131 | for (int j = 0; j < i - 2; j ++) { 132 | prev = searchArea.get(searchArea.size() - 1); 133 | next = MapHelper.translatePoint(prev, MapHelper.DISTANCE_BETWEEN_CIRCLES, 60.0); 134 | searchArea.add(next); 135 | } 136 | count = 6*(i-1)-1; 137 | } 138 | 139 | return searchArea; 140 | } 141 | 142 | 143 | public static double convertStepsToRadius(int steps) { 144 | return (steps - 1) * DISTANCE_BETWEEN_CIRCLES + SCAN_RADIUS; 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /app/src/main/java/com/omkarmoghe/pokemap/helpers/RemoteImageLoader.java: -------------------------------------------------------------------------------- 1 | package com.omkarmoghe.pokemap.helpers; 2 | 3 | import android.content.Context; 4 | import android.graphics.Bitmap; 5 | import android.graphics.drawable.Drawable; 6 | import android.widget.ImageView; 7 | 8 | import com.bumptech.glide.Glide; 9 | import com.bumptech.glide.load.engine.DiskCacheStrategy; 10 | import com.bumptech.glide.request.animation.GlideAnimation; 11 | import com.bumptech.glide.request.target.SimpleTarget; 12 | 13 | /** 14 | * Cache wrapper around the Glide image loader. 15 | * 29.07.16: for now, the second layer cache is removed, caching is handled by Glide. 16 | *

17 | * Created by aronhomberg on 26.07.16. 18 | */ 19 | public class RemoteImageLoader { 20 | 21 | public static void loadMapIcon(Context context, final String url, int pxWidth, int pxHeight, 22 | Drawable placeholderDrawable, final Callback onFetch) { 23 | Glide.with(context).load(url) 24 | .asBitmap() 25 | .skipMemoryCache(false) 26 | .placeholder(placeholderDrawable) 27 | .diskCacheStrategy(DiskCacheStrategy.RESULT) 28 | .into(new SimpleTarget(pxWidth, pxHeight) { 29 | @Override 30 | public void onResourceReady(Bitmap bitmap, GlideAnimation anim) { 31 | onFetch.onFetch(bitmap); 32 | } 33 | }); 34 | } 35 | 36 | public static void loadMapIcon(Context context, final String url, int pxWidth, int pxHeight, 37 | final Callback onFetch) { 38 | Glide.with(context).load(url) 39 | .asBitmap() 40 | .skipMemoryCache(false) 41 | .diskCacheStrategy(DiskCacheStrategy.RESULT) 42 | .into(new SimpleTarget(pxWidth, pxHeight) { 43 | @Override 44 | public void onResourceReady(Bitmap bitmap, GlideAnimation anim) { 45 | onFetch.onFetch(bitmap); 46 | } 47 | }); 48 | } 49 | 50 | public static void loadInto(ImageView view, String url, Drawable placeholderDrawable) { 51 | Glide.with(view.getContext()).load(url) 52 | .asBitmap() 53 | .skipMemoryCache(false) 54 | .placeholder(placeholderDrawable) 55 | .diskCacheStrategy(DiskCacheStrategy.SOURCE) 56 | .into(view); 57 | } 58 | 59 | public static void loadInto(ImageView view, String url) { 60 | Glide.with(view.getContext()).load(url) 61 | .asBitmap() 62 | .skipMemoryCache(false) 63 | .diskCacheStrategy(DiskCacheStrategy.SOURCE) 64 | .into(view); 65 | } 66 | 67 | public interface Callback { 68 | void onFetch(Bitmap bitmap); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /app/src/main/java/com/omkarmoghe/pokemap/models/events/CatchablePokemonEvent.java: -------------------------------------------------------------------------------- 1 | package com.omkarmoghe.pokemap.models.events; 2 | 3 | import com.pokegoapi.api.map.pokemon.CatchablePokemon; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * Created by Jon on 7/23/2016. 9 | */ 10 | public class CatchablePokemonEvent implements IEvent { 11 | 12 | private List catchablePokemon; 13 | private double lat; 14 | private double longitude; 15 | 16 | public CatchablePokemonEvent(List catchablePokemon, double lat, double longitude) { 17 | this.catchablePokemon = catchablePokemon; 18 | this.lat = lat; 19 | this.longitude = longitude; 20 | } 21 | 22 | public List getCatchablePokemon() { 23 | return catchablePokemon; 24 | } 25 | 26 | public void setCatchablePokemon(List catchablePokemon) { 27 | this.catchablePokemon = catchablePokemon; 28 | } 29 | 30 | public double getLat() { 31 | return lat; 32 | } 33 | 34 | public void setLat(double lat) { 35 | this.lat = lat; 36 | } 37 | 38 | public double getLongitude() { 39 | return longitude; 40 | } 41 | 42 | public void setLongitude(double longitude) { 43 | this.longitude = longitude; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/com/omkarmoghe/pokemap/models/events/ClearMapEvent.java: -------------------------------------------------------------------------------- 1 | package com.omkarmoghe.pokemap.models.events; 2 | 3 | 4 | /** 5 | * Created by socrates on 7/25/2016. 6 | */ 7 | public class ClearMapEvent implements IEvent { 8 | 9 | public ClearMapEvent() { 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/java/com/omkarmoghe/pokemap/models/events/GymsEvent.java: -------------------------------------------------------------------------------- 1 | package com.omkarmoghe.pokemap.models.events; 2 | 3 | import java.util.Collection; 4 | 5 | import POGOProtos.Map.Fort.FortDataOuterClass; 6 | 7 | /** 8 | * Created by aronhomberg on 7/23/2016. 9 | */ 10 | public class GymsEvent implements IEvent { 11 | 12 | private Collection gyms; 13 | private double lat; 14 | private double longitude; 15 | 16 | public GymsEvent(Collection gyms, double lat, double longitude) { 17 | this.gyms = gyms; 18 | this.lat = lat; 19 | this.longitude = longitude; 20 | } 21 | 22 | public Collection getGyms() { 23 | return gyms; 24 | } 25 | 26 | public void setGyms(Collection gyms) { 27 | this.gyms = gyms; 28 | } 29 | 30 | public double getLatitude() { 31 | return lat; 32 | } 33 | 34 | public void setLat(double lat) { 35 | this.lat = lat; 36 | } 37 | 38 | public double getLongitude() { 39 | return longitude; 40 | } 41 | 42 | public void setLongitude(double longitude) { 43 | this.longitude = longitude; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/com/omkarmoghe/pokemap/models/events/IEvent.java: -------------------------------------------------------------------------------- 1 | package com.omkarmoghe.pokemap.models.events; 2 | 3 | /** 4 | * Created by Jon on 7/23/2016. 5 | * 6 | * Simply used so that multiple event types can be returned from a single method. 7 | * 8 | */ 9 | public interface IEvent { 10 | } 11 | -------------------------------------------------------------------------------- /app/src/main/java/com/omkarmoghe/pokemap/models/events/InternalExceptionEvent.java: -------------------------------------------------------------------------------- 1 | package com.omkarmoghe.pokemap.models.events; 2 | 3 | /** 4 | * Created by aronhomberg on 25.07.16. 5 | */ 6 | public class InternalExceptionEvent implements IEvent { 7 | 8 | private Exception e; 9 | 10 | public InternalExceptionEvent(Exception e) { 11 | this.e = e; 12 | } 13 | 14 | public Exception getE() { 15 | return e; 16 | } 17 | 18 | public void setE(Exception e) { 19 | this.e = e; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/omkarmoghe/pokemap/models/events/LoginEventResult.java: -------------------------------------------------------------------------------- 1 | package com.omkarmoghe.pokemap.models.events; 2 | 3 | import com.pokegoapi.api.PokemonGo; 4 | import POGOProtos.Networking.Envelopes.RequestEnvelopeOuterClass.RequestEnvelope.AuthInfo; 5 | 6 | /** 7 | * Created by Jon on 7/23/2016. 8 | */ 9 | public class LoginEventResult implements IEvent { 10 | 11 | private boolean loggedIn; 12 | private AuthInfo authInfo; 13 | private PokemonGo pokemonGo; 14 | 15 | public LoginEventResult(boolean loggedIn, AuthInfo authInfo, PokemonGo pokemonGo) { 16 | this.loggedIn = loggedIn; 17 | this.authInfo = authInfo; 18 | this.pokemonGo = pokemonGo; 19 | } 20 | 21 | public boolean isLoggedIn() { 22 | return loggedIn; 23 | } 24 | 25 | public void setLoggedIn(boolean loggedIn) { 26 | this.loggedIn = loggedIn; 27 | } 28 | 29 | public AuthInfo getAuthInfo() { 30 | return authInfo; 31 | } 32 | 33 | public void setAuthInfo(AuthInfo authInfo) { 34 | this.authInfo = authInfo; 35 | } 36 | 37 | public PokemonGo getPokemonGo() { 38 | return pokemonGo; 39 | } 40 | 41 | public void setPokemonGo(PokemonGo pokemonGo) { 42 | this.pokemonGo = pokemonGo; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/src/main/java/com/omkarmoghe/pokemap/models/events/LurePokemonEvent.java: -------------------------------------------------------------------------------- 1 | package com.omkarmoghe.pokemap.models.events; 2 | 3 | import com.pokegoapi.api.map.pokemon.CatchablePokemon; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * Created by chris on 7/27/2016. 9 | */ 10 | 11 | public class LurePokemonEvent { 12 | private List catchablePokemon; 13 | private double lat; 14 | private double longitude; 15 | 16 | public LurePokemonEvent(List catchablePokemon, double lat, double longitude) { 17 | this.catchablePokemon = catchablePokemon; 18 | this.lat = lat; 19 | this.longitude = longitude; 20 | } 21 | 22 | public List getCatchablePokemon() { 23 | return catchablePokemon; 24 | } 25 | 26 | public void setCatchablePokemon(List catchablePokemon) { 27 | this.catchablePokemon = catchablePokemon; 28 | } 29 | 30 | public double getLat() { 31 | return lat; 32 | } 33 | 34 | public void setLat(double lat) { 35 | this.lat = lat; 36 | } 37 | 38 | public double getLongitude() { 39 | return longitude; 40 | } 41 | 42 | public void setLongitude(double longitude) { 43 | this.longitude = longitude; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/com/omkarmoghe/pokemap/models/events/MarkerExpired.java: -------------------------------------------------------------------------------- 1 | package com.omkarmoghe.pokemap.models.events; 2 | 3 | import com.google.android.gms.maps.model.Marker; 4 | import com.omkarmoghe.pokemap.models.map.PokemonMarkerExtended; 5 | import com.pokegoapi.api.map.pokemon.CatchablePokemon; 6 | 7 | /** 8 | * Created by chris on 7/26/2016. 9 | */ 10 | 11 | public class MarkerExpired { 12 | 13 | private PokemonMarkerExtended mData; 14 | 15 | public MarkerExpired(PokemonMarkerExtended markerData){ 16 | mData = markerData; 17 | } 18 | 19 | public PokemonMarkerExtended getData(){ 20 | return mData; 21 | } 22 | 23 | public Marker getMarker(){ 24 | return mData.getMarker(); 25 | } 26 | 27 | public CatchablePokemon getPokemon(){ 28 | return mData.getCatchablePokemon(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/omkarmoghe/pokemap/models/events/MarkerUpdate.java: -------------------------------------------------------------------------------- 1 | package com.omkarmoghe.pokemap.models.events; 2 | 3 | /** 4 | * Created by Rohan on 26-07-2016. 5 | */ 6 | 7 | import com.google.android.gms.maps.model.Marker; 8 | import com.omkarmoghe.pokemap.models.map.PokemonMarkerExtended; 9 | import com.pokegoapi.api.map.pokemon.CatchablePokemon; 10 | 11 | /** 12 | * Empty event. 13 | */ 14 | public class MarkerUpdate { 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/omkarmoghe/pokemap/models/events/PokestopsEvent.java: -------------------------------------------------------------------------------- 1 | package com.omkarmoghe.pokemap.models.events; 2 | 3 | import com.pokegoapi.api.map.fort.Pokestop; 4 | 5 | import java.util.Collection; 6 | 7 | /** 8 | * Created by socrates on 7/23/2016. 9 | */ 10 | public class PokestopsEvent implements IEvent { 11 | 12 | private Collection pokestops; 13 | private double lat; 14 | private double longitude; 15 | 16 | public PokestopsEvent(Collection pokestops, double lat, double longitude) { 17 | this.pokestops = pokestops; 18 | this.lat = lat; 19 | this.longitude = longitude; 20 | } 21 | 22 | public Collection getPokestops() { 23 | return pokestops; 24 | } 25 | 26 | public void setPokestops(Collection pokestops) { 27 | this.pokestops = pokestops; 28 | } 29 | 30 | public double getLatitude() { 31 | return lat; 32 | } 33 | 34 | public void setLat(double lat) { 35 | this.lat = lat; 36 | } 37 | 38 | public double getLongitude() { 39 | return longitude; 40 | } 41 | 42 | public void setLongitude(double longitude) { 43 | this.longitude = longitude; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/com/omkarmoghe/pokemap/models/events/SearchInPosition.java: -------------------------------------------------------------------------------- 1 | package com.omkarmoghe.pokemap.models.events; 2 | 3 | import com.google.android.gms.maps.model.LatLng; 4 | 5 | /** 6 | * Created by Link on 23/07/2016. 7 | */ 8 | public class SearchInPosition { 9 | 10 | private LatLng position; 11 | private int steps; 12 | 13 | public LatLng getPosition() { 14 | return position; 15 | } 16 | 17 | public void setPosition(LatLng position) { 18 | this.position = position; 19 | } 20 | 21 | public int getSteps() { 22 | return steps; 23 | } 24 | 25 | public void setSteps(int steps) { 26 | this.steps = steps; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/java/com/omkarmoghe/pokemap/models/events/ServerUnreachableEvent.java: -------------------------------------------------------------------------------- 1 | package com.omkarmoghe.pokemap.models.events; 2 | 3 | import com.pokegoapi.exceptions.RemoteServerException; 4 | 5 | /** 6 | * Created by Jon on 7/23/2016. 7 | */ 8 | public class ServerUnreachableEvent implements IEvent { 9 | 10 | private RemoteServerException e; 11 | 12 | public ServerUnreachableEvent(RemoteServerException e) { 13 | this.e = e; 14 | } 15 | 16 | public RemoteServerException getE() { 17 | return e; 18 | } 19 | 20 | public void setE(RemoteServerException e) { 21 | this.e = e; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/omkarmoghe/pokemap/models/login/GoogleLoginInfo.java: -------------------------------------------------------------------------------- 1 | package com.omkarmoghe.pokemap.models.login; 2 | 3 | /** 4 | * Created by chris on 7/26/2016. 5 | */ 6 | 7 | public class GoogleLoginInfo extends LoginInfo { 8 | 9 | private String mRefreshToken; 10 | 11 | public GoogleLoginInfo(String authToken, String refreshToken){ 12 | super(authToken); 13 | mRefreshToken = refreshToken; 14 | } 15 | 16 | public String getRefreshToken() { 17 | return mRefreshToken; 18 | } 19 | 20 | public void setRefreshToken(String refreshToken) { 21 | this.mRefreshToken = refreshToken; 22 | } 23 | 24 | @Override 25 | public String getProvider() { 26 | return PROVIDER_GOOGLE; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/java/com/omkarmoghe/pokemap/models/login/LoginInfo.java: -------------------------------------------------------------------------------- 1 | package com.omkarmoghe.pokemap.models.login; 2 | 3 | import POGOProtos.Networking.Envelopes.RequestEnvelopeOuterClass.RequestEnvelope.AuthInfo; 4 | 5 | /** 6 | * Created by chris on 7/25/2016. 7 | */ 8 | 9 | public abstract class LoginInfo { 10 | 11 | public static final String PROVIDER_GOOGLE = "google"; 12 | public static final String PROVIDER_PTC = "ptc"; 13 | 14 | private String mToken; 15 | 16 | public LoginInfo(String token){ 17 | mToken = token; 18 | } 19 | 20 | public void setToken(String token) { 21 | this.mToken = token; 22 | } 23 | 24 | public String getToken(){ 25 | return mToken; 26 | } 27 | 28 | public abstract String getProvider(); 29 | 30 | public AuthInfo createAuthInfo(){ 31 | AuthInfo.Builder builder = AuthInfo.newBuilder(); 32 | builder.setProvider(getProvider()); 33 | builder.setToken(AuthInfo.JWT.newBuilder().setContents(mToken).setUnknown2(59).build()); 34 | return builder.build(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/java/com/omkarmoghe/pokemap/models/login/PtcLoginInfo.java: -------------------------------------------------------------------------------- 1 | package com.omkarmoghe.pokemap.models.login; 2 | 3 | /** 4 | * Created by chris on 7/26/2016. 5 | */ 6 | 7 | public class PtcLoginInfo extends LoginInfo { 8 | 9 | private String mUsername; 10 | private String mPassword; 11 | 12 | public PtcLoginInfo(String authToken, String username, String password){ 13 | super(authToken); 14 | mUsername = username; 15 | mPassword = password; 16 | } 17 | 18 | public String getUsername() { 19 | return mUsername; 20 | } 21 | 22 | public void setUsername(String username) { 23 | this.mUsername = username; 24 | } 25 | 26 | public String getPassword() { 27 | return mPassword; 28 | } 29 | 30 | public void setPassword(String password) { 31 | this.mPassword = password; 32 | } 33 | 34 | @Override 35 | public String getProvider() { 36 | return PROVIDER_PTC; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/src/main/java/com/omkarmoghe/pokemap/models/map/GymMarkerExtended.java: -------------------------------------------------------------------------------- 1 | package com.omkarmoghe.pokemap.models.map; 2 | 3 | import com.google.android.gms.maps.model.Marker; 4 | import com.pokegoapi.api.map.fort.Pokestop; 5 | 6 | import POGOProtos.Map.Fort.FortDataOuterClass; 7 | 8 | /** 9 | * Created by aronhomberg on 7/26/2016. 10 | */ 11 | public class GymMarkerExtended { 12 | 13 | 14 | private FortDataOuterClass.FortData gym; 15 | private Marker marker; 16 | 17 | public GymMarkerExtended(FortDataOuterClass.FortData gym, Marker marker) { 18 | this.gym = gym; 19 | this.marker = marker; 20 | } 21 | 22 | public FortDataOuterClass.FortData getGym() { 23 | return gym; 24 | } 25 | 26 | public void setGym(FortDataOuterClass.FortData gym) { 27 | this.gym = gym; 28 | } 29 | 30 | public Marker getMarker() { 31 | return marker; 32 | } 33 | 34 | public void setMarker(Marker marker) { 35 | this.marker = marker; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/java/com/omkarmoghe/pokemap/models/map/PokemonMarkerExtended.java: -------------------------------------------------------------------------------- 1 | package com.omkarmoghe.pokemap.models.map; 2 | 3 | import com.pokegoapi.api.map.pokemon.CatchablePokemon; 4 | import com.google.android.gms.maps.model.Marker; 5 | 6 | /** 7 | * Created by socrates on 7/24/2016. 8 | */ 9 | public class PokemonMarkerExtended { 10 | 11 | 12 | private CatchablePokemon catchablePokemon; 13 | private Marker marker; 14 | 15 | public PokemonMarkerExtended(CatchablePokemon catchablePokemon, Marker marker) { 16 | this.catchablePokemon = catchablePokemon; 17 | this.marker = marker; 18 | } 19 | 20 | public CatchablePokemon getCatchablePokemon() { 21 | return catchablePokemon; 22 | } 23 | 24 | public void setCatchablePokemon(CatchablePokemon catchablePokemon) { 25 | this.catchablePokemon = catchablePokemon; 26 | } 27 | 28 | public Marker getMarker() { 29 | return marker; 30 | } 31 | 32 | public void setMarker(Marker marker) { 33 | this.marker = marker; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/com/omkarmoghe/pokemap/models/map/PokestopMarkerExtended.java: -------------------------------------------------------------------------------- 1 | package com.omkarmoghe.pokemap.models.map; 2 | 3 | import com.google.android.gms.maps.model.Marker; 4 | import com.pokegoapi.api.map.fort.Pokestop; 5 | 6 | /** 7 | * Created by socrates on 7/25/2016. 8 | */ 9 | public class PokestopMarkerExtended { 10 | 11 | 12 | private Pokestop pokestop; 13 | private Marker marker; 14 | 15 | public PokestopMarkerExtended(Pokestop pokestop, Marker marker) { 16 | this.pokestop = pokestop; 17 | this.marker = marker; 18 | } 19 | 20 | public Pokestop getPokestop() { 21 | return pokestop; 22 | } 23 | 24 | public void setPokestop(Pokestop pokestop) { 25 | this.pokestop = pokestop; 26 | } 27 | 28 | public Marker getMarker() { 29 | return marker; 30 | } 31 | 32 | public void setMarker(Marker marker) { 33 | this.marker = marker; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/com/omkarmoghe/pokemap/util/PokemonIdUtils.java: -------------------------------------------------------------------------------- 1 | package com.omkarmoghe.pokemap.util; 2 | 3 | import android.content.Context; 4 | import android.content.res.Resources; 5 | 6 | import com.omkarmoghe.pokemap.R; 7 | import com.pokegoapi.util.Log; 8 | 9 | import java.lang.reflect.Field; 10 | 11 | import POGOProtos.Enums.PokemonIdOuterClass; 12 | 13 | /** 14 | * Utility methods to ease localization and handling of pokemon IDs. 15 | *

16 | * Created by fess on 26.07.16. 17 | */ 18 | public class PokemonIdUtils { 19 | 20 | //Getting correct pokemon Id eg: 1 must be 001, 10 must be 010 21 | public static String getCorrectPokemonImageId(int pokemonNumber) { 22 | return String.format("%03d", pokemonNumber); 23 | } 24 | 25 | /** 26 | * try to resolve PokemonName from Resources 27 | * @param apiPokeName 28 | * @return 29 | */ 30 | public static String getLocalePokemonName(Context context, String apiPokeName){ 31 | 32 | int resId = context.getResources().getIdentifier(apiPokeName.toLowerCase(), "string", context.getPackageName()); 33 | return resId > 0 ? context.getString(resId) : apiPokeName; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/com/omkarmoghe/pokemap/views/BaseActivity.java: -------------------------------------------------------------------------------- 1 | package com.omkarmoghe.pokemap.views; 2 | 3 | import android.os.Bundle; 4 | import android.support.v7.app.AppCompatActivity; 5 | 6 | import com.omkarmoghe.pokemap.controllers.map.LocationManager; 7 | import com.omkarmoghe.pokemap.controllers.net.NianticManager; 8 | 9 | /** 10 | * Created by vanshilshah on 19/07/16. 11 | */ 12 | public class BaseActivity extends AppCompatActivity { 13 | public static final String TAG = "BaseActivity"; 14 | protected LocationManager.Listener locationListener; 15 | LocationManager locationManager; 16 | protected NianticManager nianticManager; 17 | 18 | @Override 19 | protected void onCreate(Bundle savedInstanceState) { 20 | super.onCreate(savedInstanceState); 21 | locationManager = LocationManager.getInstance(this); 22 | nianticManager = NianticManager.getInstance(); 23 | 24 | } 25 | 26 | @Override 27 | public void onResume(){ 28 | super.onResume(); 29 | locationManager.onResume(); 30 | if(locationListener != null){ 31 | locationManager.register(locationListener); 32 | } 33 | } 34 | 35 | @Override 36 | public void onPause(){ 37 | LocationManager.getInstance(this).onPause(); 38 | if(locationListener != null){ 39 | locationManager.unregister(locationListener); 40 | } 41 | super.onPause(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/src/main/java/com/omkarmoghe/pokemap/views/GoogleAuthActivity.java: -------------------------------------------------------------------------------- 1 | package com.omkarmoghe.pokemap.views; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.app.Activity; 5 | import android.content.Intent; 6 | import android.net.Uri; 7 | import android.support.v7.app.AppCompatActivity; 8 | import android.os.Bundle; 9 | import android.support.v7.widget.Toolbar; 10 | import android.text.TextUtils; 11 | import android.util.Log; 12 | import android.view.MenuItem; 13 | import android.webkit.WebSettings; 14 | import android.webkit.WebView; 15 | import android.webkit.WebViewClient; 16 | import android.widget.TextView; 17 | 18 | import com.omkarmoghe.pokemap.R; 19 | 20 | import okhttp3.HttpUrl; 21 | 22 | import static com.omkarmoghe.pokemap.controllers.net.GoogleManager.CLIENT_ID; 23 | import static com.omkarmoghe.pokemap.controllers.net.GoogleManager.OAUTH_ENDPOINT; 24 | 25 | public class GoogleAuthActivity extends AppCompatActivity { 26 | private static final String TAG = "GoogleAuthActivity"; 27 | 28 | private static final String ARG_URL = "Google Auth Url"; 29 | private static final String ARG_CODE = "Google User Code"; 30 | public static final String EXTRA_CODE = "Extra Google Code"; 31 | 32 | private WebView webView; 33 | 34 | public static void startForResult(Activity starter, int requestCode){ 35 | Intent intent = new Intent(starter, GoogleAuthActivity.class); 36 | starter.startActivityForResult(intent, requestCode); 37 | } 38 | 39 | @SuppressLint("SetJavaScriptEnabled") 40 | @Override 41 | protected void onCreate(Bundle savedInstanceState) { 42 | super.onCreate(savedInstanceState); 43 | setContentView(R.layout.activity_google_auth); 44 | 45 | HttpUrl url = HttpUrl.parse(OAUTH_ENDPOINT).newBuilder() 46 | .addQueryParameter("client_id", CLIENT_ID) 47 | .addQueryParameter("scope", "openid email https://www.googleapis.com/auth/userinfo.email") 48 | .addQueryParameter("response_type","code") 49 | .addQueryParameter("redirect_uri","http://127.0.0.1:8080") 50 | .build(); 51 | 52 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 53 | setSupportActionBar(toolbar); 54 | toolbar.setNavigationIcon(R.drawable.ic_arrow_back_white); 55 | 56 | webView = (WebView) findViewById(R.id.webview); 57 | 58 | 59 | WebViewClient client = new WebViewClient(){ 60 | @Override 61 | public boolean shouldOverrideUrlLoading(WebView view, String url) { 62 | if (url.startsWith("http://127.0.0.1")) { 63 | Uri uri = Uri.parse(url); 64 | 65 | sendResults(uri.getQueryParameter("code")); 66 | 67 | return true; 68 | } 69 | return super.shouldOverrideUrlLoading(view, url); 70 | } 71 | }; 72 | 73 | WebSettings webSettings = webView.getSettings(); 74 | webSettings.setJavaScriptEnabled(true); 75 | webView.setWebViewClient(client); 76 | webView.loadUrl(url.toString()); 77 | } 78 | 79 | 80 | @Override 81 | public boolean onOptionsItemSelected(MenuItem item) { 82 | int id = item.getItemId(); 83 | if (id == android.R.id.home) { 84 | onBackPressed(); 85 | return true; 86 | } 87 | return super.onOptionsItemSelected(item); 88 | } 89 | 90 | @Override 91 | public void onBackPressed() { 92 | setResult(RESULT_CANCELED); 93 | finish(); 94 | } 95 | 96 | private void sendResults(String code){ 97 | if(!TextUtils.isEmpty(code)) { 98 | Intent intent = new Intent(); 99 | intent.putExtra(EXTRA_CODE, code); 100 | setResult(RESULT_OK, intent); 101 | }else{ 102 | setResult(RESULT_CANCELED); 103 | } 104 | finish(); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /app/src/main/java/com/omkarmoghe/pokemap/views/LoginActivity.java: -------------------------------------------------------------------------------- 1 | package com.omkarmoghe.pokemap.views; 2 | 3 | import android.animation.Animator; 4 | import android.animation.AnimatorListenerAdapter; 5 | import android.annotation.TargetApi; 6 | import android.content.Intent; 7 | import android.support.design.widget.Snackbar; 8 | import android.support.v7.app.AlertDialog; 9 | import android.support.v7.app.AppCompatActivity; 10 | 11 | import android.os.Build; 12 | import android.os.Bundle; 13 | import android.text.Html; 14 | import android.text.TextUtils; 15 | import android.util.Log; 16 | import android.view.KeyEvent; 17 | import android.view.View; 18 | import android.view.View.OnClickListener; 19 | import android.view.inputmethod.EditorInfo; 20 | import android.widget.AutoCompleteTextView; 21 | import android.widget.Button; 22 | import android.widget.EditText; 23 | import android.widget.TextView; 24 | 25 | import com.google.android.gms.common.SignInButton; 26 | import com.omkarmoghe.pokemap.R; 27 | import com.omkarmoghe.pokemap.controllers.app_preferences.PokemapAppPreferences; 28 | import com.omkarmoghe.pokemap.controllers.app_preferences.PokemapSharedPreferences; 29 | import com.omkarmoghe.pokemap.controllers.net.GoogleManager; 30 | import com.omkarmoghe.pokemap.controllers.net.GoogleService; 31 | import com.omkarmoghe.pokemap.controllers.net.NianticManager; 32 | import com.omkarmoghe.pokemap.models.login.GoogleLoginInfo; 33 | import com.omkarmoghe.pokemap.models.login.LoginInfo; 34 | import com.omkarmoghe.pokemap.models.login.PtcLoginInfo; 35 | 36 | /** 37 | * A login screen that offers login via username/password. And a Google Sign in 38 | * 39 | */ 40 | public class LoginActivity extends AppCompatActivity{ 41 | 42 | private static final String TAG = "LoginActivity"; 43 | 44 | private static final int REQUEST_USER_AUTH = 1; 45 | 46 | // UI references. 47 | private AutoCompleteTextView mUsernameView; 48 | private EditText mPasswordView; 49 | private View mProgressView; 50 | private View mLoginFormView; 51 | private NianticManager mNianticManager; 52 | private NianticManager.LoginListener mNianticLoginListener; 53 | private NianticManager.AuthListener mNianticAuthListener; 54 | private GoogleManager mGoogleManager; 55 | private GoogleManager.LoginListener mGoogleLoginListener; 56 | 57 | private PokemapAppPreferences mPref; 58 | 59 | @Override 60 | protected void onCreate(Bundle savedInstanceState) { 61 | super.onCreate(savedInstanceState); 62 | 63 | mNianticManager = NianticManager.getInstance(); 64 | mGoogleManager = GoogleManager.getInstance(); 65 | mPref = new PokemapSharedPreferences(this); 66 | 67 | setContentView(R.layout.activity_login); 68 | 69 | mNianticAuthListener = new NianticManager.AuthListener() { 70 | @Override 71 | public void authSuccessful() { 72 | finishLogin(); 73 | } 74 | 75 | @Override 76 | public void authFailed(String message, String provider) { 77 | switch (provider){ 78 | case LoginInfo.PROVIDER_PTC: 79 | showPTCLoginFailed(); 80 | break; 81 | case LoginInfo.PROVIDER_GOOGLE: 82 | showGoogleLoginFailed(); 83 | break; 84 | } 85 | Log.d(TAG, "authFailed() called with: message = [" + message + "]"); 86 | } 87 | }; 88 | 89 | mNianticLoginListener = new NianticManager.LoginListener() { 90 | @Override 91 | public void authSuccessful(String authToken) { 92 | Log.d(TAG, "authSuccessful() called with: authToken = [" + authToken + "]"); 93 | PtcLoginInfo info = new PtcLoginInfo(authToken, 94 | mUsernameView.getText().toString(), mPasswordView.getText().toString()); 95 | mPref.setLoginInfo(info); 96 | mNianticManager.setLoginInfo(LoginActivity.this, info, mNianticAuthListener); 97 | } 98 | 99 | @Override 100 | public void authFailed(String message) { 101 | Log.e(TAG, "Failed to authenticate. authFailed() called with: message = [" + message + "]"); 102 | showPTCLoginFailed(); 103 | } 104 | }; 105 | 106 | mGoogleLoginListener = new GoogleManager.LoginListener() { 107 | @Override 108 | public void authSuccessful(String authToken, String refreshToken) { 109 | GoogleLoginInfo info = new GoogleLoginInfo(authToken, refreshToken); 110 | Log.d(TAG, "authSuccessful() called with: authToken = [" + authToken + "]"); 111 | mPref.setLoginInfo(info); 112 | mNianticManager.setLoginInfo(LoginActivity.this, info, mNianticAuthListener); 113 | } 114 | 115 | @Override 116 | public void authFailed(String message) { 117 | Log.d(TAG, "Failed to authenticate. authFailed() called with: message = [" + message + "]"); 118 | showGoogleLoginFailed(); 119 | } 120 | 121 | @Override 122 | public void authRequested(GoogleService.AuthRequest body) { 123 | //Do nothing 124 | } 125 | }; 126 | 127 | findViewById(R.id.txtDisclaimer).setOnClickListener(new OnClickListener() { 128 | @Override 129 | public void onClick(View view) { 130 | new AlertDialog.Builder(LoginActivity.this) 131 | .setTitle(getString(R.string.login_warning_title)) 132 | .setMessage(Html.fromHtml(getString(R.string.login_warning))) 133 | .setPositiveButton(android.R.string.ok, null) 134 | .show(); 135 | } 136 | }); 137 | 138 | // Set up the triggerAutoLogin form. 139 | mUsernameView = (AutoCompleteTextView) findViewById(R.id.username); 140 | 141 | mPasswordView = (EditText) findViewById(R.id.password); 142 | mPasswordView.setOnEditorActionListener(new TextView.OnEditorActionListener() { 143 | @Override 144 | public boolean onEditorAction(TextView textView, int id, KeyEvent keyEvent) { 145 | if (id == R.id.login || id == EditorInfo.IME_NULL) { 146 | validatePTCLoginForm(); 147 | return true; 148 | } 149 | return false; 150 | } 151 | }); 152 | 153 | LoginInfo loginInfo = mPref.getLoginInfo(); 154 | if(loginInfo != null && loginInfo instanceof PtcLoginInfo){ 155 | mUsernameView.setText(((PtcLoginInfo) loginInfo).getUsername()); 156 | mPasswordView.setText(((PtcLoginInfo) loginInfo).getPassword()); 157 | } 158 | 159 | Button signInButton = (Button) findViewById(R.id.email_sign_in_button); 160 | signInButton.setOnClickListener(new OnClickListener() { 161 | @Override 162 | public void onClick(View view) { 163 | validatePTCLoginForm(); 164 | } 165 | }); 166 | 167 | mLoginFormView = findViewById(R.id.login_form); 168 | mProgressView = findViewById(R.id.login_progress); 169 | 170 | SignInButton signInButtonGoogle = (SignInButton) findViewById(R.id.sign_in_button); 171 | signInButtonGoogle.setSize(SignInButton.SIZE_WIDE); 172 | signInButtonGoogle.setOnClickListener(new OnClickListener() { 173 | @Override 174 | public void onClick(View view) { 175 | GoogleAuthActivity.startForResult(LoginActivity.this, REQUEST_USER_AUTH); 176 | } 177 | }); 178 | 179 | triggerAutoLogin(); 180 | } 181 | 182 | private void showPTCLoginFailed() { 183 | showProgress(false); 184 | Snackbar.make((View)mLoginFormView.getParent(), getString(R.string.toast_ptc_login_error), Snackbar.LENGTH_LONG).show(); 185 | } 186 | 187 | private void showGoogleLoginFailed() { 188 | showProgress(false); 189 | Snackbar.make((View)mLoginFormView.getParent(), getString(R.string.toast_google_login_error), Snackbar.LENGTH_LONG).show(); 190 | } 191 | 192 | @Override 193 | public void onActivityResult(int requestCode, int resultCode, Intent data) { 194 | super.onActivityResult(requestCode, resultCode, data); 195 | if(resultCode == RESULT_OK){ 196 | if(requestCode == REQUEST_USER_AUTH){ 197 | showProgress(true); 198 | mGoogleManager.requestToken(data.getStringExtra(GoogleAuthActivity.EXTRA_CODE), 199 | mGoogleLoginListener); 200 | } 201 | } 202 | } 203 | 204 | /** 205 | * Attempts to sign in or register the account specified by the triggerAutoLogin form. 206 | * If there are form errors (invalid email, missing fields, etc.), the 207 | * errors are presented and no actual triggerAutoLogin attempt is made. 208 | */ 209 | private void validatePTCLoginForm() { 210 | // Reset errors. 211 | mUsernameView.setError(null); 212 | mPasswordView.setError(null); 213 | 214 | // Store values at the time of the triggerAutoLogin attempt. 215 | String username = mUsernameView.getText().toString(); 216 | String password = mPasswordView.getText().toString(); 217 | 218 | boolean cancel = false; 219 | View focusView = null; 220 | 221 | // Check for a valid password, if the user entered one. 222 | if (TextUtils.isEmpty(password)) { 223 | mPasswordView.setError(getString(R.string.error_field_required)); 224 | focusView = mPasswordView; 225 | cancel = true; 226 | } 227 | 228 | // Check for a valid username. 229 | if (TextUtils.isEmpty(username)) { 230 | mUsernameView.setError(getString(R.string.error_field_required)); 231 | focusView = mUsernameView; 232 | cancel = true; 233 | } 234 | 235 | if (cancel) { 236 | // There was an error; don't attempt triggerAutoLogin and focus the first 237 | // form field with an error. 238 | focusView.requestFocus(); 239 | } else { 240 | // Show a progress spinner, and kick off a background task to 241 | // perform the user triggerAutoLogin attempt. 242 | showProgress(true); 243 | mNianticManager.login(username, password, mNianticLoginListener); 244 | } 245 | } 246 | 247 | private void finishLogin(){ 248 | Intent intent = new Intent(this, MainActivity.class); 249 | startActivity(intent); 250 | finish(); 251 | } 252 | 253 | /** 254 | * Shows the progress UI and hides the triggerAutoLogin form. 255 | */ 256 | @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2) 257 | private void showProgress(final boolean show) { 258 | 259 | // On Honeycomb MR2 we have the ViewPropertyAnimator APIs, which allow 260 | // for very easy animations. If available, use these APIs to fade-in 261 | // the progress spinner. 262 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) { 263 | int shortAnimTime = getResources().getInteger(android.R.integer.config_shortAnimTime); 264 | 265 | mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE); 266 | mLoginFormView.animate().setDuration(shortAnimTime).alpha( 267 | show ? 0 : 1).setListener(new AnimatorListenerAdapter() { 268 | @Override 269 | public void onAnimationEnd(Animator animation) { 270 | mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE); 271 | } 272 | }); 273 | 274 | mProgressView.setVisibility(show ? View.VISIBLE : View.GONE); 275 | mProgressView.animate().setDuration(shortAnimTime).alpha( 276 | show ? 1 : 0).setListener(new AnimatorListenerAdapter() { 277 | @Override 278 | public void onAnimationEnd(Animator animation) { 279 | mProgressView.setVisibility(show ? View.VISIBLE : View.GONE); 280 | } 281 | }); 282 | } else { 283 | // The ViewPropertyAnimator APIs are not available, so simply show 284 | // and hide the relevant UI components. 285 | mProgressView.setVisibility(show ? View.VISIBLE : View.GONE); 286 | mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE); 287 | } 288 | } 289 | 290 | private void triggerAutoLogin() { 291 | if(mPref.isLoggedIn()){ 292 | showProgress(true); 293 | mNianticManager.setLoginInfo(this, mPref.getLoginInfo(), mNianticAuthListener); 294 | } 295 | } 296 | } 297 | 298 | -------------------------------------------------------------------------------- /app/src/main/java/com/omkarmoghe/pokemap/views/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.omkarmoghe.pokemap.views; 2 | 3 | import android.content.DialogInterface; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.content.SharedPreferences; 7 | import android.content.pm.PackageManager; 8 | import android.os.Bundle; 9 | import android.support.annotation.NonNull; 10 | import android.support.design.widget.Snackbar; 11 | import android.support.v4.app.FragmentManager; 12 | import android.support.v7.app.AlertDialog; 13 | import android.support.v7.widget.Toolbar; 14 | import android.util.Log; 15 | import android.view.Menu; 16 | import android.view.MenuItem; 17 | import android.view.View; 18 | 19 | import com.google.android.gms.maps.model.LatLng; 20 | import com.omkarmoghe.pokemap.R; 21 | import com.omkarmoghe.pokemap.controllers.service.PokemonNotificationService; 22 | import com.omkarmoghe.pokemap.helpers.MapHelper; 23 | import com.omkarmoghe.pokemap.models.events.ClearMapEvent; 24 | import com.omkarmoghe.pokemap.models.events.InternalExceptionEvent; 25 | import com.omkarmoghe.pokemap.models.events.LoginEventResult; 26 | import com.omkarmoghe.pokemap.models.events.SearchInPosition; 27 | import com.omkarmoghe.pokemap.models.events.ServerUnreachableEvent; 28 | import com.omkarmoghe.pokemap.controllers.map.LocationManager; 29 | import com.omkarmoghe.pokemap.views.map.MapWrapperFragment; 30 | import com.omkarmoghe.pokemap.views.settings.SettingsActivity; 31 | import com.omkarmoghe.pokemap.controllers.app_preferences.PokemapAppPreferences; 32 | import com.omkarmoghe.pokemap.controllers.app_preferences.PokemapSharedPreferences; 33 | 34 | import org.greenrobot.eventbus.EventBus; 35 | import org.greenrobot.eventbus.Subscribe; 36 | 37 | import java.util.List; 38 | 39 | public class MainActivity extends BaseActivity { 40 | private static final String TAG = "Pokemap"; 41 | private static final String MAP_FRAGMENT_TAG = "MapFragment"; 42 | 43 | private boolean skipNotificationServer; 44 | private PokemapAppPreferences pref; 45 | private SharedPreferences sharedPref; 46 | private int themeId; 47 | 48 | private Snackbar _pokeSnackbar; 49 | 50 | public void snackMe(String message,int duration){ 51 | if (null == _pokeSnackbar || _pokeSnackbar.getDuration() != duration){ 52 | View rootView = findViewById(R.id.main_container); 53 | _pokeSnackbar = Snackbar.make(rootView,"",duration); 54 | } 55 | _pokeSnackbar.setText(message); 56 | _pokeSnackbar.show(); 57 | } 58 | public void snackMe(String message){ 59 | snackMe(message, Snackbar.LENGTH_LONG); 60 | } 61 | 62 | //region Lifecycle Methods 63 | @Override 64 | protected void onCreate(Bundle savedInstanceState) { 65 | super.onCreate(savedInstanceState); 66 | 67 | sharedPref = this.getSharedPreferences(getString(R.string.pref_file_key), Context.MODE_PRIVATE); 68 | themeId = sharedPref.getInt(getString(R.string.pref_theme_no_action_bar), R.style.AppTheme_NoActionBar); 69 | setTheme(themeId); 70 | setContentView(R.layout.activity_main); 71 | 72 | pref = new PokemapSharedPreferences(this); 73 | 74 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 75 | setSupportActionBar(toolbar); 76 | 77 | FragmentManager fragmentManager = getSupportFragmentManager(); 78 | MapWrapperFragment mapWrapperFragment = (MapWrapperFragment) fragmentManager.findFragmentByTag(MAP_FRAGMENT_TAG); 79 | if(mapWrapperFragment == null) { 80 | mapWrapperFragment = MapWrapperFragment.newInstance(); 81 | } 82 | fragmentManager.beginTransaction().replace(R.id.main_container,mapWrapperFragment, MAP_FRAGMENT_TAG) 83 | .commit(); 84 | 85 | if(pref.isServiceEnabled()){ 86 | startNotificationService(); 87 | } 88 | } 89 | 90 | @Override 91 | public void onResume(){ 92 | super.onResume(); 93 | EventBus.getDefault().register(this); 94 | 95 | if(pref.isServiceEnabled()) { 96 | stopNotificationService(); 97 | } 98 | 99 | // If the theme has changed, recreate the activity. 100 | if(themeId != sharedPref.getInt(getString(R.string.pref_theme_no_action_bar), R.style.AppTheme_NoActionBar)) { 101 | recreate(); 102 | } 103 | } 104 | 105 | @Override 106 | public void onPause() { 107 | super.onPause(); 108 | EventBus.getDefault().unregister(this); 109 | 110 | if(!skipNotificationServer && pref.isServiceEnabled()){ 111 | startNotificationService(); 112 | } 113 | 114 | } 115 | 116 | //endregion 117 | 118 | //region Menu Methods 119 | @Override 120 | public boolean onCreateOptionsMenu(Menu menu) { 121 | getMenuInflater().inflate(R.menu.menu_main, menu); 122 | return true; 123 | } 124 | 125 | @Override 126 | public boolean onOptionsItemSelected(MenuItem item) { 127 | int id = item.getItemId(); 128 | if (id == R.id.action_settings) { 129 | skipNotificationServer = true; 130 | startActivityForResult(new Intent(this, SettingsActivity.class),0); 131 | } else if (id == R.id.action_clear) { 132 | EventBus.getDefault().post(new ClearMapEvent()); 133 | } else if (id == R.id.action_logout) { 134 | showLogoutPrompt(); 135 | } 136 | return super.onOptionsItemSelected(item); 137 | } 138 | //endregion 139 | 140 | private void showLogoutPrompt() { 141 | new AlertDialog.Builder(this).setTitle(R.string.action_logout).setMessage(R.string.logout_prompt_message) 142 | .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() { 143 | @Override 144 | public void onClick(DialogInterface dialogInterface, int i) { 145 | logout(); 146 | dialogInterface.dismiss(); 147 | } 148 | }) 149 | .setNegativeButton(R.string.no, new DialogInterface.OnClickListener() { 150 | @Override 151 | public void onClick(DialogInterface dialogInterface, int i) { 152 | dialogInterface.dismiss(); 153 | } 154 | }) 155 | .show(); 156 | } 157 | 158 | private void logout() { 159 | skipNotificationServer = true; 160 | pref.clearLoginCredentials(); 161 | startActivity(new Intent(this, LoginActivity.class)); 162 | finish(); 163 | } 164 | 165 | @Override 166 | protected void onActivityResult(int requestCode, int resultCode, Intent data) { 167 | skipNotificationServer = false; 168 | } 169 | 170 | @Override 171 | public void onBackPressed() { 172 | skipNotificationServer = true; 173 | finish(); 174 | } 175 | 176 | @Override 177 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { 178 | // TODO: test all this shit on a 6.0+ phone lmfao 179 | switch (requestCode) { 180 | case 703: 181 | if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { 182 | Log.d(TAG, "permission granted"); 183 | } 184 | break; 185 | } 186 | } 187 | 188 | private void startNotificationService(){ 189 | 190 | // check for if the service is already running 191 | if (PokemonNotificationService.isRunning()) { 192 | stopNotificationService(); 193 | } 194 | 195 | Intent intent = new Intent(this, PokemonNotificationService.class); 196 | startService(intent); 197 | } 198 | 199 | private void stopNotificationService() { 200 | Intent intent = new Intent(this, PokemonNotificationService.class); 201 | stopService(intent); 202 | } 203 | 204 | /** 205 | * Triggers a first pokemon scan after a successful login 206 | * 207 | * @param result Results of a log in attempt 208 | */ 209 | @Subscribe 210 | public void onEvent(LoginEventResult result) { 211 | 212 | if (result.isLoggedIn()) { 213 | 214 | LatLng latLng = LocationManager.getInstance(MainActivity.this).getLocation(); 215 | 216 | if (latLng != null) { 217 | nianticManager.getCatchablePokemon(latLng.latitude, latLng.longitude, 0D); 218 | } else { 219 | Snackbar.make(findViewById(R.id.root), getString(R.string.toast_login_error), Snackbar.LENGTH_LONG).show(); 220 | } 221 | } 222 | } 223 | 224 | /** 225 | * Called whenever a use whats to search pokemons on a different position 226 | * 227 | * @param event PoJo with LatLng obj 228 | */ 229 | @Subscribe 230 | public void onEvent(SearchInPosition event) { 231 | List list = MapHelper.getSearchArea(event.getSteps(), new LatLng(event.getPosition().latitude, event.getPosition().longitude)); 232 | snackMe(getString(R.string.toast_searching)); 233 | 234 | nianticManager.getGyms(event.getPosition().latitude, event.getPosition().longitude, 0D); 235 | nianticManager.getPokeStops(event.getPosition().latitude, event.getPosition().longitude, 0D); 236 | nianticManager.getLuredPokemon(event.getPosition().latitude, event.getPosition().longitude, 0D); 237 | 238 | for (LatLng p : list) { 239 | nianticManager.getCatchablePokemon(p.latitude, p.longitude, 0D); 240 | } 241 | } 242 | 243 | /** 244 | * Called whenever a ServerUnreachableEvent is posted to the bus. Posted when the server cannot be reached 245 | * 246 | * @param event The event information 247 | */ 248 | @Subscribe 249 | public void onEvent(ServerUnreachableEvent event) { 250 | Snackbar.make(findViewById(R.id.root), getString(R.string.toast_server_unreachable), Snackbar.LENGTH_LONG).show(); 251 | event.getE().printStackTrace(); 252 | } 253 | 254 | /** 255 | * Called whenever a InternalExceptionEvent is posted to the bus. Posted when the server cannot be reached 256 | * 257 | * @param event The event information 258 | */ 259 | @Subscribe 260 | public void onEvent(InternalExceptionEvent event) { 261 | event.getE().printStackTrace(); 262 | Snackbar.make(findViewById(R.id.root), getString(R.string.toast_internal_error), Snackbar.LENGTH_LONG).show(); 263 | } 264 | 265 | } 266 | -------------------------------------------------------------------------------- /app/src/main/java/com/omkarmoghe/pokemap/views/settings/PokemonToShowAdapter.java: -------------------------------------------------------------------------------- 1 | package com.omkarmoghe.pokemap.views.settings; 2 | 3 | import android.content.Context; 4 | import android.graphics.Bitmap; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.BaseAdapter; 9 | import android.widget.CheckedTextView; 10 | import android.widget.ImageView; 11 | 12 | import com.omkarmoghe.pokemap.R; 13 | import com.omkarmoghe.pokemap.controllers.app_preferences.PokemapAppPreferences; 14 | import com.omkarmoghe.pokemap.controllers.app_preferences.PokemapSharedPreferences; 15 | import com.omkarmoghe.pokemap.helpers.RemoteImageLoader; 16 | import com.omkarmoghe.pokemap.util.PokemonIdUtils; 17 | 18 | import java.util.ArrayList; 19 | import java.util.Collections; 20 | import java.util.HashSet; 21 | import java.util.List; 22 | import java.util.Set; 23 | 24 | import POGOProtos.Enums.PokemonIdOuterClass; 25 | 26 | /** 27 | * Custom adapter to show pokemon and their icons in the preferences screen. 28 | *

29 | * Created by fess on 26.07.16. 30 | */ 31 | class PokemonToShowAdapter extends BaseAdapter { 32 | 33 | private LayoutInflater mInflater; 34 | 35 | private final List mEntries = new ArrayList<>(); 36 | 37 | private final Set mSelected = new HashSet<>(); 38 | 39 | PokemonToShowAdapter(Context context, 40 | CharSequence[] entries) { 41 | Collections.addAll(mEntries, entries); 42 | 43 | mInflater = LayoutInflater.from(context); 44 | PokemapAppPreferences mPref = new PokemapSharedPreferences(context); 45 | mSelected.addAll(mPref.getShowablePokemonIDs()); 46 | } 47 | 48 | Set getShowablePokemonIDs() { 49 | return mSelected; 50 | } 51 | 52 | @Override 53 | public int getCount() { 54 | return mEntries.size(); 55 | } 56 | 57 | @Override 58 | public Object getItem(int position) { 59 | return mEntries.get(position); 60 | } 61 | 62 | @Override 63 | public long getItemId(int position) { 64 | return position; 65 | } 66 | 67 | @Override 68 | public View getView(int position, View view, ViewGroup viewGroup) { 69 | View row = view; 70 | CustomHolder holder; 71 | 72 | if (row == null) { 73 | row = mInflater.inflate(R.layout.item_pokemon_to_show_preference, viewGroup, false); 74 | holder = new CustomHolder(row); 75 | } else { 76 | holder = (CustomHolder) row.getTag(); 77 | } 78 | 79 | holder.bind(row, position); 80 | row.setTag(holder); 81 | 82 | return row; 83 | } 84 | 85 | private class CustomHolder { 86 | private CheckedTextView mCheckableTextView = null; 87 | private ImageView mImageView = null; 88 | 89 | CustomHolder(View row) { 90 | mCheckableTextView = (CheckedTextView) row.findViewById(R.id.textView); 91 | mImageView = (ImageView) row.findViewById(R.id.imageView); 92 | } 93 | 94 | void bind(final View row, final int position) { 95 | final PokemonIdOuterClass.PokemonId pokemonId = PokemonIdOuterClass.PokemonId.forNumber(position + 1); 96 | 97 | mCheckableTextView.setText((CharSequence) getItem(position)); 98 | mCheckableTextView.setChecked(mSelected.contains(pokemonId)); 99 | row.setOnClickListener(new View.OnClickListener() { 100 | @Override 101 | public void onClick(View view) { 102 | PokemonIdOuterClass.PokemonId pokemonId = PokemonIdOuterClass.PokemonId.forNumber(position + 1); 103 | if (mSelected.contains(pokemonId)) { 104 | mSelected.remove(pokemonId); 105 | } else { 106 | mSelected.add(pokemonId); 107 | } 108 | mCheckableTextView.setChecked(mSelected.contains(pokemonId)); 109 | } 110 | }); 111 | 112 | RemoteImageLoader.loadInto(mImageView, 113 | "http://serebii.net/pokemongo/pokemon/" + PokemonIdUtils.getCorrectPokemonImageId(pokemonId.getNumber()) + ".png"); 114 | 115 | } 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /app/src/main/java/com/omkarmoghe/pokemap/views/settings/PokemonToShowPreference.java: -------------------------------------------------------------------------------- 1 | package com.omkarmoghe.pokemap.views.settings; 2 | 3 | import android.app.AlertDialog; 4 | import android.content.Context; 5 | import android.preference.MultiSelectListPreference; 6 | import android.util.AttributeSet; 7 | 8 | import com.omkarmoghe.pokemap.controllers.app_preferences.PokemapSharedPreferences; 9 | import com.omkarmoghe.pokemap.util.PokemonIdUtils; 10 | 11 | import java.util.ArrayList; 12 | import java.util.HashSet; 13 | import java.util.List; 14 | import java.util.Set; 15 | 16 | import POGOProtos.Enums.PokemonIdOuterClass; 17 | 18 | /** 19 | * A multi-select list preference which tells which pokemons to show on the map. 20 | *

21 | * Created by fess on 26.07.16. 22 | */ 23 | public class PokemonToShowPreference extends MultiSelectListPreference { 24 | 25 | private PokemonToShowAdapter mAdapter; 26 | 27 | private PokemapSharedPreferences mPref; 28 | 29 | public PokemonToShowPreference(Context context, AttributeSet attrs) { 30 | super(context, attrs); 31 | init(context); 32 | } 33 | 34 | public PokemonToShowPreference(Context context) { 35 | super(context); 36 | init(context); 37 | } 38 | 39 | private void init(Context context) { 40 | List entries = new ArrayList<>(); 41 | List entriesValues = new ArrayList<>(); 42 | Set defaultValues = new HashSet<>(); 43 | 44 | PokemonIdOuterClass.PokemonId[] ids = PokemonIdOuterClass.PokemonId.values(); 45 | 46 | for (PokemonIdOuterClass.PokemonId pokemonId : ids) { 47 | if ((pokemonId != PokemonIdOuterClass.PokemonId.MISSINGNO) && (pokemonId != PokemonIdOuterClass.PokemonId.UNRECOGNIZED)) { 48 | entries.add(PokemonIdUtils.getLocalePokemonName(context, pokemonId.name())); 49 | entriesValues.add(String.valueOf(pokemonId.getNumber())); 50 | defaultValues.add(String.valueOf(pokemonId.getNumber())); 51 | } 52 | } 53 | 54 | setEntries(entries.toArray(new CharSequence[]{})); 55 | setEntryValues(entriesValues.toArray(new CharSequence[]{})); 56 | 57 | // all pokemons are shown by default 58 | setDefaultValue(defaultValues); 59 | 60 | mPref = new PokemapSharedPreferences(context); 61 | } 62 | 63 | @Override 64 | protected void onPrepareDialogBuilder(AlertDialog.Builder builder) { 65 | final CharSequence[] entries = getEntries(); 66 | final CharSequence[] entryValues = getEntryValues(); 67 | 68 | if (entries == null || entryValues == null || entries.length != entryValues.length) { 69 | throw new IllegalStateException("ListPreference requires an entries array and an entryValues array which are both the same length"); 70 | } 71 | 72 | mAdapter = new PokemonToShowAdapter(getContext(), entries); 73 | builder.setAdapter(mAdapter, null); 74 | } 75 | 76 | @Override 77 | protected void onDialogClosed(boolean positiveResult) { 78 | super.onDialogClosed(positiveResult); 79 | if (positiveResult) { 80 | Set pokemonIDs = mAdapter.getShowablePokemonIDs(); 81 | mPref.setShowablePokemonIDs(pokemonIDs); 82 | } 83 | } 84 | } -------------------------------------------------------------------------------- /app/src/main/java/com/omkarmoghe/pokemap/views/settings/SettingsActivity.java: -------------------------------------------------------------------------------- 1 | package com.omkarmoghe.pokemap.views.settings; 2 | 3 | import android.content.Context; 4 | import android.content.SharedPreferences; 5 | import android.os.Bundle; 6 | import android.support.v4.app.NavUtils; 7 | import android.support.v7.app.AppCompatActivity; 8 | import android.support.v7.widget.Toolbar; 9 | 10 | import com.omkarmoghe.pokemap.R; 11 | 12 | public class SettingsActivity extends AppCompatActivity { 13 | 14 | private SharedPreferences sharedPref; 15 | private int themeId; 16 | 17 | @Override 18 | protected void onCreate(Bundle savedInstanceState) { 19 | super.onCreate(savedInstanceState); 20 | 21 | sharedPref = this.getSharedPreferences(getString(R.string.pref_file_key), Context.MODE_PRIVATE); 22 | themeId = sharedPref.getInt(getString(R.string.pref_theme_no_action_bar), R.style.AppTheme_NoActionBar); 23 | setTheme(themeId); 24 | setTitle(getString(R.string.action_settings)); 25 | setContentView(R.layout.activity_settings); 26 | 27 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 28 | setSupportActionBar(toolbar); 29 | 30 | if(getSupportActionBar() != null) 31 | getSupportActionBar().setDisplayHomeAsUpEnabled(true); 32 | 33 | getFragmentManager().beginTransaction() 34 | .replace(R.id.settings_content, new SettingsFragment()) 35 | .commit(); 36 | } 37 | 38 | @Override 39 | protected void onResume() { 40 | super.onResume(); // Check if theme has changed, if so then restart the activity. 41 | if(themeId != sharedPref.getInt(getString(R.string.pref_theme_no_action_bar), R.style.AppTheme_NoActionBar)) { 42 | recreate(); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/com/omkarmoghe/pokemap/views/settings/SettingsFragment.java: -------------------------------------------------------------------------------- 1 | package com.omkarmoghe.pokemap.views.settings; 2 | 3 | import android.content.Intent; 4 | import android.content.SharedPreferences; 5 | import android.os.Bundle; 6 | import android.preference.Preference; 7 | import android.preference.PreferenceFragment; 8 | import android.preference.PreferenceManager; 9 | 10 | import com.omkarmoghe.pokemap.R; 11 | 12 | public class SettingsFragment extends PreferenceFragment { 13 | 14 | private SharedPreferences pref; 15 | private SharedPreferences.OnSharedPreferenceChangeListener listener; 16 | 17 | @Override 18 | public void onCreate(Bundle savedInstanceState) { 19 | super.onCreate(savedInstanceState); 20 | 21 | pref = PreferenceManager.getDefaultSharedPreferences(getActivity()); 22 | 23 | // Load the preferences from an XML resource 24 | addPreferencesFromResource(R.xml.preferences); 25 | // Create Theme button to link to Theme Fragment 26 | Preference button = (Preference) getPreferenceManager().findPreference(getString(R.string.pref_theme_button_key)); 27 | if (button != null) { 28 | button.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { 29 | @Override 30 | public boolean onPreferenceClick(Preference preference) { 31 | Intent intent = new Intent(getActivity(), ThemeActivity.class); 32 | startActivity(intent); 33 | return true; 34 | } 35 | }); 36 | } 37 | } 38 | 39 | @Override 40 | public void onResume() { 41 | super.onResume(); 42 | // Register change listener 43 | getPreferenceManager().getSharedPreferences().registerOnSharedPreferenceChangeListener(listener); 44 | } 45 | 46 | @Override 47 | public void onPause() { 48 | super.onPause(); 49 | // Unregister change listener 50 | getPreferenceManager().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(listener); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /app/src/main/java/com/omkarmoghe/pokemap/views/settings/ThemeActivity.java: -------------------------------------------------------------------------------- 1 | package com.omkarmoghe.pokemap.views.settings; 2 | 3 | import android.content.Context; 4 | import android.content.SharedPreferences; 5 | import android.support.v7.app.AppCompatActivity; 6 | import android.os.Bundle; 7 | import android.view.View; 8 | import android.widget.RadioButton; 9 | 10 | import com.omkarmoghe.pokemap.R; 11 | 12 | public class ThemeActivity extends AppCompatActivity { 13 | 14 | private SharedPreferences sharedPref; 15 | private int themeId; 16 | 17 | private String PREF_ID; 18 | private String PREF_ID_NO_ACTION_BAR; 19 | 20 | @Override 21 | protected void onCreate(Bundle savedInstanceState) { 22 | super.onCreate(savedInstanceState); 23 | 24 | PREF_ID = getString(R.string.pref_theme); 25 | PREF_ID_NO_ACTION_BAR = getString(R.string.pref_theme_no_action_bar); 26 | 27 | sharedPref = this.getSharedPreferences(getString(R.string.pref_file_key), Context.MODE_PRIVATE); 28 | themeId = sharedPref.getInt(getString(R.string.pref_theme), R.style.AppTheme); 29 | setTheme(themeId); 30 | 31 | setTitle(getString(R.string.preset_themes_title)); 32 | setContentView(R.layout.activity_theme); 33 | 34 | RadioButton r1 = (RadioButton) findViewById(R.id.radioButton1); 35 | RadioButton r2 = (RadioButton) findViewById(R.id.radioButton2); 36 | RadioButton r3 = (RadioButton) findViewById(R.id.radioButton3); 37 | RadioButton r4 = (RadioButton) findViewById(R.id.radioButton4); 38 | RadioButton r5 = (RadioButton) findViewById(R.id.radioButton5); 39 | 40 | switch (themeId) { 41 | case R.style.AppThemeSquirtle: 42 | r1.setChecked(true); 43 | break; 44 | case R.style.AppThemeCharmander: 45 | r2.setChecked(true); 46 | break; 47 | case R.style.AppThemeBulbasaur: 48 | r3.setChecked(true); 49 | break; 50 | case R.style.AppThemePikachu: 51 | r4.setChecked(true); 52 | break; 53 | case R.style.AppTheme: 54 | r5.setChecked(true); 55 | break; 56 | default: 57 | break; 58 | } 59 | } 60 | 61 | public void onRadioButtonClicked(View v) { 62 | 63 | SharedPreferences sharedPref = this.getSharedPreferences(getString(R.string.pref_file_key), Context.MODE_PRIVATE); 64 | SharedPreferences.Editor editor = sharedPref.edit(); 65 | 66 | boolean checked = ((RadioButton) v).isChecked(); 67 | 68 | 69 | switch(v.getId()) { 70 | case R.id.radioButton1: 71 | if(checked) { 72 | editor.putInt(PREF_ID, R.style.AppThemeSquirtle); 73 | editor.putInt(PREF_ID_NO_ACTION_BAR, R.style.AppThemeSquirtle_NoActionBar); 74 | editor.apply(); 75 | } 76 | break; 77 | case R.id.radioButton2: 78 | if(checked) { 79 | editor.putInt(PREF_ID, R.style.AppThemeCharmander); 80 | editor.putInt(PREF_ID_NO_ACTION_BAR, R.style.AppThemeCharmander_NoActionBar); 81 | editor.apply(); 82 | } 83 | break; 84 | case R.id.radioButton3: 85 | if(checked) { 86 | editor.putInt(PREF_ID, R.style.AppThemeBulbasaur); 87 | editor.putInt(PREF_ID_NO_ACTION_BAR, R.style.AppThemeBulbasaur_NoActionBar); 88 | editor.apply(); 89 | } 90 | break; 91 | case R.id.radioButton4: 92 | if(checked) { 93 | editor.putInt(PREF_ID, R.style.AppThemePikachu); 94 | editor.putInt(PREF_ID_NO_ACTION_BAR, R.style.AppThemePikachu_NoActionBar); 95 | editor.apply(); 96 | } 97 | break; 98 | case R.id.radioButton5: 99 | if(checked) { 100 | editor.putInt(PREF_ID, R.style.AppTheme); 101 | editor.putInt(PREF_ID_NO_ACTION_BAR, R.style.AppTheme_NoActionBar); 102 | editor.apply(); 103 | } 104 | break; 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_favorite_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omkarmoghe/Pokemap/5437dcfe139a65b94729f8f5ab2a5f6673143fa1/app/src/main/res/drawable-hdpi/ic_favorite_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_list_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omkarmoghe/Pokemap/5437dcfe139a65b94729f8f5ab2a5f6673143fa1/app/src/main/res/drawable-hdpi/ic_list_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_map_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omkarmoghe/Pokemap/5437dcfe139a65b94729f8f5ab2a5f6673143fa1/app/src/main/res/drawable-hdpi/ic_map_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_my_location_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omkarmoghe/Pokemap/5437dcfe139a65b94729f8f5ab2a5f6673143fa1/app/src/main/res/drawable-hdpi/ic_my_location_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_favorite_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omkarmoghe/Pokemap/5437dcfe139a65b94729f8f5ab2a5f6673143fa1/app/src/main/res/drawable-mdpi/ic_favorite_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_list_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omkarmoghe/Pokemap/5437dcfe139a65b94729f8f5ab2a5f6673143fa1/app/src/main/res/drawable-mdpi/ic_list_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_map_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omkarmoghe/Pokemap/5437dcfe139a65b94729f8f5ab2a5f6673143fa1/app/src/main/res/drawable-mdpi/ic_map_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_my_location_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omkarmoghe/Pokemap/5437dcfe139a65b94729f8f5ab2a5f6673143fa1/app/src/main/res/drawable-mdpi/ic_my_location_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_favorite_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omkarmoghe/Pokemap/5437dcfe139a65b94729f8f5ab2a5f6673143fa1/app/src/main/res/drawable-xhdpi/ic_favorite_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_list_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omkarmoghe/Pokemap/5437dcfe139a65b94729f8f5ab2a5f6673143fa1/app/src/main/res/drawable-xhdpi/ic_list_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_map_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omkarmoghe/Pokemap/5437dcfe139a65b94729f8f5ab2a5f6673143fa1/app/src/main/res/drawable-xhdpi/ic_map_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_my_location_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omkarmoghe/Pokemap/5437dcfe139a65b94729f8f5ab2a5f6673143fa1/app/src/main/res/drawable-xhdpi/ic_my_location_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_favorite_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omkarmoghe/Pokemap/5437dcfe139a65b94729f8f5ab2a5f6673143fa1/app/src/main/res/drawable-xxhdpi/ic_favorite_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_list_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omkarmoghe/Pokemap/5437dcfe139a65b94729f8f5ab2a5f6673143fa1/app/src/main/res/drawable-xxhdpi/ic_list_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_map_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omkarmoghe/Pokemap/5437dcfe139a65b94729f8f5ab2a5f6673143fa1/app/src/main/res/drawable-xxhdpi/ic_map_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_my_location_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omkarmoghe/Pokemap/5437dcfe139a65b94729f8f5ab2a5f6673143fa1/app/src/main/res/drawable-xxhdpi/ic_my_location_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_favorite_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omkarmoghe/Pokemap/5437dcfe139a65b94729f8f5ab2a5f6673143fa1/app/src/main/res/drawable-xxxhdpi/ic_favorite_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_list_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omkarmoghe/Pokemap/5437dcfe139a65b94729f8f5ab2a5f6673143fa1/app/src/main/res/drawable-xxxhdpi/ic_list_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_map_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omkarmoghe/Pokemap/5437dcfe139a65b94729f8f5ab2a5f6673143fa1/app/src/main/res/drawable-xxxhdpi/ic_map_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_my_location_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omkarmoghe/Pokemap/5437dcfe139a65b94729f8f5ab2a5f6673143fa1/app/src/main/res/drawable-xxxhdpi/ic_my_location_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_arrow_back_white.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_cancel_white_24px.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_close_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_gps_fixed_white_24px.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_google_auth.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_login.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | 19 | 20 | 24 | 25 | 34 | 35 | 38 | 39 | 46 | 47 | 48 | 49 | 52 | 53 | 63 | 64 | 65 | 66 |