diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml new file mode 100644 index 0000000..da3b139 --- /dev/null +++ b/.github/workflows/android.yml @@ -0,0 +1,92 @@ +name: Android CI + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + test: + name: Unit Test + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: set up JDK 15 + uses: actions/setup-java@v1 + with: + java-version: 15 + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Run Unit test + run: ./gradlew test + + apk: + name: Generate APK + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: set up JDK 15 + uses: actions/setup-java@v1 + with: + java-version: 15 + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Assemble App APK + run: ./gradlew assembleDebug + - name: Upload App APK + uses: actions/upload-artifact@v1 + with: + name: app-debug + path: app/build/outputs/apk/debug/app-debug.apk + + - name: Assemble Android Instrumented Unit Test + run: ./gradlew assembleDebugAndroidTest + - name: Upload Android Test APK + uses: actions/upload-artifact@v1 + with: + name: app-debug-androidTest + path: app/build/outputs/apk/androidTest/debug/app-debug-androidTest.apk + + firebase: + name: Run UI tests with Firebase Test Lab + needs: apk + runs-on: ubuntu-18.04 + + steps: + - uses: actions/checkout@v1 + + - name: Download app APK + uses: actions/download-artifact@v1 + with: + name: app-debug + + - name: Download Android test APK + uses: actions/download-artifact@v1 + with: + name: app-debug-androidTest + + - name: Login to Google Cloud + uses: google-github-actions/setup-gcloud@master + with: + version: '270.0.0' + service_account_key: ${{ secrets.FIREBASE_SERVICES_KEY }} + + - name: Set current project + run: "gcloud config set project ${{ secrets.FIREBASE_PROJECT_ID }}" + + - name: Run Instrumentation Tests in Firebase Test Lab + run: "gcloud firebase test android run + --type instrumentation + --app app-debug/app-debug.apk + --test app-debug-androidTest/app-debug-androidTest.apk + --device model=redfin,version=30,locale=en,orientation=portrait + --device model=greatlteks,version=28,locale=en,orientation=portrait + --device model=OnePlus3T,version=26,locale=en,orientation=portrait + --device model=HWMHA,version=24,locale=en,orientation=portrait + --device model=grandppltedx,version=23,locale=en,orientation=portrait + --device model=hwALE-H,version=21,locale=en,orientation=portrait" diff --git a/.gitignore b/.gitignore index 0a38ac0..3e0f851 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,62 @@ -/local.properties -/.idea/ -.DS_Store -/build -/captures -*.iml +# Built application files +*.apk +*.ap_ + +# Files for the ART/Dalvik VM +*.dex + +# Java class files +*.class + +# Generated files +bin/ +gen/ +out/ + +# Gradle files +.gradle/ +build/ + +# Local configuration file (sdk path, etc) local.properties + +# Proguard folder generated by Eclipse +proguard/ + +# Log Files +*.log + +# Android Studio Navigation editor temp files +.navigation/ + +# Android Studio captures folder +captures/ + +# IntelliJ +*.iml +.idea + +# Keystore files +# Uncomment the following line if you do not want to check your keystore files in. +#*.jks + +# External native build folder generated in Android Studio 2.2 and later +.externalNativeBuild + +# Google Services (e.g. APIs or Firebase) +google-services.json + +# Freeline +freeline.py +freeline/ +freeline_project_description.json + +# fastlane +fastlane/report.xml +fastlane/Preview.html +fastlane/screenshots +fastlane/test_output +fastlane/readme.md +*.gpg +.DS_Store +.cxx diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 6342dc8..0000000 --- a/.travis.yml +++ /dev/null @@ -1,18 +0,0 @@ -language: android -jdk: openjdk8 - -android: - components: - - tools - - build-tools-26.0.2 - - android-26 - - extra-android-m2repository - - extra-android-support - -notifications: - email: false - -before_install: - - chmod +x gradlew - -script: ./gradlew clean diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..7e879ba --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,109 @@ +Release Notes +==== + +1.2.11 +-- +* [Bug] Bug fixed [#105](https://github.com/akexorcist/Localization/pull/105) [#118](https://github.com/akexorcist/Localization/pull/118) [#114](https://github.com/akexorcist/Localization/pull/114) [#118](https://github.com/akexorcist/Localization/pull/118) +* [PR] [#125](https://github.com/akexorcist/Localization/pull/125) - Fix WebView crashing on Android 5 +* Update Gradle and dependencies version + * Compile SDK Version 31 + * Target SDK Version 31 + * Kotlin : 1.6.10 + * Gradle : 7.0.2 + * Gradle Plugin : 4.2.2 + * Activity KTX : 1.4.0 + * AndroidX AppCompat 1.4.0 + +1.2.10 +-- +* [Bug] Bug fixed [#105](https://github.com/akexorcist/Localization/issues/105) [#103](https://github.com/akexorcist/Localization/issues/103) [#92](https://github.com/akexorcist/Localization/issues/92) +* [PR] [#108](https://github.com/akexorcist/Localization/pull/108) - Fix resource not found crash +* Fix incorrect Configuration creation +* Using centralize localized logic (See `LocalizationUtility`) +* Remove `LocalizationContext` (no need anymore) +* Prevent BadParcelableException in `LocalizationActivityDelegate.checkBeforeLocaleChanging()` with try-catch +* Change `LocalizationDelegate.getResources(Context)` to `LocalizationDelegate.getResources(Context, Resources)` because resources from super class is require in this method. That's mean who does not using `LocalizationApplication` must update this method + +1.2.9 +-- +* [Bug] Bug fixed [#93](https://github.com/akexorcist/Localization/issues/93) [#95](https://github.com/akexorcist/Localization/issues/95) +* [PR] [#101](https://github.com/akexorcist/Localization/pull/101) - Update README.md +* Add LocalizationService and LocalizationServiceDelegate for Service +* Add `Context.toLocalizedContext()` extension function to convert context to localized context +* Add more sample code and UI test for Dialog Fragment, Dialog + WebView, and BroadcastReceiver +* Update Gradle and dependencies version + * Kotlin : 1.4.32 + * Gradle Plugin : 4.1.3 + * Activity KTX : 1.2.2 + +1.2.8 +---- +* [PR] [#96](https://github.com/akexorcist/Localization/issues/96) - Fix compatibility with Hilt ViewModel injection +* Add CI with GitHub Actions + +1.2.7 +---- +* [PR] [#74](https://github.com/akexorcist/Localization/pull/74) - Add setLanguageWithoutNotification +* [PR] [#83](https://github.com/akexorcist/Localization/pull/83) - fix: activity Intent can be NULL +* [Bug] Bug fixed [#72](https://github.com/akexorcist/Localization/issues/72) [#75](https://github.com/akexorcist/Localization/issues/75) +* Migrate sample project from Java to Kotlin +* New UI for sample project +* Add more sample code for Dark Theme and Hilt Dependency Injection +* Migrate UI test from Espresso to Kakao +* Update Gradle and dependencies version + * Kotlin : 1.4.31 + * Gradle Plugin : 4.1.2 + * Gradle Wrapper : 6.5 + +1.2.6 +---- +* [PR] [#66](https://github.com/akexorcist/Android-Localization/issues/66) - Fix incompatible with AppCompat 1.2.0 or higher +* [PR] [#60](https://github.com/akexorcist/Android-Localization/issues/60) - Supporting locale variants +* [Bug] Bug fixed [#65](https://github.com/akexorcist/Android-Localization/issues/65) +* Add layout resource support in LocalizationActivity's constructor +* Fix base context and application context not update in some version +* Update UI test +* Update Gradle and dependencies version + * Kotlin : 1.3.72 + * Gradle Plugin : 4.0.1 + * Gradle Wrapper : 6.1.1 + * AppCompat : 1.2.0 + +1.2.5 +---- +* [Bug] Bug fixed [#53](https://github.com/akexorcist/Android-Localization/issues/53) [#52](https://github.com/akexorcist/Android-Localization/issues/52) [#41](https://github.com/akexorcist/Android-Localization/issues/41) +* Removed dummy activity for fade in/out transition when language changing (if you want, create by yourself when onBeforeLocaleChanged(...) called) +* API level 14 supported ([#54](https://github.com/akexorcist/Android-Localization/issues/54)) +* Added example code for AndroidX Preferences + +1.2.4 +---- +* Merged PR from [#7](https://github.com/akexorcist/Android-Localization/pull/7) [#25](https://github.com/akexorcist/Android-Localization/pull/25) [#10](https://github.com/akexorcist/Android-Localization/pull/10) + +1.2.3 +---- +* [Bug] Bug fixed : Incorrect behavior in API level 24-27 (Android 7.0 - 8.1) [#30](https://github.com/akexorcist/Android-Localization/issues/30) [#37](https://github.com/akexorcist/Android-Localization/issues/37) +* [Bug] Bug fixed : setDefaultLanguage does not work properly [#28](https://github.com/akexorcist/Android-Localization/issues/28) +* Migrate to AndroidX and latest Gradle +* Migrate to Kotlin +* Add UI automated test in example code +* Move set default language to Application class (Please see the migrate instruction) +* Add pre-implemented application class for LocalizationApplicationDelegate + +1.2.2 +---- +* [Bug] Bug fixed [#18](https://github.com/akexorcist/Android-Localization/issues/18) +* Remove java 1.8 and lambda from the library +* Update gradle to 3.0 stable + +1.2.1 +---- +* Support string resource from getApplicationContext() +* Add LocalizationApplicationDelegate. So you need to custom application class in your app +* LocalizationDelegate was deprecated, replace by LocalizationActivityDelegate + +1.2.0 +---- +* [Bug] Bug fixed : Android 7.0 language [#14](https://github.com/akexorcist/Android-Localization/issues/14) +* [Bug] Language and country support [#5](https://github.com/akexorcist/Android-Localization/issues/5) +* [Bug] RTL on orientation changes [#15](https://github.com/akexorcist/Android-Localization/issues/15) [#9](https://github.com/akexorcist/Android-Localization/issues/9) \ No newline at end of file diff --git a/MIGRATE_TO_ANDROIDX.md b/MIGRATE_TO_ANDROIDX.md new file mode 100644 index 0000000..1fe49ac --- /dev/null +++ b/MIGRATE_TO_ANDROIDX.md @@ -0,0 +1,33 @@ +# Migrate to AndroidX +Since AndroidX supports per-app language preferences for backward compatibility. Please migrate this library to AndroidX for more stability, compatibility, and longer supports from Google team. + +* AppCompat `1.6.0-alpha03` or higher is required (see [AppCompat release notes](https://developer.android.com/jetpack/androidx/releases/appcompat)) +* Remove `LocalizationApplicationDelegate` from Application class +* Replace `LocalizationActivity` with `AppCompatActivity` or remove `LocalizationActivityDelegate` from your custom Activity +* Replace `setLanguage(language)` with `AppCompatDelegate.setApplicationLocales()` +```kotlin +val locales = LocaleListCompat.forLanguageTags(language) +AppCompatDelegate.setApplicationLocales(locales) +``` +* Remove `toLocalizedContext()` and use original Context +* Remove `LocalizationServiceDelegate` from Service class +* Add `androidx.appcompat.app.AppLocalesMetadataHolderService` as `` in Android Manifest (see [Support Android 12 and lower](https://developer.android.com/about/versions/13/features/app-languages#android12-impl)) +```xml + + + + + + + + +``` +* Remove this library from your project (`implementation 'com.akexorcist:localization:'`) +* Test your app + +For more information about per-app language preferences, see [Per-app language preferences](https://developer.android.com/about/versions/13/features/app-languages) diff --git a/README.md b/README.md index d0264b0..fe02409 100644 --- a/README.md +++ b/README.md @@ -1,387 +1,318 @@ +[![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-Android--Localization-brightgreen.svg?style=flat)](http://android-arsenal.com/details/1/2890) +[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.akexorcist/localization/badge.svg)](https://search.maven.org/artifact/com.akexorcist/localization) +![Minimum SDK Version](https://img.shields.io/badge/minSdkVersion-14-brightgreen) +[![Workflow Status](https://github.com/akexorcist/Android-Localization/actions/workflows/android.yml/badge.svg)](https://github.com/akexorcist/Localization/actions) -[![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-Android--LocalizationActivity-brightgreen.svg?style=flat)](http://android-arsenal.com/details/1/2890) [![Build Status](https://travis-ci.org/akexorcist/Android-LocalizationActivity.svg?branch=master)](https://travis-ci.org/akexorcist/Android-LocalizationActivity) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.akexorcist/localizationactivity/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.akexorcist/localizationactivity) +Discontinued +==== +Since Google announced Android 13 with per-app language preferences supports. This feature also backport to older Android version with AndroidX. So there's no reason to contribute this library anymore. For more stability, compatibility, and longer supports from Google team, please migrate to AndroidX. See [Migrate to AndroidX guide](./MIGRATE_TO_ANDROIDX.md). -Android-LocalizationActivity -============================== +Localization Library +==== +![Header image](https://raw.githubusercontent.com/akexorcist/Android-Localization/master/image/01-header.jpg) +Android library for in-app language changes support in your application -![Header image](https://raw.githubusercontent.com/akexorcist/Android-LocalizationActivity/master/image/01-header.jpg) -You can now chill out on supporting multiple languages on your android application. - -It is normal for your Android application to support multiple languages. And it is very easy because you can do them by putting each language in different String Resource folders. That is the only thing that developers has to do. The rest will be handled by Android system. - - -Its easiness comes with a limitation. The language of your application follows your Android System language. Life is hard when you change your application language on-the-fly. E.g., you have a language switcher button in your application. If you have this problem, you come to the right place. I have created a library to handle language changing at application level. -It is called "Localization Activity". +Feature +==== +* In-app language changing +* Default language when first launch +* Work with string resource in XML and programmatically +* RTL language support +* Align on platform behavior Demo -=============================== - -Watch a short demo video from [YouTube](https://www.youtube.com/watch?v=mFtVIFr2taY) or try it at [Google Play](https://play.google.com/store/apps/details?id=com.akexorcist.localizationapp) +==== +Try it at [Google Play](https://play.google.com/store/apps/details?id=com.akexorcist.localizationapp) Download -=============================== - -Maven -``` - - com.akexorcist - localizationactivity - 1.2.1 - +==== +Since version 1.2.9 will [move from JCenter to MavenCentral](https://developer.android.com/studio/build/jcenter-migration) + +```groovy +// build.gradle (project) +allprojects { + repositories { + mavenCentral() + /* ... */ + } +} ``` Gradle +```groovy +implementation 'com.akexorcist:localization:1.2.11' ``` -compile 'com.akexorcist:localizationactivity:1.2.1' -``` - -(Optional) You can exclude `com.android.support:appcompat-v7`, if your project doens't use AppCompat v7 and declare this library with delegate way. - - -Update -=========================== - 1.2.1 - --------------------------- -* Support string resource from getApplicationContext() -* Add LocalizationApplicationDelegate. So you need to custom application class in your app -* LocalizationDelegate was deprecated, replace by LocalizationActivityDelegate - -1.2.0 ---------------------------- -* [bug] Bug fixed : Android 7.0 language [#14](https://github.com/akexorcist/Android-LocalizationActivity/issues/14) -* [bug] Language and country support [#5](https://github.com/akexorcist/Android-LocalizationActivity/issues/5) -* [bug] RTL on orientation changes [#15](https://github.com/akexorcist/Android-LocalizationActivity/issues/15) [#9](https://github.com/akexorcist/Android-LocalizationActivity/issues/9) - - - -Feature -=========================== -* On-time language changing supported. -* Auto setup when activity was created. -* Current language config will save to `SharedPreference` automagically. -* Very easy to use it. - - -LocalizationActivity extends from AppCompatActivity -=========================== -LocalizationActivity is extended from AppCompatActivity class. So you still can use all methods from AppCompatActivity class. -![Header image](https://raw.githubusercontent.com/akexorcist/Android-LocalizationActivity/master/image/03-extend.jpg) - - -Don't like AppCompat v7? Try delegate way -=========================== -(By @AleksanderMielczarek) -```java -import android.app.Activity; -import android.content.Context; -import android.content.res.Resources; -import android.os.Bundle; - -import com.akexorcist.localizationactivity.core.LocalizationActivityDelegate; -import com.akexorcist.localizationactivity.core.OnLocaleChangedListener; - -import java.util.Locale; - -public abstract class CustomActivity extends Activity implements OnLocaleChangedListener { +(Optional) You can exclude `androidx.appcompat:appcompat`, if your project does not use AppCompat. +```groovy +implementation ('com.akexorcist:localization:1.2.11') { + exclude group: 'androidx.core', module: 'core' +} +``` - private LocalizationActivityDelegate localizationDelegate = new LocalizationActivityDelegate(this); - @Override - public void onCreate(Bundle savedInstanceState) { - localizationDelegate.addOnLocaleChangedListener(this); - localizationDelegate.onCreate(savedInstanceState); - super.onCreate(savedInstanceState); - } +Usage +==== +Custom application class which extends from `LocalizationApplication` is require. +```kotlin +class MainApplication: LocalizationApplication() { + /* ... */ + override fun getDefaultLanguage(context: Context) = Locale.ENGLISH +} +``` - @Override - public void onResume() { - super.onResume(); - localizationDelegate.onResume(this); +Either not, using `LocalizationApplicationDelegate` with additional code as below +```kotlin +class MainApplication: Application() { + private val localizationDelegate = LocalizationApplicationDelegate() + + override fun attachBaseContext(base: Context) { + localizationDelegate.setDefaultLanguage(base, Locale.ENGLISH) + super.attachBaseContext(localizationDelegate.attachBaseContext(base)) } - - @Override - protected void attachBaseContext(Context newBase) { - super.attachBaseContext(localizationDelegate.attachBaseContext(newBase)); + + override fun onConfigurationChanged(newConfig: Configuration) { + super.onConfigurationChanged(newConfig) + localizationDelegate.onConfigurationChanged(this) } - - @Override - public Context getApplicationContext() { - return localizationDelegate.getApplicationContext(super.getApplicationContext()); + + override fun getApplicationContext(): Context { + return localizationDelegate.getApplicationContext(super.getApplicationContext()) } - - @Override - public Resources getResources() { - return localizationDelegate.getResources(super.getResources()); + + override fun getResources(): Resources { + return localizationDelegate.getResources(baseContext, super.getResources()) } +} +``` - public final void setLanguage(String language) { - localizationDelegate.setLanguage(this, language); - } +For the activities, extends from `LocalizationActivity`. - public final void setLanguage(Locale locale) { - localizationDelegate.setLanguage(this, locale); - } +```kotlin +class MainActivity: LocalizationActivity() { + /* ... */ +} +``` - public final void setDefaultLanguage(String language) { - localizationDelegate.setDefaultLanguage(language); - } +Or using `LocalizationActivityDelegate` with additional code +```kotlin +open class CustomActivity : Activity(), OnLocaleChangedListener { + private val localizationDelegate = LocalizationActivityDelegate(this) - public final void setDefaultLanguage(Locale locale) { - localizationDelegate.setDefaultLanguage(locale); + public override fun onCreate(savedInstanceState: Bundle?) { + localizationDelegate.addOnLocaleChangedListener(this) + localizationDelegate.onCreate() + super.onCreate(savedInstanceState) } - public final Locale getCurrentLanguage() { - return localizationDelegate.getLanguage(this); + public override fun onResume() { + super.onResume() + localizationDelegate.onResume(this) } - // Just override method locale change event - @Override - public void onBeforeLocaleChanged() { + override fun attachBaseContext(newBase: Context) { + applyOverrideConfiguration(localizationDelegate.updateConfigurationLocale(newBase)) + super.attachBaseContext(newBase) } - @Override - public void onAfterLocaleChanged() { + override fun getApplicationContext(): Context { + return localizationDelegate.getApplicationContext(super.getApplicationContext()) } -} -``` - - -Usage -=========================== -You need to use custom application class in your project that implemented the LocalizationApplicationDelegate class. -```java -import android.app.Application; -import android.content.Context; -import android.content.res.Configuration; - -import com.akexorcist.localizationactivity.core.LocalizationApplicationDelegate; - -public class MainApplication extends Application { - LocalizationApplicationDelegate localizationDelegate = new LocalizationApplicationDelegate(this); - @Override - protected void attachBaseContext(Context base) { - super.attachBaseContext(localizationDelegate.attachBaseContext(base)); + override fun getResources(): Resources { + return localizationDelegate.getResources(super.getResources()) } - @Override - public void onConfigurationChanged(Configuration newConfig) { - super.onConfigurationChanged(newConfig); - localizationDelegate.onConfigurationChanged(this); + fun setLanguage(language: String?) { + localizationDelegate.setLanguage(this, language!!) } - @Override - public Context getApplicationContext() { - return localizationDelegate.getApplicationContext(super.getApplicationContext()); + fun setLanguage(locale: Locale?) { + localizationDelegate.setLanguage(this, locale!!) } -} -``` -In your activity, just extends from LocalizationActivity class or your custom class. + val currentLanguage: Locale + get() = localizationDelegate.getLanguage(this) -```java -import android.os.Bundle; -import android.view.View; - -import com.akexorcist.localizationactivity.ui.LocalizationActivity; - -public class MainActivity extends LocalizationActivity implements View.OnClickListener { - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_simple); - - findViewById(R.id.btn_th).setOnClickListener(this); - findViewById(R.id.btn_en).setOnClickListener(this); - } - - @Override - public void onClick(View v) { - int id = v.getId(); - if (id == R.id.btn_en) { - setLanguage("en"); - } else if (id == R.id.btn_th) { - setLanguage("th"); - } - } + // Just override method locale change event + override fun onBeforeLocaleChanged() {} + override fun onAfterLocaleChanged() {} } ``` -In the example above, when a user clicks on a button. It will change to English or Thai language. That's it! +Then prepare your multilingual content in string resource. -**It's very easy, right?** You barely do anything. +![Multilingual Content](https://raw.githubusercontent.com/akexorcist/Android-Localization/master/image/02-string_resource.jpg) -Then just build up some String Resource for English and Thai language. -![Header image](https://raw.githubusercontent.com/akexorcist/Android-LocalizationActivity/master/image/02-string_resource.jpg) - -Complete! Your application now supports multiple languages now. +Public method on LocalizationActivity +---- +It have only 4 public methods. -Public method on LocalizationActivity ---------------------------- - -I wanted it to be easy to use and does not have to do much coding. So it have only 3 public methods. - -```java -void setLanguage(String language) -void setLanguage(String language, String country) -void setLanguage(Locale locale) -String getLanguage() -void setDefaultLanguage(String language) -void setDefaultLanguage(String language, String country) -void setDefaultLanguage(Locale locale) +```kotlin +fun setLanguage(language: String) +fun setLanguage(language: String, country: Strinng) +fun setLanguage(locale: Locale) +fun getCurrentLanguage(): String ``` -**setLanguage** Set the language that you need to change. The string value given will be use for setup Locale class later. +`setLanguage` Set the language that you need to change. -Example +For example -```java +```kotlin setLanguage("th") // Language : Thailand setLanguage("th", "TH") // Language : Thailand, Country : Thai +setLanguage(Locale("th", "TH")) // Language : Thailand, Country : Thai setLanguage("en") // Language : English setLanguage("en", "GB") // Language : English, Country : Great Britain setLanguage("en", "US") // Language : English, Country : United States -setLanguage(Locale.KOREA) // Language : Korean, Country : Korea +setLanguage(Locale("en", "US")) // Language : English, Country : United States +setLanguage(Locale.KOREA) // Language : Korean, Country : Korea setLanguage(Locale.KOREAN) // Language : Korean -setLanguage(Locale.CANADA_FRENCH) // Language : French, Country : Canada +setLanguage(Locale.CANADA_FRENCH) // Language : French, Country : Canada ``` -So you must determine the correct language for Locale class. - -**getLanguage** Get current language. (Return to string locale) - -**setDefaultLanguage** Set default language if there is no language configuration. Provided that this method must called only once at first activity in your application and called before super.onCreate - -```java -@Override -public void onCreate(Bundle savedInstanceState) { - setDefaultLanguage(Locale.JAPAN); - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_main); - - ... -} -``` +`getLanguage` Get current language as string locale. -and 2 optional override methods. +And 2 optional override methods. -```java -void onBeforeLocaleChanged() -void onAfterLocaleChanged() +```kotlin +fun onBeforeLocaleChanged() +fun onAfterLocaleChanged() ``` -This override method will be called then activity language was changed. If you need to know when language has change, just override these methods. - -![Header image](https://raw.githubusercontent.com/akexorcist/Android-LocalizationActivity/master/image/04-life_cycle.jpg) +This override method will be useful when you need to know when language has changed. -Usually change the language code has a problem with activity that already created. +![Back Stack 1](https://raw.githubusercontent.com/akexorcist/Android-Localization/master/image/04-life_cycle.jpg) -![Header image](https://raw.githubusercontent.com/akexorcist/Android-LocalizationActivity/master/image/05-step_one.jpg) +When `setLanguage` was called. Current active activity will be recreated to apply the new language. -If latest activity can change the language. It does not apply to previous activity. +![Back Stack 2](https://raw.githubusercontent.com/akexorcist/Android-Localization/master/image/05-step_one.jpg) -![Header image](https://raw.githubusercontent.com/akexorcist/Android-LocalizationActivity/master/image/06-step_two.jpg) +Previous activities in back stack does not change to new language immediately. Until it back to active activity again. -But no problem for this library when application getback to previous activity. If you extend that activity to LocalizationActivity. It will changed immediately. +![Back Stack 3](https://raw.githubusercontent.com/akexorcist/Android-Localization/master/image/06-step_two.jpg) + +![Back Stack 4](https://raw.githubusercontent.com/akexorcist/Android-Localization/master/image/07-step_three.jpg) -![Header image](https://raw.githubusercontent.com/akexorcist/Android-LocalizationActivity/master/image/07-step_three.jpg) - -![Header image](https://raw.githubusercontent.com/akexorcist/Android-LocalizationActivity/master/image/08-step_four.jpg) +![Back Stack 5](https://raw.githubusercontent.com/akexorcist/Android-Localization/master/image/08-step_four.jpg) Action Bar or Toolbar's title ---------------------------- -You have to call -```java -setTitle(String title) -// or -getActionBar().setTitle(String title) - ``` - in on activity create (onCreate) every time - ```java - public class MainActivity extends Localization { - @Override - public void onCreate(Bundle onSavedInstanceState) { - ... - setTitle(R.string,user_management_screen); - } - } +---- +You have to call `setTitle(resId)` or `getActionBar().setTitle(resId)` in `onCreate(onSavedInstanceState: Bundle)` to apply the new language. + +```kotlin +class MainActivity: LocalizationActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + /* ... */ + setTitle(R.string.main_activity_title) + } +} ``` -Instance State ---------------------------- -When language was changed. An activity wil recreated. So if you have any data object. It should be handle by save/restore instance state for complelely works. (It simple way to supported portrait/landscape orientation) +Handle state changes +---- +Activity will be recreate when language has changed as common behavior for configuration changes in Android. Any Activities or Fragments which hold the data should handle the state changes. -Therefore you have to override onSaveInstance and onRestoreInstance in to your code, and handle it. -```java -import android.os.Bundle; -import android.view.View; +Change the language in Fragment +---- +Language in fragment will depends on activity. So no need for additional code in Fragment. -public class MainActivity extends LocalizationActivity implements View.OnClickListener { - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_main); +Service +--- +For normally usage, just extends from `LocalizationService` +```kotlin +class SimpleService : LocalizationService() { + /* ... */ +} +``` - // TODO Initial view and widget here +Or using `LocalizationServiceDelegate` with additional code +```kotlin +abstract class CustomService : Service() { + private val localizationDelegate: LocalizationServiceDelegate by lazy { + LocalizationServiceDelegate(this) + } - if (savedInstanceState == null) { - // TODO Activity first created - } else { - // TODO Activity recreated from screen orientation or change language - } + override fun getBaseContext(): Context { + return localizationDelegate.getBaseContext(super.getBaseContext()) } - @Override - protected void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - // TODO Save instance here + override fun getApplicationContext(): Context { + return localizationDelegate.getApplicationContext(super.getApplicationContext()) } - @Override - protected void onRestoreInstanceState(Bundle savedInstanceState) { - // TODO Restore instance here - super.onRestoreInstanceState(savedInstanceState); + override fun getResources(): Resources { + return localizationDelegate.getResources(super.getResources()) + } +} +``` + + +BroadcastReceiver +--- +BroadcastReceiver is abstract class. So we cannot create LocalizationBroadcastReceiver fot you. + +In this case, you need to convert the context in `onReceive(context: Context, intent: Intent)` to localized context with `Context.toLocalizedContext()` before using. + +```kotlin +class SimpleBroadcastReceiver : BroadcastReceiver() { + override fun onReceive(context: Context, intent: Intent) { + val localizedContext = context.toLocalizedContext() + /* ... */ } } ``` -Fragment ---------------------------- -It's affect on fragment as well. +Language resources optimization in Android App Bundle +==== +Change the language by library can cause a crash to your app when you publishing your app with Android App Bundle with language resources optimization enabled. -Fragment language configuration is depending with activity. If activity language was changed and recreated. It will apply to fragment as well. So you have to handle to Instance State on fragment like an activity. +To fix this, Using the Additional Languages API in Play Core library to download the additional language before. -About Save/Restore Instance State. Read more on The [Real Best Practices to Save/Restore Activity's and Fragment's state.](http://inthecheesefactory.com/blog/fragment-state-saving-best-practices/en) +For more information about Additional Language API : https://android-developers.googleblog.com/2019/03/the-latest-android-app-bundle-updates.html +If you don't want to implement this feature in your code, just ignore the language resources optimization by adding the Android App Bundle configuration in your app's build.gradle +```groovy +android { + /* ... */ + bundle { + language { + enableSplit = false + } + } +} +``` -Documentation -=========================== -English Version : http://www.akexorcist.com/2015/07/localization-activity-best-way-to-handle-language-en.html +ProGuard +===== +Normally, there's no require the ProGuard rules for this library. -Thai Version : http://www.akexorcist.com/2015/07/localization-activity-best-way-to-handle-language.html +But if you want to exclude this library from obfuscate and shrinking. You also can add these code to `proguard-rules.pro` +``` +-keep class com.akexorcist.localizationactivity.** { *; } +-dontwarn com.akexorcist.localizationactivity.** +``` -Special Thanks -=========================== -@first087 -@AleksanderMielczarek +Change Log +==== +See [CHANGELOG.md](CHANGELOG.md) Licence -=========================== -Copyright 2015 Akexorcist +==== +Copyright 2021 Akexorcist Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with the License. You may obtain a copy of the License in the LICENSE file, or at: diff --git a/app/build.gradle b/app/build.gradle index 6492fb6..f35ca1f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,31 +1,68 @@ apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-kapt' +apply plugin: 'dagger.hilt.android.plugin' android { - compileSdkVersion Integer.parseInt(project.ANDROID_COMPILE_SDK_VERSION) - buildToolsVersion project.ANDROID_BUILD_TOOLS_VERSION + compileSdkVersion project.compileSdkVersion defaultConfig { applicationId "com.akexorcist.localizationapp" - minSdkVersion Integer.parseInt(project.ANDROID_MIN_SDK) - targetSdkVersion Integer.parseInt(project.ANDROID_TARGET_SDK_VERSION) - versionName project.VERSION_NAME - versionCode Integer.parseInt(project.VERSION_CODE) + minSdkVersion 19 + targetSdkVersion project.targetSdkVersion + versionCode project.versionCode + versionName project.versionName + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } buildTypes { - release { + debug { minifyEnabled false + shrinkResources false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + release { + minifyEnabled true + shrinkResources true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } + compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 + sourceCompatibility project.targetJavaVersion + targetCompatibility project.targetJavaVersion + } + + kotlinOptions { + jvmTarget = project.targetJavaVersion.toString() + } + + buildFeatures { + viewBinding true + } + + testOptions { + animationsDisabled true } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation 'com.android.support:appcompat-v7:26.1.0' - implementation project(':localizationActivity') + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'androidx.viewpager:viewpager:1.0.0' + implementation 'androidx.preference:preference-ktx:1.1.1' + implementation "androidx.viewpager2:viewpager2:1.0.0" + implementation 'com.google.dagger:hilt-android:2.40.4' + kapt 'com.google.dagger:hilt-compiler:2.40.4' + + androidTestImplementation 'androidx.test:runner:1.4.0' + androidTestImplementation 'androidx.test:rules:1.4.0' + androidTestImplementation 'androidx.test.ext:junit:1.1.3' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' + androidTestImplementation 'androidx.test.espresso:espresso-web:3.4.0' + androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0' + androidTestImplementation 'com.agoda.kakao:kakao:2.4.0' + + implementation project(':localization') } diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index c7928bc..c5a1751 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -15,3 +15,6 @@ #-keepclassmembers class fqcn.of.javascript.interface.for.webview { # public *; #} + +-keep class com.akexorcist.localizationactivity.** { *; } +-dontwarn com.akexorcist.localizationactivity.** diff --git a/app/src/androidTest/java/com/akexorcist/localizationapp/AllTest.kt b/app/src/androidTest/java/com/akexorcist/localizationapp/AllTest.kt new file mode 100644 index 0000000..e71f0f5 --- /dev/null +++ b/app/src/androidTest/java/com/akexorcist/localizationapp/AllTest.kt @@ -0,0 +1,21 @@ +package com.akexorcist.localizationapp + +import org.junit.runner.RunWith +import org.junit.runners.Suite + +//@RunWith(Suite::class) +//@Suite.SuiteClasses( +// SimpleActivityTest::class, +// CustomActivityTest::class, +// StackedActivityTest::class, +// SimpleFragmentTest::class, +// NestedFragmentTest::class, +// SimpleDialogTest::class, +// DialogWebViewTest::class, +// ViewPagerTest::class, +// ListPreferencesTest::class, +// HiltDependencyInjectionTest::class, +// BroadcastReceiverTest::class, +// DarkThemeTest::class, +//) +//class AllTest \ No newline at end of file diff --git a/app/src/androidTest/java/com/akexorcist/localizationapp/ApplicationTest.java b/app/src/androidTest/java/com/akexorcist/localizationapp/ApplicationTest.java deleted file mode 100644 index 9ecb2fa..0000000 --- a/app/src/androidTest/java/com/akexorcist/localizationapp/ApplicationTest.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.akexorcist.localizationapp; - -import android.app.Application; -import android.test.ApplicationTestCase; - -/** - * Testing Fundamentals - */ -public class ApplicationTest extends ApplicationTestCase { - public ApplicationTest() { - super(Application.class); - } -} \ No newline at end of file diff --git a/app/src/androidTest/java/com/akexorcist/localizationapp/BroadcastReceiverTest.kt b/app/src/androidTest/java/com/akexorcist/localizationapp/BroadcastReceiverTest.kt new file mode 100644 index 0000000..f56319d --- /dev/null +++ b/app/src/androidTest/java/com/akexorcist/localizationapp/BroadcastReceiverTest.kt @@ -0,0 +1,101 @@ +package com.akexorcist.localizationapp + +import androidx.test.ext.junit.rules.ActivityScenarioRule +import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.uiautomator.UiDevice +import com.agoda.kakao.screen.Screen.Companion.onScreen +import com.akexorcist.localizationapp.data.ExpectedContent +import com.akexorcist.localizationapp.screen.MainActivityScreen +import com.akexorcist.localizationapp.screen.SimpleBroadcastScreen +import org.junit.Ignore +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4ClassRunner::class) +class BroadcastReceiverTest { + @JvmField + val uiDevices: UiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) + + @Rule + @JvmField + val rule = ActivityScenarioRule(MainActivity::class.java) + + @Test + @Ignore("For local running only, there is some flakiness when running on Firebase Test Lab") + fun broadcastReceiver() { + onScreen { + buttonBroadcastReceiver { + scrollTo() + click() + } + } + onScreen { + // Chinese + buttonChinese { + scrollTo() + click() + } + textViewContent { + hasText(ExpectedContent.APPLE_CHINESE) + } + // Italian + buttonItalian { + scrollTo() + click() + } + textViewContent { + hasText(ExpectedContent.APPLE_ITALIAN) + } + // Japanese + buttonJapanese { + scrollTo() + click() + } + textViewContent { + hasText(ExpectedContent.APPLE_JAPANESE) + } + // Korean + buttonKorean { + scrollTo() + click() + } + textViewContent { + hasText(ExpectedContent.APPLE_KOREAN) + } + // Portuguese + buttonPortuguese { + scrollTo() + click() + } + textViewContent { + hasText(ExpectedContent.APPLE_PORTUGUESE) + } + // Thai + buttonThai { + scrollTo() + click() + } + textViewContent { + hasText(ExpectedContent.APPLE_THAI) + } + // American + buttonAmerican { + scrollTo() + click() + } + textViewContent { + hasText(ExpectedContent.APPLE_AMERICAN) + } + buttonBack { click() } + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_AMERICAN) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_AMERICAN) + } + } + } +} diff --git a/app/src/androidTest/java/com/akexorcist/localizationapp/CustomActivityTest.kt b/app/src/androidTest/java/com/akexorcist/localizationapp/CustomActivityTest.kt new file mode 100644 index 0000000..115cddf --- /dev/null +++ b/app/src/androidTest/java/com/akexorcist/localizationapp/CustomActivityTest.kt @@ -0,0 +1,194 @@ +package com.akexorcist.localizationapp + +import androidx.test.ext.junit.rules.ActivityScenarioRule +import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.uiautomator.UiDevice +import com.agoda.kakao.screen.Screen.Companion.onScreen +import com.akexorcist.localizationapp.data.ExpectedContent +import com.akexorcist.localizationapp.screen.MainActivityScreen +import com.akexorcist.localizationapp.screen.CustomActivityScreen +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4ClassRunner::class) +class CustomActivityTest { + @JvmField + val uiDevices: UiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) + + @Rule + @JvmField + val rule = ActivityScenarioRule(MainActivity::class.java) + + @Test + fun customActivity() { + onScreen { + buttonCustomActivity { click() } + } + // Chinese + onScreen { + buttonChinese { + scrollTo() + click() + } + textViewContent { + hasText(ExpectedContent.YOUTUBE_CHINESE) + uiDevices.setOrientationRight() + hasText(ExpectedContent.YOUTUBE_CHINESE) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_CHINESE) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_CHINESE) + } + buttonCustomActivity { click() } + } + // Italian + onScreen { + textViewContent { + hasText(ExpectedContent.YOUTUBE_CHINESE) + } + buttonItalian { + scrollTo() + click() + } + textViewContent { + hasText(ExpectedContent.YOUTUBE_ITALIAN) + uiDevices.setOrientationRight() + hasText(ExpectedContent.YOUTUBE_ITALIAN) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_ITALIAN) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_ITALIAN) + } + buttonCustomActivity { click() } + } + // Japanese + onScreen { + textViewContent { + hasText(ExpectedContent.YOUTUBE_ITALIAN) + } + buttonJapanese { + scrollTo() + click() + } + textViewContent { + hasText(ExpectedContent.YOUTUBE_JAPANESE) + uiDevices.setOrientationRight() + hasText(ExpectedContent.YOUTUBE_JAPANESE) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_JAPANESE) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_JAPANESE) + } + buttonCustomActivity { click() } + } + // Korean + onScreen { + textViewContent { + hasText(ExpectedContent.YOUTUBE_JAPANESE) + } + buttonKorean { + scrollTo() + click() + } + textViewContent { + hasText(ExpectedContent.YOUTUBE_KOREAN) + uiDevices.setOrientationRight() + hasText(ExpectedContent.YOUTUBE_KOREAN) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_KOREAN) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_KOREAN) + } + buttonCustomActivity { click() } + } + // Portuguese + onScreen { + textViewContent { + hasText(ExpectedContent.YOUTUBE_KOREAN) + } + buttonPortuguese { + scrollTo() + click() + } + textViewContent { + hasText(ExpectedContent.YOUTUBE_PORTUGUESE) + uiDevices.setOrientationRight() + hasText(ExpectedContent.YOUTUBE_PORTUGUESE) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_PORTUGUESE) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_PORTUGUESE) + } + buttonCustomActivity { click() } + } + // Thai + onScreen { + textViewContent { + hasText(ExpectedContent.YOUTUBE_PORTUGUESE) + } + buttonThai { + scrollTo() + click() + } + textViewContent { + hasText(ExpectedContent.YOUTUBE_THAI) + uiDevices.setOrientationRight() + hasText(ExpectedContent.YOUTUBE_THAI) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_THAI) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_THAI) + } + buttonCustomActivity { click() } + } + // American + onScreen { + textViewContent { + hasText(ExpectedContent.YOUTUBE_THAI) + } + buttonAmerican { + scrollTo() + click() + } + textViewContent { + hasText(ExpectedContent.YOUTUBE_AMERICAN) + uiDevices.setOrientationRight() + hasText(ExpectedContent.YOUTUBE_AMERICAN) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_AMERICAN) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_AMERICAN) + } + } + } +} diff --git a/app/src/androidTest/java/com/akexorcist/localizationapp/DarkThemeTest.kt b/app/src/androidTest/java/com/akexorcist/localizationapp/DarkThemeTest.kt new file mode 100644 index 0000000..3e184e0 --- /dev/null +++ b/app/src/androidTest/java/com/akexorcist/localizationapp/DarkThemeTest.kt @@ -0,0 +1,270 @@ +package com.akexorcist.localizationapp + +import android.os.Build +import androidx.test.ext.junit.rules.ActivityScenarioRule +import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.uiautomator.UiDevice +import androidx.test.uiautomator.UiSelector +import com.agoda.kakao.screen.Screen.Companion.onScreen +import com.akexorcist.localizationapp.annotation.TargetApiLevel +import com.akexorcist.localizationapp.data.ExpectedContent +import com.akexorcist.localizationapp.screen.MainActivityScreen +import com.akexorcist.localizationapp.screen.SimpleFragmentScreen +import org.junit.Ignore +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + + +@RunWith(AndroidJUnit4ClassRunner::class) +class DarkThemeTest { + @JvmField + val uiDevices: UiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) + + @Rule + @JvmField + val rule = ActivityScenarioRule(MainActivity::class.java) + + @Test + @Ignore("For local running on Android Q+ only, dark theme in quick settings panel is required") + fun darkTheme() { + onScreen { + buttonDarkTheme { + scrollTo() + click() + } + } + // Chinese + onScreen { + buttonChinese { + scrollTo() + click() + } + textViewContent { + hasText(ExpectedContent.APPLE_CHINESE) + } + } + uiDevices.openQuickSettings() + uiDevices.findObject(UiSelector().text("Dark theme")).click() + uiDevices.pressBack() + uiDevices.pressBack() + onScreen { + textViewContent { + hasText(ExpectedContent.APPLE_CHINESE) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_CHINESE) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_CHINESE) + } + buttonDarkTheme { + scrollTo() + click() + } + } + // Italian + onScreen { + textViewContent { + hasText(ExpectedContent.APPLE_CHINESE) + } + buttonItalian { + scrollTo() + click() + } + textViewContent { + hasText(ExpectedContent.APPLE_ITALIAN) + } + } + uiDevices.openQuickSettings() + uiDevices.findObject(UiSelector().text("Dark theme")).click() + uiDevices.pressBack() + uiDevices.pressBack() + onScreen { + textViewContent { + hasText(ExpectedContent.APPLE_ITALIAN) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_ITALIAN) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_ITALIAN) + } + buttonDarkTheme { + scrollTo() + click() + } + } + // Japanese + onScreen { + textViewContent { + hasText(ExpectedContent.APPLE_ITALIAN) + } + buttonJapanese { + scrollTo() + click() + } + textViewContent { + hasText(ExpectedContent.APPLE_JAPANESE) + } + } + uiDevices.openQuickSettings() + uiDevices.findObject(UiSelector().text("Dark theme")).click() + uiDevices.pressBack() + uiDevices.pressBack() + onScreen { + textViewContent { + hasText(ExpectedContent.APPLE_JAPANESE) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_JAPANESE) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_JAPANESE) + } + buttonDarkTheme { + scrollTo() + click() + } + } + // Korean + onScreen { + textViewContent { + hasText(ExpectedContent.APPLE_JAPANESE) + } + buttonKorean { + scrollTo() + click() + } + textViewContent { + hasText(ExpectedContent.APPLE_KOREAN) + } + } + uiDevices.openQuickSettings() + uiDevices.findObject(UiSelector().text("Dark theme")).click() + uiDevices.pressBack() + uiDevices.pressBack() + onScreen { + textViewContent { + hasText(ExpectedContent.APPLE_KOREAN) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_KOREAN) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_KOREAN) + } + buttonDarkTheme { + scrollTo() + click() + } + } + // Portuguese + onScreen { + textViewContent { + hasText(ExpectedContent.APPLE_KOREAN) + } + buttonPortuguese { + scrollTo() + click() + } + textViewContent { + hasText(ExpectedContent.APPLE_PORTUGUESE) + } + } + uiDevices.openQuickSettings() + uiDevices.findObject(UiSelector().text("Dark theme")).click() + uiDevices.pressBack() + uiDevices.pressBack() + onScreen { + textViewContent { + hasText(ExpectedContent.APPLE_PORTUGUESE) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_PORTUGUESE) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_PORTUGUESE) + } + buttonDarkTheme { + scrollTo() + click() + } + } + // Thai + onScreen { + textViewContent { + hasText(ExpectedContent.APPLE_PORTUGUESE) + } + buttonThai { + scrollTo() + click() + } + textViewContent { + hasText(ExpectedContent.APPLE_THAI) + } + } + uiDevices.openQuickSettings() + uiDevices.findObject(UiSelector().text("Dark theme")).click() + uiDevices.pressBack() + uiDevices.pressBack() + onScreen { + textViewContent { + hasText(ExpectedContent.APPLE_THAI) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_THAI) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_THAI) + } + buttonDarkTheme { + scrollTo() + click() + } + } + // American + onScreen { + textViewContent { + hasText(ExpectedContent.APPLE_THAI) + } + buttonAmerican { + scrollTo() + click() + } + textViewContent { + hasText(ExpectedContent.APPLE_AMERICAN) + } + } + uiDevices.openQuickSettings() + uiDevices.findObject(UiSelector().text("Dark theme")).click() + uiDevices.pressBack() + uiDevices.pressBack() + onScreen { + textViewContent { + hasText(ExpectedContent.APPLE_AMERICAN) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_AMERICAN) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_AMERICAN) + } + } + } +} diff --git a/app/src/androidTest/java/com/akexorcist/localizationapp/DialogWebViewTest.kt b/app/src/androidTest/java/com/akexorcist/localizationapp/DialogWebViewTest.kt new file mode 100644 index 0000000..05f1fab --- /dev/null +++ b/app/src/androidTest/java/com/akexorcist/localizationapp/DialogWebViewTest.kt @@ -0,0 +1,96 @@ +package com.akexorcist.localizationapp + +import androidx.test.ext.junit.rules.ActivityScenarioRule +import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.uiautomator.UiDevice +import com.agoda.kakao.screen.Screen.Companion.onScreen +import com.akexorcist.localizationapp.data.ExpectedContent +import com.akexorcist.localizationapp.screen.DialogWebViewLanguageChooserScreen +import com.akexorcist.localizationapp.screen.DialogWebViewMainScreen +import com.akexorcist.localizationapp.screen.DialogWebViewSiteScreen +import com.akexorcist.localizationapp.screen.MainActivityScreen +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import androidx.test.espresso.web.webdriver.Locator +import org.junit.Ignore + +@RunWith(AndroidJUnit4ClassRunner::class) +class DialogWebViewTest { + @JvmField + val uiDevices: UiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) + + @Rule + @JvmField + val rule = ActivityScenarioRule(MainActivity::class.java) + + @Test + fun dialogAndWebView() { + // Italy + onScreen { + buttonDialogWebView { + scrollTo() + click() + } + } + onScreen { + buttonChangeLanguage { click() } + } + onScreen { + buttonItalian { click() } + } + onScreen { + buttonShowWebsite { click() } + } + onScreen { + webViewContent { + withElement(Locator.ID, "content") { + hasText(ExpectedContent.HELLO_WORLD_ITALIAN) + } + } + buttonBack { click() } + } + onScreen { + buttonBack { click() } + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_ITALIAN) + } + } + + // American + onScreen { + buttonDialogWebView { + scrollTo() + click() + } + } + onScreen { + buttonChangeLanguage { click() } + } + onScreen { + buttonAmerican { click() } + } + onScreen { + buttonShowWebsite { click() } + } + onScreen { + webViewContent { + withElement(Locator.ID, "content") { + hasText(ExpectedContent.HELLO_WORLD_AMERICAN) + } + } + buttonBack { click() } + } + onScreen { + buttonBack { click() } + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_AMERICAN) + } + } + } +} diff --git a/app/src/androidTest/java/com/akexorcist/localizationapp/HiltDependencyInjectionTest.kt b/app/src/androidTest/java/com/akexorcist/localizationapp/HiltDependencyInjectionTest.kt new file mode 100644 index 0000000..48573b8 --- /dev/null +++ b/app/src/androidTest/java/com/akexorcist/localizationapp/HiltDependencyInjectionTest.kt @@ -0,0 +1,215 @@ +package com.akexorcist.localizationapp + +import androidx.test.ext.junit.rules.ActivityScenarioRule +import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.uiautomator.UiDevice +import com.agoda.kakao.screen.Screen.Companion.onScreen +import com.akexorcist.localizationapp.data.ExpectedContent +import com.akexorcist.localizationapp.screen.MainActivityScreen +import com.akexorcist.localizationapp.screen.HiltDependencyInjectionScreen +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4ClassRunner::class) +class HiltDependencyInjectionTest { + @JvmField + val uiDevices: UiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) + + @Rule + @JvmField + val rule = ActivityScenarioRule(MainActivity::class.java) + + @Test + fun hiltDependencyInjection() { + onScreen { + buttonHilt { + scrollTo() + click() + } + } + // Chinese + onScreen { + buttonChinese { + scrollTo() + click() + } + textViewContent { + hasText(ExpectedContent.APPLE_CHINESE) + uiDevices.setOrientationRight() + hasText(ExpectedContent.APPLE_CHINESE) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_CHINESE) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_CHINESE) + } + buttonHilt { + scrollTo() + click() + } + } + // Italian + onScreen { + textViewContent { + hasText(ExpectedContent.APPLE_CHINESE) + } + buttonItalian { + scrollTo() + click() + } + textViewContent { + hasText(ExpectedContent.APPLE_ITALIAN) + uiDevices.setOrientationRight() + hasText(ExpectedContent.APPLE_ITALIAN) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_ITALIAN) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_ITALIAN) + } + buttonHilt { + scrollTo() + click() + } + } + // Japanese + onScreen { + textViewContent { + hasText(ExpectedContent.APPLE_ITALIAN) + } + buttonJapanese { + scrollTo() + click() + } + textViewContent { + hasText(ExpectedContent.APPLE_JAPANESE) + uiDevices.setOrientationRight() + hasText(ExpectedContent.APPLE_JAPANESE) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_JAPANESE) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_JAPANESE) + } + buttonHilt { + scrollTo() + click() + } + } + // Korean + onScreen { + textViewContent { + hasText(ExpectedContent.APPLE_JAPANESE) + } + buttonKorean { + scrollTo() + click() + } + textViewContent { + hasText(ExpectedContent.APPLE_KOREAN) + uiDevices.setOrientationRight() + hasText(ExpectedContent.APPLE_KOREAN) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_KOREAN) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_KOREAN) + } + buttonHilt { + scrollTo() + click() + } + } + // Portuguese + onScreen { + textViewContent { + hasText(ExpectedContent.APPLE_KOREAN) + } + buttonPortuguese { + scrollTo() + click() + } + textViewContent { + hasText(ExpectedContent.APPLE_PORTUGUESE) + uiDevices.setOrientationRight() + hasText(ExpectedContent.APPLE_PORTUGUESE) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_PORTUGUESE) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_PORTUGUESE) + } + buttonHilt { + scrollTo() + click() + } + } + // Thai + onScreen { + textViewContent { + hasText(ExpectedContent.APPLE_PORTUGUESE) + } + buttonThai { + scrollTo() + click() + } + textViewContent { + hasText(ExpectedContent.APPLE_THAI) + uiDevices.setOrientationRight() + hasText(ExpectedContent.APPLE_THAI) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_THAI) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_THAI) + } + buttonHilt { + scrollTo() + click() + } + } + // American + onScreen { + textViewContent { + hasText(ExpectedContent.APPLE_THAI) + } + buttonAmerican { + scrollTo() + click() + } + textViewContent { + hasText(ExpectedContent.APPLE_AMERICAN) + uiDevices.setOrientationRight() + hasText(ExpectedContent.APPLE_AMERICAN) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_AMERICAN) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_AMERICAN) + } + } + } +} diff --git a/app/src/androidTest/java/com/akexorcist/localizationapp/ListPreferencesTest.kt b/app/src/androidTest/java/com/akexorcist/localizationapp/ListPreferencesTest.kt new file mode 100644 index 0000000..82361f2 --- /dev/null +++ b/app/src/androidTest/java/com/akexorcist/localizationapp/ListPreferencesTest.kt @@ -0,0 +1,154 @@ +package com.akexorcist.localizationapp + +import androidx.test.ext.junit.rules.ActivityScenarioRule +import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.uiautomator.UiDevice +import com.agoda.kakao.screen.Screen.Companion.onScreen +import com.akexorcist.localizationapp.data.ExpectedContent +import com.akexorcist.localizationapp.screen.MainActivityScreen +import com.akexorcist.localizationapp.screen.ListPreferencesScreen +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4ClassRunner::class) +class ListPreferencesTest { + @JvmField + val uiDevices: UiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) + + @Rule + @JvmField + val rule = ActivityScenarioRule(MainActivity::class.java) + + @Test + fun listPreferences() { + onScreen { + buttonListPreferences { + scrollTo() + click() + } + } + // Chinese + onScreen { + buttonChangeLanguage { click() } + buttonChinese { click() } + textViewTitle { hasText(ExpectedContent.HELLO_WORLD_CHINESE) } + uiDevices.setOrientationRight() + pressBack() + } + onScreen { + textViewTitle { hasText(ExpectedContent.HELLO_WORLD_CHINESE) } + uiDevices.setOrientationNatural() + textViewTitle { hasText(ExpectedContent.HELLO_WORLD_CHINESE) } + buttonListPreferences { + scrollTo() + click() + } + } + // Italian + onScreen { + textViewTitle { hasText(ExpectedContent.HELLO_WORLD_CHINESE) } + buttonChangeLanguage { click() } + buttonItalian { click() } + textViewTitle { hasText(ExpectedContent.HELLO_WORLD_ITALIAN) } + uiDevices.setOrientationRight() + pressBack() + } + onScreen { + textViewTitle { hasText(ExpectedContent.HELLO_WORLD_ITALIAN) } + uiDevices.setOrientationNatural() + textViewTitle { hasText(ExpectedContent.HELLO_WORLD_ITALIAN) } + buttonListPreferences { + scrollTo() + click() + } + } + // Japanese + onScreen { + textViewTitle { hasText(ExpectedContent.HELLO_WORLD_ITALIAN) } + buttonChangeLanguage { click() } + buttonJapanese { click() } + textViewTitle { hasText(ExpectedContent.HELLO_WORLD_JAPANESE) } + uiDevices.setOrientationRight() + pressBack() + } + onScreen { + textViewTitle { hasText(ExpectedContent.HELLO_WORLD_JAPANESE) } + uiDevices.setOrientationNatural() + textViewTitle { hasText(ExpectedContent.HELLO_WORLD_JAPANESE) } + buttonListPreferences { + scrollTo() + click() + } + } + // Korean + onScreen { + textViewTitle { hasText(ExpectedContent.HELLO_WORLD_JAPANESE) } + buttonChangeLanguage { click() } + buttonKorean { click() } + textViewTitle { hasText(ExpectedContent.HELLO_WORLD_KOREAN) } + uiDevices.setOrientationRight() + pressBack() + } + onScreen { + textViewTitle { hasText(ExpectedContent.HELLO_WORLD_KOREAN) } + uiDevices.setOrientationNatural() + textViewTitle { hasText(ExpectedContent.HELLO_WORLD_KOREAN) } + buttonListPreferences { + scrollTo() + click() + } + } + // Portuguese + onScreen { + textViewTitle { hasText(ExpectedContent.HELLO_WORLD_KOREAN) } + buttonChangeLanguage { click() } + buttonPortuguese { click() } + textViewTitle { hasText(ExpectedContent.HELLO_WORLD_PORTUGUESE) } + uiDevices.setOrientationRight() + pressBack() + } + onScreen { + textViewTitle { hasText(ExpectedContent.HELLO_WORLD_PORTUGUESE) } + uiDevices.setOrientationNatural() + textViewTitle { hasText(ExpectedContent.HELLO_WORLD_PORTUGUESE) } + buttonListPreferences { + scrollTo() + click() + } + } + // Thai + onScreen { + textViewTitle { hasText(ExpectedContent.HELLO_WORLD_PORTUGUESE) } + buttonChangeLanguage { click() } + buttonThai { click() } + textViewTitle { hasText(ExpectedContent.HELLO_WORLD_THAI) } + uiDevices.setOrientationRight() + pressBack() + } + onScreen { + textViewTitle { hasText(ExpectedContent.HELLO_WORLD_THAI) } + uiDevices.setOrientationNatural() + textViewTitle { hasText(ExpectedContent.HELLO_WORLD_THAI) } + buttonListPreferences { + scrollTo() + click() + } + } + // American + onScreen { + textViewTitle { hasText(ExpectedContent.HELLO_WORLD_THAI) } + buttonChangeLanguage { click() } + buttonAmerican { click() } + textViewTitle { hasText(ExpectedContent.HELLO_WORLD_AMERICAN) } + uiDevices.setOrientationRight() + pressBack() + } + onScreen { + textViewTitle { hasText(ExpectedContent.HELLO_WORLD_AMERICAN) } + uiDevices.setOrientationNatural() + textViewTitle { hasText(ExpectedContent.HELLO_WORLD_AMERICAN) } + } + } +} diff --git a/app/src/androidTest/java/com/akexorcist/localizationapp/NestedFragmentTest.kt b/app/src/androidTest/java/com/akexorcist/localizationapp/NestedFragmentTest.kt new file mode 100644 index 0000000..af4a353 --- /dev/null +++ b/app/src/androidTest/java/com/akexorcist/localizationapp/NestedFragmentTest.kt @@ -0,0 +1,215 @@ +package com.akexorcist.localizationapp + +import androidx.test.ext.junit.rules.ActivityScenarioRule +import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.uiautomator.UiDevice +import com.agoda.kakao.screen.Screen.Companion.onScreen +import com.akexorcist.localizationapp.data.ExpectedContent +import com.akexorcist.localizationapp.screen.MainActivityScreen +import com.akexorcist.localizationapp.screen.NestedFragmentScreen +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4ClassRunner::class) +class NestedFragmentTest { + @JvmField + val uiDevices: UiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) + + @Rule + @JvmField + val rule = ActivityScenarioRule(MainActivity::class.java) + + @Test + fun nestedFragment() { + onScreen { + buttonNestedFragment { + scrollTo() + click() + } + } + // Chinese + onScreen { + buttonChinese { + scrollTo() + click() + } + textViewContent { + hasText(ExpectedContent.APPLE_CHINESE) + uiDevices.setOrientationRight() + hasText(ExpectedContent.APPLE_CHINESE) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_CHINESE) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_CHINESE) + } + buttonNestedFragment { + scrollTo() + click() + } + } + // Italian + onScreen { + textViewContent { + hasText(ExpectedContent.APPLE_CHINESE) + } + buttonItalian { + scrollTo() + click() + } + textViewContent { + hasText(ExpectedContent.APPLE_ITALIAN) + uiDevices.setOrientationRight() + hasText(ExpectedContent.APPLE_ITALIAN) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_ITALIAN) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_ITALIAN) + } + buttonNestedFragment { + scrollTo() + click() + } + } + // Japanese + onScreen { + textViewContent { + hasText(ExpectedContent.APPLE_ITALIAN) + } + buttonJapanese { + scrollTo() + click() + } + textViewContent { + hasText(ExpectedContent.APPLE_JAPANESE) + uiDevices.setOrientationRight() + hasText(ExpectedContent.APPLE_JAPANESE) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_JAPANESE) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_JAPANESE) + } + buttonNestedFragment { + scrollTo() + click() + } + } + // Korean + onScreen { + textViewContent { + hasText(ExpectedContent.APPLE_JAPANESE) + } + buttonKorean { + scrollTo() + click() + } + textViewContent { + hasText(ExpectedContent.APPLE_KOREAN) + uiDevices.setOrientationRight() + hasText(ExpectedContent.APPLE_KOREAN) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_KOREAN) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_KOREAN) + } + buttonNestedFragment { + scrollTo() + click() + } + } + // Portuguese + onScreen { + textViewContent { + hasText(ExpectedContent.APPLE_KOREAN) + } + buttonPortuguese { + scrollTo() + click() + } + textViewContent { + hasText(ExpectedContent.APPLE_PORTUGUESE) + uiDevices.setOrientationRight() + hasText(ExpectedContent.APPLE_PORTUGUESE) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_PORTUGUESE) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_PORTUGUESE) + } + buttonNestedFragment { + scrollTo() + click() + } + } + // Thai + onScreen { + textViewContent { + hasText(ExpectedContent.APPLE_PORTUGUESE) + } + buttonThai { + scrollTo() + click() + } + textViewContent { + hasText(ExpectedContent.APPLE_THAI) + uiDevices.setOrientationRight() + hasText(ExpectedContent.APPLE_THAI) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_THAI) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_THAI) + } + buttonNestedFragment { + scrollTo() + click() + } + } + // American + onScreen { + textViewContent { + hasText(ExpectedContent.APPLE_THAI) + } + buttonAmerican { + scrollTo() + click() + } + textViewContent { + hasText(ExpectedContent.APPLE_AMERICAN) + uiDevices.setOrientationRight() + hasText(ExpectedContent.APPLE_AMERICAN) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_AMERICAN) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_AMERICAN) + } + } + } +} diff --git a/app/src/androidTest/java/com/akexorcist/localizationapp/SimpleActivityTest.kt b/app/src/androidTest/java/com/akexorcist/localizationapp/SimpleActivityTest.kt new file mode 100644 index 0000000..5582823 --- /dev/null +++ b/app/src/androidTest/java/com/akexorcist/localizationapp/SimpleActivityTest.kt @@ -0,0 +1,215 @@ +package com.akexorcist.localizationapp + +import androidx.test.ext.junit.rules.ActivityScenarioRule +import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.uiautomator.UiDevice +import com.agoda.kakao.screen.Screen.Companion.onScreen +import com.akexorcist.localizationapp.data.ExpectedContent +import com.akexorcist.localizationapp.screen.MainActivityScreen +import com.akexorcist.localizationapp.screen.SimpleActivityScreen +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4ClassRunner::class) +class SimpleActivityTest { + @JvmField + val uiDevices: UiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) + + @Rule + @JvmField + val rule = ActivityScenarioRule(MainActivity::class.java) + + @Test + fun simpleActivity() { + onScreen { + buttonSimpleActivity { + scrollTo() + click() + } + } + // Chinese + onScreen { + buttonChinese { + scrollTo() + click() + } + textViewContent { + hasText(ExpectedContent.YOUTUBE_CHINESE) + uiDevices.setOrientationRight() + hasText(ExpectedContent.YOUTUBE_CHINESE) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_CHINESE) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_CHINESE) + } + buttonSimpleActivity { + scrollTo() + click() + } + } + // Italian + onScreen { + textViewContent { + hasText(ExpectedContent.YOUTUBE_CHINESE) + } + buttonItalian { + scrollTo() + click() + } + textViewContent { + hasText(ExpectedContent.YOUTUBE_ITALIAN) + uiDevices.setOrientationRight() + hasText(ExpectedContent.YOUTUBE_ITALIAN) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_ITALIAN) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_ITALIAN) + } + buttonSimpleActivity { + scrollTo() + click() + } + } + // Japanese + onScreen { + textViewContent { + hasText(ExpectedContent.YOUTUBE_ITALIAN) + } + buttonJapanese { + scrollTo() + click() + } + textViewContent { + hasText(ExpectedContent.YOUTUBE_JAPANESE) + uiDevices.setOrientationRight() + hasText(ExpectedContent.YOUTUBE_JAPANESE) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_JAPANESE) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_JAPANESE) + } + buttonSimpleActivity { + scrollTo() + click() + } + } + // Korean + onScreen { + textViewContent { + hasText(ExpectedContent.YOUTUBE_JAPANESE) + } + buttonKorean { + scrollTo() + click() + } + textViewContent { + hasText(ExpectedContent.YOUTUBE_KOREAN) + uiDevices.setOrientationRight() + hasText(ExpectedContent.YOUTUBE_KOREAN) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_KOREAN) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_KOREAN) + } + buttonSimpleActivity { + scrollTo() + click() + } + } + // Portuguese + onScreen { + textViewContent { + hasText(ExpectedContent.YOUTUBE_KOREAN) + } + buttonPortuguese { + scrollTo() + click() + } + textViewContent { + hasText(ExpectedContent.YOUTUBE_PORTUGUESE) + uiDevices.setOrientationRight() + hasText(ExpectedContent.YOUTUBE_PORTUGUESE) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_PORTUGUESE) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_PORTUGUESE) + } + buttonSimpleActivity { + scrollTo() + click() + } + } + // Thai + onScreen { + textViewContent { + hasText(ExpectedContent.YOUTUBE_PORTUGUESE) + } + buttonThai { + scrollTo() + click() + } + textViewContent { + hasText(ExpectedContent.YOUTUBE_THAI) + uiDevices.setOrientationRight() + hasText(ExpectedContent.YOUTUBE_THAI) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_THAI) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_THAI) + } + buttonSimpleActivity { + scrollTo() + click() + } + } + // American + onScreen { + textViewContent { + hasText(ExpectedContent.YOUTUBE_THAI) + } + buttonAmerican { + scrollTo() + click() + } + textViewContent { + hasText(ExpectedContent.YOUTUBE_AMERICAN) + uiDevices.setOrientationRight() + hasText(ExpectedContent.YOUTUBE_AMERICAN) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_AMERICAN) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_AMERICAN) + } + } + } +} diff --git a/app/src/androidTest/java/com/akexorcist/localizationapp/SimpleDialogTest.kt b/app/src/androidTest/java/com/akexorcist/localizationapp/SimpleDialogTest.kt new file mode 100644 index 0000000..fc26276 --- /dev/null +++ b/app/src/androidTest/java/com/akexorcist/localizationapp/SimpleDialogTest.kt @@ -0,0 +1,177 @@ +package com.akexorcist.localizationapp + +import androidx.test.ext.junit.rules.ActivityScenarioRule +import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.uiautomator.UiDevice +import com.agoda.kakao.screen.Screen.Companion.onScreen +import com.akexorcist.localizationapp.data.ExpectedContent +import com.akexorcist.localizationapp.screen.MainActivityScreen +import com.akexorcist.localizationapp.screen.SimpleDialogContentScreen +import com.akexorcist.localizationapp.screen.SimpleDialogLanguageChooserScreen +import com.akexorcist.localizationapp.screen.SimpleDialogMainScreen +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4ClassRunner::class) +class SimpleDialogTest { + @JvmField + val uiDevices: UiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) + + @Rule + @JvmField + val rule = ActivityScenarioRule(MainActivity::class.java) + + @Test + fun simpleDialog() { + onScreen { + buttonSimpleDialog { + scrollTo() + click() + } + } + // Chinese + onScreen { + buttonChangeLanguage { click() } + } + onScreen { + buttonChinese { click() } + } + onScreen { + buttonShowContent { click() } + } + onScreen { + textViewContent { + hasText(ExpectedContent.YOUTUBE_CHINESE) + uiDevices.setOrientationRight() + hasText(ExpectedContent.YOUTUBE_CHINESE) + } + pressBack() + uiDevices.setOrientationNatural() + } + // Italian + onScreen { + buttonChangeLanguage { click() } + } + onScreen { + buttonItalian { click() } + } + onScreen { + buttonShowContent { click() } + } + onScreen { + textViewContent { + hasText(ExpectedContent.YOUTUBE_ITALIAN) + uiDevices.setOrientationRight() + hasText(ExpectedContent.YOUTUBE_ITALIAN) + } + pressBack() + uiDevices.setOrientationNatural() + } + // Japanese + onScreen { + buttonChangeLanguage { click() } + } + onScreen { + buttonJapanese { click() } + } + onScreen { + buttonShowContent { click() } + } + onScreen { + textViewContent { + hasText(ExpectedContent.YOUTUBE_JAPANESE) + uiDevices.setOrientationRight() + hasText(ExpectedContent.YOUTUBE_JAPANESE) + } + pressBack() + uiDevices.setOrientationNatural() + } + // Korean + onScreen { + buttonChangeLanguage { click() } + } + onScreen { + buttonKorean { click() } + } + onScreen { + buttonShowContent { click() } + } + onScreen { + textViewContent { + hasText(ExpectedContent.YOUTUBE_KOREAN) + uiDevices.setOrientationRight() + hasText(ExpectedContent.YOUTUBE_KOREAN) + } + pressBack() + uiDevices.setOrientationNatural() + } + // Portuguese + onScreen { + buttonChangeLanguage { click() } + } + onScreen { + buttonPortuguese { click() } + } + onScreen { + buttonShowContent { click() } + } + onScreen { + textViewContent { + hasText(ExpectedContent.YOUTUBE_PORTUGUESE) + uiDevices.setOrientationRight() + hasText(ExpectedContent.YOUTUBE_PORTUGUESE) + } + pressBack() + uiDevices.setOrientationNatural() + } + // Thai + onScreen { + buttonChangeLanguage { click() } + } + onScreen { + buttonThai { click() } + } + onScreen { + buttonShowContent { click() } + } + onScreen { + textViewContent { + hasText(ExpectedContent.YOUTUBE_THAI) + uiDevices.setOrientationRight() + hasText(ExpectedContent.YOUTUBE_THAI) + } + pressBack() + uiDevices.setOrientationNatural() + } + // American + onScreen { + buttonChangeLanguage { click() } + } + onScreen { + buttonAmerican { click() } + } + onScreen { + buttonShowContent { click() } + } + onScreen { + textViewContent { + hasText(ExpectedContent.YOUTUBE_AMERICAN) + uiDevices.setOrientationRight() + hasText(ExpectedContent.YOUTUBE_AMERICAN) + } + pressBack() + uiDevices.setOrientationNatural() + } + // End + onScreen { + buttonBack { click() } + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_AMERICAN) + } + } + } +} diff --git a/app/src/androidTest/java/com/akexorcist/localizationapp/SimpleFragmentTest.kt b/app/src/androidTest/java/com/akexorcist/localizationapp/SimpleFragmentTest.kt new file mode 100644 index 0000000..dfae560 --- /dev/null +++ b/app/src/androidTest/java/com/akexorcist/localizationapp/SimpleFragmentTest.kt @@ -0,0 +1,215 @@ +package com.akexorcist.localizationapp + +import androidx.test.ext.junit.rules.ActivityScenarioRule +import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.uiautomator.UiDevice +import com.agoda.kakao.screen.Screen.Companion.onScreen +import com.akexorcist.localizationapp.data.ExpectedContent +import com.akexorcist.localizationapp.screen.MainActivityScreen +import com.akexorcist.localizationapp.screen.SimpleFragmentScreen +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4ClassRunner::class) +class SimpleFragmentTest { + @JvmField + val uiDevices: UiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) + + @Rule + @JvmField + val rule = ActivityScenarioRule(MainActivity::class.java) + + @Test + fun simpleFragment() { + onScreen { + buttonSimpleFragment { + scrollTo() + click() + } + } + // Chinese + onScreen { + buttonChinese { + scrollTo() + click() + } + textViewContent { + hasText(ExpectedContent.APPLE_CHINESE) + uiDevices.setOrientationRight() + hasText(ExpectedContent.APPLE_CHINESE) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_CHINESE) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_CHINESE) + } + buttonSimpleFragment { + scrollTo() + click() + } + } + // Italian + onScreen { + textViewContent { + hasText(ExpectedContent.APPLE_CHINESE) + } + buttonItalian { + scrollTo() + click() + } + textViewContent { + hasText(ExpectedContent.APPLE_ITALIAN) + uiDevices.setOrientationRight() + hasText(ExpectedContent.APPLE_ITALIAN) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_ITALIAN) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_ITALIAN) + } + buttonSimpleFragment { + scrollTo() + click() + } + } + // Japanese + onScreen { + textViewContent { + hasText(ExpectedContent.APPLE_ITALIAN) + } + buttonJapanese { + scrollTo() + click() + } + textViewContent { + hasText(ExpectedContent.APPLE_JAPANESE) + uiDevices.setOrientationRight() + hasText(ExpectedContent.APPLE_JAPANESE) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_JAPANESE) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_JAPANESE) + } + buttonSimpleFragment { + scrollTo() + click() + } + } + // Korean + onScreen { + textViewContent { + hasText(ExpectedContent.APPLE_JAPANESE) + } + buttonKorean { + scrollTo() + click() + } + textViewContent { + hasText(ExpectedContent.APPLE_KOREAN) + uiDevices.setOrientationRight() + hasText(ExpectedContent.APPLE_KOREAN) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_KOREAN) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_KOREAN) + } + buttonSimpleFragment { + scrollTo() + click() + } + } + // Portuguese + onScreen { + textViewContent { + hasText(ExpectedContent.APPLE_KOREAN) + } + buttonPortuguese { + scrollTo() + click() + } + textViewContent { + hasText(ExpectedContent.APPLE_PORTUGUESE) + uiDevices.setOrientationRight() + hasText(ExpectedContent.APPLE_PORTUGUESE) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_PORTUGUESE) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_PORTUGUESE) + } + buttonSimpleFragment { + scrollTo() + click() + } + } + // Thai + onScreen { + textViewContent { + hasText(ExpectedContent.APPLE_PORTUGUESE) + } + buttonThai { + scrollTo() + click() + } + textViewContent { + hasText(ExpectedContent.APPLE_THAI) + uiDevices.setOrientationRight() + hasText(ExpectedContent.APPLE_THAI) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_THAI) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_THAI) + } + buttonSimpleFragment { + scrollTo() + click() + } + } + // American + onScreen { + textViewContent { + hasText(ExpectedContent.APPLE_THAI) + } + buttonAmerican { + scrollTo() + click() + } + textViewContent { + hasText(ExpectedContent.APPLE_AMERICAN) + uiDevices.setOrientationRight() + hasText(ExpectedContent.APPLE_AMERICAN) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_AMERICAN) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_AMERICAN) + } + } + } +} diff --git a/app/src/androidTest/java/com/akexorcist/localizationapp/StackedActivityTest.kt b/app/src/androidTest/java/com/akexorcist/localizationapp/StackedActivityTest.kt new file mode 100644 index 0000000..e6c4574 --- /dev/null +++ b/app/src/androidTest/java/com/akexorcist/localizationapp/StackedActivityTest.kt @@ -0,0 +1,230 @@ +package com.akexorcist.localizationapp + +import androidx.test.ext.junit.rules.ActivityScenarioRule +import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.uiautomator.UiDevice +import com.agoda.kakao.screen.Screen.Companion.onScreen +import com.akexorcist.localizationapp.data.ExpectedContent +import com.akexorcist.localizationapp.screen.MainActivityScreen +import com.akexorcist.localizationapp.screen.StackedHomeScreen +import com.akexorcist.localizationapp.screen.StackedLanguageChooserScreen +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4ClassRunner::class) +class StackedActivityTest { + @JvmField + val uiDevices: UiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) + + @Rule + @JvmField + val rule = ActivityScenarioRule(MainActivity::class.java) + + @Test + fun stackedActivity() { + onScreen { + buttonStackedActivity { + scrollTo() + click() + } + } + // Chinese + onScreen { + buttonChangeLanguage { click() } + } + onScreen { + buttonChinese { click() } + } + onScreen { + textViewContent { + hasText(ExpectedContent.YOUTUBE_CHINESE) + uiDevices.setOrientationRight() + hasText(ExpectedContent.YOUTUBE_CHINESE) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_CHINESE) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_CHINESE) + } + buttonStackedActivity { + scrollTo() + click() + } + } + // Italian + onScreen { + textViewContent { + hasText(ExpectedContent.YOUTUBE_CHINESE) + } + buttonChangeLanguage { click() } + } + onScreen { + buttonItalian { click() } + } + onScreen { + textViewContent { + hasText(ExpectedContent.YOUTUBE_ITALIAN) + uiDevices.setOrientationRight() + hasText(ExpectedContent.YOUTUBE_ITALIAN) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_ITALIAN) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_ITALIAN) + } + buttonStackedActivity { + scrollTo() + click() + } + } + // Japanese + onScreen { + textViewContent { + hasText(ExpectedContent.YOUTUBE_ITALIAN) + } + buttonChangeLanguage { click() } + } + onScreen { + buttonJapanese { click() } + } + onScreen { + textViewContent { + hasText(ExpectedContent.YOUTUBE_JAPANESE) + uiDevices.setOrientationRight() + hasText(ExpectedContent.YOUTUBE_JAPANESE) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_JAPANESE) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_JAPANESE) + } + buttonStackedActivity { + scrollTo() + click() + } + } + // Korean + onScreen { + textViewContent { + hasText(ExpectedContent.YOUTUBE_JAPANESE) + } + buttonChangeLanguage { click() } + } + onScreen { + buttonKorean { click() } + } + onScreen { + textViewContent { + hasText(ExpectedContent.YOUTUBE_KOREAN) + uiDevices.setOrientationRight() + hasText(ExpectedContent.YOUTUBE_KOREAN) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_KOREAN) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_KOREAN) + } + buttonStackedActivity { + scrollTo() + click() + } + } + // Portuguese + onScreen { + textViewContent { + hasText(ExpectedContent.YOUTUBE_KOREAN) + } + buttonChangeLanguage { click() } + } + onScreen { + buttonPortuguese { click() } + } + onScreen { + textViewContent { + hasText(ExpectedContent.YOUTUBE_PORTUGUESE) + uiDevices.setOrientationRight() + hasText(ExpectedContent.YOUTUBE_PORTUGUESE) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_PORTUGUESE) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_PORTUGUESE) + } + buttonStackedActivity { + scrollTo() + click() + } + } + // Thai + onScreen { + textViewContent { + hasText(ExpectedContent.YOUTUBE_PORTUGUESE) + } + buttonChangeLanguage { click() } + } + onScreen { + buttonThai { click() } + } + onScreen { + textViewContent { + hasText(ExpectedContent.YOUTUBE_THAI) + uiDevices.setOrientationRight() + hasText(ExpectedContent.YOUTUBE_THAI) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_THAI) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_THAI) + } + buttonStackedActivity { + scrollTo() + click() + } + } + // American + onScreen { + textViewContent { + hasText(ExpectedContent.YOUTUBE_THAI) + } + buttonChangeLanguage { click() } + } + onScreen { + buttonAmerican { click() } + } + onScreen { + textViewContent { + hasText(ExpectedContent.YOUTUBE_AMERICAN) + uiDevices.setOrientationRight() + hasText(ExpectedContent.YOUTUBE_AMERICAN) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_AMERICAN) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_AMERICAN) + } + } + } +} diff --git a/app/src/androidTest/java/com/akexorcist/localizationapp/ViewPagerTest.kt b/app/src/androidTest/java/com/akexorcist/localizationapp/ViewPagerTest.kt new file mode 100644 index 0000000..fe292a5 --- /dev/null +++ b/app/src/androidTest/java/com/akexorcist/localizationapp/ViewPagerTest.kt @@ -0,0 +1,365 @@ +package com.akexorcist.localizationapp + +import androidx.test.ext.junit.rules.ActivityScenarioRule +import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.uiautomator.UiDevice +import com.agoda.kakao.screen.Screen.Companion.onScreen +import com.akexorcist.localizationapp.data.ExpectedContent +import com.akexorcist.localizationapp.screen.MainActivityScreen +import com.akexorcist.localizationapp.screen.ViewPagerScreen +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4ClassRunner::class) +class ViewPagerTest { + @JvmField + val uiDevices: UiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) + + @Rule + @JvmField + val rule = ActivityScenarioRule(MainActivity::class.java) + + @Test + fun viewPager() { + onScreen { + buttonViewPager { + scrollTo() + click() + } + } + // Chinese + onScreen { + buttonChinese { + scrollTo() + click() + } + textViewOne { + hasText(ExpectedContent.ONE_CHINESE) + } + buttonNext { click() } + textViewTwo { + hasText(ExpectedContent.TWO_CHINESE) + } + buttonNext { click() } + textViewThree { + hasText(ExpectedContent.THREE_CHINESE) + } + buttonNext { click() } + textViewHello { + hasText(ExpectedContent.HELLO_WORLD_CHINESE) + uiDevices.setOrientationRight() + hasText(ExpectedContent.HELLO_WORLD_CHINESE) + } + buttonPrevious { click() } + textViewThree { + hasText(ExpectedContent.THREE_CHINESE) + } + buttonPrevious { click() } + textViewTwo { + hasText(ExpectedContent.TWO_CHINESE) + } + buttonPrevious { click() } + textViewOne { + hasText(ExpectedContent.ONE_CHINESE) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_CHINESE) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_CHINESE) + } + buttonViewPager { + scrollTo() + click() + } + } + // Italian + onScreen { + buttonItalian { + scrollTo() + click() + } + textViewOne { + hasText(ExpectedContent.ONE_ITALIAN) + } + buttonNext { click() } + textViewTwo { + hasText(ExpectedContent.TWO_ITALIAN) + } + buttonNext { click() } + textViewThree { + hasText(ExpectedContent.THREE_ITALIAN) + } + buttonNext { click() } + textViewHello { + hasText(ExpectedContent.HELLO_WORLD_ITALIAN) + uiDevices.setOrientationRight() + hasText(ExpectedContent.HELLO_WORLD_ITALIAN) + } + buttonPrevious { click() } + textViewThree { + hasText(ExpectedContent.THREE_ITALIAN) + } + buttonPrevious { click() } + textViewTwo { + hasText(ExpectedContent.TWO_ITALIAN) + } + buttonPrevious { click() } + textViewOne { + hasText(ExpectedContent.ONE_ITALIAN) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_ITALIAN) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_ITALIAN) + } + buttonViewPager { + scrollTo() + click() + } + } + // Japanese + onScreen { + buttonJapanese { + scrollTo() + click() + } + textViewOne { + hasText(ExpectedContent.ONE_JAPANESE) + } + buttonNext { click() } + textViewTwo { + hasText(ExpectedContent.TWO_JAPANESE) + } + buttonNext { click() } + textViewThree { + hasText(ExpectedContent.THREE_JAPANESE) + } + buttonNext { click() } + textViewHello { + hasText(ExpectedContent.HELLO_WORLD_JAPANESE) + uiDevices.setOrientationRight() + hasText(ExpectedContent.HELLO_WORLD_JAPANESE) + } + buttonPrevious { click() } + textViewThree { + hasText(ExpectedContent.THREE_JAPANESE) + } + buttonPrevious { click() } + textViewTwo { + hasText(ExpectedContent.TWO_JAPANESE) + } + buttonPrevious { click() } + textViewOne { + hasText(ExpectedContent.ONE_JAPANESE) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_JAPANESE) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_JAPANESE) + } + buttonViewPager { + scrollTo() + click() + } + } + // Korean + onScreen { + buttonKorean { + scrollTo() + click() + } + textViewOne { + hasText(ExpectedContent.ONE_KOREAN) + } + buttonNext { click() } + textViewTwo { + hasText(ExpectedContent.TWO_KOREAN) + } + buttonNext { click() } + textViewThree { + hasText(ExpectedContent.THREE_KOREAN) + } + buttonNext { click() } + textViewHello { + hasText(ExpectedContent.HELLO_WORLD_KOREAN) + uiDevices.setOrientationRight() + hasText(ExpectedContent.HELLO_WORLD_KOREAN) + } + buttonPrevious { click() } + textViewThree { + hasText(ExpectedContent.THREE_KOREAN) + } + buttonPrevious { click() } + textViewTwo { + hasText(ExpectedContent.TWO_KOREAN) + } + buttonPrevious { click() } + textViewOne { + hasText(ExpectedContent.ONE_KOREAN) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_KOREAN) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_KOREAN) + } + buttonViewPager { + scrollTo() + click() + } + } + // Portuguese + onScreen { + buttonPortuguese { + scrollTo() + click() + } + textViewOne { + hasText(ExpectedContent.ONE_PORTUGUESE) + } + buttonNext { click() } + textViewTwo { + hasText(ExpectedContent.TWO_PORTUGUESE) + } + buttonNext { click() } + textViewThree { + hasText(ExpectedContent.THREE_PORTUGUESE) + } + buttonNext { click() } + textViewHello { + hasText(ExpectedContent.HELLO_WORLD_PORTUGUESE) + uiDevices.setOrientationRight() + hasText(ExpectedContent.HELLO_WORLD_PORTUGUESE) + } + buttonPrevious { click() } + textViewThree { + hasText(ExpectedContent.THREE_PORTUGUESE) + } + buttonPrevious { click() } + textViewTwo { + hasText(ExpectedContent.TWO_PORTUGUESE) + } + buttonPrevious { click() } + textViewOne { + hasText(ExpectedContent.ONE_PORTUGUESE) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_PORTUGUESE) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_PORTUGUESE) + } + buttonViewPager { + scrollTo() + click() + } + } + // Thai + onScreen { + buttonThai { + scrollTo() + click() + } + textViewOne { + hasText(ExpectedContent.ONE_THAI) + } + buttonNext { click() } + textViewTwo { + hasText(ExpectedContent.TWO_THAI) + } + buttonNext { click() } + textViewThree { + hasText(ExpectedContent.THREE_THAI) + } + buttonNext { click() } + textViewHello { + hasText(ExpectedContent.HELLO_WORLD_THAI) + uiDevices.setOrientationRight() + hasText(ExpectedContent.HELLO_WORLD_THAI) + } + buttonPrevious { click() } + textViewThree { + hasText(ExpectedContent.THREE_THAI) + } + buttonPrevious { click() } + textViewTwo { + hasText(ExpectedContent.TWO_THAI) + } + buttonPrevious { click() } + textViewOne { + hasText(ExpectedContent.ONE_THAI) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_THAI) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_THAI) + } + buttonViewPager { + scrollTo() + click() + } + } + // American + onScreen { + buttonAmerican { + scrollTo() + click() + } + textViewOne { + hasText(ExpectedContent.ONE_AMERICAN) + } + buttonNext { click() } + textViewTwo { + hasText(ExpectedContent.TWO_AMERICAN) + } + buttonNext { click() } + textViewThree { + hasText(ExpectedContent.THREE_AMERICAN) + } + buttonNext { click() } + textViewHello { + hasText(ExpectedContent.HELLO_WORLD_AMERICAN) + uiDevices.setOrientationRight() + hasText(ExpectedContent.HELLO_WORLD_AMERICAN) + } + buttonPrevious { click() } + textViewThree { + hasText(ExpectedContent.THREE_AMERICAN) + } + buttonPrevious { click() } + textViewTwo { + hasText(ExpectedContent.TWO_AMERICAN) + } + buttonPrevious { click() } + textViewOne { + hasText(ExpectedContent.ONE_AMERICAN) + } + pressBack() + } + onScreen { + textViewTitle { + hasText(ExpectedContent.HELLO_WORLD_AMERICAN) + uiDevices.setOrientationNatural() + hasText(ExpectedContent.HELLO_WORLD_AMERICAN) + } + } + } +} diff --git a/app/src/androidTest/java/com/akexorcist/localizationapp/annotation/TargetApiLevel.kt b/app/src/androidTest/java/com/akexorcist/localizationapp/annotation/TargetApiLevel.kt new file mode 100644 index 0000000..2b5535f --- /dev/null +++ b/app/src/androidTest/java/com/akexorcist/localizationapp/annotation/TargetApiLevel.kt @@ -0,0 +1,5 @@ +package com.akexorcist.localizationapp.annotation + +@Target(AnnotationTarget.FUNCTION) +@Retention(AnnotationRetention.RUNTIME) +annotation class TargetApiLevel(val value: Int) diff --git a/app/src/androidTest/java/com/akexorcist/localizationapp/data/ExpectedContent.kt b/app/src/androidTest/java/com/akexorcist/localizationapp/data/ExpectedContent.kt new file mode 100644 index 0000000..18964cb --- /dev/null +++ b/app/src/androidTest/java/com/akexorcist/localizationapp/data/ExpectedContent.kt @@ -0,0 +1,51 @@ +package com.akexorcist.localizationapp.data + +object ExpectedContent { + const val YOUTUBE_AMERICAN = "When you open the YouTube app, you’ll land on What to Watch. What to Watch highlights recent uploads and activity from your subscriptions and videos recommended for you. You will also see popular content and YouTube Mixes if you’ve previously watched music videos. You can navigate back to this feed at any time from the Guide." + const val YOUTUBE_CHINESE = "打开 YouTube 应用时,您看到的是“精彩视频”页面。“精彩视频”显示您的订阅中近期上传的视频与活动,以及为您推荐的视频。如果您之前观看过音乐视频,那么还能看到一些热门内容以及 YouTube 合辑。您随时可以从导视面板导航回这个 Feed。" + const val YOUTUBE_ITALIAN = "Quando apri l'app YouTube, viene visualizzata la sezione Che cosa guardare. In questa sezione vengono messi in evidenza i caricamenti recenti, le attività provenienti dalle tue iscrizioni e i video consigliati. Vengono anche visualizzati i contenuti popolari e i Mix di YouTube se hai già guardato video musicali in precedenza. Puoi tornare a questo feed in qualsiasi momento dalla Guida." + const val YOUTUBE_JAPANESE = "YouTube アプリを開くと、[あなたへのおすすめ] ページが表示されます。[あなたへのおすすめ] では登録チャンネルの最新アップロードやアクティビティ、おすすめの動画が紹介されます。また、以前にミュージック ビデオを視聴した場合は人気のコンテンツや YouTube ミックスリストも表示されます。ガイドから、いつでもこのフィードに戻ることができます。" + const val YOUTUBE_KOREAN = "YouTube 앱을 열면 볼만한 동영상 페이지가 표시됩니다. 볼만한 동영상에는 구독 채널의 최근 업로드 동영상과 활동 및 맞춤 동영상이 강조표시됩니다. 이전에 뮤직 비디오를 본 적이 있다면 인기 콘텐츠와 YouTube 믹스도 표시됩니다. 언제든 가이드에서 이 피드로 되돌아갈 수 있습니다." + const val YOUTUBE_PORTUGUESE = "Ao abrir a aplicação YouTube, é-lhe apresentada a página O que ver. A página O que ver destaca os carregamentos e as atividades mais recentes das suas subscrições e os vídeos recomendados para si. Verá ainda os conteúdos mais populares e também Mixes do YouTube, caso tenha acedido a vídeos de música anteriormente. Pode regressar a este feed em qualquer momento através do Guia." + const val YOUTUBE_THAI = "เมื่อคุณเปิดแอป YouTube คุณจะเข้ามาที่ ดูอะไรดี โดยส่วน ดูอะไรดี จะไฮไลต์การอัปโหลดและกิจกรรมล่าสุดจากช่องที่คุณติดตาม และวิดีโอที่แนะนำสำหรับคุณ นอกจากนี้ คุณยังจะเห็นเนื้อหาที่ได้รับความนิยมและ YouTube มิกซ์หากได้ดูมิวสิกวิดีโอไปก่อนหน้านี้ คุณสามารถกลับมาที่ฟีดนี้ได้ตลอดเวลาจากเมนู คำแนะนำ" + + const val APPLE_AMERICAN = "The apple tree (Malus domestica) is a deciduous tree in the rose family best known for its sweet, pomaceous fruit, the apple. It is cultivated worldwide as a fruit tree, and is the most widely grown species in the genus Malus. The tree originated in Central Asia, where its wild ancestor, Malus sieversii, is still found today. Apples have been grown for thousands of years in Asia and Europe, and were brought to North America by European colonists. Apples have religious and mythological significance in many cultures, including Norse, Greek and European Christian traditions. Apple trees are large if grown from seed, but small if grafted onto roots (rootstock). There are more than 7,500 known cultivars of apples, resulting in a range of desired characteristics. Different cultivars are bred for various tastes and uses, including cooking, eating raw and cider production. Apples are generally propagated by grafting, although wild apples grow readily from seed. Trees and fruit are prone to a number of fungal, bacterial and pest problems, which can be controlled by a number of organic and non-organic means. In 2010, the fruit's genome was decoded as part of research on disease control and selective breeding in apple production. About 80 million tons of apples were grown worldwide in 2013, and China produced almost half of this total.[3] The United States is the second-leading producer, with more than 6% of world production. Turkey is third, followed by Italy, India and Poland. Apples are often eaten raw, but can also be found in many prepared foods (especially desserts) and drinks. Many beneficial health effects are thought to result from eating apples; however, two types of allergies are attributed to various proteins found in the fruit." + const val APPLE_CHINESE = "蘋果樹是落葉喬木,通常樹木可高至15米,但栽培樹木一般只高3–5米左右。樹幹呈灰褐色,樹皮有一定程度的脫落。果實一般呈紅色,但需視乎品種而定。蘋果開花期是基於各地氣候而定,但一般集中在4–5月份。蘋果是異花授粉植物,大部分品種自花不能結成果實。一般蘋果栽種後,於2–3年才開始結出果實。果實成長期之長短,一般早熟品種為65–87天,中熟品種為90–133天,晚熟品種則為137–168天。在一般情形下,栽種後蘋果可有15-50年壽命。苹果原產於欧洲和中亞及中国新疆地区。哈薩克的阿拉木圖与新疆阿力麻里有蘋果城的美譽。中国古代的林檎、柰、花红等水果被认为是中国土生苹果品种或与苹果相似的水果。苹果在中国的栽培记录可以追溯至西汉时期,汉武帝时,上林苑中曾栽培林檎和柰,当时多用于薰香衣裳等,亦有置于床头当香熏或置于衣服,最初作为香囊,较少食用。但也有看法认为,林檎和柰是现在的沙果,曾被誤認為蘋果,真正意义上的苹果是元朝时期从中亚地区传入中国,当时只有在宫廷才可享用。现代汉语所说的“苹果”一词源于梵语,为古印度佛經中所說的一种水果,最早被称为“频婆”,后被汉语借用,并有“平波”、“苹婆”等写法。明朝万历年间的農書《群芳谱·果谱》中,有“苹果”词条,称:“苹果,出北地,燕赵者尤佳。接用林檎体。树身耸直,叶青,似林檎而大,果如梨而圆滑。生青,熟则半红半白,或全红,光洁可爱玩,香闻数步。味甘松,未熟者食如棉絮,过熟又沙烂不堪食,惟八九分熟者最佳”。许多中国农学史、果树史专家认为这是汉语中最早使用“苹果”一词。" + const val APPLE_ITALIAN = "La mela è il frutto (più precisamente si tratta di un falso frutto a pomo) del melo. Il melo ha origine in Asia centrale e l'evoluzione dei meli botanici risalirebbe al Neolitico. La specie è presente in Italia nominalmente con circa 2000 varietà, ma la definizione più precisa è difficile data la sovrapposizione storica delle denominazioni, e le specie estinte o irreperibili. La mela è il frutto più destagionalizzato (lo si trova tutto l'anno) e ciò richiede la presenza di impianti che provvedono alla conservazione e ne distribuiscano la disponibilità su di un ampio arco di tempo. La maturazione naturale varia da fine agosto a metà ottobre. La disponibilità alla conservazione naturale dei frutti è drasticamente diversa nelle differenti varietà; dati gli elevati contenuti in acidi organici, di norma la conservazione va da uno a quattro mesi. Nella conservazione industriale sono importanti le condizioni fisiche in cui questa avviene. Dopo il raccolto, i frutti sono conservati a temperature da 1,0 a 3,5 °C con umidità relativa del 59–68%. Per conservazioni prolungate si ricorre a conservazioni in celle con atmosfera controllata (più ricca di CO2). La mela ha un potere antiossidante (ORAC) con un indice di valore 4275[1] poiché contiene vitamine importanti come provitamina A, vitamine B1, B2, B6, E e C, niacina e acido folico, insieme a flavonoidi e carotenoidi, dall'effetto antiossidante." + const val APPLE_JAPANESE = "リンゴ は、バラ科リンゴ属の落葉高木樹。またはその果実のこと。植物学上はセイヨウリンゴと呼ぶ。 原産地はカザフスタン南部、キルギスタン、タジキスタンとされており、ここからヨーロッパやアジアルートで日本にも広まったと考えられている。現在[いつ?]日本で栽培されているものは、明治時代以降に導入されたものであり、日本において、病害抵抗性、食味、収量などの点から品種改良が加えられた。人口比で比較しても日本の青森における生産量は多く、日本ブランド名で(元々の日本リンゴ農家などから商標に関する係争があり)中国でも多量に生産されている。現在[いつ?]は7500以上の品種が栽培されており、亜寒帯、亜熱帯及び温帯で栽培可能であるが、暑さに弱いため熱帯での栽培は難しい。 リンゴの木は、落葉高木で晩春頃に白い5弁花が開花する。リンゴの果実は直径約3–15 cm、重さ約35–1000 g。色は赤や黄緑または黄色をしている。熟するとヘプタコサンを含んだ蝋状の分泌物に覆われる。 リンゴの蜜は比重が大きいため、水の中に入れると沈む。他の果実の部分は比重が小さいため水に浮かぶ。" + const val APPLE_KOREAN = "사과나무 는 장미목 장미과 배나무아과 사과나무속에 딸린 종이다. 그 열매는 사과(沙果; 砂果)라 하며, 세계적으로 가장 널리 재배되는 과일 품종 가운데 하나이다. 사전적으로 평과(苹果)라고도 한다. 나무는 높이 5~12미터에 이르는 작은 낙엽수이며, 넓고 밀집된 잔가지가 많은 수관을 가진다. 잎은 번갈아가며 배열된 모양의 단순한 타원형으로 끝은 날카롭고 톱니모양의 모서리, 가냘프고 솜털이 나 있는 하단 부분, 5~12센티미터 길이와 3~6센티미터 너비, 2~5센티미터의 잎꼭지의 특징을 가진다. 꽃은 잎과 함께 봄에 나는데 꽃 색깔은 흰색이며 처음에는 엷은 핑크색을 띠기도 한다. 직경은 2.5~3.5센티미터이며 꽃잎은 다섯 개이다. 열매는 가을에 익는데 보통 지름이 5~9센티미터이다. 드물지만 15센티미터에 이르기도 한다. 씨앗에는 미량의 사이안화물이 함유되어 있다. 과자(사과파이), 샐러드, 주스 등의 재료로 쓰이고 날로 먹는다. 농약이 묻어있으면 날로는 먹지 않는 것이 좋다. 세계적으로 재배되고 있는 품종은 700여 종이 되지만, 대한민국에서 유실수로 재배되고 있는 품종은 10여 종이다. 사과의 품종은 수확기에 따라 조생종·중생종·만생종으로 나뉘고, 색깔에 따라 홍색사과·황색사과·녹색사과로 구분한다. 현재 널리 재배되고 있는 품종에는 스타킹·골든딜리셔스·축 등이 있고, 근래에는 조나골드·후지 등이 있다. 대한민국에서는 홍옥이 오랫동안 재배되었다." + const val APPLE_PORTUGUESE = "A maçã é o pseudofruto pomáceo da macieira,1 árvore da família Rosaceae. É um dos pseudofrutos de árvore mais cultivados, e o mais conhecido dos muitos membros do género Malus que são usados \u200B\u200Bpelos seres humanos. As maçãs crescem em pequenas árvores, de folha caducifólia que florescem na Primavera e produzem fruto no Outono. A árvore é originária da Ásia Ocidental, onde o seu ancestral selvagem, Malus sieversii, ainda é encontrado atualmente. As maçãs têm sido cultivadas há milhares de anos na Ásia e Europa, tendo sido trazidas para a América do Norte pelos colonizadores europeus. As maçãs têm estado presentes na mitologia e religiões de muitas culturas, incluindo as tradições nórdica, grega e cristã. Em 2010, o genoma da fruta foi descodificado, levando a uma nova compreensão no controle de doenças e na reprodução seletiva durante a produção da maçã. Existem mais de 7.500 plantações conhecidas de maçãs, resultando numa gama de características desejadas. A maçã sempre foi uma importante fonte alimentícia em regiões de clima frio. Provavelmente, a macieira é a árvore cultivada há mais tempo pelo homem[carece de fontes]. É a espécie de fruta, à exceção dos cítricos, que pode ser conservada durante mais tempo, conservando boa parte de seu valor nutritivo. As maçãs de inverno, colhidas no final do outono e guardadas em câmaras ou armazéns acima do ponto de congelamento, têm sido um alimento destacado durante milênios na Ásia e na Europa e, desde 1800, nos Estados Unidos." + const val APPLE_THAI = "แอปเปิลเป็นผลไม้ในตระกูล Rosaceae แอปเปิลเป็นผลไม้ที่นิยมมากที่สุดชนิดหนึ่งในโลก เป็นไม้ผลเมืองหนาว มีต้นกำเนิดในบริเวณประเทศอิหร่านในปัจจุบัน จากนั้นจึงกระจายพันธุ์ไปยังเทือกเขาคอเคซัสและลุ่มแม่น้ำไทกริส–ยูเฟรติส แล้วแพร่หลายต่อไปในทวีปยุโรป ทวีปอเมริกา และดินแดนอื่นทั่วโลก ในประเทศไทยปลูกได้ในพื้นที่ภาคเหนือ เช่นที่ดอยอ่างขาง ต้นแอปเปิลจะสูงประมาณ 5–12 เมตร เป็นไม้เนื้อแข็ง ใบเขียวเข้มเป็นมัน ขอบหยัก ดอกออกเป็นกลุ่มสีขาวอมชมพู ผลกลมรี มีรอยบุ๋มทั้งขั้วผลและท้ายผล ผลแอปเปิลมีเปลือกบาง สีแดง เขียว และเหลืองตามสายพันธุ์ เนื้อในเป็นเหมือนทรายละเอียดสีเหลืองนวล เมล็ดมีขนาดเล็ก สีดำ แอปเปิลเป็นไม้ยืนต้นขนาดเล็ก ผลัดใบ สูง 3 – 12 เมตร เรือนยอดกว้าง กิ่งหนาแน่น ใบรูปไข่เรียงสลับ ยาว 5 – 12 ซม. กว้าง 3 – 6 ซม. ก้านใบยาว 2 - 5 ซม. ปลายใบแหลม ขอบใบหยักคล้ายฟันเลื่อย ใต้ใบปกคลุมด้วยขนนุ่มเล็กน้อย ดอกเกิดขึ้นพร้อมการแตกใบใหม่ในฤดูใบไม้ผลิ ดอกมีสีขาวแต้มสีชมพู และเข้มขึ้นเมื่อดอกใกล้โรย มีกลีบดอกห้ากลีบ เส้นผ่าศูนย์กลาง 2.5 - 3.5 ซม. ผลสุกในฤดูใบไม้ร่วง โดยทั่วไปมีเส้นผ่าศูนย์กลาง 5 - 9 ซม. กลางผลมีคาร์เพล (carpel) ห้าโพรงเรียงตัวในรูปดาวห้าแฉก แต่ละโพรงบรรจุไปด้วยเมล็ดหนึ่งถึงสามเมล็ด" + + const val HELLO_WORLD_AMERICAN = "Hello world" + const val HELLO_WORLD_CHINESE = "您好世界" + const val HELLO_WORLD_ITALIAN = "Ciao mondo" + const val HELLO_WORLD_JAPANESE = "こんにちは世界" + const val HELLO_WORLD_KOREAN = "안녕하세요세계" + const val HELLO_WORLD_PORTUGUESE = "Olá mundo" + const val HELLO_WORLD_THAI = "สวัสดีชาวโลก" + + const val ONE_AMERICAN = "One" + const val ONE_CHINESE = "一" + const val ONE_ITALIAN = "Uno" + const val ONE_JAPANESE = "一" + const val ONE_KOREAN = "하나" + const val ONE_PORTUGUESE = "Um" + const val ONE_THAI = "หนึ่ง" + + const val TWO_AMERICAN = "Two" + const val TWO_CHINESE = "二" + const val TWO_ITALIAN = "Due" + const val TWO_JAPANESE = "二" + const val TWO_KOREAN = "두" + const val TWO_PORTUGUESE = "Dois" + const val TWO_THAI = "สอง" + + const val THREE_AMERICAN = "Three" + const val THREE_CHINESE = "三" + const val THREE_ITALIAN = "Tre" + const val THREE_JAPANESE = "三" + const val THREE_KOREAN = "세" + const val THREE_PORTUGUESE = "Três" + const val THREE_THAI = "สาม" +} diff --git a/app/src/androidTest/java/com/akexorcist/localizationapp/screen/CustomActivityScreen.kt b/app/src/androidTest/java/com/akexorcist/localizationapp/screen/CustomActivityScreen.kt new file mode 100644 index 0000000..a85562f --- /dev/null +++ b/app/src/androidTest/java/com/akexorcist/localizationapp/screen/CustomActivityScreen.kt @@ -0,0 +1,17 @@ +package com.akexorcist.localizationapp.screen + +import com.agoda.kakao.screen.Screen +import com.agoda.kakao.text.KButton +import com.agoda.kakao.text.KTextView +import com.akexorcist.localizationapp.R + +class CustomActivityScreen : Screen() { + val buttonAmerican = KButton { withId(R.id.btn_american) } + val buttonChinese = KButton { withId(R.id.btn_chinese) } + val buttonItalian = KButton { withId(R.id.btn_italian) } + val buttonJapanese = KButton { withId(R.id.btn_japanese) } + val buttonKorean = KButton { withId(R.id.btn_korean) } + val buttonPortuguese = KButton { withId(R.id.btn_portuguese) } + val buttonThai = KButton { withId(R.id.btn_thai) } + val textViewContent = KTextView { withId(R.id.text_view_content) } +} diff --git a/app/src/androidTest/java/com/akexorcist/localizationapp/screen/DarkThemeScreen.kt b/app/src/androidTest/java/com/akexorcist/localizationapp/screen/DarkThemeScreen.kt new file mode 100644 index 0000000..29f0cab --- /dev/null +++ b/app/src/androidTest/java/com/akexorcist/localizationapp/screen/DarkThemeScreen.kt @@ -0,0 +1,17 @@ +package com.akexorcist.localizationapp.screen + +import com.agoda.kakao.screen.Screen +import com.agoda.kakao.text.KButton +import com.agoda.kakao.text.KTextView +import com.akexorcist.localizationapp.R + +class DarkThemeScreen : Screen() { + val buttonAmerican = KButton { withId(R.id.btn_american) } + val buttonChinese = KButton { withId(R.id.btn_chinese) } + val buttonItalian = KButton { withId(R.id.btn_italian) } + val buttonJapanese = KButton { withId(R.id.btn_japanese) } + val buttonKorean = KButton { withId(R.id.btn_korean) } + val buttonPortuguese = KButton { withId(R.id.btn_portuguese) } + val buttonThai = KButton { withId(R.id.btn_thai) } + val textViewContent = KTextView { withId(R.id.text_view_content) } +} diff --git a/app/src/androidTest/java/com/akexorcist/localizationapp/screen/DialogWebViewLanguageChooserScreen.kt b/app/src/androidTest/java/com/akexorcist/localizationapp/screen/DialogWebViewLanguageChooserScreen.kt new file mode 100644 index 0000000..af9b1fc --- /dev/null +++ b/app/src/androidTest/java/com/akexorcist/localizationapp/screen/DialogWebViewLanguageChooserScreen.kt @@ -0,0 +1,15 @@ +package com.akexorcist.localizationapp.screen + +import com.agoda.kakao.screen.Screen +import com.agoda.kakao.text.KButton +import com.akexorcist.localizationapp.R + +class DialogWebViewLanguageChooserScreen : Screen() { + val buttonAmerican = KButton { withId(R.id.btn_american) } + val buttonChinese = KButton { withId(R.id.btn_chinese) } + val buttonItalian = KButton { withId(R.id.btn_italian) } + val buttonJapanese = KButton { withId(R.id.btn_japanese) } + val buttonKorean = KButton { withId(R.id.btn_korean) } + val buttonPortuguese = KButton { withId(R.id.btn_portuguese) } + val buttonThai = KButton { withId(R.id.btn_thai) } +} diff --git a/app/src/androidTest/java/com/akexorcist/localizationapp/screen/DialogWebViewMainScreen.kt b/app/src/androidTest/java/com/akexorcist/localizationapp/screen/DialogWebViewMainScreen.kt new file mode 100644 index 0000000..afb9130 --- /dev/null +++ b/app/src/androidTest/java/com/akexorcist/localizationapp/screen/DialogWebViewMainScreen.kt @@ -0,0 +1,11 @@ +package com.akexorcist.localizationapp.screen + +import com.agoda.kakao.screen.Screen +import com.agoda.kakao.text.KButton +import com.akexorcist.localizationapp.R + +class DialogWebViewMainScreen : Screen() { + val buttonBack = KButton { withId(R.id.btn_back) } + val buttonShowWebsite = KButton { withId(R.id.btn_show_website) } + val buttonChangeLanguage = KButton { withId(R.id.btn_change_language) } +} diff --git a/app/src/androidTest/java/com/akexorcist/localizationapp/screen/DialogWebViewSiteScreen.kt b/app/src/androidTest/java/com/akexorcist/localizationapp/screen/DialogWebViewSiteScreen.kt new file mode 100644 index 0000000..6cf65e0 --- /dev/null +++ b/app/src/androidTest/java/com/akexorcist/localizationapp/screen/DialogWebViewSiteScreen.kt @@ -0,0 +1,11 @@ +package com.akexorcist.localizationapp.screen + +import com.agoda.kakao.screen.Screen +import com.agoda.kakao.text.KButton +import com.agoda.kakao.web.KWebView +import com.akexorcist.localizationapp.R + +class DialogWebViewSiteScreen : Screen() { + val buttonBack = KButton { withId(R.id.btn_back) } + val webViewContent = KWebView { withId(R.id.wv_content) } +} diff --git a/app/src/androidTest/java/com/akexorcist/localizationapp/screen/HiltDependencyInjectionScreen.kt b/app/src/androidTest/java/com/akexorcist/localizationapp/screen/HiltDependencyInjectionScreen.kt new file mode 100644 index 0000000..17317d4 --- /dev/null +++ b/app/src/androidTest/java/com/akexorcist/localizationapp/screen/HiltDependencyInjectionScreen.kt @@ -0,0 +1,17 @@ +package com.akexorcist.localizationapp.screen + +import com.agoda.kakao.screen.Screen +import com.agoda.kakao.text.KButton +import com.agoda.kakao.text.KTextView +import com.akexorcist.localizationapp.R + +class HiltDependencyInjectionScreen : Screen() { + val buttonAmerican = KButton { withId(R.id.btn_american) } + val buttonChinese = KButton { withId(R.id.btn_chinese) } + val buttonItalian = KButton { withId(R.id.btn_italian) } + val buttonJapanese = KButton { withId(R.id.btn_japanese) } + val buttonKorean = KButton { withId(R.id.btn_korean) } + val buttonPortuguese = KButton { withId(R.id.btn_portuguese) } + val buttonThai = KButton { withId(R.id.btn_thai) } + val textViewContent = KTextView { withId(R.id.text_view_content) } +} diff --git a/app/src/androidTest/java/com/akexorcist/localizationapp/screen/ListPreferencesScreen.kt b/app/src/androidTest/java/com/akexorcist/localizationapp/screen/ListPreferencesScreen.kt new file mode 100644 index 0000000..52479c6 --- /dev/null +++ b/app/src/androidTest/java/com/akexorcist/localizationapp/screen/ListPreferencesScreen.kt @@ -0,0 +1,22 @@ +package com.akexorcist.localizationapp.screen + +import com.agoda.kakao.screen.Screen +import com.agoda.kakao.text.KButton +import com.agoda.kakao.text.KTextView +import com.akexorcist.localizationapp.R + +class ListPreferencesScreen : Screen() { + val buttonChangeLanguage = KButton { withText(R.string.change_language) } + val buttonAmerican = KButton { withText(R.string.american) } + val buttonChinese = KButton { withText(R.string.chinese) } + val buttonItalian = KButton { withText(R.string.italian) } + val buttonJapanese = KButton { withText(R.string.japanese) } + val buttonKorean = KButton { withText(R.string.korean) } + val buttonPortuguese = KButton { withText(R.string.portuguese) } + val buttonThai = KButton { withText(R.string.thai) } + val textViewTitle: KTextView + get() = KTextView { + withId(android.R.id.title) + withIndex(0) {} + } +} diff --git a/app/src/androidTest/java/com/akexorcist/localizationapp/screen/MainActivityScreen.kt b/app/src/androidTest/java/com/akexorcist/localizationapp/screen/MainActivityScreen.kt new file mode 100644 index 0000000..876249b --- /dev/null +++ b/app/src/androidTest/java/com/akexorcist/localizationapp/screen/MainActivityScreen.kt @@ -0,0 +1,22 @@ +package com.akexorcist.localizationapp.screen + +import com.agoda.kakao.screen.Screen +import com.agoda.kakao.text.KButton +import com.agoda.kakao.text.KTextView +import com.akexorcist.localizationapp.R + +open class MainActivityScreen : Screen() { + val textViewTitle = KTextView { withId(R.id.text_view_title) } + val buttonSimpleActivity = KButton { withId(R.id.btn_simple_activity) } + val buttonCustomActivity = KButton { withId(R.id.btn_custom_activity) } + val buttonStackedActivity = KButton { withId(R.id.btn_stacked_activity) } + val buttonSimpleFragment = KButton { withId(R.id.btn_simple_fragment) } + val buttonNestedFragment = KButton { withId(R.id.btn_nested_fragment) } + val buttonSimpleDialog = KButton { withId(R.id.btn_dialog_fragment) } + val buttonDialogWebView = KButton { withId(R.id.btn_dialog_web_view) } + val buttonViewPager = KButton { withId(R.id.btn_view_pager) } + val buttonListPreferences = KButton { withId(R.id.btn_list_preferences) } + val buttonDarkTheme = KButton { withId(R.id.btn_dark_theme) } + val buttonHilt = KButton { withId(R.id.btn_hilt) } + val buttonBroadcastReceiver = KButton { withId(R.id.btn_broadcast_receiver) } +} diff --git a/app/src/androidTest/java/com/akexorcist/localizationapp/screen/NestedFragmentScreen.kt b/app/src/androidTest/java/com/akexorcist/localizationapp/screen/NestedFragmentScreen.kt new file mode 100644 index 0000000..f0f55da --- /dev/null +++ b/app/src/androidTest/java/com/akexorcist/localizationapp/screen/NestedFragmentScreen.kt @@ -0,0 +1,17 @@ +package com.akexorcist.localizationapp.screen + +import com.agoda.kakao.screen.Screen +import com.agoda.kakao.text.KButton +import com.agoda.kakao.text.KTextView +import com.akexorcist.localizationapp.R + +class NestedFragmentScreen : Screen() { + val buttonAmerican = KButton { withId(R.id.btn_american) } + val buttonChinese = KButton { withId(R.id.btn_chinese) } + val buttonItalian = KButton { withId(R.id.btn_italian) } + val buttonJapanese = KButton { withId(R.id.btn_japanese) } + val buttonKorean = KButton { withId(R.id.btn_korean) } + val buttonPortuguese = KButton { withId(R.id.btn_portuguese) } + val buttonThai = KButton { withId(R.id.btn_thai) } + val textViewContent = KTextView { withId(R.id.text_view_content) } +} diff --git a/app/src/androidTest/java/com/akexorcist/localizationapp/screen/SimpleActivityScreen.kt b/app/src/androidTest/java/com/akexorcist/localizationapp/screen/SimpleActivityScreen.kt new file mode 100644 index 0000000..d3e9d74 --- /dev/null +++ b/app/src/androidTest/java/com/akexorcist/localizationapp/screen/SimpleActivityScreen.kt @@ -0,0 +1,17 @@ +package com.akexorcist.localizationapp.screen + +import com.agoda.kakao.screen.Screen +import com.agoda.kakao.text.KButton +import com.agoda.kakao.text.KTextView +import com.akexorcist.localizationapp.R + +class SimpleActivityScreen : Screen() { + val buttonAmerican = KButton { withId(R.id.btn_american) } + val buttonChinese = KButton { withId(R.id.btn_chinese) } + val buttonItalian = KButton { withId(R.id.btn_italian) } + val buttonJapanese = KButton { withId(R.id.btn_japanese) } + val buttonKorean = KButton { withId(R.id.btn_korean) } + val buttonPortuguese = KButton { withId(R.id.btn_portuguese) } + val buttonThai = KButton { withId(R.id.btn_thai) } + val textViewContent = KTextView { withId(R.id.text_view_content) } +} diff --git a/app/src/androidTest/java/com/akexorcist/localizationapp/screen/SimpleBroadcastScreen.kt b/app/src/androidTest/java/com/akexorcist/localizationapp/screen/SimpleBroadcastScreen.kt new file mode 100644 index 0000000..715643c --- /dev/null +++ b/app/src/androidTest/java/com/akexorcist/localizationapp/screen/SimpleBroadcastScreen.kt @@ -0,0 +1,18 @@ +package com.akexorcist.localizationapp.screen + +import com.agoda.kakao.screen.Screen +import com.agoda.kakao.text.KButton +import com.agoda.kakao.text.KTextView +import com.akexorcist.localizationapp.R + +class SimpleBroadcastScreen : Screen() { + val buttonBack = KButton { withId(R.id.btn_back) } + val buttonAmerican = KButton { withId(R.id.btn_american) } + val buttonChinese = KButton { withId(R.id.btn_chinese) } + val buttonItalian = KButton { withId(R.id.btn_italian) } + val buttonJapanese = KButton { withId(R.id.btn_japanese) } + val buttonKorean = KButton { withId(R.id.btn_korean) } + val buttonPortuguese = KButton { withId(R.id.btn_portuguese) } + val buttonThai = KButton { withId(R.id.btn_thai) } + val textViewContent = KTextView { withId(R.id.text_view_content) } +} diff --git a/app/src/androidTest/java/com/akexorcist/localizationapp/screen/SimpleDialogContentScreen.kt b/app/src/androidTest/java/com/akexorcist/localizationapp/screen/SimpleDialogContentScreen.kt new file mode 100644 index 0000000..db74cd1 --- /dev/null +++ b/app/src/androidTest/java/com/akexorcist/localizationapp/screen/SimpleDialogContentScreen.kt @@ -0,0 +1,9 @@ +package com.akexorcist.localizationapp.screen + +import com.agoda.kakao.screen.Screen +import com.agoda.kakao.text.KTextView +import com.akexorcist.localizationapp.R + +class SimpleDialogContentScreen : Screen() { + val textViewContent = KTextView { withId(R.id.text_view_content) } +} diff --git a/app/src/androidTest/java/com/akexorcist/localizationapp/screen/SimpleDialogLanguageChooserScreen.kt b/app/src/androidTest/java/com/akexorcist/localizationapp/screen/SimpleDialogLanguageChooserScreen.kt new file mode 100644 index 0000000..46f1f91 --- /dev/null +++ b/app/src/androidTest/java/com/akexorcist/localizationapp/screen/SimpleDialogLanguageChooserScreen.kt @@ -0,0 +1,15 @@ +package com.akexorcist.localizationapp.screen + +import com.agoda.kakao.screen.Screen +import com.agoda.kakao.text.KButton +import com.akexorcist.localizationapp.R + +class SimpleDialogLanguageChooserScreen : Screen() { + val buttonAmerican = KButton { withId(R.id.btn_american) } + val buttonChinese = KButton { withId(R.id.btn_chinese) } + val buttonItalian = KButton { withId(R.id.btn_italian) } + val buttonJapanese = KButton { withId(R.id.btn_japanese) } + val buttonKorean = KButton { withId(R.id.btn_korean) } + val buttonPortuguese = KButton { withId(R.id.btn_portuguese) } + val buttonThai = KButton { withId(R.id.btn_thai) } +} diff --git a/app/src/androidTest/java/com/akexorcist/localizationapp/screen/SimpleDialogMainScreen.kt b/app/src/androidTest/java/com/akexorcist/localizationapp/screen/SimpleDialogMainScreen.kt new file mode 100644 index 0000000..3cd0ceb --- /dev/null +++ b/app/src/androidTest/java/com/akexorcist/localizationapp/screen/SimpleDialogMainScreen.kt @@ -0,0 +1,11 @@ +package com.akexorcist.localizationapp.screen + +import com.agoda.kakao.screen.Screen +import com.agoda.kakao.text.KButton +import com.akexorcist.localizationapp.R + +class SimpleDialogMainScreen : Screen() { + val buttonBack = KButton { withId(R.id.btn_back) } + val buttonChangeLanguage = KButton { withId(R.id.btn_change_language) } + val buttonShowContent = KButton { withId(R.id.btn_show_content) } +} diff --git a/app/src/androidTest/java/com/akexorcist/localizationapp/screen/SimpleFragmentScreen.kt b/app/src/androidTest/java/com/akexorcist/localizationapp/screen/SimpleFragmentScreen.kt new file mode 100644 index 0000000..f617b4d --- /dev/null +++ b/app/src/androidTest/java/com/akexorcist/localizationapp/screen/SimpleFragmentScreen.kt @@ -0,0 +1,17 @@ +package com.akexorcist.localizationapp.screen + +import com.agoda.kakao.screen.Screen +import com.agoda.kakao.text.KButton +import com.agoda.kakao.text.KTextView +import com.akexorcist.localizationapp.R + +class SimpleFragmentScreen : Screen() { + val buttonAmerican = KButton { withId(R.id.btn_american) } + val buttonChinese = KButton { withId(R.id.btn_chinese) } + val buttonItalian = KButton { withId(R.id.btn_italian) } + val buttonJapanese = KButton { withId(R.id.btn_japanese) } + val buttonKorean = KButton { withId(R.id.btn_korean) } + val buttonPortuguese = KButton { withId(R.id.btn_portuguese) } + val buttonThai = KButton { withId(R.id.btn_thai) } + val textViewContent = KTextView { withId(R.id.text_view_content) } +} diff --git a/app/src/androidTest/java/com/akexorcist/localizationapp/screen/StackedHomeScreen.kt b/app/src/androidTest/java/com/akexorcist/localizationapp/screen/StackedHomeScreen.kt new file mode 100644 index 0000000..60ca18d --- /dev/null +++ b/app/src/androidTest/java/com/akexorcist/localizationapp/screen/StackedHomeScreen.kt @@ -0,0 +1,11 @@ +package com.akexorcist.localizationapp.screen + +import com.agoda.kakao.screen.Screen +import com.agoda.kakao.text.KButton +import com.agoda.kakao.text.KTextView +import com.akexorcist.localizationapp.R + +class StackedHomeScreen : Screen() { + val buttonChangeLanguage = KButton { withId(R.id.btn_change_language) } + val textViewContent = KTextView { withId(R.id.text_view_content) } +} diff --git a/app/src/androidTest/java/com/akexorcist/localizationapp/screen/StackedLanguageChooserScreen.kt b/app/src/androidTest/java/com/akexorcist/localizationapp/screen/StackedLanguageChooserScreen.kt new file mode 100644 index 0000000..742be99 --- /dev/null +++ b/app/src/androidTest/java/com/akexorcist/localizationapp/screen/StackedLanguageChooserScreen.kt @@ -0,0 +1,15 @@ +package com.akexorcist.localizationapp.screen + +import com.agoda.kakao.screen.Screen +import com.agoda.kakao.text.KButton +import com.akexorcist.localizationapp.R + +class StackedLanguageChooserScreen : Screen() { + val buttonAmerican = KButton { withId(R.id.btn_american) } + val buttonChinese = KButton { withId(R.id.btn_chinese) } + val buttonItalian = KButton { withId(R.id.btn_italian) } + val buttonJapanese = KButton { withId(R.id.btn_japanese) } + val buttonKorean = KButton { withId(R.id.btn_korean) } + val buttonPortuguese = KButton { withId(R.id.btn_portuguese) } + val buttonThai = KButton { withId(R.id.btn_thai) } +} diff --git a/app/src/androidTest/java/com/akexorcist/localizationapp/screen/ViewPagerScreen.kt b/app/src/androidTest/java/com/akexorcist/localizationapp/screen/ViewPagerScreen.kt new file mode 100644 index 0000000..d6e28e7 --- /dev/null +++ b/app/src/androidTest/java/com/akexorcist/localizationapp/screen/ViewPagerScreen.kt @@ -0,0 +1,22 @@ +package com.akexorcist.localizationapp.screen + +import com.agoda.kakao.screen.Screen +import com.agoda.kakao.text.KButton +import com.agoda.kakao.text.KTextView +import com.akexorcist.localizationapp.R + +class ViewPagerScreen : Screen() { + val buttonAmerican = KButton { withId(R.id.btn_american) } + val buttonChinese = KButton { withId(R.id.btn_chinese) } + val buttonItalian = KButton { withId(R.id.btn_italian) } + val buttonJapanese = KButton { withId(R.id.btn_japanese) } + val buttonKorean = KButton { withId(R.id.btn_korean) } + val buttonPortuguese = KButton { withId(R.id.btn_portuguese) } + val buttonThai = KButton { withId(R.id.btn_thai) } + val buttonPrevious = KButton { withId(R.id.btn_prev) } + val buttonNext = KButton { withId(R.id.btn_next) } + val textViewHello = KTextView { withId(R.id.text_view_hello) } + val textViewOne = KTextView { withId(R.id.text_view_one) } + val textViewTwo = KTextView { withId(R.id.text_view_two) } + val textViewThree = KTextView { withId(R.id.text_view_three) } +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ce015dd..3316e98 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -4,25 +4,75 @@ - + - - - - - - - + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/ic_launcher-playstore.png b/app/src/main/ic_launcher-playstore.png new file mode 100644 index 0000000..36fe9f7 Binary files /dev/null and b/app/src/main/ic_launcher-playstore.png differ diff --git a/app/src/main/java/com/akexorcist/localizationapp/MainActivity.java b/app/src/main/java/com/akexorcist/localizationapp/MainActivity.java deleted file mode 100644 index 332958e..0000000 --- a/app/src/main/java/com/akexorcist/localizationapp/MainActivity.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.akexorcist.localizationapp; - -import android.content.Intent; -import android.os.Bundle; -import android.view.View; - -import com.akexorcist.localizationactivity.ui.LocalizationActivity; -import com.akexorcist.localizationapp.customactivity.SimpleCustomActivity; -import com.akexorcist.localizationapp.nestedfragment.NestedFragmentActivity; -import com.akexorcist.localizationapp.simpleactivity.SimpleActivity; -import com.akexorcist.localizationapp.simplefragment.SimpleFragmentActivity; -import com.akexorcist.localizationapp.stackedactivity.Stack1Activity; -import com.akexorcist.localizationapp.viewpager.ViewPagerActivity; - -public class MainActivity extends LocalizationActivity { - - @Override - public void onCreate(Bundle savedInstanceState) { - // You can set default language when first time running. Must to setup before onCreate was called. - setDefaultLanguage("th"); - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_main); - - findViewById(R.id.btn_simple_activity).setOnClickListener(onSimpleActivityClick()); - findViewById(R.id.btn_custom_activity).setOnClickListener(onCustomActivityClick()); - findViewById(R.id.btn_stacked_activity).setOnClickListener(onStackedActivityClick()); - findViewById(R.id.btn_activity_fragment).setOnClickListener(onSimpleFragmentClick()); - findViewById(R.id.btn_activity_nested_fragment).setOnClickListener(onNestedFragmentClick()); - findViewById(R.id.btn_activity_view_pager).setOnClickListener(onViewPagerClick()); - } - - public View.OnClickListener onSimpleActivityClick() { - return view -> goToActivity(SimpleActivity.class); - } - - public View.OnClickListener onCustomActivityClick() { - return view -> goToActivity(SimpleCustomActivity.class); - } - - public View.OnClickListener onStackedActivityClick() { - return view -> goToActivity(Stack1Activity.class); - } - - public View.OnClickListener onSimpleFragmentClick() { - return view -> goToActivity(SimpleFragmentActivity.class); - } - - private View.OnClickListener onNestedFragmentClick() { - return view -> goToActivity(NestedFragmentActivity.class); - } - - public View.OnClickListener onViewPagerClick() { - return view -> goToActivity(ViewPagerActivity.class); - } - - public void goToActivity(Class activity) { - Intent intent = new Intent(this, activity); - startActivity(intent); - } -} diff --git a/app/src/main/java/com/akexorcist/localizationapp/MainActivity.kt b/app/src/main/java/com/akexorcist/localizationapp/MainActivity.kt new file mode 100644 index 0000000..8a49fc8 --- /dev/null +++ b/app/src/main/java/com/akexorcist/localizationapp/MainActivity.kt @@ -0,0 +1,45 @@ +package com.akexorcist.localizationapp + +import android.content.Intent +import android.os.Bundle +import com.akexorcist.localizationactivity.ui.LocalizationActivity +import com.akexorcist.localizationapp.broadcast.SimpleBroadcastActivity +import com.akexorcist.localizationapp.customactivity.SimpleCustomActivity +import com.akexorcist.localizationapp.darktheme.DarkThemeActivity +import com.akexorcist.localizationapp.databinding.ActivityMainBinding +import com.akexorcist.localizationapp.dialogwebview.DialogWebViewMainActivity +import com.akexorcist.localizationapp.simpledialog.SimpleDialogMainActivity +import com.akexorcist.localizationapp.hilt.HiltActivity +import com.akexorcist.localizationapp.nestedfragment.NestedFragmentActivity +import com.akexorcist.localizationapp.preferences.ListPreferencesActivity +import com.akexorcist.localizationapp.simpleactivity.SimpleActivity +import com.akexorcist.localizationapp.simplefragment.SimpleFragmentActivity +import com.akexorcist.localizationapp.stackedactivity.StackedHomeActivity +import com.akexorcist.localizationapp.viewpager.ViewPagerActivity + +class MainActivity : LocalizationActivity() { + private val binding: ActivityMainBinding by lazy { ActivityMainBinding.inflate(layoutInflater) } + + public override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(binding.root) + + binding.textViewTitle.setText(R.string.hello_world) + binding.btnSimpleActivity.setOnClickListener { goToActivity(SimpleActivity::class.java) } + binding.btnCustomActivity.setOnClickListener { goToActivity(SimpleCustomActivity::class.java) } + binding.btnStackedActivity.setOnClickListener { goToActivity(StackedHomeActivity::class.java) } + binding.btnSimpleFragment.setOnClickListener { goToActivity(SimpleFragmentActivity::class.java) } + binding.btnNestedFragment.setOnClickListener { goToActivity(NestedFragmentActivity::class.java) } + binding.btnDialogFragment.setOnClickListener { goToActivity(SimpleDialogMainActivity::class.java) } + binding.btnDialogWebView.setOnClickListener { goToActivity(DialogWebViewMainActivity::class.java) } + binding.btnViewPager.setOnClickListener { goToActivity(ViewPagerActivity::class.java) } + binding.btnListPreferences.setOnClickListener { goToActivity(ListPreferencesActivity::class.java) } + binding.btnDarkTheme.setOnClickListener { goToActivity(DarkThemeActivity::class.java) } + binding.btnHilt.setOnClickListener { goToActivity(HiltActivity::class.java) } + binding.btnBroadcastReceiver.setOnClickListener { goToActivity(SimpleBroadcastActivity::class.java) } + } + + private fun goToActivity(activity: Class<*>?) { + startActivity(Intent(this, activity)) + } +} diff --git a/app/src/main/java/com/akexorcist/localizationapp/MainApplication.java b/app/src/main/java/com/akexorcist/localizationapp/MainApplication.java deleted file mode 100644 index 723120c..0000000 --- a/app/src/main/java/com/akexorcist/localizationapp/MainApplication.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.akexorcist.localizationapp; - -import android.app.Application; -import android.content.Context; -import android.content.res.Configuration; - -import com.akexorcist.localizationactivity.core.LocalizationApplicationDelegate; - -/** - * Created by Akexorcist on 10/19/2017 AD. - */ - -public class MainApplication extends Application { - LocalizationApplicationDelegate localizationDelegate = new LocalizationApplicationDelegate(this); - - @Override - protected void attachBaseContext(Context base) { - super.attachBaseContext(localizationDelegate.attachBaseContext(base)); - } - - @Override - public void onConfigurationChanged(Configuration newConfig) { - super.onConfigurationChanged(newConfig); - localizationDelegate.onConfigurationChanged(this); - } - - @Override - public Context getApplicationContext() { - return localizationDelegate.getApplicationContext(super.getApplicationContext()); - } -} diff --git a/app/src/main/java/com/akexorcist/localizationapp/MainApplication.kt b/app/src/main/java/com/akexorcist/localizationapp/MainApplication.kt new file mode 100644 index 0000000..0984129 --- /dev/null +++ b/app/src/main/java/com/akexorcist/localizationapp/MainApplication.kt @@ -0,0 +1,38 @@ +package com.akexorcist.localizationapp + +import android.app.Application +import android.content.Context +import android.content.res.Configuration +import android.content.res.Resources +import android.webkit.WebView +import com.akexorcist.localizationactivity.core.LocalizationApplicationDelegate +import dagger.hilt.android.HiltAndroidApp +import java.util.* + +@HiltAndroidApp +class MainApplication : Application() { + private val localizationDelegate = LocalizationApplicationDelegate() + + override fun onCreate() { + super.onCreate() + localizationDelegate.onCreate(this) + } + + override fun attachBaseContext(base: Context) { + localizationDelegate.setDefaultLanguage(base, Locale.ENGLISH) + super.attachBaseContext(localizationDelegate.attachBaseContext(base)) + } + + override fun onConfigurationChanged(newConfig: Configuration) { + super.onConfigurationChanged(newConfig) + localizationDelegate.onConfigurationChanged(this) + } + + override fun getApplicationContext(): Context { + return localizationDelegate.getApplicationContext(super.getApplicationContext()) + } + + override fun getResources(): Resources { + return localizationDelegate.getResources(baseContext, super.getResources()) + } +} diff --git a/app/src/main/java/com/akexorcist/localizationapp/broadcast/BroadcastEvent.kt b/app/src/main/java/com/akexorcist/localizationapp/broadcast/BroadcastEvent.kt new file mode 100644 index 0000000..211cf2b --- /dev/null +++ b/app/src/main/java/com/akexorcist/localizationapp/broadcast/BroadcastEvent.kt @@ -0,0 +1,10 @@ +package com.akexorcist.localizationapp.broadcast + +object BroadcastEvent { + // Activity -> Broadcast Receiver + const val ACTION_TO_BROADCAST = "com.akexorcist.localizationapp.receiver.action.TO_BROADCAST" + + // Broadcast Receiver -> Activity + const val ACTION_TO_ACTIVITY = "com.akexorcist.localizationapp.receiver.action.TO_ACTIVITY" + const val EXTRA_CONTENT = "com.akexorcist.localizationapp.receiver.extra.CONTENT" +} diff --git a/app/src/main/java/com/akexorcist/localizationapp/broadcast/SimpleBroadcastActivity.kt b/app/src/main/java/com/akexorcist/localizationapp/broadcast/SimpleBroadcastActivity.kt new file mode 100644 index 0000000..cdd0429 --- /dev/null +++ b/app/src/main/java/com/akexorcist/localizationapp/broadcast/SimpleBroadcastActivity.kt @@ -0,0 +1,57 @@ +package com.akexorcist.localizationapp.broadcast + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import android.content.IntentFilter +import android.os.Bundle +import com.akexorcist.localizationactivity.ui.LocalizationActivity +import com.akexorcist.localizationapp.databinding.ActivitySimpleBroadcastBinding + +class SimpleBroadcastActivity : LocalizationActivity() { + private val binding by lazy { ActivitySimpleBroadcastBinding.inflate(layoutInflater) } + + public override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(binding.root) + + binding.btnBack.setOnClickListener { super.onBackPressed() } + binding.layoutLanguageChooser.btnAmerican.setOnClickListener { onChangeLanguageButtonClicked("en") } + binding.layoutLanguageChooser.btnChinese.setOnClickListener { onChangeLanguageButtonClicked("zh") } + binding.layoutLanguageChooser.btnItalian.setOnClickListener { onChangeLanguageButtonClicked("it") } + binding.layoutLanguageChooser.btnJapanese.setOnClickListener { onChangeLanguageButtonClicked("ja") } + binding.layoutLanguageChooser.btnKorean.setOnClickListener { onChangeLanguageButtonClicked("ko") } + binding.layoutLanguageChooser.btnPortuguese.setOnClickListener { onChangeLanguageButtonClicked("pt") } + binding.layoutLanguageChooser.btnThai.setOnClickListener { onChangeLanguageButtonClicked("th") } + } + + private fun onChangeLanguageButtonClicked(language: String) { + setLanguage(language) + getContentFromBroadcastReceiver() + } + + private fun getContentFromBroadcastReceiver() { + val intent = Intent(BroadcastEvent.ACTION_TO_BROADCAST).apply { + `package` = packageName + } + sendBroadcast(intent) + } + + override fun onStart() { + super.onStart() + val filter = IntentFilter(BroadcastEvent.ACTION_TO_ACTIVITY) + registerReceiver(broadcastReceiver, filter) + } + + override fun onStop() { + super.onStop() + unregisterReceiver(broadcastReceiver) + } + + private val broadcastReceiver = object : BroadcastReceiver() { + override fun onReceive(context: Context, intent: Intent) { + val content = intent.getStringExtra(BroadcastEvent.EXTRA_CONTENT) + binding.textViewContent.text = content + } + } +} diff --git a/app/src/main/java/com/akexorcist/localizationapp/broadcast/SimpleBroadcastReceiver.kt b/app/src/main/java/com/akexorcist/localizationapp/broadcast/SimpleBroadcastReceiver.kt new file mode 100644 index 0000000..a4766c1 --- /dev/null +++ b/app/src/main/java/com/akexorcist/localizationapp/broadcast/SimpleBroadcastReceiver.kt @@ -0,0 +1,19 @@ +package com.akexorcist.localizationapp.broadcast + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import com.akexorcist.localizationactivity.core.toLocalizedContext +import com.akexorcist.localizationapp.R + +class SimpleBroadcastReceiver : BroadcastReceiver() { + override fun onReceive(context: Context, intent: Intent) { + val localizedContext = context.toLocalizedContext() + val content = localizedContext.getString(R.string.sample_apple_story) + val broadcastIntent = Intent(BroadcastEvent.ACTION_TO_ACTIVITY).apply { + `package` = context.packageName + putExtra(BroadcastEvent.EXTRA_CONTENT, content) + } + context.sendBroadcast(broadcastIntent) + } +} diff --git a/app/src/main/java/com/akexorcist/localizationapp/customactivity/CustomActivity.java b/app/src/main/java/com/akexorcist/localizationapp/customactivity/CustomActivity.java deleted file mode 100644 index 7160530..0000000 --- a/app/src/main/java/com/akexorcist/localizationapp/customactivity/CustomActivity.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.akexorcist.localizationapp.customactivity; - -import android.app.Activity; -import android.content.Context; -import android.content.res.Resources; -import android.os.Bundle; - -import com.akexorcist.localizationactivity.core.LocalizationActivityDelegate; -import com.akexorcist.localizationactivity.core.OnLocaleChangedListener; - -import java.util.Locale; - -/** - * Created by Akexorcist on 6/23/16 AD. - */ -public abstract class CustomActivity extends Activity implements OnLocaleChangedListener { - - private LocalizationActivityDelegate localizationDelegate = new LocalizationActivityDelegate(this); - - @Override - public void onCreate(Bundle savedInstanceState) { - localizationDelegate.addOnLocaleChangedListener(this); - localizationDelegate.onCreate(savedInstanceState); - super.onCreate(savedInstanceState); - } - - @Override - public void onResume() { - super.onResume(); - localizationDelegate.onResume(this); - } - - @Override - protected void attachBaseContext(Context newBase) { - super.attachBaseContext(localizationDelegate.attachBaseContext(newBase)); - } - - @Override - public Context getApplicationContext() { - return localizationDelegate.getApplicationContext(super.getApplicationContext()); - } - - @Override - public Resources getResources() { - return localizationDelegate.getResources(super.getResources()); - } - - public final void setLanguage(String language) { - localizationDelegate.setLanguage(this, language); - } - - public final void setLanguage(Locale locale) { - localizationDelegate.setLanguage(this, locale); - } - - public final void setDefaultLanguage(String language) { - localizationDelegate.setDefaultLanguage(language); - } - - public final void setDefaultLanguage(Locale locale) { - localizationDelegate.setDefaultLanguage(locale); - } - - public final Locale getCurrentLanguage() { - return localizationDelegate.getLanguage(this); - } - - // Just override method locale change event - @Override - public void onBeforeLocaleChanged() { - } - - @Override - public void onAfterLocaleChanged() { - } -} diff --git a/app/src/main/java/com/akexorcist/localizationapp/customactivity/CustomActivity.kt b/app/src/main/java/com/akexorcist/localizationapp/customactivity/CustomActivity.kt new file mode 100644 index 0000000..edda101 --- /dev/null +++ b/app/src/main/java/com/akexorcist/localizationapp/customactivity/CustomActivity.kt @@ -0,0 +1,54 @@ +package com.akexorcist.localizationapp.customactivity + +import android.app.Activity +import android.content.Context +import android.content.res.Resources +import android.os.Bundle +import com.akexorcist.localizationactivity.core.LocalizationActivityDelegate +import com.akexorcist.localizationactivity.core.OnLocaleChangedListener +import java.util.* + +open class CustomActivity : Activity(), OnLocaleChangedListener { + private val localizationDelegate by lazy { + LocalizationActivityDelegate(this) + } + + public override fun onCreate(savedInstanceState: Bundle?) { + localizationDelegate.addOnLocaleChangedListener(this) + localizationDelegate.onCreate() + super.onCreate(savedInstanceState) + } + + public override fun onResume() { + super.onResume() + localizationDelegate.onResume(this) + } + + override fun attachBaseContext(newBase: Context) { + applyOverrideConfiguration(localizationDelegate.updateConfigurationLocale(newBase)) + super.attachBaseContext(newBase) + } + + override fun getApplicationContext(): Context { + return localizationDelegate.getApplicationContext(super.getApplicationContext()) + } + + override fun getResources(): Resources { + return localizationDelegate.getResources(super.getResources()) + } + + fun setLanguage(language: String?) { + localizationDelegate.setLanguage(this, language!!) + } + + fun setLanguage(locale: Locale?) { + localizationDelegate.setLanguage(this, locale!!) + } + + val currentLanguage: Locale + get() = localizationDelegate.getLanguage(this) + + // Just override method locale change event + override fun onBeforeLocaleChanged() {} + override fun onAfterLocaleChanged() {} +} diff --git a/app/src/main/java/com/akexorcist/localizationapp/customactivity/SimpleCustomActivity.java b/app/src/main/java/com/akexorcist/localizationapp/customactivity/SimpleCustomActivity.java deleted file mode 100644 index 04ed672..0000000 --- a/app/src/main/java/com/akexorcist/localizationapp/customactivity/SimpleCustomActivity.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.akexorcist.localizationapp.customactivity; - -import android.os.Bundle; -import android.view.View; -import android.widget.HorizontalScrollView; - -import com.akexorcist.localizationapp.R; - -public class SimpleCustomActivity extends CustomActivity { - private final String KEY_SCROLL_X = "scroll_x"; - - private HorizontalScrollView svLanguageChooser; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_simple); - - // Activity title is not change the language automatically. - setTitle(R.string.hello_world); - - findViewById(R.id.btn_america).setOnClickListener(onAmericaLanguageSelected()); - findViewById(R.id.btn_china).setOnClickListener(onChinaLanguageSelected()); - findViewById(R.id.btn_italy).setOnClickListener(onItalyLanguageSelected()); - findViewById(R.id.btn_japan).setOnClickListener(onJapanLanguageSelected()); - findViewById(R.id.btn_korea).setOnClickListener(onKoreaLanguageSelected()); - findViewById(R.id.btn_portugal).setOnClickListener(onPortugalLanguageSelected()); - findViewById(R.id.btn_thai).setOnClickListener(onThaiLanguageSelected()); - - svLanguageChooser = findViewById(R.id.sv_language_chooser); - } - - @Override - public void onSaveInstanceState(Bundle outState) { - // Save x-position of horizontal scroll view. - outState.putInt(KEY_SCROLL_X, svLanguageChooser.getScrollX()); - super.onSaveInstanceState(outState); - } - - @Override - public void onRestoreInstanceState(Bundle savedInstanceState) { - super.onRestoreInstanceState(savedInstanceState); - // Restore x-position of horizontal scroll view. - svLanguageChooser.scrollTo(savedInstanceState.getInt(KEY_SCROLL_X), 0); - } - - private View.OnClickListener onAmericaLanguageSelected() { - return view -> setLanguage("en"); - } - - private View.OnClickListener onChinaLanguageSelected() { - return view -> setLanguage("zh"); - } - - private View.OnClickListener onItalyLanguageSelected() { - return view -> setLanguage("it"); - } - - private View.OnClickListener onJapanLanguageSelected() { - return view -> setLanguage("ja"); - } - - private View.OnClickListener onKoreaLanguageSelected() { - return view -> setLanguage("ko"); - } - - private View.OnClickListener onPortugalLanguageSelected() { - return view -> setLanguage("pt"); - } - - private View.OnClickListener onThaiLanguageSelected() { - return view -> setLanguage("th"); - } -} diff --git a/app/src/main/java/com/akexorcist/localizationapp/customactivity/SimpleCustomActivity.kt b/app/src/main/java/com/akexorcist/localizationapp/customactivity/SimpleCustomActivity.kt new file mode 100644 index 0000000..c091ca6 --- /dev/null +++ b/app/src/main/java/com/akexorcist/localizationapp/customactivity/SimpleCustomActivity.kt @@ -0,0 +1,43 @@ +package com.akexorcist.localizationapp.customactivity + +import android.os.Bundle +import com.akexorcist.localizationapp.R +import com.akexorcist.localizationapp.databinding.ActivityCustomBinding + +class SimpleCustomActivity : CustomActivity() { + private val binding: ActivityCustomBinding by lazy { ActivityCustomBinding.inflate(layoutInflater) } + + companion object { + private const val KEY_SCROLL_X = "scroll_x" + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(binding.root) + + // Activity title is not change the language automatically. + setTitle(R.string.hello_world) + binding.btnBack.setOnClickListener { super.onBackPressed() } + binding.layoutLanguageChooser.btnAmerican.setOnClickListener { setLanguage("en") } + binding.layoutLanguageChooser.btnChinese.setOnClickListener { setLanguage("zh") } + binding.layoutLanguageChooser.btnItalian.setOnClickListener { setLanguage("it") } + binding.layoutLanguageChooser.btnJapanese.setOnClickListener { setLanguage("ja") } + binding.layoutLanguageChooser.btnKorean.setOnClickListener { setLanguage("ko") } + binding.layoutLanguageChooser.btnPortuguese.setOnClickListener { setLanguage("pt") } + binding.layoutLanguageChooser.btnThai.setOnClickListener { setLanguage("th") } + } + + public override fun onSaveInstanceState(outState: Bundle) { + // Save x-position of horizontal scroll view. + outState.putInt(KEY_SCROLL_X, binding.layoutLanguageChooser.svLanguageChooser.scrollX) + super.onSaveInstanceState(outState) + } + + public override fun onRestoreInstanceState(savedInstanceState: Bundle) { + super.onRestoreInstanceState(savedInstanceState) + // Restore x-position of horizontal scroll view. + binding.layoutLanguageChooser.svLanguageChooser.scrollTo( + savedInstanceState.getInt(KEY_SCROLL_X), 0 + ) + } +} diff --git a/app/src/main/java/com/akexorcist/localizationapp/darktheme/DarkThemeActivity.kt b/app/src/main/java/com/akexorcist/localizationapp/darktheme/DarkThemeActivity.kt new file mode 100644 index 0000000..8c75cdc --- /dev/null +++ b/app/src/main/java/com/akexorcist/localizationapp/darktheme/DarkThemeActivity.kt @@ -0,0 +1,48 @@ +package com.akexorcist.localizationapp.darktheme + +import android.os.Bundle +import android.util.Log +import androidx.appcompat.app.AppCompatDelegate +import androidx.fragment.app.commit +import com.akexorcist.localizationactivity.ui.LocalizationActivity +import com.akexorcist.localizationapp.databinding.ActivityDarkThemeBinding + +class DarkThemeActivity : LocalizationActivity() { + private val binding: ActivityDarkThemeBinding by lazy { ActivityDarkThemeBinding.inflate(layoutInflater) } + + companion object { + private const val KEY_SCROLL_X = "scroll_x" + } + + public override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(binding.root) + + binding.btnBack.setOnClickListener { super.onBackPressed() } + binding.layoutLanguageChooser.btnAmerican.setOnClickListener { setLanguage("en") } + binding.layoutLanguageChooser.btnChinese.setOnClickListener { setLanguage("zh") } + binding.layoutLanguageChooser.btnItalian.setOnClickListener { setLanguage("it") } + binding.layoutLanguageChooser.btnJapanese.setOnClickListener { setLanguage("ja") } + binding.layoutLanguageChooser.btnKorean.setOnClickListener { setLanguage("ko") } + binding.layoutLanguageChooser.btnPortuguese.setOnClickListener { setLanguage("pt") } + binding.layoutLanguageChooser.btnThai.setOnClickListener { setLanguage("th") } + + if (savedInstanceState == null) { + supportFragmentManager.commit { + replace(binding.layoutFragmentContainer.id, DarkThemeFragment.newInstance()) + } + } + } + + public override fun onSaveInstanceState(outState: Bundle) { + // Save x-position of horizontal scroll view. + outState.putInt(KEY_SCROLL_X, binding.layoutLanguageChooser.svLanguageChooser.scrollX) + super.onSaveInstanceState(outState) + } + + public override fun onRestoreInstanceState(savedInstanceState: Bundle) { + super.onRestoreInstanceState(savedInstanceState) + // Restore x-position of horizontal scroll view. + binding.layoutLanguageChooser.svLanguageChooser.scrollTo(savedInstanceState.getInt(KEY_SCROLL_X), 0) + } +} diff --git a/app/src/main/java/com/akexorcist/localizationapp/darktheme/DarkThemeFragment.kt b/app/src/main/java/com/akexorcist/localizationapp/darktheme/DarkThemeFragment.kt new file mode 100644 index 0000000..7e34f5a --- /dev/null +++ b/app/src/main/java/com/akexorcist/localizationapp/darktheme/DarkThemeFragment.kt @@ -0,0 +1,39 @@ +package com.akexorcist.localizationapp.darktheme + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import com.akexorcist.localizationapp.databinding.FragmentDarkThemeBinding +import com.akexorcist.localizationapp.simplefragment.SimpleFragment + +class DarkThemeFragment : Fragment() { + private lateinit var binding: FragmentDarkThemeBinding + + companion object { + private const val KEY_SCROLL_Y = "scroll_y" + + fun newInstance(): Fragment { + return DarkThemeFragment() + } + } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { + binding = FragmentDarkThemeBinding.inflate(layoutInflater, container, false) + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + if (savedInstanceState != null) { + // Restore y-position of scroll view. + binding.svAppleStory.scrollTo(0, savedInstanceState.getInt(KEY_SCROLL_Y)) + } + } + + override fun onSaveInstanceState(outState: Bundle) { + // Save y-position of scroll view. + outState.putInt(KEY_SCROLL_Y, binding.svAppleStory.scrollY) + super.onSaveInstanceState(outState) + } +} diff --git a/app/src/main/java/com/akexorcist/localizationapp/dialogwebview/DialogWebViewLanguageChooserFragment.kt b/app/src/main/java/com/akexorcist/localizationapp/dialogwebview/DialogWebViewLanguageChooserFragment.kt new file mode 100644 index 0000000..044a95c --- /dev/null +++ b/app/src/main/java/com/akexorcist/localizationapp/dialogwebview/DialogWebViewLanguageChooserFragment.kt @@ -0,0 +1,39 @@ +package com.akexorcist.localizationapp.dialogwebview + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.DialogFragment +import com.akexorcist.localizationactivity.ui.LocalizationActivity +import com.akexorcist.localizationapp.databinding.FragmentDialogWebviewLanguageChooserBinding + +class DialogWebViewLanguageChooserFragment : DialogFragment() { + private lateinit var binding: FragmentDialogWebviewLanguageChooserBinding + + companion object { + fun newInstance(): DialogWebViewLanguageChooserFragment = DialogWebViewLanguageChooserFragment() + } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { + binding = FragmentDialogWebviewLanguageChooserBinding.inflate(layoutInflater, container, false) + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + binding.btnAmerican.setOnClickListener { changeLanguage("en") } + binding.btnChinese.setOnClickListener { changeLanguage("zh") } + binding.btnItalian.setOnClickListener { changeLanguage("it") } + binding.btnJapanese.setOnClickListener { changeLanguage("ja") } + binding.btnKorean.setOnClickListener { changeLanguage("ko") } + binding.btnPortuguese.setOnClickListener { changeLanguage("pt") } + binding.btnThai.setOnClickListener { changeLanguage("th") } + } + + private fun changeLanguage(language: String) { + (requireActivity() as? LocalizationActivity)?.setLanguage(language) + dismiss() + } +} diff --git a/app/src/main/java/com/akexorcist/localizationapp/dialogwebview/DialogWebViewMainActivity.kt b/app/src/main/java/com/akexorcist/localizationapp/dialogwebview/DialogWebViewMainActivity.kt new file mode 100644 index 0000000..2109459 --- /dev/null +++ b/app/src/main/java/com/akexorcist/localizationapp/dialogwebview/DialogWebViewMainActivity.kt @@ -0,0 +1,23 @@ +package com.akexorcist.localizationapp.dialogwebview + +import android.content.Intent +import android.os.Bundle +import com.akexorcist.localizationactivity.ui.LocalizationActivity +import com.akexorcist.localizationapp.databinding.ActivityDialogWebviewMainBinding + +class DialogWebViewMainActivity : LocalizationActivity() { + private val binding: ActivityDialogWebviewMainBinding by lazy { ActivityDialogWebviewMainBinding.inflate(layoutInflater) } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(binding.root) + + binding.btnBack.setOnClickListener { super.onBackPressed() } + binding.btnShowWebsite.setOnClickListener { + startActivity(Intent(this, DialogWebViewSiteActivity::class.java)) + } + binding.btnChangeLanguage.setOnClickListener { + DialogWebViewLanguageChooserFragment.newInstance().show(supportFragmentManager, null) + } + } +} diff --git a/app/src/main/java/com/akexorcist/localizationapp/dialogwebview/DialogWebViewSiteActivity.kt b/app/src/main/java/com/akexorcist/localizationapp/dialogwebview/DialogWebViewSiteActivity.kt new file mode 100644 index 0000000..15e9742 --- /dev/null +++ b/app/src/main/java/com/akexorcist/localizationapp/dialogwebview/DialogWebViewSiteActivity.kt @@ -0,0 +1,42 @@ +package com.akexorcist.localizationapp.dialogwebview + +import android.annotation.SuppressLint +import android.graphics.Color +import android.os.Bundle +import com.akexorcist.localizationactivity.ui.LocalizationActivity +import com.akexorcist.localizationapp.R +import com.akexorcist.localizationapp.databinding.ActivityDialogWebviewSiteBinding + +class DialogWebViewSiteActivity : LocalizationActivity() { + private val binding: ActivityDialogWebviewSiteBinding by lazy { ActivityDialogWebviewSiteBinding.inflate(layoutInflater) } + + @SuppressLint("SetJavaScriptEnabled") + public override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(binding.root) + binding.btnBack.setOnClickListener { super.onBackPressed() } + binding.wvContent.run { + settings.javaScriptEnabled = true + setBackgroundColor(Color.TRANSPARENT) + loadData(htmlData, "text/html", "UTF-8") + } + } + + private val htmlData: String + get() = """ + + + + + +

+ ${getString(R.string.hello_world)} +

+ + + """.trimIndent() +} diff --git a/app/src/main/java/com/akexorcist/localizationapp/hilt/HiltActivity.kt b/app/src/main/java/com/akexorcist/localizationapp/hilt/HiltActivity.kt new file mode 100644 index 0000000..cf71cba --- /dev/null +++ b/app/src/main/java/com/akexorcist/localizationapp/hilt/HiltActivity.kt @@ -0,0 +1,20 @@ +package com.akexorcist.localizationapp.hilt + +import android.os.Bundle +import com.akexorcist.localizationactivity.ui.LocalizationActivity +import com.akexorcist.localizationapp.databinding.ActivityHiltBinding +import dagger.hilt.android.AndroidEntryPoint +import javax.inject.Inject + +@AndroidEntryPoint +class HiltActivity : LocalizationActivity() { + private val binding: ActivityHiltBinding by lazy { ActivityHiltBinding.inflate(layoutInflater) } + + @Inject + lateinit var storyProvider: StoryProvider + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(binding.root) + } +} diff --git a/app/src/main/java/com/akexorcist/localizationapp/hilt/HiltFragmentWithViewModel.kt b/app/src/main/java/com/akexorcist/localizationapp/hilt/HiltFragmentWithViewModel.kt new file mode 100644 index 0000000..36dcf50 --- /dev/null +++ b/app/src/main/java/com/akexorcist/localizationapp/hilt/HiltFragmentWithViewModel.kt @@ -0,0 +1,69 @@ +package com.akexorcist.localizationapp.hilt + +import android.os.Bundle +import android.view.View +import android.widget.Button +import android.widget.ImageButton +import android.widget.ScrollView +import android.widget.TextView +import androidx.fragment.app.Fragment +import androidx.fragment.app.viewModels +import com.akexorcist.localizationactivity.ui.LocalizationActivity +import com.akexorcist.localizationapp.R +import dagger.hilt.android.AndroidEntryPoint + + +@AndroidEntryPoint +class HiltFragmentWithViewModel : Fragment(R.layout.fragment_hilt) { + + private val hiltViewModel: HiltViewModel by viewModels() + + private var languageChooserScrollView: ScrollView? = null + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + setupUi(view) + } + + private fun setupUi(view: View) { + languageChooserScrollView = view.findViewById(R.id.sv_language_chooser) + + view.findViewById(R.id.text_view_content).text = hiltViewModel.storyProvider.getAppleStory() + view.findViewById