commit
7d0a35c506
71 changed files with 992 additions and 612 deletions
|
@ -3,6 +3,13 @@
|
|||
- Single Sign on for all Nextcloud Android Apps!
|
||||
|
||||
|
||||
0.9.9.26
|
||||
---------------------
|
||||
- Fix - <a href="https://github.com/owncloud/News-Android-App/issues/726">#726 Add new feed fails</a>
|
||||
- Fix - <a href="https://github.com/owncloud/News-Android-App/issues/744">#744 Fix issues when adding feeds (Thanks @Unpublished)</a>
|
||||
- Feature - <a href="https://github.com/owncloud/News-Android-App/issues/747">#747 Add option to share article when using chrome-custom-tabs</a>
|
||||
|
||||
|
||||
0.9.9.25
|
||||
---------------------
|
||||
- Fix - app crashes
|
||||
|
|
|
@ -16,24 +16,31 @@ android {
|
|||
minSdkVersion Integer.parseInt(project.ANDROID_BUILD_MIN_SDK_VERSION)
|
||||
targetSdkVersion Integer.parseInt(project.ANDROID_BUILD_TARGET_SDK_VERSION)
|
||||
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
//testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
testInstrumentationRunner "de.luhmer.owncloudnewsreader.CustomTestRunner"
|
||||
vectorDrawables.useSupportLibrary = true
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
debug {
|
||||
shrinkResources true
|
||||
minifyEnabled true
|
||||
// TODO check if proguard-android.txt is used at all.. it's supposed to get it from the sdk. so we can delete it in this repo!
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
|
||||
testProguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
|
||||
useProguard true
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
testProguardFiles 'proguard-test.pro'
|
||||
pseudoLocalesEnabled true
|
||||
}
|
||||
release {
|
||||
shrinkResources true
|
||||
minifyEnabled true
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
|
||||
testProguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
|
||||
useProguard true
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
testProguardFiles 'proguard-test.pro'
|
||||
//signingConfig signingConfigs.debug
|
||||
}
|
||||
}
|
||||
|
@ -63,10 +70,11 @@ android {
|
|||
|
||||
checkReleaseBuilds false
|
||||
|
||||
// Or, if you prefer, you can continue to check for errors in release builds,
|
||||
// but continue the build even when errors are found:
|
||||
// if set to true (default), stops the build if errors are found.
|
||||
abortOnError true
|
||||
|
||||
abortOnError false
|
||||
// if true, only report errors.
|
||||
ignoreWarnings true
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
|
@ -82,19 +90,22 @@ android {
|
|||
exclude 'LICENSE.txt'
|
||||
exclude 'META-INF/services/javax.annotation.processing.Processor'
|
||||
}
|
||||
|
||||
// Gradle automatically adds 'android.test.runner' as a dependency.
|
||||
useLibrary 'android.test.runner'
|
||||
useLibrary 'android.test.base'
|
||||
useLibrary 'android.test.mock'
|
||||
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
jcenter()
|
||||
maven { url "https://jitpack.io" }
|
||||
maven { url 'https://guardian.github.com/maven/repo-releases' } //needed for com.gu:option:1.3 in Android-DirectoryChooser
|
||||
maven { url "https://dl.bintray.com/lukaville/maven" } //Needed for com.nbsp:library:1.02 in Material File Picker
|
||||
maven { url "https://jitpack.io" }
|
||||
|
||||
}
|
||||
|
||||
final SUPPORT_VERSION = '28.0.0'
|
||||
|
||||
dependencies {
|
||||
// core android studio module
|
||||
//compile project(':core')
|
||||
|
@ -103,22 +114,26 @@ dependencies {
|
|||
// implementation 'com.google.android.gms:play-services:4.2.42'
|
||||
//implementation project(':Android-SingleSignOn')
|
||||
//implementation project(path: ':MaterialShowcaseView:library', configuration: 'default')
|
||||
implementation 'com.github.nextcloud:Android-SingleSignOn:0.3.0'
|
||||
//implementation 'com.github.nextcloud:Android-SingleSignOn:e781a33e01'
|
||||
implementation 'com.github.nextcloud:Android-SingleSignOn:unit-testing-SNAPSHOT'
|
||||
implementation 'com.github.David-Development:MaterialShowcaseView:bf6afa225d'
|
||||
|
||||
implementation "com.android.support:support-v4:${SUPPORT_VERSION}"
|
||||
implementation "com.android.support:support-compat:${SUPPORT_VERSION}"
|
||||
implementation "com.android.support:appcompat-v7:${SUPPORT_VERSION}"
|
||||
implementation "com.android.support:design:${SUPPORT_VERSION}"
|
||||
implementation "com.android.support:palette-v7:${SUPPORT_VERSION}"
|
||||
implementation "com.android.support:recyclerview-v7:${SUPPORT_VERSION}"
|
||||
implementation "com.android.support:customtabs:${SUPPORT_VERSION}"
|
||||
implementation "com.android.support:cardview-v7:${SUPPORT_VERSION}"
|
||||
// https://mvnrepository.com/artifact/androidx.legacy/legacy-support-v4
|
||||
implementation "androidx.legacy:legacy-support-v4:1.0.0"
|
||||
implementation "androidx.core:core:1.1.0-alpha05"
|
||||
implementation "androidx.appcompat:appcompat:1.1.0-alpha02"
|
||||
|
||||
// https://mvnrepository.com/artifact/com.google.android.material/material
|
||||
implementation "com.google.android.material:material:1.1.0-alpha04"
|
||||
implementation "androidx.palette:palette:1.0.0"
|
||||
implementation "androidx.recyclerview:recyclerview:1.1.0-alpha3"
|
||||
implementation "androidx.browser:browser:1.0.0"
|
||||
implementation "androidx.cardview:cardview:1.0.0"
|
||||
//implementation 'de.mrmaffen:holocircularprogressbar:1.0.1'
|
||||
implementation 'com.nostra13.universalimageloader:universal-image-loader:1.9.5'
|
||||
implementation 'com.google.code.gson:gson:2.8.5'
|
||||
implementation 'com.jakewharton:butterknife:8.8.1'
|
||||
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
|
||||
implementation 'com.jakewharton:butterknife:10.1.0'
|
||||
annotationProcessor 'com.jakewharton:butterknife-compiler:10.1.0'
|
||||
|
||||
compileOnly 'com.google.auto.value:auto-value:1.1'
|
||||
annotationProcessor 'com.google.auto.value:auto-value:1.1'
|
||||
|
@ -127,12 +142,14 @@ dependencies {
|
|||
|
||||
implementation 'org.greenrobot:eventbus:3.1.1'
|
||||
implementation 'de.greenrobot:greendao:2.0.0'
|
||||
implementation 'de.greenrobot:greendao-generator:2.0.0'
|
||||
implementation ('de.greenrobot:greendao-generator:2.0.0') {
|
||||
exclude group: 'org.freemarker'
|
||||
}
|
||||
//implementation 'org.freemarker:freemarker:2.3.23' //Required for DAO generation
|
||||
//implementation 'org.apache.commons:commons-lang3:3.4'
|
||||
implementation 'com.github.gabrielemariotti.changeloglib:changelog:2.1.0'
|
||||
implementation 'org.jsoup:jsoup:1.11.3'
|
||||
implementation ('net.rdrei.android.dirchooser:library:3.0@aar') { transitive = true; }
|
||||
implementation ('net.rdrei.android.dirchooser:library:3.0@aar') { transitive = true }
|
||||
|
||||
|
||||
implementation 'com.google.dagger:dagger:2.16'
|
||||
|
@ -154,38 +171,67 @@ dependencies {
|
|||
|
||||
extraImplementation 'com.github.tommus:youtube-android-player-api:1.2.2'
|
||||
|
||||
testImplementation 'org.robolectric:robolectric:3.0-rc3'
|
||||
|
||||
testImplementation 'junit:junit:4.12'
|
||||
testImplementation("org.mockito:mockito-core:1.10.19") {
|
||||
exclude group: 'org.hamcrest'
|
||||
}
|
||||
testImplementation 'com.google.dexmaker:dexmaker:1.2'
|
||||
testImplementation 'com.google.dexmaker:dexmaker-mockito:1.2'
|
||||
testImplementation 'com.squareup.okhttp3:mockwebserver:3.8.0'
|
||||
testImplementation 'com.squareup.okhttp3:mockwebserver:3.14.0'
|
||||
|
||||
|
||||
androidTestAnnotationProcessor "com.google.dagger:dagger-compiler:2.16"
|
||||
|
||||
//androidTestCompile 'com.squareup.okhttp:mockwebserver:2.5.0'
|
||||
// https://mvnrepository.com/artifact/com.squareup.okhttp3/mockwebserver
|
||||
androidTestImplementation group: 'com.squareup.okhttp3', name: 'mockwebserver', version: '3.8.0'
|
||||
//androidTestImplementation group: 'com.squareup.okhttp3', name: 'mockwebserver', version: '3.14.0'
|
||||
|
||||
|
||||
androidTestAnnotationProcessor 'com.google.auto.value:auto-value:1.5.2'
|
||||
androidTestImplementation "com.android.support:support-annotations:${SUPPORT_VERSION}"
|
||||
androidTestImplementation 'com.android.support.test:runner:1.0.2'
|
||||
androidTestImplementation 'com.android.support.test:rules:1.0.2'
|
||||
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
|
||||
androidTestImplementation('com.android.support.test.espresso:espresso-contrib:2.2') {
|
||||
// this library uses the newest app compat v22 but the espresso contrib still v21.
|
||||
// you have to specifically exclude the older versions of the contrib library or
|
||||
// there will be some conflicts
|
||||
exclude group: 'com.android.support', module: 'appcompat'
|
||||
exclude group: 'com.android.support', module: 'support-v4'
|
||||
exclude module: 'recyclerview-v7'
|
||||
}
|
||||
|
||||
androidTestImplementation 'tools.fastlane:screengrab:1.2.0'
|
||||
androidTestImplementation("org.mockito:mockito-core:1.10.19") {
|
||||
exclude group: 'org.hamcrest'
|
||||
}
|
||||
androidTestImplementation 'com.google.dexmaker:dexmaker:1.2'
|
||||
androidTestImplementation 'com.google.dexmaker:dexmaker-mockito:1.2'
|
||||
//androidTestImplementation 'org.mockito:mockito-core:2.25.1'
|
||||
androidTestImplementation 'org.mockito:mockito-android:2.18.3'
|
||||
|
||||
|
||||
//androidTestImplementation 'com.google.dexmaker:dexmaker:1.2'
|
||||
//androidTestImplementation 'com.google.dexmaker:dexmaker-mockito:1.2'
|
||||
|
||||
//androidTestImplementation 'org.robolectric:robolectric:3.0-rc3'
|
||||
|
||||
// Core library
|
||||
androidTestImplementation 'androidx.test:core:1.1.0'
|
||||
|
||||
// AndroidJUnitRunner and JUnit Rules
|
||||
androidTestImplementation 'androidx.test:runner:1.1.1'
|
||||
androidTestImplementation 'androidx.test:rules:1.1.1'
|
||||
|
||||
// Assertions
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.0'
|
||||
androidTestImplementation 'androidx.test.ext:truth:1.1.0'
|
||||
androidTestImplementation 'com.google.truth:truth:0.42'
|
||||
|
||||
// Espresso dependencies
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.1.1'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-intents:3.1.1'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-accessibility:3.1.1'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-web:3.1.1'
|
||||
androidTestImplementation 'androidx.test.espresso.idling:idling-concurrent:3.1.1'
|
||||
|
||||
// The following Espresso dependency can be either "implementation"
|
||||
// or "androidTestImplementation", depending on whether you want the
|
||||
// dependency to appear on your APK's compile classpath or the test APK
|
||||
// classpath.
|
||||
//androidTestImplementation 'androidx.test.espresso:espresso-idling-resource:3.1.1'
|
||||
}
|
||||
|
||||
/*
|
||||
// Workaround for https://github.com/mockito/mockito/issues/1511#issuecomment-458544398
|
||||
configurations.all {
|
||||
resolutionStrategy.eachDependency { details ->
|
||||
if (details.requested.group == 'net.bytebuddy') {
|
||||
details.useVersion "1.8.22"
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
|
@ -1,61 +0,0 @@
|
|||
# This is a configuration file for ProGuard.
|
||||
# http://proguard.sourceforge.net/index.html#manual/usage.html
|
||||
|
||||
-dontusemixedcaseclassnames
|
||||
-dontskipnonpubliclibraryclasses
|
||||
-verbose
|
||||
|
||||
# Optimization is turned off by default. Dex does not like code run
|
||||
# through the ProGuard optimize and preverify steps (and performs some
|
||||
# of these optimizations on its own).
|
||||
-dontoptimize
|
||||
-dontpreverify
|
||||
# Note that if you want to enable optimization, you cannot just
|
||||
# include optimization flags in your own project configuration file;
|
||||
# instead you will need to point to the
|
||||
# "proguard-android-optimize.txt" file instead of this one from your
|
||||
# project.properties file.
|
||||
|
||||
-keepattributes *Annotation*
|
||||
-keep public class com.google.vending.licensing.ILicensingService
|
||||
-keep public class com.android.vending.licensing.ILicensingService
|
||||
|
||||
# For native methods, see http://proguard.sourceforge.net/manual/examples.html#native
|
||||
-keepclasseswithmembernames class * {
|
||||
native <methods>;
|
||||
}
|
||||
|
||||
# keep setters in Views so that animations can still work.
|
||||
# see http://proguard.sourceforge.net/manual/examples.html#beans
|
||||
-keepclassmembers public class * extends android.view.View {
|
||||
void set*(***);
|
||||
*** get*();
|
||||
}
|
||||
|
||||
# We want to keep methods in Activity that could be used in the XML attribute onClick
|
||||
-keepclassmembers class * extends android.app.Activity {
|
||||
public void *(android.view.View);
|
||||
}
|
||||
|
||||
# For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations
|
||||
-keepclassmembers enum * {
|
||||
public static **[] values();
|
||||
public static ** valueOf(java.lang.String);
|
||||
}
|
||||
|
||||
-keep class * implements android.os.Parcelable {
|
||||
public static final android.os.Parcelable$Creator *;
|
||||
}
|
||||
|
||||
-keepnames class * implements android.os.Parcelable {
|
||||
public static final ** CREATOR;
|
||||
}
|
||||
|
||||
-keepclassmembers class **.R$* {
|
||||
public static <fields>;
|
||||
}
|
||||
|
||||
# The support library contains references to newer platform versions.
|
||||
# Don't warn about those in case this app is linking against an older
|
||||
# platform version. We know about them, and they are safe.
|
||||
-dontwarn android.support.**
|
|
@ -29,8 +29,6 @@
|
|||
-dontwarn org.mockito.**
|
||||
|
||||
|
||||
|
||||
|
||||
-keepnames class * implements java.io.Serializable
|
||||
|
||||
-keepclassmembers class * implements java.io.Serializable {
|
||||
|
@ -113,4 +111,58 @@
|
|||
-keep class de.greenrobot.** { *; }
|
||||
-dontwarn de.greenrobot.daogenerator.DaoGenerator
|
||||
|
||||
-keepclassmembers class * extends de.greenrobot.dao.AbstractDao { *; }
|
||||
-keepclassmembers class * extends de.greenrobot.dao.AbstractDao { *; }
|
||||
|
||||
|
||||
###############
|
||||
# Guava (official)
|
||||
## Not yet defined: follow https://github.com/google/guava/issues/2117
|
||||
# Guava (unofficial)
|
||||
## https://github.com/google/guava/issues/2926#issuecomment-325455128
|
||||
## https://stackoverflow.com/questions/9120338/proguard-configuration-for-guava-with-obfuscation-and-optimization
|
||||
-dontwarn com.google.common.base.**
|
||||
-dontwarn com.google.errorprone.annotations.**
|
||||
-dontwarn com.google.j2objc.annotations.**
|
||||
-dontwarn java.lang.ClassValue
|
||||
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
|
||||
-dontwarn javax.annotation.**
|
||||
-dontwarn javax.inject.**
|
||||
-dontwarn sun.misc.Unsafe
|
||||
|
||||
# Added for guava 23.5-android
|
||||
-dontwarn afu.org.checkerframework.**
|
||||
-dontwarn org.checkerframework.**
|
||||
|
||||
|
||||
|
||||
|
||||
#-ignorewarnings
|
||||
#-keep class * {
|
||||
# public private *;
|
||||
#}
|
||||
|
||||
|
||||
### OkHttp
|
||||
# https://github.com/square/okhttp/blob/master/README.md
|
||||
-dontwarn okhttp3.**
|
||||
-dontwarn okio.**
|
||||
-dontwarn javax.annotation.**
|
||||
-dontwarn org.conscrypt.**
|
||||
# A resource is loaded with a relative path so the package of this class must be preserved.
|
||||
-keepnames class okhttp3.internal.publicsuffix.PublicSuffixDatabase
|
||||
|
||||
# JSR 305 annotations are for embedding nullability information.
|
||||
-dontwarn javax.annotation.**
|
||||
|
||||
# OkHttp platform used only on JVM and when Conscrypt dependency is available.
|
||||
-dontwarn okhttp3.internal.platform.ConscryptPlatform
|
||||
|
||||
-keep interface org.conscrypt.Conscrypt { *; }
|
||||
-keep class org.conscrypt.Conscrypt { *; }
|
||||
|
||||
|
||||
|
||||
# https://stackoverflow.com/a/39777485
|
||||
# Also, note that this rule should be added to the regular proguard file(the one of listed in proguardFiles) and not the test one(declared as testProguardFile)
|
||||
# java.lang.NoSuchMethodError: No virtual method getParameter
|
||||
-keepclasseswithmembers public class com.nextcloud.android.sso.aidl.NextcloudRequest { *; }
|
48
News-Android-App/proguard-test.pro
Normal file
48
News-Android-App/proguard-test.pro
Normal file
|
@ -0,0 +1,48 @@
|
|||
# proguard-test.pro:
|
||||
-include proguard-rules.pro
|
||||
-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
|
||||
|
||||
-dontwarn androidx.test.espresso.**
|
||||
|
||||
|
||||
###############
|
||||
# Required for Mockito
|
||||
-keep class retrofit2.NextcloudRetrofitApiBuilder { *; }
|
||||
-keep class net.bytebuddy.* { *; }
|
||||
-dontwarn net.bytebuddy.**
|
||||
|
||||
-keep class module-info
|
||||
-keepattributes Module*
|
||||
-dontwarn org.mockito.**
|
||||
|
||||
|
||||
# Proguard rules that are applied to your test apk/code.
|
||||
-ignorewarnings
|
||||
|
||||
-keepattributes *Annotation*
|
||||
|
||||
-dontnote junit.framework.**
|
||||
-dontnote junit.runner.**
|
||||
|
||||
-dontwarn android.test.**
|
||||
-dontwarn android.support.test.**
|
||||
-dontwarn org.junit.**
|
||||
-dontwarn org.hamcrest.**
|
||||
-dontwarn com.squareup.javawriter.JavaWriter
|
||||
|
||||
-dontwarn androidx.concurrent.futures.AbstractResolvableFuture
|
||||
-dontwarn org.conscrypt.Conscrypt
|
||||
#com.google.common.util.concurrent.ListenableFuture
|
||||
-keep interface okhttp3.internal.platform.ConscryptPlatform
|
||||
-keep class okhttp3.internal.platform.ConscryptPlatform
|
||||
|
||||
-keep class org.conscrypt.Conscrypt { *; }
|
||||
-keep interface org.conscrypt.Conscrypt { *; }
|
||||
|
||||
|
||||
#org.conscrypt
|
||||
-dontwarn org.conscrypt.**
|
||||
#-keep class org.conscrypt.** { *; }
|
||||
#-keep interface org.conscrypt.** { *; }
|
14
News-Android-App/src/androidTest/AndroidManifest.xml
Normal file
14
News-Android-App/src/androidTest/AndroidManifest.xml
Normal file
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="your.package.name">
|
||||
|
||||
<uses-sdk tools:overrideLibrary="android.support.test.uiautomator.v18"/>
|
||||
|
||||
<application>
|
||||
<!-- You don't need to include android:required="false" if your app's minSdkVersion is 28 or higher. -->
|
||||
<uses-library android:name="android.test.runner" android:required="false" />
|
||||
<uses-library android:name="android.test.base" android:required="false" />
|
||||
<uses-library android:name="android.test.mock" android:required="false" />
|
||||
</application>
|
||||
</manifest>
|
|
@ -0,0 +1,133 @@
|
|||
package com.nextcloud.android.sso.api;
|
||||
|
||||
|
||||
import com.nextcloud.android.sso.aidl.NextcloudRequest;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.test.filters.LargeTest;
|
||||
import androidx.test.rule.ActivityTestRule;
|
||||
import de.luhmer.owncloudnewsreader.NewFeedActivity;
|
||||
import de.luhmer.owncloudnewsreader.R;
|
||||
import de.luhmer.owncloudnewsreader.TestApplication;
|
||||
import de.luhmer.owncloudnewsreader.di.ApiProvider;
|
||||
import de.luhmer.owncloudnewsreader.di.TestApiProvider;
|
||||
import de.luhmer.owncloudnewsreader.di.TestComponent;
|
||||
|
||||
import static androidx.test.espresso.Espresso.onView;
|
||||
import static androidx.test.espresso.action.ViewActions.click;
|
||||
import static androidx.test.espresso.action.ViewActions.closeSoftKeyboard;
|
||||
import static androidx.test.espresso.action.ViewActions.typeText;
|
||||
import static androidx.test.espresso.assertion.ViewAssertions.matches;
|
||||
import static androidx.test.espresso.matcher.ViewMatchers.hasErrorText;
|
||||
import static androidx.test.espresso.matcher.ViewMatchers.withId;
|
||||
import static junit.framework.Assert.assertFalse;
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
import static junit.framework.Assert.fail;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.timeout;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
|
||||
//@RunWith(AndroidJUnit4.class)
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
@LargeTest
|
||||
public class NewFeedTests {
|
||||
|
||||
@Rule
|
||||
public ActivityTestRule<NewFeedActivity> activityRule = new ActivityTestRule<>(NewFeedActivity.class);
|
||||
|
||||
protected @Inject ApiProvider mApi;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
TestComponent ac = (TestComponent) ((TestApplication)(activityRule.getActivity().getApplication())).getAppComponent();
|
||||
ac.inject(this);
|
||||
|
||||
// Reset Spy object
|
||||
mApi.initApi(null);
|
||||
//reset(((TestApiProvider)mApi).networkRequestSpy);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addNewFeed() {
|
||||
String feed = TestApiProvider.NEW_FEED_SUCCESS;
|
||||
|
||||
// Type text and then press the button.
|
||||
onView(withId(R.id.et_feed_url)).perform(typeText(feed), closeSoftKeyboard());
|
||||
onView(withId(R.id.btn_addFeed)).perform(click());
|
||||
|
||||
try {
|
||||
verifyRequest(feed);
|
||||
|
||||
//onView(withId(R.id.et_feed_url)).check(matches(hasErrorText(nullValue(String.class))));
|
||||
|
||||
// Check Activity existed
|
||||
Thread.sleep(1000);
|
||||
assertFalse(activityRule.getActivity().getWindow().getDecorView().isShown());
|
||||
} catch (Exception e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addExistingFeed() {
|
||||
String feed = TestApiProvider.NEW_FEED_EXISTING;
|
||||
|
||||
// Type text and then press the button.
|
||||
onView(withId(R.id.et_feed_url)).perform(typeText(feed), closeSoftKeyboard());
|
||||
onView(withId(R.id.btn_addFeed)).perform(click());
|
||||
|
||||
try {
|
||||
verifyRequest(feed);
|
||||
|
||||
// Check Activity still open
|
||||
Thread.sleep(1000);
|
||||
assertTrue(activityRule.getActivity().getWindow().getDecorView().isShown());
|
||||
|
||||
onView(withId(R.id.et_feed_url)).check(matches(hasErrorText(is("Feed konnte nicht hinzugefügt werden: Existiert bereits"))));
|
||||
} catch (Exception e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addInvalidFeed() {
|
||||
String feed = TestApiProvider.NEW_FEED_FAIL;
|
||||
|
||||
// Type text and then press the button.
|
||||
onView(withId(R.id.et_feed_url)).perform(typeText(feed), closeSoftKeyboard());
|
||||
onView(withId(R.id.btn_addFeed)).perform(click());
|
||||
|
||||
try {
|
||||
verifyRequest(feed);
|
||||
|
||||
// Check Activity still open
|
||||
Thread.sleep(1000);
|
||||
assertTrue(activityRule.getActivity().getWindow().getDecorView().isShown());
|
||||
|
||||
onView(withId(R.id.et_feed_url)).check(matches(hasErrorText(is("FeedIo\\Adapter\\NotFoundException: Client error: `GET http://feeds2.feedburner.com/stadt-bremerhaven/dqXM222` resulted in a `404 Feed not found error: ..."))));
|
||||
} catch (Exception e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// Verify that the API was actually called
|
||||
private void verifyRequest(String feed) throws Exception {
|
||||
NetworkRequest nr = ((TestApiProvider)mApi).networkRequestSpy;
|
||||
ArgumentCaptor<NextcloudRequest> argument = ArgumentCaptor.forClass(NextcloudRequest.class);
|
||||
verify(nr, timeout(2000)).performNetworkRequest(argument.capture(), any());
|
||||
assertEquals("/index.php/apps/news/api/v1-2/feeds", argument.getValue().getUrl());
|
||||
assertEquals(feed, argument.getValue().getParameter().get("url"));
|
||||
assertEquals("0", argument.getValue().getParameter().get("folderId"));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package de.luhmer.owncloudnewsreader;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.test.runner.AndroidJUnitRunner;
|
||||
|
||||
public class CustomTestRunner extends AndroidJUnitRunner {
|
||||
|
||||
/*
|
||||
@Override
|
||||
public void onCreate(Bundle arguments) {
|
||||
// The workaround for Mockito issue #922
|
||||
// https://github.com/mockito/mockito/issues/922
|
||||
|
||||
arguments.putString("notPackage", "net.bytebuddy");
|
||||
super.onCreate(arguments);
|
||||
}
|
||||
*/
|
||||
|
||||
public Application newApplication(ClassLoader cl, String className, Context context) throws IllegalAccessException, InstantiationException, ClassNotFoundException {
|
||||
return super.newApplication(cl, TestApplication.class.getName(), context);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
package de.luhmer.owncloudnewsreader;
|
||||
|
||||
import de.luhmer.owncloudnewsreader.di.DaggerTestComponent;
|
||||
import de.luhmer.owncloudnewsreader.di.TestApiModule;
|
||||
|
||||
public class TestApplication extends NewsReaderApplication {
|
||||
|
||||
@Override
|
||||
public void initDaggerAppComponent() {
|
||||
// Dagger%COMPONENT_NAME%
|
||||
|
||||
mAppComponent = DaggerTestComponent.builder()
|
||||
.apiModule(new TestApiModule(this))
|
||||
.build();
|
||||
|
||||
// If a Dagger 2 component does not have any constructor arguments for any of its modules,
|
||||
// then we can use .create() as a shortcut instead:
|
||||
//mAppComponent = DaggerAppComponent.create();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
package de.luhmer.owncloudnewsreader.di;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import com.nextcloud.android.sso.AccountImporter;
|
||||
import com.nextcloud.android.sso.helper.SingleAccountHelper;
|
||||
import com.nextcloud.android.sso.model.SingleSignOnAccount;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import de.luhmer.owncloudnewsreader.SettingsActivity;
|
||||
import de.luhmer.owncloudnewsreader.ssl.MemorizingTrustManager;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyInt;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class TestApiModule extends ApiModule {
|
||||
|
||||
private Application application;
|
||||
|
||||
public TestApiModule(Application application) {
|
||||
super(application);
|
||||
this.application = application;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SharedPreferences providesSharedPreferences() {
|
||||
SharedPreferences sharedPrefs = mock(SharedPreferences.class);
|
||||
final Context context = mock(Context.class);
|
||||
when(context.getSharedPreferences(anyString(), anyInt())).thenReturn(sharedPrefs);
|
||||
|
||||
// Turn on Single-Sign-On
|
||||
when(sharedPrefs.getBoolean(SettingsActivity.SW_USE_SINGLE_SIGN_ON, false)).thenReturn(true);
|
||||
|
||||
// Set cache size
|
||||
when(sharedPrefs.getString(eq(SettingsActivity.SP_MAX_CACHE_SIZE), any())).thenReturn("500");
|
||||
|
||||
|
||||
// Add dummy account
|
||||
String accountName = "test-account";
|
||||
String username = "david";
|
||||
String token = "abc";
|
||||
String server_url = "http://nextcloud.com/";
|
||||
|
||||
String prefKey = "PREF_ACCOUNT_STRING" + accountName;
|
||||
SingleSignOnAccount ssoAccount = new SingleSignOnAccount(accountName, username, token, server_url);
|
||||
|
||||
try {
|
||||
AccountImporter.getSharedPreferences(application).edit().putString(prefKey, SingleSignOnAccount.toString(ssoAccount)).commit();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
//try {
|
||||
// when(sharedPrefs.getString(eq(prefKey), any())).thenReturn(SingleSignOnAccount.toString(ssoAccount));
|
||||
//} catch (IOException e) {
|
||||
// e.printStackTrace();
|
||||
//}
|
||||
|
||||
SingleAccountHelper.setCurrentAccount(application, accountName);
|
||||
|
||||
return sharedPrefs;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ApiProvider provideAPI(MemorizingTrustManager mtm, SharedPreferences sp) {
|
||||
ApiProvider apiProvider = new TestApiProvider(mtm, sp, application);
|
||||
return apiProvider;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
package de.luhmer.owncloudnewsreader.di;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Looper;
|
||||
import android.os.NetworkOnMainThreadException;
|
||||
import android.util.Log;
|
||||
|
||||
import com.nextcloud.android.sso.aidl.NextcloudRequest;
|
||||
import com.nextcloud.android.sso.api.NetworkRequest;
|
||||
import com.nextcloud.android.sso.api.NextcloudAPI;
|
||||
import com.nextcloud.android.sso.exceptions.NextcloudHttpRequestFailedException;
|
||||
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
import de.luhmer.owncloudnewsreader.helper.GsonConfig;
|
||||
import de.luhmer.owncloudnewsreader.reader.nextcloud.API;
|
||||
import de.luhmer.owncloudnewsreader.ssl.MemorizingTrustManager;
|
||||
import retrofit2.NextcloudRetrofitApiBuilder;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
|
||||
public class TestApiProvider extends ApiProvider {
|
||||
|
||||
private static final String TAG = TestApiProvider.class.getCanonicalName();
|
||||
|
||||
public static final String NEW_FEED_SUCCESS = "http://test.de/new";
|
||||
public static final String NEW_FEED_EXISTING = "http://test.de/existing";
|
||||
public static final String NEW_FEED_FAIL = "http://test.de/fail";
|
||||
private static final String NEW_FEED_EXISTING_ERROR_MESSAGE = "{\"message\":\"Feed konnte nicht hinzugef\\u00fcgt werden: Existiert bereits\"}";
|
||||
private static final String NEW_FEED_FAIL_ERROR_MESSAGE = "{\"message\":\"FeedIo\\\\Adapter\\\\NotFoundException: Client error: `GET http:\\/\\/feeds2.feedburner.com\\/stadt-bremerhaven\\/dqXM222` resulted in a `404 Feed not found error: FeedBurner cannot locate this feed URI.` response:\\n\\u003Chtml\\u003E\\n\\u003Chead\\u003E\\n\\u003Cstyle type=\\\"text\\/css\\\"\\u003E\\na:link, a:visited {\\n color: #000099;\\n text-decoration: underline;\\n}\\n\\na:hover {\\n (truncated...)\\n in \\/apps2\\/news\\/lib\\/Fetcher\\/Client\\/FeedIoClient.php:57\\nStack trace:\\n#0 \\/apps2\\/news\\/vendor\\/debril\\/feed-io\\/src\\/FeedIo\\/Reader.php(116): OCA\\\\News\\\\Fetcher\\\\Client\\\\FeedIoClient-\\u003EgetResponse('http:\\/\\/feeds2.f...', Object(DateTime))\\n#1 \\/apps2\\/news\\/vendor\\/debril\\/feed-io\\/src\\/FeedIo\\/FeedIo.php(286): FeedIo\\\\Reader-\\u003Eread('http:\\/\\/feeds2.f...', Object(FeedIo\\\\Feed), Object(DateTime))\\n#2 \\/apps2\\/news\\/lib\\/Fetcher\\/FeedFetcher.php(77): FeedIo\\\\FeedIo-\\u003Eread('http:\\/\\/feeds2.f...')\\n#3 \\/apps2\\/news\\/lib\\/Fetcher\\/Fetcher.php(68): OCA\\\\News\\\\Fetcher\\\\FeedFetcher-\\u003Efetch('http:\\/\\/feeds2.f...', true, NULL, NULL, NULL)\\n#4 \\/apps2\\/news\\/lib\\/Service\\/FeedService.php(116): OCA\\\\News\\\\Fetcher\\\\Fetcher-\\u003Efetch('http:\\/\\/feeds2.f...', true, NULL, NULL, NULL)\\n#5 \\/apps2\\/news\\/lib\\/Controller\\/FeedApiController.php(96): OCA\\\\News\\\\Service\\\\FeedService-\\u003Ecreate('http:\\/\\/feeds2.f...', 0, 'david')\\n#6 \\/nextcloud\\/lib\\/private\\/AppFramework\\/Http\\/Dispatcher.php(166): OCA\\\\News\\\\Controller\\\\FeedApiController-\\u003Ecreate('http:\\/\\/feeds2.f...', 0)\\n#7 \\/nextcloud\\/lib\\/private\\/AppFramework\\/Http\\/Dispatcher.php(99): OC\\\\AppFramework\\\\Http\\\\Dispatcher-\\u003EexecuteController(Object(OCA\\\\News\\\\Controller\\\\FeedApiController), 'create')\\n#8 \\/nextcloud\\/lib\\/private\\/AppFramework\\/App.php(118): OC\\\\AppFramework\\\\Http\\\\Dispatcher-\\u003Edispatch(Object(OCA\\\\News\\\\Controller\\\\FeedApiController), 'create')\\n#9 \\/nextcloud\\/lib\\/private\\/AppFramework\\/Routing\\/RouteActionHandler.php(47): OC\\\\AppFramework\\\\App::main('OCA\\\\\\\\News\\\\\\\\Contro...', 'create', Object(OC\\\\AppFramework\\\\DependencyInjection\\\\DIContainer), Array)\\n#10 [internal function]: OC\\\\AppFramework\\\\Routing\\\\RouteActionHandler-\\u003E__invoke(Array)\\n#11 \\/nextcloud\\/lib\\/private\\/Route\\/Router.php(297): call_user_func(Object(OC\\\\AppFramework\\\\Routing\\\\RouteActionHandler), Array)\\n#12 \\/nextcloud\\/lib\\/base.php(987): OC\\\\Route\\\\Router-\\u003Ematch('\\/apps\\/news\\/api\\/...')\\n#13 \\/nextcloud\\/index.php(42): OC::handleRequest()\\n#14 {main}\"}";
|
||||
|
||||
|
||||
public NewsTestNetworkRequest networkRequestSpy;
|
||||
|
||||
TestApiProvider(MemorizingTrustManager mtm, SharedPreferences sp, Context context) {
|
||||
super(mtm, sp, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initSsoApi(final NextcloudAPI.ApiConnectedListener callback) {
|
||||
NewsTestNetworkRequest networkRequest = new NewsTestNetworkRequest(callback);
|
||||
networkRequestSpy = Mockito.spy(networkRequest);
|
||||
|
||||
// By spying on the method "performNetworkRequest" we can later check if requests were build correctly
|
||||
try {
|
||||
Mockito.doCallRealMethod().when(networkRequestSpy).performNetworkRequest(any(), any());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
NextcloudAPI nextcloudAPI = new NextcloudAPI(GsonConfig.GetGson(), networkRequestSpy);
|
||||
mApi = new NextcloudRetrofitApiBuilder(nextcloudAPI, API.mApiEndpoint).create(API.class);
|
||||
}
|
||||
|
||||
|
||||
class NewsTestNetworkRequest extends NetworkRequest {
|
||||
|
||||
NewsTestNetworkRequest(NextcloudAPI.ApiConnectedListener callback) {
|
||||
super(null, null, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void connect() {
|
||||
super.connect();
|
||||
mCallback.onConnected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream performNetworkRequest(NextcloudRequest request, InputStream requestBodyInputStream) throws Exception {
|
||||
if(Looper.myLooper() == Looper.getMainLooper()) {
|
||||
throw new NetworkOnMainThreadException();
|
||||
}
|
||||
|
||||
Log.w(TAG, "Requested URL: " + request.getUrl());
|
||||
InputStream inputStream;
|
||||
switch (request.getUrl()) {
|
||||
case "/index.php/apps/news/api/v1-2/feeds":
|
||||
inputStream = handleCreateFeed(request);
|
||||
break;
|
||||
default:
|
||||
throw new UnsupportedOperationException("Not implemented yet!");
|
||||
}
|
||||
return inputStream;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// https://github.com/nextcloud/news/blob/master/docs/externalapi/Legacy.md#create-a-feed
|
||||
private InputStream handleCreateFeed(NextcloudRequest request) throws NextcloudHttpRequestFailedException {
|
||||
switch (request.getParameter().get("url")) {
|
||||
case NEW_FEED_SUCCESS:
|
||||
return stringToInputStream("");
|
||||
case NEW_FEED_EXISTING:
|
||||
throw new NextcloudHttpRequestFailedException(409, new Throwable(NEW_FEED_EXISTING_ERROR_MESSAGE));
|
||||
case NEW_FEED_FAIL:
|
||||
throw new NextcloudHttpRequestFailedException(422, new Throwable(NEW_FEED_FAIL_ERROR_MESSAGE));
|
||||
default:
|
||||
throw new UnsupportedOperationException("Not implemented yet!");
|
||||
}
|
||||
}
|
||||
|
||||
private InputStream stringToInputStream(String data) {
|
||||
return new ByteArrayInputStream(data.getBytes(Charset.forName("UTF-8")));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package de.luhmer.owncloudnewsreader.di;
|
||||
|
||||
import com.nextcloud.android.sso.api.NewFeedTests;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import dagger.Component;
|
||||
|
||||
@Singleton
|
||||
@Component(modules = { ApiModule.class })
|
||||
public interface TestComponent extends AppComponent {
|
||||
void inject(NewFeedTests test);
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
package de.luhmer.owncloudnewsreader.tests;
|
||||
|
||||
import android.support.test.filters.LargeTest;
|
||||
import android.support.test.rule.ActivityTestRule;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
import androidx.test.filters.LargeTest;
|
||||
import androidx.test.rule.ActivityTestRule;
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.runner.RunWith;
|
||||
|
|
|
@ -4,14 +4,14 @@ import android.content.SharedPreferences;
|
|||
import android.os.Bundle;
|
||||
import android.os.SystemClock;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.test.espresso.Espresso;
|
||||
import android.support.test.espresso.contrib.RecyclerViewActions;
|
||||
import android.support.test.espresso.matcher.ViewMatchers;
|
||||
import android.support.test.filters.LargeTest;
|
||||
import android.support.test.rule.ActivityTestRule;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import androidx.test.espresso.Espresso;
|
||||
import androidx.test.espresso.contrib.RecyclerViewActions;
|
||||
import androidx.test.espresso.matcher.ViewMatchers;
|
||||
import androidx.test.filters.LargeTest;
|
||||
import androidx.test.rule.ActivityTestRule;
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
|
@ -27,17 +27,19 @@ import de.luhmer.owncloudnewsreader.NewsReaderListActivity;
|
|||
import de.luhmer.owncloudnewsreader.R;
|
||||
import de.luhmer.owncloudnewsreader.adapter.NewsListRecyclerAdapter;
|
||||
import de.luhmer.owncloudnewsreader.adapter.ViewHolder;
|
||||
import helper.OrientationChangeAction;
|
||||
import helper.RecyclerViewAssertions;
|
||||
|
||||
import static android.support.test.InstrumentationRegistry.getInstrumentation;
|
||||
import static android.support.test.InstrumentationRegistry.registerInstance;
|
||||
import static android.support.test.espresso.Espresso.onView;
|
||||
import static android.support.test.espresso.action.ViewActions.click;
|
||||
import static android.support.test.espresso.assertion.ViewAssertions.doesNotExist;
|
||||
import static android.support.test.espresso.assertion.ViewAssertions.matches;
|
||||
import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
|
||||
import static android.support.test.espresso.matcher.ViewMatchers.isRoot;
|
||||
import static android.support.test.espresso.matcher.ViewMatchers.withEffectiveVisibility;
|
||||
import static android.support.test.espresso.matcher.ViewMatchers.withId;
|
||||
import static androidx.test.InstrumentationRegistry.getInstrumentation;
|
||||
import static androidx.test.InstrumentationRegistry.registerInstance;
|
||||
import static androidx.test.espresso.Espresso.onView;
|
||||
import static androidx.test.espresso.action.ViewActions.click;
|
||||
import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist;
|
||||
import static androidx.test.espresso.assertion.ViewAssertions.matches;
|
||||
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
|
||||
import static androidx.test.espresso.matcher.ViewMatchers.isRoot;
|
||||
import static androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility;
|
||||
import static androidx.test.espresso.matcher.ViewMatchers.withId;
|
||||
import static junit.framework.TestCase.assertNotNull;
|
||||
import static junit.framework.TestCase.fail;
|
||||
|
||||
|
@ -154,9 +156,9 @@ public class NewsReaderListActivityUiTests {
|
|||
sleep(0.5f);
|
||||
|
||||
if(!testFirstPosition) {
|
||||
onView(withId(android.support.design.R.id.snackbar_text)).check(matches(isDisplayed()));
|
||||
onView(withId(com.google.android.material.R.id.snackbar_text)).check(matches(isDisplayed()));
|
||||
} else {
|
||||
onView(withId(android.support.design.R.id.snackbar_text)).check(doesNotExist());
|
||||
onView(withId(com.google.android.material.R.id.snackbar_text)).check(doesNotExist());
|
||||
}
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
|
|
|
@ -6,41 +6,50 @@ import android.content.Intent;
|
|||
import android.content.SharedPreferences;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.test.InstrumentationRegistry;
|
||||
import android.support.test.filters.LargeTest;
|
||||
import android.support.test.rule.ActivityTestRule;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import androidx.test.InstrumentationRegistry;
|
||||
import androidx.test.filters.LargeTest;
|
||||
import androidx.test.rule.ActivityTestRule;
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
import de.luhmer.owncloudnewsreader.NewsReaderListActivity;
|
||||
import de.luhmer.owncloudnewsreader.R;
|
||||
import de.luhmer.owncloudnewsreader.helper.ThemeChooser;
|
||||
|
||||
import static android.preference.PreferenceManager.KEY_HAS_SET_DEFAULT_VALUES;
|
||||
import static android.support.test.InstrumentationRegistry.getInstrumentation;
|
||||
import static android.support.test.espresso.Espresso.onData;
|
||||
import static android.support.test.espresso.Espresso.onView;
|
||||
import static android.support.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu;
|
||||
import static android.support.test.espresso.action.ViewActions.click;
|
||||
import static android.support.test.espresso.assertion.ViewAssertions.matches;
|
||||
import static android.support.test.espresso.matcher.PreferenceMatchers.withKey;
|
||||
import static android.support.test.espresso.matcher.PreferenceMatchers.withSummary;
|
||||
import static android.support.test.espresso.matcher.PreferenceMatchers.withTitle;
|
||||
import static android.support.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed;
|
||||
import static android.support.test.espresso.matcher.ViewMatchers.withContentDescription;
|
||||
import static android.support.test.espresso.matcher.ViewMatchers.withText;
|
||||
import static androidx.test.InstrumentationRegistry.getInstrumentation;
|
||||
import static androidx.test.espresso.Espresso.onData;
|
||||
import static androidx.test.espresso.Espresso.onView;
|
||||
import static androidx.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu;
|
||||
import static androidx.test.espresso.action.ViewActions.click;
|
||||
import static androidx.test.espresso.assertion.ViewAssertions.matches;
|
||||
import static androidx.test.espresso.matcher.PreferenceMatchers.withKey;
|
||||
import static androidx.test.espresso.matcher.PreferenceMatchers.withSummary;
|
||||
import static androidx.test.espresso.matcher.PreferenceMatchers.withTitle;
|
||||
import static androidx.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed;
|
||||
import static androidx.test.espresso.matcher.ViewMatchers.withContentDescription;
|
||||
import static androidx.test.espresso.matcher.ViewMatchers.withId;
|
||||
import static androidx.test.espresso.matcher.ViewMatchers.withText;
|
||||
import static de.luhmer.owncloudnewsreader.SettingsActivity.CB_OLED_MODE;
|
||||
import static de.luhmer.owncloudnewsreader.SettingsActivity.SP_APP_THEME;
|
||||
import static helper.CustomMatchers.withBackgroundColor;
|
||||
import static junit.framework.TestCase.assertTrue;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.core.AllOf.allOf;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@LargeTest
|
||||
|
@ -58,14 +67,43 @@ public class NightModeTest {
|
|||
return mActivityRule.getActivity();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void resetSharedPrefs() {
|
||||
Context context = getInstrumentation().getTargetContext();
|
||||
SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
|
||||
// Reset SharedPrefs
|
||||
// https://developer.android.com/guide/topics/ui/settings#Defaults
|
||||
mPrefs.edit()
|
||||
.remove(CB_OLED_MODE)
|
||||
.remove(SP_APP_THEME)
|
||||
.commit();
|
||||
|
||||
assertThat(mPrefs.contains(SP_APP_THEME), equalTo(false));
|
||||
assertThat(mPrefs.contains(CB_OLED_MODE), equalTo(false));
|
||||
|
||||
|
||||
SharedPreferences defaultValueSp = context.getSharedPreferences(KEY_HAS_SET_DEFAULT_VALUES, Context.MODE_PRIVATE);
|
||||
defaultValueSp.edit().putBoolean(KEY_HAS_SET_DEFAULT_VALUES, false).commit();
|
||||
|
||||
|
||||
/*
|
||||
// Set Fixed time
|
||||
Instant.now(
|
||||
Clock.fixed(
|
||||
Instant.parse( "2019-04-05T18:00:00Z"), ZoneOffset.UTC
|
||||
)
|
||||
);
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testBackgroundDaylightTheme() {
|
||||
public void testBackgroundDaylightTheme() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
|
||||
launchActivity();
|
||||
|
||||
// Type text and then press the button.
|
||||
boolean isDarkTheme = ThemeChooser.getInstance(getActivity()).isDarkTheme(getActivity());
|
||||
assertThat(isDarkTheme, equalTo(false));
|
||||
//onView(withId(R.id.sliding_layout)).check(ViewAssertions.matches(CustomMatchers.withBackgroundColor(android.R.color.white, getActivity())));
|
||||
assertFalse(isDarkTheme());
|
||||
onView(withId(R.id.sliding_layout)).check(matches(withBackgroundColor(android.R.color.white, getActivity())));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -78,14 +116,12 @@ public class NightModeTest {
|
|||
sleep();
|
||||
switchOled();
|
||||
navigateUp();
|
||||
boolean isDarkTheme = ThemeChooser.getInstance(getActivity()).isDarkTheme(getActivity());
|
||||
assertFalse(isDarkTheme);
|
||||
assertFalse(isDarkTheme());
|
||||
|
||||
sleep();
|
||||
|
||||
//onView(withId(R.id.sliding_layout)).check(ViewAssertions.matches(CustomMatchers.withBackgroundColor(android.R.color.white, getActivity())));
|
||||
assertThat(ThemeChooser.getInstance(getActivity()).OLEDActive, equalTo(false));
|
||||
assertThat(ThemeChooser.getInstance(getActivity()).DarkThemeActive, equalTo(false));
|
||||
assertEquals(ThemeChooser.THEME.LIGHT, getPrivateField("mSelectedTheme"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -98,12 +134,11 @@ public class NightModeTest {
|
|||
changeAppTheme(R.string.pref_display_apptheme_light);
|
||||
navigateUp();
|
||||
|
||||
boolean isDarkTheme = ThemeChooser.getInstance(getActivity()).isDarkTheme(getActivity());
|
||||
assertThat(ThemeChooser.getInstance(getActivity()).isOledMode(getActivity(), false), equalTo(false));
|
||||
assertThat(isDarkTheme, equalTo(false));
|
||||
assertThat(ThemeChooser.getInstance(getActivity()).OLEDActive, equalTo(false));
|
||||
assertThat(ThemeChooser.getInstance(getActivity()).DarkThemeActive, equalTo(false));
|
||||
sleep();
|
||||
boolean isDarkTheme = isDarkTheme();
|
||||
assertFalse(ThemeChooser.getInstance(getActivity()).isOledMode(getActivity(), false));
|
||||
assertFalse(isDarkTheme);
|
||||
assertEquals(ThemeChooser.THEME.LIGHT, getPrivateField("mSelectedTheme"));
|
||||
//sleep();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -116,12 +151,11 @@ public class NightModeTest {
|
|||
changeAppTheme(R.string.pref_display_apptheme_dark);
|
||||
navigateUp();
|
||||
sleep();
|
||||
boolean isDarkTheme = ThemeChooser.getInstance(getActivity()).isDarkTheme(getActivity());
|
||||
boolean isDarkTheme = isDarkTheme();
|
||||
assertThat(ThemeChooser.getInstance(getActivity()).isOledMode(getActivity(), false), equalTo(false));
|
||||
assertThat(isDarkTheme, equalTo(true));
|
||||
assertThat(ThemeChooser.getInstance(getActivity()).OLEDActive, equalTo(false));
|
||||
assertThat(ThemeChooser.getInstance(getActivity()).DarkThemeActive, equalTo(true));
|
||||
sleep();
|
||||
assertEquals(ThemeChooser.THEME.DARK, getPrivateField("mSelectedTheme"));
|
||||
//sleep();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -135,12 +169,11 @@ public class NightModeTest {
|
|||
switchOled();
|
||||
navigateUp();
|
||||
sleep();
|
||||
boolean isDarkTheme = ThemeChooser.getInstance(getActivity()).isDarkTheme(getActivity());
|
||||
assertThat(ThemeChooser.getInstance(getActivity()).isOledMode(getActivity(), false), equalTo(true));
|
||||
assertThat(isDarkTheme, equalTo(true));
|
||||
assertThat(ThemeChooser.getInstance(getActivity()).OLEDActive, equalTo(true));
|
||||
assertThat(ThemeChooser.getInstance(getActivity()).DarkThemeActive, equalTo(true));
|
||||
sleep();
|
||||
boolean isDarkTheme = isDarkTheme();
|
||||
assertTrue(ThemeChooser.getInstance(getActivity()).isOledMode(getActivity(), false));
|
||||
assertTrue(isDarkTheme);
|
||||
assertEquals(ThemeChooser.THEME.OLED, getPrivateField("mSelectedTheme"));
|
||||
//sleep();
|
||||
}
|
||||
|
||||
private void sleep() {
|
||||
|
@ -185,25 +218,7 @@ public class NightModeTest {
|
|||
.perform(click());
|
||||
}
|
||||
|
||||
@Before
|
||||
public void resetSharedPrefs() {
|
||||
Context context = getInstrumentation().getTargetContext();
|
||||
SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
|
||||
// Reset SharedPrefs
|
||||
// https://developer.android.com/guide/topics/ui/settings#Defaults
|
||||
mPrefs.edit()
|
||||
.remove(CB_OLED_MODE)
|
||||
.remove(SP_APP_THEME)
|
||||
.commit();
|
||||
|
||||
assertThat(mPrefs.contains(SP_APP_THEME), equalTo(false));
|
||||
assertThat(mPrefs.contains(CB_OLED_MODE), equalTo(false));
|
||||
|
||||
|
||||
SharedPreferences defaultValueSp = context.getSharedPreferences(KEY_HAS_SET_DEFAULT_VALUES, Context.MODE_PRIVATE);
|
||||
defaultValueSp.edit().putBoolean(KEY_HAS_SET_DEFAULT_VALUES, false).commit();
|
||||
}
|
||||
|
||||
|
||||
private void launchActivity() {
|
||||
|
@ -222,4 +237,36 @@ public class NightModeTest {
|
|||
//assertFalse(ThemeChooser.getInstance(getActivity()).isDarkTheme(getActivity()));
|
||||
//assertFalse(ThemeChooser.getInstance(getActivity()).isOledMode(getActivity(), true));
|
||||
}
|
||||
|
||||
private boolean isDarkTheme() {
|
||||
ThemeChooser themeChooser = ThemeChooser.getInstance(getActivity());
|
||||
|
||||
try {
|
||||
Method method = ThemeChooser.class.getDeclaredMethod("isDarkTheme", Context.class);
|
||||
method.setAccessible(true);
|
||||
boolean isDarkTheme = (boolean) method.invoke(themeChooser, getActivity());
|
||||
return isDarkTheme;
|
||||
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
|
||||
fail(e.toString() + " - " + e.getMessage());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private Object getPrivateField(String fieldName) {
|
||||
ThemeChooser themeChooser = ThemeChooser.getInstance(getActivity());
|
||||
|
||||
try {
|
||||
Field[] fields = ThemeChooser.class.getDeclaredFields();
|
||||
for (Field field : fields) {
|
||||
if(fieldName.equals(field.getName())) {
|
||||
field.setAccessible(true);
|
||||
return field.get(themeChooser);
|
||||
}
|
||||
}
|
||||
} catch (IllegalAccessException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,162 +0,0 @@
|
|||
package de.luhmer.owncloudnewsreader.tests;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.test.InstrumentationRegistry;
|
||||
import android.support.test.filters.LargeTest;
|
||||
import android.support.test.rule.ActivityTestRule;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import de.luhmer.owncloudnewsreader.NewsReaderListActivity;
|
||||
import okhttp3.HttpUrl;
|
||||
import okhttp3.mockwebserver.MockResponse;
|
||||
import okhttp3.mockwebserver.MockWebServer;
|
||||
|
||||
import static android.support.test.InstrumentationRegistry.registerInstance;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@LargeTest
|
||||
public class SyncTests {
|
||||
|
||||
private MockWebServer server;
|
||||
//private HttpUrl baseUrl;
|
||||
|
||||
@Rule
|
||||
public ActivityTestRule<NewsReaderListActivity> mActivityRule = new ActivityTestRule<>(
|
||||
NewsReaderListActivity.class);
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
registerInstance(InstrumentationRegistry.getInstrumentation(), new Bundle());
|
||||
|
||||
// Create a MockWebServer. These are lean enough that you can create a new
|
||||
// instance for every unit test.
|
||||
server = new MockWebServer();
|
||||
server.start();
|
||||
// Ask the server for its URL. You'll need this to make HTTP requests.
|
||||
//baseUrl = server.url("/");
|
||||
|
||||
//HttpJsonRequest.init(mActivityRule.getActivity());
|
||||
//HttpJsonRequest.getInstance().setCredentials("test", "test", baseUrl.toString());
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@Test
|
||||
public void testVersionInfo() throws Exception {
|
||||
// Schedule some responses.
|
||||
server.enqueue(new MockResponse().setBody(getSampleVersionInfoV2()));
|
||||
|
||||
String versionNumber = OwnCloudReaderMethods.GetVersionNumber(baseUrl);
|
||||
assertEquals("5.2.3", versionNumber);
|
||||
|
||||
API api = API.GetRightApiForVersion(versionNumber, baseUrl);
|
||||
assertTrue(api instanceof APIv2);
|
||||
}
|
||||
*/
|
||||
|
||||
private String getSampleVersionInfoV2() {
|
||||
JsonObject jVer = new JsonObject();
|
||||
jVer.addProperty("version", "5.2.3");
|
||||
return jVer.toString();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@Test
|
||||
public void testFeedSync() throws Exception {
|
||||
|
||||
JsonObject jFeed = new JsonObject();
|
||||
JsonObject jF = new JsonObject();
|
||||
jF.addProperty("id", "-1");
|
||||
jF.addProperty("url", "");
|
||||
jF.addProperty("title", "-1");
|
||||
jF.addProperty("faviconLink", "-1");
|
||||
jF.addProperty("added", "-1");
|
||||
jF.addProperty("folderId", "-1");
|
||||
jF.addProperty("ordering", "-1"); //TODO implement this field!
|
||||
jF.addProperty("link", "-1");
|
||||
jF.addProperty("pinned", "-1");
|
||||
JsonArray jFeedArr = new JsonArray();
|
||||
jFeedArr.add(jF);
|
||||
jFeed.add("feeds", jFeedArr);
|
||||
|
||||
|
||||
server.enqueue(new MockResponse().setBody(getSampleVersionInfoV2()));
|
||||
server.enqueue(new MockResponse().setBody(jFeed.toString()));
|
||||
|
||||
String versionNumber = OwnCloudReaderMethods.GetVersionNumber(baseUrl);
|
||||
API api = API.GetRightApiForVersion(versionNumber, baseUrl);
|
||||
assertTrue(api instanceof APIv2);
|
||||
|
||||
int[] res = OwnCloudReaderMethods.GetFeeds(mActivity, api);
|
||||
assertEquals(1, res[0]);
|
||||
assertEquals(1, res[1]);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
@Test
|
||||
public void testItemSync() {
|
||||
JsonObject jItem = new JsonObject();
|
||||
JsonObject jI = new JsonObject();
|
||||
jI.addProperty("id", "-1");
|
||||
jI.addProperty("guid", "http://grulja.wordpress.com/?p=76");
|
||||
jI.addProperty("guidHash", "3059047a572cd9cd5d0bf645faffd077");
|
||||
jI.addProperty("url", "http://grulja.wordpress.com/2013/04/29/plasma-nm-after-the-solid-sprint/");
|
||||
jI.addProperty("title", "Plasma-nm after the solid sprint");
|
||||
jI.addProperty("author", "Jan Grulich (grulja)");
|
||||
jI.addProperty("pubDate", 1367270544);
|
||||
jI.addProperty("body", "<p>At first I have to say...</p>");
|
||||
jI.addProperty("enclosureMime", (String) null);
|
||||
jI.addProperty("enclosureLink", (String) null);
|
||||
jI.addProperty("feedId", "-1");
|
||||
jI.addProperty("unread", true);
|
||||
jI.addProperty("starred", false);
|
||||
jI.addProperty("lastModified", 1367273003);
|
||||
|
||||
JsonArray jItemArr = new JsonArray();
|
||||
jItemArr.add(jI);
|
||||
jItem.add("feeds", jItemArr);
|
||||
|
||||
|
||||
server.enqueue(new MockResponse().setBody(getSampleVersionInfoV2()));
|
||||
server.enqueue(new MockResponse().setBody(jItem.toString()));
|
||||
|
||||
/*
|
||||
String versionNumber = OwnCloudReaderMethods.GetVersionNumber(baseUrl);
|
||||
API api = API.GetRightApiForVersion(versionNumber, baseUrl);
|
||||
assertTrue(api instanceof APIv2);
|
||||
|
||||
int res2 = OwnCloudReaderMethods.GetItems(FeedItemTags.ALL, mActivity, "0", true, "0", "0", api); //TODO verify params
|
||||
assertEquals(1, res2);
|
||||
*/
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
// Shut down the server. Instances cannot be reused.
|
||||
server.shutdown();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
private void sleep(float seconds) {
|
||||
try {
|
||||
Thread.sleep((long) seconds * 1000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
package de.luhmer.owncloudnewsreader.tests;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import dagger.Provides;
|
||||
import de.luhmer.owncloudnewsreader.di.ApiModule;
|
||||
import de.luhmer.owncloudnewsreader.di.ApiProvider;
|
||||
import de.luhmer.owncloudnewsreader.ssl.MemorizingTrustManager;
|
||||
|
||||
public class TestApiModule extends ApiModule {
|
||||
|
||||
private Application mApplication;
|
||||
|
||||
public TestApiModule(Application application) {
|
||||
super(application);
|
||||
this.mApplication = application;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SharedPreferences providesSharedPreferences() {
|
||||
return Mockito.mock(SharedPreferences.class);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public ApiProvider provideAPI(MemorizingTrustManager mtm, SharedPreferences sp) {
|
||||
return new ApiProvider(mtm, sp, mApplication);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package de.luhmer.owncloudnewsreader.tests;
|
||||
package helper;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
|
@ -8,8 +8,8 @@ import android.graphics.drawable.ColorDrawable;
|
|||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.StateListDrawable;
|
||||
import android.os.Build;
|
||||
import android.support.test.espresso.matcher.BoundedMatcher;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import androidx.test.espresso.matcher.BoundedMatcher;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
|
@ -38,7 +38,7 @@ public class CustomMatchers {
|
|||
Drawable drawable = view.getBackground();
|
||||
Drawable otherDrawable = ContextCompat.getDrawable(view.getContext(), resourceColorId);
|
||||
|
||||
if (drawable instanceof ColorDrawable && otherDrawable instanceof ColorDrawable) {
|
||||
if (drawable instanceof ColorDrawable) {
|
||||
int colorId = ((ColorDrawable) drawable).getColor();
|
||||
|
||||
if(colorId == resourceColorId) {
|
||||
|
@ -47,7 +47,9 @@ public class CustomMatchers {
|
|||
error = "FAILED Got: " + colorId;
|
||||
}
|
||||
} else {
|
||||
error = "Not color drawables!!";
|
||||
Log.e(TAG, drawable.toString());
|
||||
Log.e(TAG, otherDrawable.toString());
|
||||
error = "Not ColorDrawable's!!";
|
||||
}
|
||||
|
||||
return false;
|
|
@ -23,21 +23,21 @@
|
|||
*
|
||||
*/
|
||||
|
||||
package de.luhmer.owncloudnewsreader.tests;
|
||||
package helper;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.support.test.espresso.UiController;
|
||||
import android.support.test.espresso.ViewAction;
|
||||
import android.support.test.runner.lifecycle.ActivityLifecycleMonitorRegistry;
|
||||
import android.support.test.runner.lifecycle.Stage;
|
||||
import androidx.test.espresso.UiController;
|
||||
import androidx.test.espresso.ViewAction;
|
||||
import androidx.test.runner.lifecycle.ActivityLifecycleMonitorRegistry;
|
||||
import androidx.test.runner.lifecycle.Stage;
|
||||
import android.view.View;
|
||||
|
||||
import org.hamcrest.Matcher;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import static android.support.test.espresso.matcher.ViewMatchers.isRoot;
|
||||
import static androidx.test.espresso.matcher.ViewMatchers.isRoot;
|
||||
|
||||
/**
|
||||
* An Espresso ViewAction that changes the orientation of the screen
|
|
@ -1,9 +1,9 @@
|
|||
package de.luhmer.owncloudnewsreader.tests;
|
||||
package helper;
|
||||
|
||||
import android.support.test.espresso.NoMatchingViewException;
|
||||
import android.support.test.espresso.ViewAssertion;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import androidx.test.espresso.NoMatchingViewException;
|
||||
import androidx.test.espresso.ViewAssertion;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import android.view.View;
|
||||
|
||||
public class RecyclerViewAssertions implements ViewAssertion {
|
|
@ -2,9 +2,9 @@ package screengrab;
|
|||
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.test.rule.ActivityTestRule;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
import android.support.v4.view.GravityCompat;
|
||||
import androidx.test.rule.ActivityTestRule;
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
import androidx.core.view.GravityCompat;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.ClassRule;
|
||||
|
@ -31,8 +31,10 @@ import tools.fastlane.screengrab.locale.LocaleTestRule;
|
|||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ScreenshotTest {
|
||||
|
||||
@ClassRule
|
||||
public static final LocaleTestRule localTestRule = new LocaleTestRule();
|
||||
|
||||
@Rule
|
||||
public ActivityTestRule<NewsReaderListActivity> mActivityRule = new ActivityTestRule<>(NewsReaderListActivity.class);
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
android:label="@string/app_name"
|
||||
android:launchMode="singleTop">
|
||||
<intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
|
@ -139,7 +139,7 @@
|
|||
android:label="@string/auto_sync_string"
|
||||
android:syncable="true" />
|
||||
<provider
|
||||
android:name="android.support.v4.content.FileProvider"
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="${applicationId}.provider"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
|
@ -205,7 +205,7 @@
|
|||
</intent-filter>
|
||||
</service> <!-- android:process=":podcastPlaybackService" -->
|
||||
|
||||
<receiver android:name="android.support.v4.media.session.MediaButtonReceiver">
|
||||
<receiver android:name="androidx.media.session.MediaButtonReceiver">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MEDIA_BUTTON" />
|
||||
<action android:name="android.media.AUDIO_BECOMING_NOISY" />
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package de.luhmer.owncloudnewsreader;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Created by benson on 11/20/15.
|
||||
|
|
|
@ -26,7 +26,6 @@ import android.content.Context;
|
|||
import android.content.SharedPreferences;
|
||||
import android.os.AsyncTask;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.v7.widget.ViewUtils;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
import android.view.LayoutInflater;
|
||||
|
@ -45,6 +44,7 @@ import android.widget.TextView;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.core.view.ViewCompat;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import de.luhmer.owncloudnewsreader.R;
|
||||
|
@ -333,7 +333,7 @@ public class SubscriptionExpandableListAdapter extends BaseExpandableListAdapter
|
|||
rotation = 180;
|
||||
contentDescriptionId = R.string.content_desc_collapse;
|
||||
} else {
|
||||
if (ViewUtils.isLayoutRtl(listView)) {
|
||||
if (ViewCompat.getLayoutDirection(listView) == ViewCompat.LAYOUT_DIRECTION_RTL) {
|
||||
rotation = -90; // mirror for rtl layout
|
||||
} else {
|
||||
rotation = 90;
|
||||
|
|
|
@ -30,9 +30,7 @@ import android.content.SharedPreferences;
|
|||
import android.content.SharedPreferences.Editor;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.design.widget.TextInputLayout;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import android.text.Editable;
|
||||
import android.text.InputType;
|
||||
import android.text.SpannableString;
|
||||
|
@ -54,6 +52,7 @@ import android.widget.Switch;
|
|||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.google.android.material.textfield.TextInputLayout;
|
||||
import com.nextcloud.android.sso.AccountImporter;
|
||||
import com.nextcloud.android.sso.api.NextcloudAPI;
|
||||
import com.nextcloud.android.sso.exceptions.NextcloudFilesAppNotInstalledException;
|
||||
|
@ -68,6 +67,7 @@ import java.net.URL;
|
|||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import de.luhmer.owncloudnewsreader.authentication.AuthenticatorActivity;
|
||||
|
|
|
@ -7,10 +7,6 @@ import android.content.Context;
|
|||
import android.content.Intent;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.util.Xml;
|
||||
|
@ -25,6 +21,8 @@ import android.widget.Toast;
|
|||
|
||||
import com.nbsp.materialfilepicker.ui.FilePickerActivity;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
|
@ -43,6 +41,10 @@ import java.util.Map;
|
|||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
|
@ -255,11 +257,7 @@ public class NewFeedActivity extends AppCompatActivity {
|
|||
}
|
||||
}
|
||||
|
||||
final Map<String, Object> feedMap = new HashMap<>(2);
|
||||
feedMap.put("url", feedUrl);
|
||||
feedMap.put("folderId", folderId);
|
||||
|
||||
Feed feed = mApi.getAPI().createFeed(feedMap).execute().body().get(0);
|
||||
Feed feed = mApi.getAPI().createFeed(feedUrl, folderId).execute().body().get(0);
|
||||
Log.v(TAG, "New Feed-ID: " + feed.getId());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
@ -336,36 +334,61 @@ public class NewFeedActivity extends AppCompatActivity {
|
|||
// perform the user login attempt.
|
||||
showProgress(true);
|
||||
|
||||
final Map<String, Object> feedMap = new HashMap<>(2);
|
||||
feedMap.put("url", urlToFeed);
|
||||
feedMap.put("folderId", folder.getId());
|
||||
mApi.getAPI().createFeed(feedMap).enqueue(new Callback<List<Feed>>() {
|
||||
mApi.getAPI().createFeed(urlToFeed, folder.getId()).enqueue(new Callback<List<Feed>>() {
|
||||
@Override
|
||||
public void onResponse(Call<List<Feed>> call, Response<List<Feed>> response) {
|
||||
showProgress(false);
|
||||
public void onResponse(Call<List<Feed>> call, final Response<List<Feed>> response) {
|
||||
runOnUiThread(() -> {
|
||||
showProgress(false);
|
||||
|
||||
if (response.isSuccessful()) {
|
||||
Intent returnIntent = new Intent();
|
||||
returnIntent.putExtra("success", true);
|
||||
setResult(RESULT_OK,returnIntent);
|
||||
if (response.isSuccessful()) {
|
||||
Intent returnIntent = new Intent();
|
||||
returnIntent.putExtra("success", true);
|
||||
setResult(RESULT_OK, returnIntent);
|
||||
|
||||
finish();
|
||||
} else {
|
||||
mFeedUrlView.setError(getString(R.string.login_dialog_text_something_went_wrong));
|
||||
mFeedUrlView.requestFocus();
|
||||
}
|
||||
finish();
|
||||
} else {
|
||||
try {
|
||||
String errorMessage = response.errorBody().string();
|
||||
try {
|
||||
//Log.e(TAG, errorMessage);
|
||||
JSONObject jObjError= new JSONObject(errorMessage);
|
||||
errorMessage = jObjError.getString("message");
|
||||
errorMessage = truncate(errorMessage, 150);
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG, "Extracting error message failed: " + errorMessage, e);
|
||||
}
|
||||
mFeedUrlView.setError(errorMessage);
|
||||
Log.e(TAG, errorMessage);
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "IOException", e);
|
||||
mFeedUrlView.setError(getString(R.string.login_dialog_text_something_went_wrong));
|
||||
}
|
||||
mFeedUrlView.requestFocus();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<List<Feed>> call, Throwable t) {
|
||||
showProgress(false);
|
||||
public void onFailure(Call<List<Feed>> call, final Throwable t) {
|
||||
runOnUiThread(() -> {
|
||||
showProgress(false);
|
||||
|
||||
mFeedUrlView.setError(getString(R.string.login_dialog_text_something_went_wrong) + " - " + OkHttpSSLClient.HandleExceptions((Exception) t).getMessage());
|
||||
mFeedUrlView.requestFocus();
|
||||
mFeedUrlView.setError(getString(R.string.login_dialog_text_something_went_wrong) + " - " + OkHttpSSLClient.HandleExceptions((Exception) t).getMessage());
|
||||
mFeedUrlView.requestFocus();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public static String truncate(String str, int len) {
|
||||
if (str.length() > len) {
|
||||
return str.substring(0, len) + "...";
|
||||
} else {
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isUrlValid(String url) {
|
||||
try {
|
||||
new URL(url);
|
||||
|
|
|
@ -29,15 +29,10 @@ import android.content.pm.ResolveInfo;
|
|||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.customtabs.CustomTabsIntent;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.FragmentPagerAdapter;
|
||||
import android.support.v4.app.FragmentStatePagerAdapter;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.support.v4.view.ViewPager.OnPageChangeListener;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import androidx.browser.customtabs.CustomTabsIntent;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import android.text.Html;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
|
@ -52,12 +47,17 @@ import java.util.HashSet;
|
|||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentPagerAdapter;
|
||||
import androidx.fragment.app.FragmentStatePagerAdapter;
|
||||
import androidx.viewpager.widget.PagerAdapter;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import de.luhmer.owncloudnewsreader.database.DatabaseConnectionOrm;
|
||||
import de.luhmer.owncloudnewsreader.database.DatabaseConnectionOrm.SORT_DIRECTION;
|
||||
import de.luhmer.owncloudnewsreader.database.model.RssItem;
|
||||
import de.luhmer.owncloudnewsreader.helper.PostDelayHandler;
|
||||
import de.luhmer.owncloudnewsreader.model.PodcastItem;
|
||||
import de.luhmer.owncloudnewsreader.model.TTSItem;
|
||||
import de.luhmer.owncloudnewsreader.widget.WidgetProvider;
|
||||
|
@ -66,12 +66,12 @@ public class NewsDetailActivity extends PodcastFragmentActivity {
|
|||
|
||||
private static final String TAG = NewsDetailActivity.class.getCanonicalName();
|
||||
/**
|
||||
* The {@link android.support.v4.view.PagerAdapter} that will provide
|
||||
* The {@link PagerAdapter} that will provide
|
||||
* fragments for each of the sections. We use a
|
||||
* {@link android.support.v4.app.FragmentPagerAdapter} derivative, which
|
||||
* {@link FragmentPagerAdapter} derivative, which
|
||||
* will keep every loaded fragment in memory. If this becomes too memory
|
||||
* intensive, it may be best to switch to a
|
||||
* {@link android.support.v4.app.FragmentStatePagerAdapter}.
|
||||
* {@link FragmentStatePagerAdapter}.
|
||||
*/
|
||||
private SectionsPagerAdapter mSectionsPagerAdapter;
|
||||
protected @BindView(R.id.toolbar) Toolbar toolbar;
|
||||
|
@ -169,7 +169,7 @@ public class NewsDetailActivity extends PodcastFragmentActivity {
|
|||
super.onDestroy();
|
||||
}
|
||||
|
||||
private OnPageChangeListener onPageChangeListener = new OnPageChangeListener() {
|
||||
private ViewPager.OnPageChangeListener onPageChangeListener = new ViewPager.OnPageChangeListener() {
|
||||
|
||||
@Override
|
||||
public void onPageSelected(int pos) {
|
||||
|
|
|
@ -28,11 +28,8 @@ import android.net.Uri;
|
|||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.customtabs.CustomTabsIntent;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentTransaction;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import androidx.browser.customtabs.CustomTabsIntent;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import android.util.Log;
|
||||
import android.view.ContextMenu;
|
||||
import android.view.LayoutInflater;
|
||||
|
@ -58,6 +55,9 @@ import java.net.URL;
|
|||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import de.luhmer.owncloudnewsreader.adapter.ProgressBarWebChromeClient;
|
||||
|
@ -269,11 +269,12 @@ public class NewsDetailFragment extends Fragment implements RssItemToHtmlTask.Li
|
|||
mTvOfflineVersion.setVisibility(View.GONE);
|
||||
switch (selectedBrowser) {
|
||||
case 0: // Custom Tabs
|
||||
CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
|
||||
builder.setToolbarColor(ContextCompat.getColor(getActivity(), R.color.colorPrimary));
|
||||
builder.setShowTitle(true);
|
||||
builder.setStartAnimations(getActivity(), R.anim.slide_in_right, R.anim.slide_out_left);
|
||||
builder.setExitAnimations(getActivity(), R.anim.slide_in_left, R.anim.slide_out_right);
|
||||
CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder()
|
||||
.setToolbarColor(ContextCompat.getColor(getActivity(), R.color.colorPrimary))
|
||||
.setShowTitle(true)
|
||||
.setStartAnimations(getActivity(), R.anim.slide_in_right, R.anim.slide_out_left)
|
||||
.setExitAnimations(getActivity(), R.anim.slide_in_left, R.anim.slide_out_right)
|
||||
.addDefaultShareMenuItem();
|
||||
builder.build().launchUrl(getActivity(), Uri.parse(url));
|
||||
return true;
|
||||
case 1: // External Browser
|
||||
|
|
|
@ -16,8 +16,7 @@ import android.net.Uri;
|
|||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.support.v4.app.ActivityCompat;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
|
@ -41,10 +40,11 @@ import java.util.ArrayList;
|
|||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import de.luhmer.owncloudnewsreader.helper.NewsFileUtils;
|
||||
import de.luhmer.owncloudnewsreader.notification.NextcloudNotificationManager;
|
||||
|
||||
import static android.support.v4.content.PermissionChecker.checkSelfPermission;
|
||||
import static androidx.core.content.PermissionChecker.checkSelfPermission;
|
||||
|
||||
public class NewsDetailImageDialogFragment extends DialogFragment {
|
||||
|
||||
|
|
|
@ -10,6 +10,8 @@ import de.luhmer.owncloudnewsreader.helper.ForegroundListener;
|
|||
|
||||
public class NewsReaderApplication extends Application {
|
||||
|
||||
protected AppComponent mAppComponent;
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
|
@ -33,13 +35,7 @@ public class NewsReaderApplication extends Application {
|
|||
//mAppComponent = DaggerAppComponent.create();
|
||||
}
|
||||
|
||||
private AppComponent mAppComponent;
|
||||
|
||||
public AppComponent getAppComponent() {
|
||||
return mAppComponent;
|
||||
}
|
||||
|
||||
public void setAppComponent(AppComponent appComponent) {
|
||||
this.mAppComponent = appComponent;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,15 +32,12 @@ import android.os.Bundle;
|
|||
import android.os.Handler;
|
||||
import android.os.Parcelable;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v4.view.GestureDetectorCompat;
|
||||
import android.support.v4.widget.SwipeRefreshLayout;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.DefaultItemAnimator;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.support.v7.widget.helper.ItemTouchHelper;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.view.GestureDetectorCompat;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.DefaultItemAnimator;
|
||||
import androidx.recyclerview.widget.ItemTouchHelper;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.GestureDetector;
|
||||
|
@ -53,6 +50,9 @@ import android.widget.Toast;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import de.luhmer.owncloudnewsreader.adapter.NewsListRecyclerAdapter;
|
||||
|
@ -291,7 +291,7 @@ public class NewsReaderDetailFragment extends Fragment {
|
|||
ButterKnife.bind(this, rootView);
|
||||
|
||||
recyclerView.setHasFixedSize(true);
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false));
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity(), RecyclerView.VERTICAL, false));
|
||||
recyclerView.setItemAnimator(new DefaultItemAnimator());
|
||||
|
||||
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new NewsReaderItemTouchHelperCallback());
|
||||
|
|
|
@ -37,22 +37,13 @@ import android.net.Uri;
|
|||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.FragmentTransaction;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v4.view.GravityCompat;
|
||||
import android.support.v4.widget.DrawerLayout;
|
||||
import android.support.v4.widget.SwipeRefreshLayout;
|
||||
import android.support.v4.widget.ViewDragHelper;
|
||||
import android.support.v7.app.ActionBarDrawerToggle;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.view.GravityCompat;
|
||||
import androidx.appcompat.app.ActionBarDrawerToggle;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
|
@ -61,6 +52,7 @@ import android.widget.SearchView;
|
|||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
import com.nextcloud.android.sso.AccountImporter;
|
||||
import com.nextcloud.android.sso.api.NextcloudAPI;
|
||||
import com.nextcloud.android.sso.exceptions.NextcloudFilesAppAccountNotFoundException;
|
||||
|
@ -82,6 +74,14 @@ import java.lang.reflect.Field;
|
|||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import androidx.customview.widget.ViewDragHelper;
|
||||
import androidx.drawerlayout.widget.DrawerLayout;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import de.luhmer.owncloudnewsreader.ListView.SubscriptionExpandableListAdapter;
|
||||
|
@ -510,7 +510,7 @@ public class NewsReaderListActivity extends PodcastFragmentActivity implements
|
|||
// Setting android:TextColor to #000 in the light theme results in black on black
|
||||
// text on the Snackbar, set the text back to white,
|
||||
// TODO: find a cleaner way to do this
|
||||
TextView textView = snackbar.getView().findViewById(android.support.design.R.id.snackbar_text);
|
||||
TextView textView = snackbar.getView().findViewById(com.google.android.material.R.id.snackbar_text);
|
||||
textView.setTextColor(Color.WHITE);
|
||||
snackbar.show();
|
||||
}
|
||||
|
@ -918,15 +918,14 @@ public class NewsReaderListActivity extends PodcastFragmentActivity implements
|
|||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, final Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
|
||||
if(resultCode == RESULT_OK) {
|
||||
UpdateListView();
|
||||
getSlidingListFragment().ListViewNotifyDataSetChanged();
|
||||
if(resultCode == RESULT_OK) {
|
||||
UpdateListView();
|
||||
getSlidingListFragment().ListViewNotifyDataSetChanged();
|
||||
}
|
||||
|
||||
if(requestCode == RESULT_SETTINGS)
|
||||
{
|
||||
if(requestCode == RESULT_SETTINGS) {
|
||||
//Update settings of image Loader
|
||||
mApi.initApi(new NextcloudAPI.ApiConnectedListener() {
|
||||
@Override
|
||||
|
@ -984,7 +983,7 @@ public class NewsReaderListActivity extends PodcastFragmentActivity implements
|
|||
}
|
||||
|
||||
private void ensureCorrectTheme(Intent data) {
|
||||
SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
String oldListLayout = data.getStringExtra(SettingsActivity.SP_FEED_LIST_LAYOUT);
|
||||
String newListLayout = mPrefs.getString(SettingsActivity.SP_FEED_LIST_LAYOUT,"0");
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@ import android.app.Activity;
|
|||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.LayoutInflater;
|
||||
|
@ -28,6 +27,7 @@ import java.util.Map;
|
|||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import de.luhmer.owncloudnewsreader.database.DatabaseConnectionOrm;
|
||||
|
@ -42,7 +42,7 @@ import io.reactivex.functions.Consumer;
|
|||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
|
||||
public class NewsReaderListDialogFragment extends DialogFragment{
|
||||
public class NewsReaderListDialogFragment extends DialogFragment {
|
||||
|
||||
protected @Inject ApiProvider mApi;
|
||||
|
||||
|
|
|
@ -25,7 +25,6 @@ import android.content.Context;
|
|||
import android.content.SharedPreferences;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.util.Base64;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
|
@ -50,6 +49,7 @@ import java.io.Serializable;
|
|||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import de.luhmer.owncloudnewsreader.ListView.SubscriptionExpandableListAdapter;
|
||||
|
|
|
@ -4,8 +4,7 @@ import android.content.Context;
|
|||
import android.content.DialogInterface;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import android.text.InputFilter;
|
||||
import android.util.Log;
|
||||
import android.view.ContextThemeWrapper;
|
||||
|
@ -38,6 +37,7 @@ import java.lang.reflect.Field;
|
|||
import java.util.Arrays;
|
||||
import java.util.Locale;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
|
|
|
@ -11,13 +11,13 @@ import android.os.Bundle;
|
|||
import android.os.Handler;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ResultReceiver;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import android.support.v4.media.MediaBrowserCompat;
|
||||
import android.support.v4.media.session.MediaControllerCompat;
|
||||
import android.support.v4.media.session.MediaSessionCompat;
|
||||
import android.support.v4.view.GravityCompat;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import androidx.core.view.GravityCompat;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
import android.view.SurfaceView;
|
||||
|
|
|
@ -42,15 +42,14 @@ import android.preference.PreferenceFragment;
|
|||
import android.preference.PreferenceManager;
|
||||
import android.preference.TwoStatePreference;
|
||||
import android.provider.Settings;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.design.widget.AppBarLayout;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v7.widget.AppCompatCheckBox;
|
||||
import android.support.v7.widget.AppCompatCheckedTextView;
|
||||
import android.support.v7.widget.AppCompatEditText;
|
||||
import android.support.v7.widget.AppCompatRadioButton;
|
||||
import android.support.v7.widget.AppCompatSpinner;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.appcompat.widget.AppCompatCheckBox;
|
||||
import androidx.appcompat.widget.AppCompatCheckedTextView;
|
||||
import androidx.appcompat.widget.AppCompatEditText;
|
||||
import androidx.appcompat.widget.AppCompatRadioButton;
|
||||
import androidx.appcompat.widget.AppCompatSpinner;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
|
@ -59,6 +58,8 @@ import android.view.View;
|
|||
import android.widget.LinearLayout;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.google.android.material.appbar.AppBarLayout;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.List;
|
||||
|
||||
|
|
|
@ -7,9 +7,8 @@ import android.content.Context;
|
|||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
|
@ -18,6 +17,7 @@ import android.view.ViewGroup;
|
|||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ListView;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import de.luhmer.owncloudnewsreader.authentication.AccountGeneral;
|
||||
|
|
|
@ -5,10 +5,11 @@ import android.content.res.TypedArray;
|
|||
import android.graphics.Canvas;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
public class DividerItemDecoration extends RecyclerView.ItemDecoration {
|
||||
|
||||
private Drawable mDivider;
|
||||
|
@ -40,7 +41,7 @@ public class DividerItemDecoration extends RecyclerView.ItemDecoration {
|
|||
return;
|
||||
|
||||
if (!(parent.getLayoutManager() instanceof LinearLayoutManager) ||
|
||||
((LinearLayoutManager)parent.getLayoutManager()).getOrientation() != LinearLayoutManager.VERTICAL) {
|
||||
((LinearLayoutManager)parent.getLayoutManager()).getOrientation() != RecyclerView.VERTICAL) {
|
||||
throw new IllegalStateException(
|
||||
"DividerItemDecoration can only be used with a vertical LinearLayoutManager.");
|
||||
}
|
||||
|
|
|
@ -3,9 +3,6 @@ package de.luhmer.owncloudnewsreader.adapter;
|
|||
import android.content.SharedPreferences;
|
||||
import android.os.AsyncTask;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
|
@ -18,6 +15,9 @@ import java.util.ArrayList;
|
|||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import de.luhmer.owncloudnewsreader.R;
|
||||
import de.luhmer.owncloudnewsreader.SettingsActivity;
|
||||
import de.luhmer.owncloudnewsreader.database.DatabaseConnectionOrm;
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
package de.luhmer.owncloudnewsreader.adapter;
|
||||
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.View;
|
||||
import android.widget.ProgressBar;
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import de.luhmer.owncloudnewsreader.R;
|
||||
|
||||
public class ProgressViewHolder extends RecyclerView.ViewHolder {
|
||||
|
|
|
@ -5,9 +5,8 @@ import android.content.res.TypedArray;
|
|||
import android.graphics.Color;
|
||||
import android.graphics.Typeface;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import android.text.Html;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableString;
|
||||
|
@ -30,6 +29,7 @@ import org.greenrobot.eventbus.Subscribe;
|
|||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import de.luhmer.owncloudnewsreader.R;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package de.luhmer.owncloudnewsreader.authentication;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import de.luhmer.owncloudnewsreader.NewsReaderListActivity;
|
||||
import de.luhmer.owncloudnewsreader.R;
|
||||
|
|
|
@ -20,7 +20,7 @@ import android.content.IntentFilter;
|
|||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.net.Uri;
|
||||
import android.support.customtabs.CustomTabsService;
|
||||
import androidx.browser.customtabs.CustomTabsService;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ package de.luhmer.owncloudnewsreader.di;
|
|||
import android.app.Application;
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import com.google.gson.FieldNamingPolicy;
|
||||
import com.google.gson.Gson;
|
||||
|
|
|
@ -2,7 +2,7 @@ package de.luhmer.owncloudnewsreader.di;
|
|||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.support.annotation.NonNull;
|
||||
import androidx.annotation.NonNull;
|
||||
import android.util.Log;
|
||||
|
||||
import com.nextcloud.android.sso.api.NextcloudAPI;
|
||||
|
@ -14,6 +14,7 @@ import com.nostra13.universalimageloader.core.DisplayImageOptions;
|
|||
import com.nostra13.universalimageloader.core.ImageLoader;
|
||||
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import de.luhmer.owncloudnewsreader.SettingsActivity;
|
||||
import de.luhmer.owncloudnewsreader.helper.GsonConfig;
|
||||
import de.luhmer.owncloudnewsreader.reader.OkHttpImageDownloader;
|
||||
|
@ -35,9 +36,9 @@ public class ApiProvider {
|
|||
|
||||
private static final String TAG = ApiProvider.class.getCanonicalName();
|
||||
private final MemorizingTrustManager mMemorizingTrustManager;
|
||||
private final SharedPreferences mPrefs;
|
||||
private API mApi;
|
||||
private Context context;
|
||||
protected final SharedPreferences mPrefs;
|
||||
protected Context context;
|
||||
protected API mApi;
|
||||
|
||||
|
||||
public ApiProvider(MemorizingTrustManager mtm, SharedPreferences sp, Context context) {
|
||||
|
@ -89,7 +90,7 @@ public class ApiProvider {
|
|||
mApi = retrofit.create(API.class);
|
||||
}
|
||||
|
||||
private void initSsoApi(final NextcloudAPI.ApiConnectedListener callback) {
|
||||
protected void initSsoApi(final NextcloudAPI.ApiConnectedListener callback) {
|
||||
try {
|
||||
SingleSignOnAccount ssoAccount = SingleAccountHelper.getCurrentSingleSignOnAccount(context);
|
||||
NextcloudAPI nextcloudAPI = new NextcloudAPI(context, ssoAccount, GsonConfig.GetGson(), callback);
|
||||
|
@ -125,4 +126,9 @@ public class ApiProvider {
|
|||
public API getAPI() {
|
||||
return mApi;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public void setAPI(API api) {
|
||||
this.mApi = api;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import android.annotation.TargetApi;
|
|||
import android.content.Context;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
import android.support.annotation.WorkerThread;
|
||||
import androidx.annotation.WorkerThread;
|
||||
import android.text.TextUtils;
|
||||
import android.webkit.WebResourceResponse;
|
||||
|
||||
|
|
|
@ -22,11 +22,11 @@ package de.luhmer.owncloudnewsreader.helper;
|
|||
import android.content.res.Configuration;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceActivity;
|
||||
import android.support.annotation.LayoutRes;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.app.AppCompatDelegate;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AppCompatDelegate;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
|
|
@ -24,6 +24,8 @@ import android.util.AttributeSet;
|
|||
import android.util.TypedValue;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.appcompat.widget.AppCompatTextView;
|
||||
|
||||
/**
|
||||
* Text view that auto adjusts text size to fit within the view.
|
||||
* If the text size equals the minimum text size and still does not
|
||||
|
@ -32,7 +34,7 @@ import android.widget.TextView;
|
|||
* @author Chase Colburn
|
||||
* @since Apr 4, 2011
|
||||
*/
|
||||
public class AutoResizeTextView extends TextView {
|
||||
public class AutoResizeTextView extends AppCompatTextView {
|
||||
|
||||
// Minimum text size for this text view
|
||||
public static final float MIN_TEXT_SIZE = 20;
|
||||
|
|
|
@ -23,8 +23,8 @@ package de.luhmer.owncloudnewsreader.helper;
|
|||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v7.graphics.Palette;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.palette.graphics.Palette;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
|
|
|
@ -26,7 +26,7 @@ import android.content.Context;
|
|||
import android.content.SharedPreferences;
|
||||
import android.content.res.Configuration;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.v7.app.AppCompatDelegate;
|
||||
import androidx.appcompat.app.AppCompatDelegate;
|
||||
import android.util.Log;
|
||||
|
||||
import de.luhmer.owncloudnewsreader.R;
|
||||
|
|
|
@ -12,15 +12,17 @@ import android.graphics.BitmapFactory;
|
|||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.service.notification.StatusBarNotification;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import android.support.v4.content.FileProvider;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
import androidx.core.content.FileProvider;
|
||||
import android.support.v4.media.MediaDescriptionCompat;
|
||||
import android.support.v4.media.MediaMetadataCompat;
|
||||
import android.support.v4.media.session.MediaButtonReceiver;
|
||||
import android.support.v4.media.session.MediaControllerCompat;
|
||||
import android.support.v4.media.session.MediaSessionCompat;
|
||||
import android.support.v4.media.session.PlaybackStateCompat;
|
||||
|
||||
import androidx.media.session.MediaButtonReceiver;
|
||||
import androidx.media.app.NotificationCompat.MediaStyle;
|
||||
|
||||
import com.nostra13.universalimageloader.core.ImageLoader;
|
||||
import com.nostra13.universalimageloader.core.assist.ImageSize;
|
||||
|
||||
|
@ -199,7 +201,7 @@ public class NextcloudNotificationManager {
|
|||
boolean isPlaying = controller.getPlaybackState().getState() == PlaybackStateCompat.STATE_PLAYING;
|
||||
builder.addAction(getPlayPauseAction(context, isPlaying));
|
||||
|
||||
builder.setStyle(new android.support.v4.media.app.NotificationCompat.MediaStyle()
|
||||
builder.setStyle(new MediaStyle()
|
||||
//.setShowActionsInCompactView(0) // show only play/pause in compact view
|
||||
.setMediaSession(mediaSession.getSessionToken())
|
||||
.setShowCancelButton(true)
|
||||
|
|
|
@ -15,6 +15,8 @@ import okhttp3.ResponseBody;
|
|||
import retrofit2.Call;
|
||||
import retrofit2.http.Body;
|
||||
import retrofit2.http.DELETE;
|
||||
import retrofit2.http.Field;
|
||||
import retrofit2.http.FormUrlEncoded;
|
||||
import retrofit2.http.GET;
|
||||
import retrofit2.http.POST;
|
||||
import retrofit2.http.PUT;
|
||||
|
@ -54,8 +56,9 @@ public interface API {
|
|||
@POST("folders")
|
||||
Call<List<Folder>> createFolder(@Body Map<String, Object> folderMap);
|
||||
|
||||
@FormUrlEncoded
|
||||
@POST("feeds")
|
||||
Call<List<Feed>> createFeed(@Body Map<String, Object> feedMap);
|
||||
Call<List<Feed>> createFeed(@Field("url") String url, @Field("folderId") Long parentFolderID);
|
||||
|
||||
|
||||
@PUT("feeds/{feedId}/rename")
|
||||
|
|
|
@ -24,9 +24,9 @@ package de.luhmer.owncloudnewsreader.services;
|
|||
import android.app.NotificationManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.JobIntentService;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.app.JobIntentService;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
import android.util.Log;
|
||||
|
||||
import com.nostra13.universalimageloader.core.ImageLoader;
|
||||
|
|
|
@ -8,7 +8,7 @@ import android.content.Intent;
|
|||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
import android.util.Log;
|
||||
import android.webkit.ConsoleMessage;
|
||||
import android.webkit.ValueCallback;
|
||||
|
|
|
@ -6,7 +6,7 @@ import android.app.NotificationManager;
|
|||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
|
|
|
@ -8,12 +8,12 @@ import android.media.AudioManager;
|
|||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.ResultReceiver;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import android.support.v4.media.MediaBrowserCompat;
|
||||
import android.support.v4.media.MediaBrowserServiceCompat;
|
||||
import androidx.media.MediaBrowserServiceCompat;
|
||||
import android.support.v4.media.MediaMetadataCompat;
|
||||
import android.support.v4.media.session.MediaButtonReceiver;
|
||||
import androidx.media.session.MediaButtonReceiver;
|
||||
import android.support.v4.media.session.MediaSessionCompat;
|
||||
import android.support.v4.media.session.PlaybackStateCompat;
|
||||
import android.telephony.PhoneStateListener;
|
||||
|
|
|
@ -25,7 +25,7 @@ import android.app.ActivityManager;
|
|||
import android.app.ActivityManager.RunningServiceInfo;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.support.v4.app.JobIntentService;
|
||||
import androidx.core.app.JobIntentService;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
|
|
|
@ -31,9 +31,9 @@ import android.content.DialogInterface.OnCancelListener;
|
|||
import android.content.DialogInterface.OnClickListener;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import de.luhmer.owncloudnewsreader.R;
|
||||
|
||||
public class MemorizingDialogFragment extends DialogFragment
|
||||
|
|
|
@ -41,9 +41,7 @@ import android.graphics.BitmapFactory;
|
|||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
|
||||
|
@ -64,6 +62,8 @@ import javax.net.ssl.TrustManager;
|
|||
import javax.net.ssl.TrustManagerFactory;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import de.luhmer.owncloudnewsreader.R;
|
||||
|
||||
/**
|
||||
|
|
|
@ -3,6 +3,7 @@ package de.luhmer.owncloudnewsreader.ssl;
|
|||
import android.annotation.SuppressLint;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Build;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import com.google.gson.JsonParseException;
|
||||
|
||||
|
@ -29,7 +30,6 @@ import okhttp3.Interceptor;
|
|||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.internal.Util;
|
||||
import okhttp3.logging.HttpLoggingInterceptor;
|
||||
|
||||
/**
|
||||
|
@ -38,6 +38,7 @@ import okhttp3.logging.HttpLoggingInterceptor;
|
|||
|
||||
public class OkHttpSSLClient {
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
|
||||
public static OkHttpClient GetSslClient(HttpUrl baseUrl, String username, String password, SharedPreferences sp, MemorizingTrustManager mtm) {
|
||||
// set location of the keystore
|
||||
MemorizingTrustManager.setKeyStoreFile("private", "sslkeys.bks");
|
||||
|
@ -48,7 +49,7 @@ public class OkHttpSSLClient {
|
|||
OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder()
|
||||
.connectTimeout(30, TimeUnit.SECONDS)
|
||||
.readTimeout(30, TimeUnit.MINUTES)
|
||||
.addInterceptor(new AuthorizationInterceptor(baseUrl, Credentials.basic(username, password, Util.UTF_8)))
|
||||
.addInterceptor(new AuthorizationInterceptor(baseUrl, Credentials.basic(username, password, java.nio.charset.StandardCharsets.UTF_8)))
|
||||
.addInterceptor(interceptor);
|
||||
|
||||
// register MemorizingTrustManager for HTTPS
|
||||
|
|
|
@ -4,7 +4,7 @@ import android.app.Notification;
|
|||
import android.app.NotificationManager;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
import android.support.v4.media.MediaMetadataCompat;
|
||||
import android.support.v4.media.session.MediaSessionCompat;
|
||||
import android.support.v4.media.session.PlaybackStateCompat;
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
sothree:umanoParallaxOffset="100dp"
|
||||
sothree:umanoShadowHeight="4dp"> <!-- sothree:dragView="@+id/name" -->
|
||||
|
||||
<android.support.design.widget.CoordinatorLayout
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
android:id="@+id/coordinator_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
@ -53,7 +53,7 @@
|
|||
|
||||
</de.luhmer.owncloudnewsreader.view.ZoomableRelativeLayout>
|
||||
|
||||
</android.support.design.widget.CoordinatorLayout>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/podcast_frame"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_height="match_parent"
|
||||
|
@ -100,4 +100,4 @@
|
|||
android:id="@+id/toolbar_layout"
|
||||
layout="@layout/toolbar_layout" />
|
||||
|
||||
</android.support.design.widget.CoordinatorLayout>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
|
@ -1,4 +1,4 @@
|
|||
<android.support.design.widget.CoordinatorLayout
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_height="match_parent"
|
||||
|
@ -17,7 +17,7 @@
|
|||
sothree:umanoParallaxOffset="100dp"
|
||||
sothree:umanoDragView="@+id/name">
|
||||
|
||||
<android.support.v4.view.ViewPager
|
||||
<androidx.viewpager.widget.ViewPager
|
||||
android:id="@+id/pager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
|
@ -39,7 +39,7 @@
|
|||
android:paddingTop="4dp"
|
||||
android:textColor="#fff" />
|
||||
-->
|
||||
</android.support.v4.view.ViewPager>
|
||||
</androidx.viewpager.widget.ViewPager>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/podcast_frame"
|
||||
|
@ -74,4 +74,4 @@
|
|||
android:layoutDirection="ltr"
|
||||
style="?android:attr/progressBarStyleHorizontal" />
|
||||
|
||||
</android.support.design.widget.CoordinatorLayout>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
|
|
@ -10,12 +10,12 @@
|
|||
sothree:umanoParallaxOffset="100dp"
|
||||
sothree:umanoShadowHeight="4dp"> <!-- sothree:dragView="@+id/name" -->
|
||||
|
||||
<android.support.v4.widget.DrawerLayout
|
||||
<androidx.drawerlayout.widget.DrawerLayout
|
||||
android:id="@+id/drawer_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<android.support.design.widget.CoordinatorLayout
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
android:id="@+id/coordinator_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
@ -63,7 +63,7 @@
|
|||
|
||||
|
||||
|
||||
</android.support.design.widget.CoordinatorLayout>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/left_drawer"
|
||||
|
@ -71,7 +71,7 @@
|
|||
android:layout_height="match_parent"
|
||||
android:layout_gravity="start" />
|
||||
|
||||
</android.support.v4.widget.DrawerLayout>
|
||||
</androidx.drawerlayout.widget.DrawerLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/podcast_frame"
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
android:text="Use single sign on" />
|
||||
|
||||
|
||||
<android.support.design.widget.TextInputLayout
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/username_container"
|
||||
|
@ -36,9 +36,9 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<android.support.design.widget.TextInputLayout
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/username_container"
|
||||
|
@ -56,9 +56,9 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<android.support.design.widget.TextInputLayout
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/url_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
@ -78,7 +78,7 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imgView_ShowPassword"
|
||||
|
|
|
@ -4,19 +4,19 @@
|
|||
android:layout_height="match_parent"
|
||||
tools:showIn="@layout/activity_newsreader">
|
||||
|
||||
<android.support.v4.widget.SwipeRefreshLayout
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
android:id="@+id/swipeRefresh"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/list"
|
||||
style="?android:attr/textAppearanceLarge"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scrollbars="vertical" />
|
||||
|
||||
</android.support.v4.widget.SwipeRefreshLayout>
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_no_items_available"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.v7.widget.CardView
|
||||
<androidx.cardview.widget.CardView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
||||
|
@ -142,4 +142,4 @@
|
|||
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
||||
</android.support.v7.widget.CardView>
|
||||
</androidx.cardview.widget.CardView>
|
|
@ -1,13 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.design.widget.AppBarLayout
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<android.support.v7.widget.Toolbar
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:theme="@style/ToolbarTheme" />
|
||||
|
||||
</android.support.design.widget.AppBarLayout>
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
|
@ -20,4 +20,6 @@
|
|||
ANDROID_BUILD_MIN_SDK_VERSION=17
|
||||
ANDROID_BUILD_TARGET_SDK_VERSION=28
|
||||
ANDROID_BUILD_TOOLS_VERSION=28.0.3
|
||||
ANDROID_BUILD_SDK_VERSION=28
|
||||
ANDROID_BUILD_SDK_VERSION=28
|
||||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
Loading…
Reference in a new issue