├── module_androidtest_only ├── .gitignore ├── src │ └── main │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── com │ │ └── hitherejoe │ │ └── module_androidtest_only │ │ ├── injection │ │ ├── component │ │ │ ├── TestComponent.java │ │ │ └── DataManagerTestComponent.java │ │ ├── module │ │ │ ├── DataManagerTestModule.java │ │ │ └── ApplicationTestModule.java │ │ └── TestComponentRule.java │ │ ├── util │ │ └── TestDataManager.java │ │ └── MainActivityTest.java ├── proguard-rules.pro └── build.gradle ├── app ├── .gitignore ├── src │ ├── main │ │ ├── res │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── drawable-v21 │ │ │ │ └── touchable_background_white.xml │ │ │ ├── layout │ │ │ │ ├── activity_main.xml │ │ │ │ ├── activity_user.xml │ │ │ │ ├── layout_offline.xml │ │ │ │ ├── item_comments_header.xml │ │ │ │ ├── fragment_stories.xml │ │ │ │ ├── activity_view_story.xml │ │ │ │ ├── item_comment.xml │ │ │ │ ├── activity_comments.xml │ │ │ │ └── item_post.xml │ │ │ ├── drawable │ │ │ │ ├── selector_button.xml │ │ │ │ └── touchable_background_white.xml │ │ │ ├── values-w820dp │ │ │ │ └── dimens.xml │ │ │ ├── menu │ │ │ │ ├── main.xml │ │ │ │ └── view_story.xml │ │ │ ├── values │ │ │ │ ├── dimens.xml │ │ │ │ ├── colors.xml │ │ │ │ ├── styles.xml │ │ │ │ └── strings.xml │ │ │ └── xml │ │ │ │ └── app_tracker.xml │ │ ├── java │ │ │ └── com │ │ │ │ └── hitherejoe │ │ │ │ └── mvvm_hackernews │ │ │ │ ├── model │ │ │ │ ├── User.java │ │ │ │ ├── Comment.java │ │ │ │ └── Post.java │ │ │ │ ├── util │ │ │ │ ├── ViewUtils.java │ │ │ │ ├── DataUtils.java │ │ │ │ ├── DialogFactory.java │ │ │ │ └── MockModelsUtil.java │ │ │ │ ├── injection │ │ │ │ ├── scope │ │ │ │ │ └── PerDataManager.java │ │ │ │ ├── component │ │ │ │ │ ├── DataManagerComponent.java │ │ │ │ │ └── ApplicationComponent.java │ │ │ │ └── module │ │ │ │ │ ├── ApplicationModule.java │ │ │ │ │ └── DataManagerModule.java │ │ │ │ ├── data │ │ │ │ ├── remote │ │ │ │ │ ├── RetrofitHelper.java │ │ │ │ │ └── HackerNewsService.java │ │ │ │ └── DataManager.java │ │ │ │ ├── view │ │ │ │ ├── activity │ │ │ │ │ ├── BaseActivity.java │ │ │ │ │ ├── UserActivity.java │ │ │ │ │ ├── MainActivity.java │ │ │ │ │ ├── CommentsActivity.java │ │ │ │ │ └── ViewStoryActivity.java │ │ │ │ ├── adapter │ │ │ │ │ ├── PostAdapter.java │ │ │ │ │ └── CommentAdapter.java │ │ │ │ └── fragment │ │ │ │ │ └── StoriesFragment.java │ │ │ │ ├── viewModel │ │ │ │ ├── CommentHeaderViewModel.java │ │ │ │ ├── CommentViewModel.java │ │ │ │ └── PostViewModel.java │ │ │ │ └── HackerNewsApplication.java │ │ └── AndroidManifest.xml │ └── test │ │ └── java │ │ └── com │ │ └── hitherejoe │ │ └── mvvm_hackernews │ │ ├── util │ │ └── DefaultConfig.java │ │ ├── CommentHeaderViewModelTest.java │ │ ├── CommentViewModelTest.java │ │ ├── PostViewModelTest.java │ │ └── DataManagerTest.java ├── proguard-rules.pro ├── build.gradle └── manifest-merger-release-report.txt ├── settings.gradle ├── images └── screens.png ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .gitignore ├── .travis.yml ├── circle.yml ├── gradle.properties ├── gradlew.bat ├── README.md └── gradlew /module_androidtest_only/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | *iml 3 | *.iml 4 | .idea -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app', ':module_androidtest_only' 2 | -------------------------------------------------------------------------------- /images/screens.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YiuChoi/MVVM_Hacker_News/master/images/screens.png -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YiuChoi/MVVM_Hacker_News/master/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YiuChoi/MVVM_Hacker_News/master/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YiuChoi/MVVM_Hacker_News/master/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YiuChoi/MVVM_Hacker_News/master/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YiuChoi/MVVM_Hacker_News/master/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YiuChoi/MVVM_Hacker_News/master/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /local.properties 3 | /.idea/workspace.xml 4 | .DS_Store 5 | /build 6 | .idea/ 7 | *iml 8 | *.iml 9 | */build 10 | app/hackernews.apk 11 | app/hackernews12.apk 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v21/touchable_background_white.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_user.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sat Jan 03 10:20:28 GMT 2015 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/selector_button.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/java/com/hitherejoe/mvvm_hackernews/model/User.java: -------------------------------------------------------------------------------- 1 | package com.hitherejoe.mvvm_hackernews.model; 2 | 3 | import java.util.List; 4 | 5 | public class User { 6 | 7 | public String about; 8 | public String id; 9 | public long karma; 10 | public List submitted; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /app/src/test/java/com/hitherejoe/mvvm_hackernews/util/DefaultConfig.java: -------------------------------------------------------------------------------- 1 | package com.hitherejoe.mvvm_hackernews.util; 2 | 3 | public class DefaultConfig { 4 | //The api level that Robolectric will use to run the unit tests 5 | public static final int EMULATE_SDK = 21; 6 | public static final String MANIFEST = "./src/main/AndroidManifest.xml"; 7 | } -------------------------------------------------------------------------------- /module_androidtest_only/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/touchable_background_white.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/java/com/hitherejoe/mvvm_hackernews/util/ViewUtils.java: -------------------------------------------------------------------------------- 1 | package com.hitherejoe.mvvm_hackernews.util; 2 | 3 | import android.content.Context; 4 | import android.util.DisplayMetrics; 5 | 6 | public class ViewUtils { 7 | 8 | public static float convertPixelsToDp(float px, Context context){ 9 | DisplayMetrics metrics = context.getResources().getDisplayMetrics(); 10 | return px / (metrics.densityDpi / 160f); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/res/menu/main.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/java/com/hitherejoe/mvvm_hackernews/util/DataUtils.java: -------------------------------------------------------------------------------- 1 | package com.hitherejoe.mvvm_hackernews.util; 2 | 3 | import android.content.Context; 4 | import android.net.ConnectivityManager; 5 | 6 | public class DataUtils { 7 | 8 | public static boolean isNetworkAvailable(Context context) { 9 | ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); 10 | return connectivityManager.getActiveNetworkInfo() != null; 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/java/com/hitherejoe/mvvm_hackernews/injection/scope/PerDataManager.java: -------------------------------------------------------------------------------- 1 | package com.hitherejoe.mvvm_hackernews.injection.scope; 2 | 3 | import java.lang.annotation.Retention; 4 | import java.lang.annotation.RetentionPolicy; 5 | 6 | import javax.inject.Scope; 7 | 8 | /** 9 | * A scoping annotation to permit objects whose lifetime should 10 | * conform to the life of the DataManager to be memorised in the 11 | * correct component. 12 | */ 13 | @Scope 14 | @Retention(RetentionPolicy.RUNTIME) 15 | public @interface PerDataManager { 16 | } -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 6 | 24sp 7 | 22sp 8 | 20sp 9 | 18sp 10 | 16sp 11 | 14sp 12 | 13 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: android 2 | android: 3 | components: 4 | - platform-tools 5 | - tools 6 | 7 | # The BuildTools version used by your project 8 | - build-tools-23.0.0 9 | 10 | # The SDK version used to compile your project 11 | - android-22 12 | 13 | # Additional components 14 | # - extra-google-google_play_services 15 | # - extra-google-m2repository 16 | - extra-android-m2repository 17 | 18 | before_script: 19 | - chmod +x gradlew 20 | #Build, and run tests 21 | script: "./gradlew build testDebugUnitTest" 22 | sudo: false -------------------------------------------------------------------------------- /module_androidtest_only/src/main/java/com/hitherejoe/module_androidtest_only/injection/component/TestComponent.java: -------------------------------------------------------------------------------- 1 | package com.hitherejoe.module_androidtest_only.injection.component; 2 | 3 | 4 | import com.hitherejoe.module_androidtest_only.injection.module.ApplicationTestModule; 5 | import com.hitherejoe.mvvm_hackernews.injection.component.ApplicationComponent; 6 | 7 | import javax.inject.Singleton; 8 | 9 | import dagger.Component; 10 | 11 | @Singleton 12 | @Component(modules = ApplicationTestModule.class) 13 | public interface TestComponent extends ApplicationComponent { 14 | 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/hitherejoe/mvvm_hackernews/injection/component/DataManagerComponent.java: -------------------------------------------------------------------------------- 1 | package com.hitherejoe.mvvm_hackernews.injection.component; 2 | 3 | import com.hitherejoe.mvvm_hackernews.data.DataManager; 4 | import com.hitherejoe.mvvm_hackernews.injection.module.DataManagerModule; 5 | import com.hitherejoe.mvvm_hackernews.injection.scope.PerDataManager; 6 | 7 | import dagger.Component; 8 | 9 | @PerDataManager 10 | @Component(dependencies = ApplicationComponent.class, modules = DataManagerModule.class) 11 | public interface DataManagerComponent { 12 | 13 | void inject(DataManager dataManager); 14 | } -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FF6600 4 | #e65c00 5 | #FF8C3F 6 | #D4D4D4 7 | #E9E9E9 8 | #A8A8A8 9 | #FFFFFF 10 | #000000 11 | #FAFAFA 12 | #D7D7D7 13 | #DD000000 14 | -------------------------------------------------------------------------------- /module_androidtest_only/src/main/java/com/hitherejoe/module_androidtest_only/injection/component/DataManagerTestComponent.java: -------------------------------------------------------------------------------- 1 | package com.hitherejoe.module_androidtest_only.injection.component; 2 | 3 | 4 | import com.hitherejoe.module_androidtest_only.injection.module.DataManagerTestModule; 5 | import com.hitherejoe.mvvm_hackernews.injection.component.DataManagerComponent; 6 | import com.hitherejoe.mvvm_hackernews.injection.scope.PerDataManager; 7 | 8 | import dagger.Component; 9 | 10 | @PerDataManager 11 | @Component(dependencies = TestComponent.class, modules = DataManagerTestModule.class) 12 | public interface DataManagerTestComponent extends DataManagerComponent { 13 | } -------------------------------------------------------------------------------- /app/src/main/res/menu/view_story.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 8 | 11 | 14 | -------------------------------------------------------------------------------- /app/src/main/java/com/hitherejoe/mvvm_hackernews/injection/component/ApplicationComponent.java: -------------------------------------------------------------------------------- 1 | package com.hitherejoe.mvvm_hackernews.injection.component; 2 | 3 | import android.app.Application; 4 | 5 | import com.hitherejoe.mvvm_hackernews.data.DataManager; 6 | import com.hitherejoe.mvvm_hackernews.injection.module.ApplicationModule; 7 | import com.hitherejoe.mvvm_hackernews.view.activity.MainActivity; 8 | 9 | import javax.inject.Singleton; 10 | 11 | import dagger.Component; 12 | 13 | @Singleton 14 | @Component(modules = ApplicationModule.class) 15 | public interface ApplicationComponent { 16 | 17 | void inject(MainActivity mainActivity); 18 | 19 | Application application(); 20 | DataManager dataManager(); 21 | } -------------------------------------------------------------------------------- /circle.yml: -------------------------------------------------------------------------------- 1 | test: 2 | override: 3 | # start the emulator 4 | - emulator -avd circleci-android22 -no-audio -no-window: 5 | background: true 6 | parallel: true 7 | # wait for it to have booted 8 | - circle-android wait-for-boot 9 | - sleep 30 10 | - adb shell input touchscreen swipe 370 735 370 400 11 | - sleep 30 12 | - adb shell input keyevent 82 13 | - sleep 30 14 | # run tests against the emulator. 15 | - ./gradlew connectedAndroidTest 16 | # copy the build outputs to artifacts 17 | - cp -r app/build/outputs $CIRCLE_ARTIFACTS 18 | # copy the test results to the test results directory. 19 | - cp -r app/build/outputs/androidTest-results/* $CIRCLE_TEST_REPORTS 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/hitherejoe/mvvm_hackernews/data/remote/RetrofitHelper.java: -------------------------------------------------------------------------------- 1 | package com.hitherejoe.mvvm_hackernews.data.remote; 2 | 3 | import com.google.gson.GsonBuilder; 4 | 5 | import retrofit.RestAdapter; 6 | import retrofit.converter.GsonConverter; 7 | 8 | public class RetrofitHelper { 9 | 10 | public HackerNewsService newHackerNewsService() { 11 | RestAdapter restAdapter = new RestAdapter.Builder() 12 | .setEndpoint(HackerNewsService.ENDPOINT) 13 | .setLogLevel(RestAdapter.LogLevel.FULL) 14 | .setConverter(new GsonConverter(new GsonBuilder().create())) 15 | .build(); 16 | return restAdapter.create(HackerNewsService.class); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Applications/Android Studio.app/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /module_androidtest_only/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/hitherejoe/Dev/android-sdk-macosx/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Settings specified in this file will override any Gradle settings 5 | # configured through the IDE. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true -------------------------------------------------------------------------------- /app/src/main/java/com/hitherejoe/mvvm_hackernews/view/activity/BaseActivity.java: -------------------------------------------------------------------------------- 1 | package com.hitherejoe.mvvm_hackernews.view.activity; 2 | 3 | import android.app.FragmentManager; 4 | import android.support.v7.app.AppCompatActivity; 5 | import android.view.MenuItem; 6 | 7 | public class BaseActivity extends AppCompatActivity { 8 | 9 | @Override 10 | public boolean onOptionsItemSelected(MenuItem item) { 11 | switch (item.getItemId()) { 12 | case android.R.id.home: 13 | FragmentManager fm = getFragmentManager(); 14 | if (fm.getBackStackEntryCount() > 0) { 15 | fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE); 16 | } else { 17 | finish(); 18 | } 19 | return true; 20 | default: 21 | return super.onOptionsItemSelected(item); 22 | } 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/hitherejoe/mvvm_hackernews/injection/module/ApplicationModule.java: -------------------------------------------------------------------------------- 1 | package com.hitherejoe.mvvm_hackernews.injection.module; 2 | 3 | import android.app.Application; 4 | 5 | import com.hitherejoe.mvvm_hackernews.data.DataManager; 6 | 7 | import javax.inject.Singleton; 8 | 9 | import dagger.Module; 10 | import dagger.Provides; 11 | 12 | /** 13 | * Provide application-level dependencies. Mainly singleton object that can be injected from 14 | * anywhere in the app. 15 | */ 16 | @Module 17 | public class ApplicationModule { 18 | protected final Application mApplication; 19 | 20 | public ApplicationModule(Application application) { 21 | mApplication = application; 22 | } 23 | 24 | @Provides 25 | @Singleton 26 | Application provideApplication() { 27 | return mApplication; 28 | } 29 | 30 | @Provides 31 | @Singleton 32 | DataManager provideDataManager() { 33 | return new DataManager(mApplication); 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /app/src/main/java/com/hitherejoe/mvvm_hackernews/injection/module/DataManagerModule.java: -------------------------------------------------------------------------------- 1 | package com.hitherejoe.mvvm_hackernews.injection.module; 2 | 3 | import com.hitherejoe.mvvm_hackernews.data.remote.HackerNewsService; 4 | import com.hitherejoe.mvvm_hackernews.data.remote.RetrofitHelper; 5 | import com.hitherejoe.mvvm_hackernews.injection.scope.PerDataManager; 6 | 7 | import dagger.Module; 8 | import dagger.Provides; 9 | import rx.Scheduler; 10 | import rx.schedulers.Schedulers; 11 | 12 | /** 13 | * Provide dependencies to the DataManager, mainly Helper classes and Retrofit services. 14 | */ 15 | @Module 16 | public class DataManagerModule { 17 | 18 | public DataManagerModule() { 19 | 20 | } 21 | 22 | @Provides 23 | @PerDataManager 24 | HackerNewsService provideHackerNewsService() { 25 | return new RetrofitHelper().newHackerNewsService(); 26 | } 27 | 28 | @Provides 29 | @PerDataManager 30 | Scheduler provideSubscribeScheduler() { 31 | return Schedulers.io(); 32 | } 33 | } -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_offline.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 16 | 17 |