From 66206cd43186dadd657312a06a5911089807befd Mon Sep 17 00:00:00 2001 From: chuparCh0pper Date: Tue, 27 Sep 2016 15:57:25 +0200 Subject: [PATCH] added HatchNotification originally made by MaT-PT https://github.com/chuparCh0pper/PoGoIV_xposed/commit/612649c7d9c0faab89805e063fcbf9f88c417084 added translation of pokemon names added Helper class to calc level and ivs --- .../com/icecream/snorlax/common/Helper.java | 63 +++++++ .../encounter/EncounterNotification.java | 3 +- .../module/feature/hatch/EggHatchRewards.java | 25 +++ .../snorlax/module/feature/hatch/Hatch.java | 150 +++++++++++++++++ .../feature/hatch/HatchNotification.java | 150 +++++++++++++++++ .../feature/hatch/HatchPreferences.java | 42 +++++ app/src/main/res/drawable/egg.png | Bin 0 -> 4820 bytes app/src/main/res/values-de/pokemons.xml | 156 ++++++++++++++++++ app/src/main/res/values-fr/pokemons.xml | 156 ++++++++++++++++++ app/src/main/res/values/bools.xml | 1 + app/src/main/res/values/pokemons.xml | 156 ++++++++++++++++++ app/src/main/res/values/strings.xml | 5 + 12 files changed, 906 insertions(+), 1 deletion(-) create mode 100644 app/src/main/java/com/icecream/snorlax/common/Helper.java create mode 100644 app/src/main/java/com/icecream/snorlax/module/feature/hatch/EggHatchRewards.java create mode 100644 app/src/main/java/com/icecream/snorlax/module/feature/hatch/Hatch.java create mode 100644 app/src/main/java/com/icecream/snorlax/module/feature/hatch/HatchNotification.java create mode 100644 app/src/main/java/com/icecream/snorlax/module/feature/hatch/HatchPreferences.java create mode 100644 app/src/main/res/drawable/egg.png create mode 100644 app/src/main/res/values-de/pokemons.xml create mode 100644 app/src/main/res/values-fr/pokemons.xml create mode 100644 app/src/main/res/values/pokemons.xml diff --git a/app/src/main/java/com/icecream/snorlax/common/Helper.java b/app/src/main/java/com/icecream/snorlax/common/Helper.java new file mode 100644 index 0000000..d37cc01 --- /dev/null +++ b/app/src/main/java/com/icecream/snorlax/common/Helper.java @@ -0,0 +1,63 @@ +package com.icecream.snorlax.common; + +import android.content.res.Resources; + +import com.icecream.snorlax.R; + +import POGOProtos.Data.PokemonDataOuterClass; + +public class Helper { + + private static String[] pokemonNames = null; + + // from https://github.com/farkam135/GoIV/blob/master/app/src/main/java/com/kamron/pogoiv/Data.java#L8 + private static final double[] CpM = {0.0939999967813492, 0.135137432089339, 0.166397869586945, 0.192650913155325, 0.215732470154762, 0.236572651424822, 0.255720049142838, 0.273530372106572, 0.290249884128571, 0.306057381389863 + , 0.321087598800659, 0.335445031996451, 0.349212676286697, 0.362457736609939, 0.375235587358475, 0.387592407713878, 0.399567276239395, 0.4111935532161, 0.422500014305115, 0.432926420512509, 0.443107545375824 + , 0.453059948165049, 0.46279838681221, 0.472336085311278, 0.481684952974319, 0.490855807179549, 0.499858438968658, 0.5087017489616, 0.517393946647644, 0.525942516110322, 0.534354329109192, 0.542635753803599 + , 0.550792694091797, 0.558830584490385, 0.566754519939423, 0.57456912814537, 0.582278907299042, 0.589887907888945, 0.597400009632111, 0.604823648665171, 0.61215728521347, 0.619404107958234, 0.626567125320435 + , 0.633649178748576, 0.6406529545784, 0.647580971386554, 0.654435634613037, 0.661219265805859, 0.667934000492096, 0.674581885647492, 0.681164920330048, 0.687684901255373, 0.694143652915955, 0.700542901033063 + , 0.706884205341339, 0.713169074873823, 0.719399094581604, 0.725575586915154, 0.731700003147125, 0.734741038550429, 0.737769484519958, 0.740785579737136, 0.743789434432983, 0.746781197247765, 0.749761044979095 + , 0.752729099732281, 0.75568550825119, 0.758630370209851, 0.761563837528229, 0.76448604959218, 0.767397165298462, 0.770297293677362, 0.773186504840851, 0.776064947064992, 0.778932750225067, 0.781790050767666 + , 0.784636974334717, 0.787473608513275, 0.790300011634827}; + + + public static float calcLevel(PokemonDataOuterClass.PokemonData pokemonData) { + if (pokemonData.getIsEgg()) + return 0; + return calcLevel(pokemonData.getCpMultiplier() + pokemonData.getAdditionalCpMultiplier()); + } + + private static float calcLevel(float cpMultiplier) { + float level = 1; + for (double currentCpM : CpM) { + if (Math.abs(cpMultiplier - currentCpM) < 0.0001) { + return level; + } + level += 0.5; + } + return level; + } + + public static double calcPotential(PokemonDataOuterClass.PokemonData encounteredPokemon) { + return (double) Math.round(((encounteredPokemon.getIndividualAttack() + encounteredPokemon.getIndividualDefense() + encounteredPokemon.getIndividualStamina()) / 45.0 * 100.0) * 10) / 10; + } + + private static void loadPokemonNames(Resources resources) { + pokemonNames = resources.getStringArray(R.array.pokemon); + } + + public static String[] getPokemonNames(Resources resources) { + if (pokemonNames == null) { + loadPokemonNames(resources); + } + return pokemonNames; + } + + public static String getPokemonName(int pokemonNumber, Resources resources) { + String[] pokemonNames = getPokemonNames(resources); + if (pokemonNumber > 0 && pokemonNumber <= pokemonNames.length) + return getPokemonNames(resources)[pokemonNumber - 1]; + else + return "(unknown Pokémon: " + pokemonNumber + ")"; + } +} diff --git a/app/src/main/java/com/icecream/snorlax/module/feature/encounter/EncounterNotification.java b/app/src/main/java/com/icecream/snorlax/module/feature/encounter/EncounterNotification.java index 93b6105..2fabcf2 100644 --- a/app/src/main/java/com/icecream/snorlax/module/feature/encounter/EncounterNotification.java +++ b/app/src/main/java/com/icecream/snorlax/module/feature/encounter/EncounterNotification.java @@ -37,6 +37,7 @@ import android.view.View; import com.icecream.snorlax.R; +import com.icecream.snorlax.common.Helper; import com.icecream.snorlax.common.Strings; import com.icecream.snorlax.module.context.pokemongo.PokemonGo; import com.icecream.snorlax.module.context.snorlax.Snorlax; @@ -70,7 +71,7 @@ void show(int pokemonNumber, String pokemonName, double iv, int attack, int defe getLargeIconHeight(), false )) - .setContentTitle(mContext.getString(R.string.notification_title, pokemonName)) + .setContentTitle(mContext.getString(R.string.notification_title, Helper.getPokemonName(pokemonNumber, mResources))) .setContentText(mContext.getString(R.string.notification_content, iv, attack, defense, stamina, cp, level, hp)) .setStyle(new NotificationCompat.InboxStyle() .addLine(mContext.getString(R.string.notification_categoty_stats_content, iv, attack, defense, stamina, cp, level, hp)) diff --git a/app/src/main/java/com/icecream/snorlax/module/feature/hatch/EggHatchRewards.java b/app/src/main/java/com/icecream/snorlax/module/feature/hatch/EggHatchRewards.java new file mode 100644 index 0000000..744d8e8 --- /dev/null +++ b/app/src/main/java/com/icecream/snorlax/module/feature/hatch/EggHatchRewards.java @@ -0,0 +1,25 @@ +package com.icecream.snorlax.module.feature.hatch; + +class EggHatchRewards { + private int experienceAwarded; + private int candyAwarded; + private int stardustAwarded; + + public EggHatchRewards(int experienceAwarded, int candyAwarded, int stardustAwarded) { + this.experienceAwarded = experienceAwarded; + this.candyAwarded = candyAwarded; + this.stardustAwarded = stardustAwarded; + } + + public int getExperienceAwarded() { + return experienceAwarded; + } + + public int getCandyAwarded() { + return candyAwarded; + } + + public int getStardustAwarded() { + return stardustAwarded; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/icecream/snorlax/module/feature/hatch/Hatch.java b/app/src/main/java/com/icecream/snorlax/module/feature/hatch/Hatch.java new file mode 100644 index 0000000..5ebee84 --- /dev/null +++ b/app/src/main/java/com/icecream/snorlax/module/feature/hatch/Hatch.java @@ -0,0 +1,150 @@ +package com.icecream.snorlax.module.feature.hatch; + +import android.support.v4.util.Pair; + +import com.google.protobuf.ByteString; +import com.google.protobuf.InvalidProtocolBufferException; +import com.icecream.snorlax.module.feature.Feature; +import com.icecream.snorlax.module.feature.mitm.MitmRelay; +import com.icecream.snorlax.module.util.Log; +import com.icecream.snorlax.module.util.RxFuncitons; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.inject.Singleton; + +import POGOProtos.Data.PokemonDataOuterClass; +import POGOProtos.Inventory.InventoryDeltaOuterClass; +import POGOProtos.Inventory.InventoryItemDataOuterClass; +import POGOProtos.Inventory.InventoryItemOuterClass; +import POGOProtos.Networking.Requests.RequestOuterClass; +import POGOProtos.Networking.Requests.RequestTypeOuterClass; +import POGOProtos.Networking.Responses.GetHatchedEggsResponseOuterClass; +import POGOProtos.Networking.Responses.GetInventoryResponseOuterClass; +import rx.Observable; +import rx.Subscription; + +@Singleton +public final class Hatch implements Feature { + + private final MitmRelay mMitmRelay; + private final HatchPreferences mPreferences; + private final HatchNotification mHatchNotification; + private Subscription mSubscription; + + private final Map hatchedEggs = new HashMap<>(); + + public Hatch(MitmRelay mitmRelay, HatchPreferences hatchPreferences, HatchNotification hatchNotification) { + this.mMitmRelay = mitmRelay; + this.mPreferences = hatchPreferences; + this.mHatchNotification = hatchNotification; + } + + private void onHatch(ByteString bytes) { + try { + GetHatchedEggsResponseOuterClass.GetHatchedEggsResponse getHatchedEggsResponse = GetHatchedEggsResponseOuterClass.GetHatchedEggsResponse.parseFrom(bytes); + + if (!getHatchedEggsResponse.getSuccess()) + return; + + for (int i = 0, l = getHatchedEggsResponse.getPokemonIdCount(); i < l; i++) { + EggHatchRewards eggHatchRewards = new EggHatchRewards(getHatchedEggsResponse.getExperienceAwarded(i), + getHatchedEggsResponse.getCandyAwarded(i), + getHatchedEggsResponse.getStardustAwarded(i)); + hatchedEggs.put(getHatchedEggsResponse.getPokemonId(i), eggHatchRewards); + } + + } catch (InvalidProtocolBufferException e) { + Log.d("GetHatchedEggsResponse failed: %s" + e.getMessage()); + Log.e(e); + } + } + + + private void onInventoryUpdate(ByteString bytes) { + try { + GetInventoryResponseOuterClass.GetInventoryResponse getInventoryResponse = GetInventoryResponseOuterClass.GetInventoryResponse.parseFrom(bytes); + + if (!getInventoryResponse.getSuccess() || !getInventoryResponse.hasInventoryDelta()) + return; + + // First time (delta.getOriginalTimestampMs() == 0L) the server sends the full inventory, + // after that only what has changed since the last request + InventoryDeltaOuterClass.InventoryDelta inventoryDelta = getInventoryResponse.getInventoryDelta(); + + List hatchedEggsAwardedList = new ArrayList(); + List hatchedEggsAwardedListPokemonData = new ArrayList(); + + for (InventoryItemOuterClass.InventoryItem inventoryItem : inventoryDelta.getInventoryItemsList()) { + if (inventoryItem.hasInventoryItemData()) { + InventoryItemDataOuterClass.InventoryItemData inventoryItemData = inventoryItem.getInventoryItemData(); + + if (inventoryItemData.hasPokemonData()) { + PokemonDataOuterClass.PokemonData pokemonData = inventoryItemData.getPokemonData(); + long pokemonId = pokemonData.getId(); + + if (hatchedEggs.containsKey(pokemonId)) { + hatchedEggsAwardedList.add(hatchedEggs.get(pokemonId)); + hatchedEggs.remove(pokemonId); + + hatchedEggsAwardedListPokemonData.add(pokemonData); + + } + } + } + } + + + } catch (InvalidProtocolBufferException e) { + Log.d("GetInventoryResponse failed: %s" + e.getMessage()); + Log.e(e); + } + } + + @Override + public void subscribe() { + unsubscribe(); + + mSubscription = mMitmRelay + .getObservable() + .compose(mPreferences.isEnabled()) + .flatMap(envelope -> { + List requests = envelope.getRequest().getRequestsList(); + + for (int i = 0; i < requests.size(); i++) { + RequestTypeOuterClass.RequestType type = requests.get(i).getRequestType(); + + switch (type) { + case GET_HATCHED_EGGS: + case GET_INVENTORY: + return Observable.just(new Pair<>(type, envelope.getResponse().getReturns(i))); + default: + break; + } + + } + return Observable.empty(); + }) + .subscribe(pair -> { + switch (pair.first) { + case GET_HATCHED_EGGS: + onHatch(pair.second); + break; + case GET_INVENTORY: + onInventoryUpdate(pair.second); + break; + default: + break; + } + } + , Log::e); + } + + @Override + public void unsubscribe() { + RxFuncitons.unsubscribe(mSubscription); + } +} diff --git a/app/src/main/java/com/icecream/snorlax/module/feature/hatch/HatchNotification.java b/app/src/main/java/com/icecream/snorlax/module/feature/hatch/HatchNotification.java new file mode 100644 index 0000000..37329af --- /dev/null +++ b/app/src/main/java/com/icecream/snorlax/module/feature/hatch/HatchNotification.java @@ -0,0 +1,150 @@ + +package com.icecream.snorlax.module.feature.hatch; + +import android.app.Notification; +import android.app.NotificationManager; +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.os.Handler; +import android.os.Looper; +import android.support.annotation.DrawableRes; +import android.support.v7.app.NotificationCompat; +import android.view.View; + +import com.icecream.snorlax.R; +import com.icecream.snorlax.module.context.pokemongo.PokemonGo; +import com.icecream.snorlax.module.context.snorlax.Snorlax; + +import java.util.List; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import POGOProtos.Data.PokemonDataOuterClass; + +import static com.icecream.snorlax.common.Helper.calcLevel; +import static com.icecream.snorlax.common.Helper.calcPotential; +import static com.icecream.snorlax.common.Helper.getPokemonName; + +@Singleton +final class HatchNotification { + + private final Context mContext; + private final Resources mResources; + private final NotificationManager mNotificationManager; + + @Inject + HatchNotification(@Snorlax Context context, @Snorlax Resources resources, @PokemonGo NotificationManager notificationManager) { + mContext = context; + mResources = resources; + mNotificationManager = notificationManager; + } + + @SuppressWarnings("deprecation") + void show(List hatchedEggsAwardedList, List hatchedEggsAwardedListPokemonData) { + new Handler(Looper.getMainLooper()).post(() -> { + + if (hatchedEggsAwardedList == null || hatchedEggsAwardedListPokemonData == null + || hatchedEggsAwardedList.size() != hatchedEggsAwardedListPokemonData.size()) + return; + + String title = ""; + String summary = ""; + final StringBuilder longText = new StringBuilder(512); + int eggsHatched = 0; + int experienceAwardedTotal = 0; + int stardustAwardedTotal = 0; + String lastHatchedPokemonName = ""; + + for (int i = 0; i < hatchedEggsAwardedList.size(); i++) { + int experienceAwarded = hatchedEggsAwardedList.get(i).getExperienceAwarded(); + int candyAwarded = hatchedEggsAwardedList.get(i).getCandyAwarded(); + int stardustAwarded = hatchedEggsAwardedList.get(i).getStardustAwarded(); + + PokemonDataOuterClass.PokemonData pokemonData = hatchedEggsAwardedListPokemonData.get(i); + + eggsHatched++; + experienceAwardedTotal += experienceAwarded; + stardustAwardedTotal += stardustAwarded; + lastHatchedPokemonName = getPokemonName(pokemonData.getPokemonIdValue(), mResources); + + if (longText.length() > 0) + longText.append('\n'); + longText.append(lastHatchedPokemonName).append(" \uD83D\uDC23 "); + longText.append(experienceAwarded).append(" XP | "); + longText.append(candyAwarded).append(" Cd. | "); + longText.append(stardustAwarded).append(" SD.\n"); + longText.append("L. ").append(calcLevel(pokemonData)); + longText.append(" | IVs: ").append(calcPotential(pokemonData)); + longText.append("% | ").append(pokemonData.getIndividualAttack()); + longText.append("/").append(pokemonData.getIndividualDefense()); + longText.append("/").append(pokemonData.getIndividualStamina()); + } + + if (eggsHatched > 0) { + if (eggsHatched > 1) { + title = "Eggs hatched: " + eggsHatched; + } else { + title = "Egg hatched: " + lastHatchedPokemonName; + } + summary = eggsHatched + " egg" + (eggsHatched > 1 ? "s" : "") + " hatched, got " + + experienceAwardedTotal + " XP, " + stardustAwardedTotal + " Stardust"; + } + + + Notification notification = new NotificationCompat.Builder(mContext) + .setSmallIcon(R.drawable.ic_pokeball) + .setLargeIcon(Bitmap.createScaledBitmap( + BitmapFactory.decodeResource( + mResources, + getEggResourceId() + ), + getLargeIconWidth(), + getLargeIconHeight(), + false + )) + .setContentTitle(title) + .setContentText(summary) + .setStyle(new NotificationCompat.BigTextStyle().bigText(longText)) + .setAutoCancel(true) + .setVibrate(new long[]{0, 60, 300, 60}) + .setPriority(Notification.PRIORITY_MAX) + .setCategory(NotificationCompat.CATEGORY_ALARM) + .build(); + + hideIcon(notification); + + mNotificationManager.notify(1000, notification); + }); + } + + @DrawableRes + private int getEggResourceId() { + return mResources.getIdentifier("egg", "drawable", mContext.getPackageName()); + } + + private int getLargeIconWidth() { + return mResources.getDimensionPixelSize(android.R.dimen.notification_large_icon_width); + } + + private int getLargeIconHeight() { + return mResources.getDimensionPixelSize(android.R.dimen.notification_large_icon_height); + } + + @SuppressWarnings("deprecation") + private void hideIcon(Notification notification) { + int iconId = mResources.getIdentifier("right_icon", "id", android.R.class.getPackage().getName()); + if (iconId != 0) { + if (notification.contentView != null) { + notification.contentView.setViewVisibility(iconId, View.INVISIBLE); + } + if (notification.bigContentView != null) { + notification.bigContentView.setViewVisibility(iconId, View.INVISIBLE); + } + } + } + + +} diff --git a/app/src/main/java/com/icecream/snorlax/module/feature/hatch/HatchPreferences.java b/app/src/main/java/com/icecream/snorlax/module/feature/hatch/HatchPreferences.java new file mode 100644 index 0000000..8a2a55e --- /dev/null +++ b/app/src/main/java/com/icecream/snorlax/module/feature/hatch/HatchPreferences.java @@ -0,0 +1,42 @@ +package com.icecream.snorlax.module.feature.hatch; + +import android.content.res.Resources; + +import com.icecream.snorlax.R; +import com.icecream.snorlax.module.context.snorlax.Snorlax; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import de.robv.android.xposed.XSharedPreferences; +import rx.Observable; + +@Singleton +final class HatchPreferences { + + private final Resources mResources; + private final XSharedPreferences mPreferences; + + @Inject + HatchPreferences(@Snorlax Resources resources, XSharedPreferences preferences) { + mResources = resources; + mPreferences = preferences; + } + + Observable.Transformer isEnabled() { + return observable -> observable + .doOnNext(t -> mPreferences.reload()) + .filter(t -> { + final boolean excepted = getPreferenceDefaultValue(); + return excepted == getPreference(excepted); + }); + } + + private boolean getPreferenceDefaultValue() { + return mResources.getBoolean(R.bool.preference_hatch_notification_enable); + } + + private boolean getPreference(boolean defaultValue) { + return mPreferences.getBoolean(mResources.getString(R.string.preference_hatch_notification_enable_key), defaultValue); + } +} diff --git a/app/src/main/res/drawable/egg.png b/app/src/main/res/drawable/egg.png new file mode 100644 index 0000000000000000000000000000000000000000..676a27b736bafd39e68e08477fe13ce6071add79 GIT binary patch literal 4820 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 y@yYl?8}Eu + + + Bisasam + Bisaknosp + Bisaflor + Glumanda + Glutexo + Glurak + Schiggy + Schillok + Turtok + Raupy + Safcon + Smettbo + Hornliu + Kokuna + Bibor + Taubsi + Tauboga + Tauboss + Rattfratz + Rattikarl + Habitak + Ibitak + Rettan + Arbok + Pikachu + Raichu + Sandan + Sandamer + Nidoran♀ + Nidorina + Nidoqueen + Nidoran♂ + Nidorino + Nidoking + Piepi + Pixi + Vulpix + Vulnona + Pummeluff + Knuddeluff + Zubat + Golbat + Myrapla + Duflor + Giflor + Paras + Parasek + Bluzuk + Omot + Digda + Digdri + Mauzi + Snobilikat + Enton + Entoron + Menki + Rasaff + Fukano + Arkani + Quapsel + Quaputzi + Quappo + Abra + Kadabra + Simsala + Machollo + Maschock + Machomei + Knofensa + Ultrigaria + Sarzenia + Tentacha + Tentoxa + Kleinstein + Georok + Geowaz + Ponita + Gallopa + Flegmon + Lahmus + Magnetilo + Magneton + Porenta + Dodu + Dodri + Jurob + Jugong + Sleima + Sleimok + Muschas + Austos + Nebulak + Alpollo + Gengar + Onix + Traumato + Hypno + Krabby + Kingler + Voltobal + Lektrobal + Owei + Kokowei + Tragosso + Knogga + Kicklee + Nockchan + Schlurp + Smogon + Smogmog + Rihorn + Rizeros + Chaneira + Tangela + Kangama + Seeper + Seemon + Goldini + Golking + Sterndu + Starmie + Pantimos + Sichlor + Rossana + Elektek + Magmar + Pinsir + Tauros + Karpador + Garados + Lapras + Ditto + Evoli + Aquana + Blitza + Flamara + Porygon + Amonitas + Amoroso + Kabuto + Kabutops + Aerodactyl + Relaxo + Arktos + Zapdos + Lavados + Dratini + Dragonir + Dragoran + Mewtu + Mew + + \ No newline at end of file diff --git a/app/src/main/res/values-fr/pokemons.xml b/app/src/main/res/values-fr/pokemons.xml new file mode 100644 index 0000000..720bc6f --- /dev/null +++ b/app/src/main/res/values-fr/pokemons.xml @@ -0,0 +1,156 @@ + + + + Bulbizarre + Herbizarre + Florizarre + Salamèche + Reptincel + Dracaufeu + Carapuce + Carabaffe + Tortank + Chenipan + Chrysacier + Papilusion + Aspicot + Coconfort + Dardargnan + Roucool + Roucoups + Roucarnage + Rattata + Rattatac + Piafabec + Rapasdepic + Abo + Arbok + Pikachu + Raichu + Sabelette + Sablaireau + Nidoran♀ + Nidorina + Nidoqueen + Nidoran♂ + Nidorino + Nidoking + Mélofée + Mélodelfe + Goupix + Feunard + Rondoudou + Grodoudou + Nosferapti + Nosferalto + Mystherbe + Ortide + Rafflesia + Paras + Parasect + Mimitoss + Aéromite + Taupiqueur + Triopikeur + Miaouss + Persian + Psykokwak + Akwakwak + Férosinge + Colossinge + Caninos + Arcanin + Ptitard + Têtarte + Tartard + Abra + Kadabra + Alakazam + Machoc + Machopeur + Mackogneur + Chétiflor + Boustiflor + Empiflor + Tentacool + Tentacruel + Racaillou + Gravalanch + Grolem + Ponyta + Galopa + Ramoloss + Flagadoss + Magnéti + Magnéton + Canarticho + Doduo + Dodrio + Otaria + Lamantine + Tadmorv + Grotadmorv + Kokiyas + Crustabri + Fantominus + Spectrum + Ectoplasma + Onix + Soporifik + Hypnomade + Krabby + Krabboss + Voltorbe + Électrode + Nœunœuf + Noadkoko + Osselait + Ossatueur + Kicklee + Tygnon + Excelangue + Smogo + Smogogo + Rhinocorne + Rhinoféros + Leveinard + Saquedeneu + Kangourex + Hypotrempe + Hypocéan + Poissirène + Poissoroy + Stari + Staross + M.Mime + Insécateur + Lippoutou + Élektek + Magmar + Scarabrute + Tauros + Magicarpe + Léviator + Lokhlass + Métamorph + Évoli + Aquali + Voltali + Pyroli + Porygon + Amonita + Amonistar + Kabuto + Kabutops + Ptéra + Ronflex + Artikodin + Électhor + Sulfura + Minidraco + Draco + Dracolosse + Mewtwo + Mew + + \ No newline at end of file diff --git a/app/src/main/res/values/bools.xml b/app/src/main/res/values/bools.xml index e0aa051..384766c 100644 --- a/app/src/main/res/values/bools.xml +++ b/app/src/main/res/values/bools.xml @@ -3,4 +3,5 @@ true true true + true diff --git a/app/src/main/res/values/pokemons.xml b/app/src/main/res/values/pokemons.xml new file mode 100644 index 0000000..57196fd --- /dev/null +++ b/app/src/main/res/values/pokemons.xml @@ -0,0 +1,156 @@ + + + + Bulbasaur + Ivysaur + Venusaur + Charmander + Charmeleon + Charizard + Squirtle + Wartortle + Blastoise + Caterpie + Metapod + Butterfree + Weedle + Kakuna + Beedrill + Pidgey + Pidgeotto + Pidgeot + Rattata + Raticate + Spearow + Fearow + Ekans + Arbok + Pikachu + Raichu + Sandshrew + Sandslash + Nidoran♀ + Nidorina + Nidoqueen + Nidoran♂ + Nidorino + Nidoking + Clefairy + Clefable + Vulpix + Ninetales + Jigglypuff + Wigglytuff + Zubat + Golbat + Oddish + Gloom + Vileplume + Paras + Parasect + Venonat + Venomoth + Diglett + Dugtrio + Meowth + Persian + Psyduck + Golduck + Mankey + Primeape + Growlithe + Arcanine + Poliwag + Poliwhirl + Poliwrath + Abra + Kadabra + Alakazam + Machop + Machoke + Machamp + Bellsprout + Weepinbell + Victreebel + Tentacool + Tentacruel + Geodude + Graveler + Golem + Ponyta + Rapidash + Slowpoke + Slowbro + Magnemite + Magneton + Farfetch\'d + Doduo + Dodrio + Seel + Dewgong + Grimer + Muk + Shellder + Cloyster + Gastly + Haunter + Gengar + Onix + Drowzee + Hypno + Krabby + Kingler + Voltorb + Electrode + Exeggcute + Exeggutor + Cubone + Marowak + Hitmonlee + Hitmonchan + Lickitung + Koffing + Weezing + Rhyhorn + Rhydon + Chansey + Tangela + Kangaskhan + Horsea + Seadra + Goldeen + Seaking + Staryu + Starmie + Mr. Mime + Scyther + Jynx + Electabuzz + Magmar + Pinsir + Tauros + Magikarp + Gyarados + Lapras + Ditto + Eevee + Vaporeon + Jolteon + Flareon + Porygon + Omanyte + Omastar + Kabuto + Kabutops + Aerodactyl + Snorlax + Articuno + Zapdos + Moltres + Dratini + Dragonair + Dragonite + Mewtwo + Mew + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 30665d7..0e6dc54 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -44,4 +44,9 @@ Enable catch notifications Show catch result via system toast + Hatch Notifications + hatch_notification_key + Enable hatch notifications + Show hatch result via system toast +