Showing preview only (210K chars total). Download the full file or copy to clipboard to get everything.
Repository: FuckBoilerplate/RxSocialConnect-Android
Branch: 2.x
Commit: ea10cd91da53
Files: 84
Total size: 184.0 KB
Directory structure:
gitextract_6_iuv5ls/
├── .gitignore
├── LICENSE.txt
├── README.md
├── app/
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src/
│ ├── androidTest/
│ │ └── java/
│ │ └── org/
│ │ └── fuckboilerplate/
│ │ └── rxsocialconnect/
│ │ ├── ActivityTest.java
│ │ ├── FragmentTest.java
│ │ ├── RxSocialConnectInterceptorsTest.java
│ │ └── RxSocialConnectTest.java
│ └── main/
│ ├── AndroidManifest.xml
│ ├── java/
│ │ └── org/
│ │ └── fuckboilerplate/
│ │ └── rxsocialconnect/
│ │ ├── SampleApp.java
│ │ ├── StartActivity.java
│ │ ├── connections/
│ │ │ ├── ChooseActivityOrFragment.java
│ │ │ ├── ConnectionsActivity.java
│ │ │ ├── ConnectionsFragment.java
│ │ │ ├── Helper.java
│ │ │ └── HostActivityFragment.java
│ │ └── interceptors/
│ │ ├── InterceptorsActivity.java
│ │ └── Repository.java
│ └── res/
│ ├── layout/
│ │ ├── choose_activity_or_fragment.xml
│ │ ├── connections.xml
│ │ ├── host_activity_fragment.xml
│ │ ├── interceptors.xml
│ │ └── start_activity.xml
│ ├── values/
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ ├── values-v21/
│ │ └── styles.xml
│ └── values-w820dp/
│ └── dimens.xml
├── build.gradle
├── core/
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src/
│ ├── main/
│ │ ├── AndroidManifest.xml
│ │ ├── java/
│ │ │ └── org/
│ │ │ └── fuckboilerplate/
│ │ │ └── rx_social_connect/
│ │ │ ├── NotActiveTokenFoundException.java
│ │ │ ├── Response.java
│ │ │ ├── RxSocialConnect.java
│ │ │ ├── internal/
│ │ │ │ ├── ActivityConnect.java
│ │ │ │ ├── encryption/
│ │ │ │ │ ├── BuiltInEncryptor.java
│ │ │ │ │ ├── Encryptor.java
│ │ │ │ │ └── FileEncryptor.java
│ │ │ │ ├── persistence/
│ │ │ │ │ ├── Disk.java
│ │ │ │ │ ├── OAuth1AccessToken.java
│ │ │ │ │ ├── OAuth2AccessToken.java
│ │ │ │ │ └── TokenCache.java
│ │ │ │ └── services/
│ │ │ │ ├── OAuth1Service.java
│ │ │ │ ├── OAuth2Service.java
│ │ │ │ └── Service.java
│ │ │ └── query_string/
│ │ │ ├── QueryString.java
│ │ │ └── QueryStringStrategy.java
│ │ └── res/
│ │ ├── layout/
│ │ │ └── connection_activity.xml
│ │ └── values/
│ │ └── strings.xml
│ └── test/
│ └── java/
│ └── org/
│ └── fuckboilerplate/
│ └── rx_social_connect/
│ ├── OAuth2AccessTokenTest.java
│ ├── QueryStringTest.java
│ └── internal/
│ └── persistence/
│ └── TokenCacheTest.java
├── gradle/
│ └── wrapper/
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── gson_converter/
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src/
│ ├── main/
│ │ ├── AndroidManifest.xml
│ │ ├── java/
│ │ │ └── io/
│ │ │ └── victoralbertos/
│ │ │ └── rx_social_connect/
│ │ │ └── GsonConverter.java
│ │ └── res/
│ │ └── values/
│ │ └── strings.xml
│ └── test/
│ └── java/
│ └── io/
│ └── victoralbertos/
│ └── rx_social_connect/
│ └── ExampleUnitTest.java
├── okhttp_interceptors/
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src/
│ ├── main/
│ │ ├── AndroidManifest.xml
│ │ ├── java/
│ │ │ └── io/
│ │ │ └── victoralbertos/
│ │ │ └── rx_social_connect/
│ │ │ ├── OAuth1Interceptor.java
│ │ │ └── OAuth2Interceptor.java
│ │ └── res/
│ │ └── values/
│ │ └── strings.xml
│ └── test/
│ └── java/
│ └── io/
│ └── victoralbertos/
│ └── rx_social_connect/
│ ├── OAuth1TwitterInterceptorTest.java
│ ├── OAuth1YahooInterceptorTest.java
│ ├── OAuth2FacebookInterceptorTest.java
│ ├── OAuth2GoogleInterceptorTest.java
│ ├── OAuth2LinkedinInterceptorTest.java
│ └── base/
│ ├── OAuth1InterceptorTest.java
│ └── OAuth2InterceptorTest.java
└── settings.gradle
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
# Built application files
*.apk
*.ap_
# Files for the Dalvik VM
*.dex
# Java class files
*.class
# Generated files
bin/
gen/
# Gradle files
.gradle/
**/build/
# Local configuration file (sdk path, etc)
local.properties
# Proguard folder generated by Eclipse
proguard/
# Log Files
*.log
# Android Studio
.navigation/
.idea/
**/*.iml
# Android Studio captures folder
captures/
# .DS_Store files
**/.DS_Store
# Credentials
app/src/androidTest/java/org/fuckboilerplate/rxsocialconnect/Credentials.java
================================================
FILE: LICENSE.txt
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2016 Fuck Boilerplate
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: README.md
================================================
:warning: Deprecated :warning:
Use [SocialConnect](https://github.com/cookpad/SocialConnect) instead.
[](http://android-arsenal.com/details/1/3616)
OAuth RxJava extension for Android. iOS version is located at this [repository](https://github.com/FuckBoilerplate/RxSocialConnect-iOS).
# RxSocialConnect
RxSocialConnect simplifies the process of retrieving authorizations tokens from multiple social networks to a minimalist observable call, from any Fragment or Activity.
```java
OAuth20Service facebookService = //...
RxSocialConnect.with(fragmentOrActivity, facebookService)
.subscribe(response -> response.targetUI().showResponse(response.token()));
```
## Features:
* Webview implementation to handle the sequent steps of oauth process.
* Storage of tokens encrypted locally
* Automatic refreshing tokens taking care of expiration date.
* I/O operations performed on secondary threads and automatic sync with user interface on the main thread, thanks to [RxAndroid](https://github.com/ReactiveX/RxAndroid)
* Mayor social network supported, more than 16 providers; including Facebook, Twitter, GooglePlus, LinkedIn and so on. Indeed, it supports as many providers as [ScribeJava](https://github.com/scribejava/scribejava/tree/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples) does, because RxSocialConnect is a reactive-android wrapper around it.
* Honors the observable chain. [RxOnActivityResult](https://github.com/VictorAlbertos/RxActivityResult) allows RxSocialConnect to transform every oauth process into an observable for a wonderful chaining process.
## Setup
Add the JitPack repository in your build.gradle (top level module):
```gradle
allprojects {
repositories {
jcenter()
maven { url "https://jitpack.io" }
}
}
```
And add next dependencies in the build.gradle of android app module:
```gradle
dependencies {
compile 'com.github.VictorAlbertos.RxSocialConnect-Android:core:1.0.1-2.x'
compile 'io.reactivex.rxjava2:rxjava:2.0.5'
}
```
## Usage
Because RxSocialConnect uses RxActivityResult to deal with intent calls, all its requirements and features are inherited too.
Before attempting to use RxSocialConnect, you need to call `RxSocialConnect.register` in your Android `Application` class, supplying as parameter the current instance and an encryption key in order to save the tokens on disk encrypted, as long as an implementation of [JSONConverter](https://github.com/FuckBoilerplate/RxSocialConnect-Android/blob/master/core/src/main/java/org/fuckboilerplate/rx_social_connect/JSONConverter.java) interface.
Because RxSocialConnect uses internally [Jolyglot](https://github.com/VictorAlbertos/Jolyglot) to save on disk the tokens retrieved, you need to add one of the next dependency to gradle.
```gradle
dependencies {
// To use Gson
compile 'com.github.VictorAlbertos.Jolyglot:gson:0.0.3'
// To use Jackson
compile 'com.github.VictorAlbertos.Jolyglot:jackson:0.0.3'
// To use Moshi
compile 'com.github.VictorAlbertos.Jolyglot:moshi:0.0.3'
}
```
```java
public class SampleApp extends Application {
@Override public void onCreate() {
super.onCreate();
RxSocialConnect.register(this, "myEncryptionKey")
.using(new GsonSpeaker());
}
}
```
Every feature RxSocialConnect exposes can be accessed from both, an `activity` or a `fragment` instance.
**Limitation:**: Your fragments need to extend from `android.support.v4.app.Fragment` instead of `android.app.Fragment`, otherwise they won't be notified.
The generic type of the `observable` returned by RxSocialConnect when subscribing to any of its providers is always an instance of [Response](https://github.com/FuckBoilerplate/RxSocialConnect-Android/blob/master/core/src/main/java/org/fuckboilerplate/rx_social_connect/Response.java) class.
This instance holds a reference to the current Activity/Fragment, accessible calling `targetUI()` method. Because the original one may be recreated it would be unsafe calling it. Instead, you must call any method/variable of your Activity/Fragment from this instance encapsulated in the `response` instance.
Also, this instance holds a reference to the token.
### Retrieving tokens using OAuth1.
On social networks which use OAuth1 protocol to authenticate users (such us Twitter), you need to build a [OAuth10aService](https://github.com/scribejava/scribejava/blob/master/scribejava-core/src/main/java/com/github/scribejava/core/oauth/OAuth10aService.java) instance and pass it to RxSocialConnect.
```java
OAuth10aService twitterService = new ServiceBuilder()
.apiKey(consumerKey)
.apiSecret(consumerSecret)
.callback(callbackUrl)
.build(TwitterApi.instance());
RxSocialConnect.with(fragmentOrActivity, twitterService)
.subscribe(response -> {
OAuth1AccessToken token = response.token();
response.targetUI().showToken(token.getToken());
response.targetUI().showToken(token.getTokenSecret());
});
```
Once the OAuth1 process has been successfully completed, you can retrieve the cached token calling `RxSocialConnect.getTokenOAuth1(defaultApi10aClass)` -where `defaultApi10aClass` is the provider `class` used on the oauth1 process.
```java
RxSocialConnect.getTokenOAuth1(TwitterApi.class)
.subscribe(token -> showResponse(token),
error -> showError(error));
```
### Retrieving tokens using OAuth2.
On social networks which use OAuth2 protocol to authenticate users (such us Facebook, Google+ or LinkedIn), you need to build a [OAuth20Service](https://github.com/scribejava/scribejava/blob/master/scribejava-core/src/main/java/com/github/scribejava/core/oauth/OAuth20Service.java) instance and pass it to RxSocialConnect.
```java
OAuth20Service facebookService = new ServiceBuilder()
.apiKey(appId)
.apiSecret(appSecret)
.callback(callbackUrl)
.scope("public_profile")
.build(FacebookApi.instance());
RxSocialConnect.with(fragmentOrActivity, facebookService)
.subscribe(response -> {
OAuth2AccessToken token = response.token();
response.targetUI().showToken(token.getAccessToken());
});
```
Once the OAuth2 process has been successfully completed, you can retrieve the cached token calling `RxSocialConnect.getTokenOAuth2(defaultApi20Class)` -where `defaultApi20Class` is the provider `class` used on the oauth2 process.
```java
RxSocialConnect.getTokenOAuth2(FacebookApi.class)
.subscribe(token -> showResponse(token),
error -> showError(error));
```
### Token lifetime.
After retrieving the token, RxSocialConnect will save it on disk to return it on future calls without doing again the oauth process. This token only will be evicted from cache if it is a OAuth2AccessToken instance and its expiration time has been fulfilled.
But, if you need to close an specific connection (or delete the token from the disk for that matters), you can call `RxSocialConnect.closeConnection(baseApiClass)` at any time to evict the cached token -where `baseApiClass` is the provider `class` used on the oauth process.
```java
//Facebook
RxSocialConnect.closeConnection(FacebookApi.class)
.subscribe(_I -> showToast("Facebook disconnected"));
//Twitter
RxSocialConnect.closeConnection(TwitterApi.class)
.subscribe(_I -> showToast("Twitter disconnected"));
```
You can also close all the connections at once, calling `RxSocialConnect.closeConnections()`
```java
RxSocialConnect.closeConnections()
.subscribe(_I -> showToast("All disconnected"));
```
### OkHttp interceptors.
RxSocialConnect can be powered with [OkHttp](https://github.com/square/okhttp) (or [Retrofit](https://github.com/square/retrofit) for that matters) to bypass authentication header configuration when dealing with specific endpoints.
Using the interceptors provided by RxSocialConnect, it's a 0 configuration process to be able to reach any http resource from any api client (Facebook, Twitter, etc).
First of all, install RxSocialConnectInterceptors library using gradle:
```gradle
dependencies {
compile 'com.github.VictorAlbertos.RxSocialConnect-Android:okhttp_interceptors:1.0.1-2.x'
}
```
After you have retrieved a valid token -if you attempt to use these interceptors prior to retrieving a valid token a [NotActiveTokenFoundException](https://github.com/FuckBoilerplate/RxSocialConnect-Android/blob/master/core/src/main/java/org/fuckboilerplate/rx_social_connect/NotActiveTokenFoundException.java) will be thrown, you can now use [OAuth1Interceptor](https://github.com/FuckBoilerplate/RxSocialConnect-Android/blob/master/okhttp_interceptors/src/main/java/io/victoralbertos/rx_social_connect/OAuth1Interceptor.java) or [OAuth2Interceptor](https://github.com/FuckBoilerplate/RxSocialConnect-Android/blob/master/okhttp_interceptors/src/main/java/io/victoralbertos/rx_social_connect/OAuth2Interceptor.java) classes to bypass the authentication headers configuration, depending on the OAuth version of your social network of interest.
#### OAuth1Interceptor.
```java
OAuth10aService yahooService = //...
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new OAuth1Interceptor(yahooService))
.build();
//If using retrofit...
YahooApiRest yahooApiRest = new Retrofit.Builder()
.baseUrl("")
.client(client)
.build().create(YahooApiRest.class);
```
#### OAuth2Interceptor.
```java
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new OAuth2Interceptor(FacebookApi.class))
.build();
//If using retrofit...
FacebookApiRest facebookApiRest = new Retrofit.Builder()
.baseUrl("")
.client(client)
.build().create(FacebookApiRest.class);
```
Now you are ready to perform any http call against any api in the same way you would do it for no OAuth apis.
## Examples
* Social networks connections examples can be found [here](https://github.com/FuckBoilerplate/RxSocialConnect-Android/tree/master/app/src/main/java/org/fuckboilerplate/rxsocialconnect/connections).
* OkHttp interceptors examples can be found [here](https://github.com/FuckBoilerplate/RxSocialConnect-Android/tree/master/app/src/main/java/org/fuckboilerplate/rxsocialconnect/interceptors).
## Proguard
```
-dontwarn javax.xml.bind.DatatypeConverter
-dontwarn org.apache.commons.codec.**
-dontwarn com.ning.http.client.**
keep class org.fuckboilerplate.rx_social_connect.internal.persistence.OAuth1AccessToken {
<fields>;
}
-keep class org.fuckboilerplate.rx_social_connect.internal.persistence.OAuth2AccessToken {
<fields>;
}
```
## Credits
* Oauth core authentication: [ScribeJava](https://github.com/scribejava/scribejava)
## Author
**Víctor Albertos**
* <https://twitter.com/_victorAlbertos>
* <https://www.linkedin.com/in/victoralbertos>
* <https://github.com/VictorAlbertos>
## Another author's libraries using RxJava:
* [RxCache](https://github.com/VictorAlbertos/RxCache): Reactive caching library for Android and Java.
* [Mockery](https://github.com/VictorAlbertos/Mockery): Android and Java library for mocking and testing networking layers with built-in support for Retrofit
* [RxActivityResult](https://github.com/VictorAlbertos/RxActivityResult): A reactive-tiny-badass-vindictive library to break with the OnActivityResult implementation as it breaks the observables chain.
* [RxFcm](https://github.com/VictorAlbertos/RxFcm): RxJava extension for Android Firebase Cloud Messaging (aka fcm).
* [RxPaparazzo](https://github.com/FuckBoilerplate/RxPaparazzo): RxJava extension for Android to take images using camera and gallery.
================================================
FILE: app/.gitignore
================================================
/build
================================================
FILE: app/build.gradle
================================================
apply plugin: 'com.android.application'
apply plugin: 'me.tatarka.retrolambda'
buildscript {
repositories {
mavenCentral()
jcenter()
}
dependencies {
classpath 'me.tatarka:gradle-retrolambda:3.2.4'
}
}
android {
compileSdkVersion 25
buildToolsVersion "25.0.0"
defaultConfig {
applicationId "org.fuckboilerplate.rxsocialconnect"
minSdkVersion 18
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
lintOptions {
abortOnError false
}
packagingOptions {
exclude 'META-INF/maven/com.google.guava/guava/pom.properties'
exclude 'META-INF/maven/com.google.guava/guava/pom.xml'
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:25.1.1'
compile 'com.android.support:design:25.1.1'
compile project(':core')
compile project(':okhttp_interceptors')
compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
compile "com.github.VictorAlbertos.Jolyglot:gson:0.0.3"
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
compile 'com.android.support:support-annotations:25.1.1'
testCompile 'junit:junit:4.12'
androidTestCompile ("com.android.support.test:runner:0.5") {
exclude module: 'support-annotations'
}
androidTestCompile ("com.android.support.test:rules:0.5") {
exclude module: 'support-annotations'
}
androidTestCompile ("com.android.support.test.espresso:espresso-web:2.2.2") {
exclude module: 'support-annotations'
exclude module: 'support-v4'
exclude module: 'appcompat-v7'
exclude module: 'design'
exclude module: 'support-v13'
}
androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.2'
}
================================================
FILE: app/proguard-rules.pro
================================================
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /Users/victor/Documents/AndroidStudio/android_sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
================================================
FILE: app/src/androidTest/java/org/fuckboilerplate/rxsocialconnect/ActivityTest.java
================================================
/*
* Copyright 2016 FuckBoilerplate
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.fuckboilerplate.rxsocialconnect;
import android.support.test.rule.ActivityTestRule;
import org.fuckboilerplate.rxsocialconnect.connections.ConnectionsActivity;
import org.junit.Rule;
public class ActivityTest extends RxSocialConnectTest {
@Rule public ActivityTestRule<ConnectionsActivity> mActivityRule = new ActivityTestRule(ConnectionsActivity.class);
}
================================================
FILE: app/src/androidTest/java/org/fuckboilerplate/rxsocialconnect/FragmentTest.java
================================================
/*
* Copyright 2016 FuckBoilerplate
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.fuckboilerplate.rxsocialconnect;
import android.support.test.rule.ActivityTestRule;
import org.fuckboilerplate.rxsocialconnect.connections.HostActivityFragment;
import org.junit.Rule;
public class FragmentTest extends RxSocialConnectTest {
@Rule public ActivityTestRule<HostActivityFragment> mActivityRule = new ActivityTestRule(HostActivityFragment.class);
}
================================================
FILE: app/src/androidTest/java/org/fuckboilerplate/rxsocialconnect/RxSocialConnectInterceptorsTest.java
================================================
package org.fuckboilerplate.rxsocialconnect;
import android.support.test.espresso.matcher.BoundedMatcher;
import android.support.test.espresso.web.webdriver.DriverAtoms;
import android.support.test.espresso.web.webdriver.Locator;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.view.View;
import android.widget.TextView;
import org.fuckboilerplate.rxsocialconnect.interceptors.InterceptorsActivity;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.junit.FixMethodOrder;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
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.matches;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
import static android.support.test.espresso.web.sugar.Web.onWebView;
import static android.support.test.espresso.web.webdriver.DriverAtoms.findElement;
import static android.support.test.espresso.web.webdriver.DriverAtoms.webClick;
/**
* To run the test first revoke permissions app from Facebook user profile.
* Also, be aware that running these test will change the token value, so the unit tests of rx_social_connect_interceptors
* related with yahoo and facebook will fail because the token will not longer be valid. So you need to update the token value
* in the appropriate files after running this test.
*/
@RunWith(AndroidJUnit4.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class RxSocialConnectInterceptorsTest {
@Rule public ActivityTestRule<InterceptorsActivity> mActivityRule = new ActivityTestRule(InterceptorsActivity.class);
@Test public void _a1_Connect_With_Facebook() {
onView(withId(R.id.bt_connect_facebook)).perform(click());
waitTime();
onWebView()
.withElement(findElement(Locator.NAME, "email"))
.perform(DriverAtoms.webKeys(Credentials.EMAIL))
.withElement(findElement(Locator.NAME, "pass"))
.perform(DriverAtoms.webKeys(Credentials.PASSWORD))
.withElement(findElement(Locator.NAME, "login"))
.perform(webClick());
waitTime();
onWebView()
.withElement(findElement(Locator.NAME, "__CONFIRM__"))
.perform(webClick());
waitTime();
}
@Test public void _a2_Show_Profile_Facebook() {
onView(withId(R.id.tv_profile)).check(matches(shouldBeEmpty(true)));
onView(withId(R.id.bt_show_profile_facebook)).perform(click());
waitTime();
onView(withId(R.id.tv_profile)).check(matches(shouldBeEmpty(false)));
}
@Test public void _b1_Connect_With_Yahoo() {
onView(withId(R.id.bt_connect_yahoo)).perform(click());
waitTime();
onWebView()
.withElement(findElement(Locator.NAME, "username"))
.perform(DriverAtoms.webKeys(Credentials.EMAIL_YAHOO))
.withElement(findElement(Locator.NAME, "signin"))
.perform(webClick());
waitTime();
onWebView()
.withElement(findElement(Locator.NAME, "passwd"))
.perform(DriverAtoms.webKeys(Credentials.PASSWORD))
.withElement(findElement(Locator.NAME, "signin"))
.perform(webClick());
waitTime();
onWebView()
.withElement(findElement(Locator.NAME, "agree"))
.perform(webClick());
waitTime();
}
@Test public void _b2_Show_Profile_Yahoo() {
onView(withId(R.id.tv_profile)).check(matches(shouldBeEmpty(true)));
onView(withId(R.id.bt_show_profile_yahoo)).perform(click());
waitTime();
onView(withId(R.id.tv_profile)).check(matches(shouldBeEmpty(false)));
}
private Matcher<View> shouldBeEmpty(boolean shouldBeEmpty) {
return new BoundedMatcher<View, TextView>(TextView.class) {
@Override public void describeTo(Description description) {
description.appendText("no empty text: ");
}
@Override public boolean matchesSafely(TextView textView) {
String text = textView.getText().toString();
if (shouldBeEmpty) return text.isEmpty();
else return !text.isEmpty();
}
};
}
private void waitTime() {
try {Thread.sleep(3500);}
catch (InterruptedException e) { e.printStackTrace();}
}
}
================================================
FILE: app/src/androidTest/java/org/fuckboilerplate/rxsocialconnect/RxSocialConnectTest.java
================================================
/*
* Copyright 2016 FuckBoilerplate
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.fuckboilerplate.rxsocialconnect;
import android.os.RemoteException;
import android.support.test.InstrumentationRegistry;
import android.support.test.espresso.matcher.BoundedMatcher;
import android.support.test.espresso.web.webdriver.DriverAtoms;
import android.support.test.espresso.web.webdriver.Locator;
import android.support.test.runner.AndroidJUnit4;
import android.support.test.uiautomator.UiDevice;
import android.view.View;
import android.widget.TextView;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
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.matches;
import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
import static android.support.test.espresso.web.sugar.Web.onWebView;
import static android.support.test.espresso.web.webdriver.DriverAtoms.findElement;
import static android.support.test.espresso.web.webdriver.DriverAtoms.webClick;
/**
* Remove permissions for the app from facebook user profile before to run the test.
*/
@RunWith(AndroidJUnit4.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public abstract class RxSocialConnectTest {
@Test public void _a1_Connect_With_Facebook() {
onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(true)));
onView(withId(R.id.bt_facebook)).perform(click());
waitTime();
rotateDevice();
onWebView()
.withElement(findElement(Locator.NAME, "email"))
.perform(DriverAtoms.webKeys(Credentials.EMAIL))
.withElement(findElement(Locator.NAME, "pass"))
.perform(DriverAtoms.webKeys(Credentials.PASSWORD))
.withElement(findElement(Locator.NAME, "login"))
.perform(webClick())
.withElement(findElement(Locator.NAME, "__CONFIRM__"))
.perform(webClick());
waitTime();
onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(false)));
}
@Test public void _a2_Connected_Facebook() {
onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(true)));
onView(withId(R.id.bt_facebook)).perform(click());
waitTime();
onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(false)));
}
@Test public void _a3_Get_Token_Facebook() {
onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(true)));
onView(withId(R.id.bt_facebook_get_token)).perform(click());
waitTime();
onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(false)));
}
@Test public void _a4_Disconnect_Facebook() {
onView(withId(R.id.bt_facebook_disconnect)).perform(click());
waitTime();
}
@Test public void _a5_Get_Token_Error_Facebook() {
onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(true)));
onView(withId(R.id.bt_facebook_get_token)).perform(click());
waitTime();
onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(true)));
}
@Test public void _a6_Facebook_Does_Not_Store_Cookies() {
onView(withId(R.id.bt_facebook)).perform(click());
waitTime();
onView(withId(R.id.webview)).check(matches(isDisplayed()));
}
@Test public void _b1_Connect_With_Google() {
onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(true)));
onView(withId(R.id.bt_google)).perform(click());
waitTime();
rotateDevice();
onWebView()
.withElement(findElement(Locator.NAME, "Email"))
.perform(DriverAtoms.webKeys(Credentials.EMAIL))
.withElement(findElement(Locator.NAME, "signIn"))
.perform(webClick());
waitTime();
onWebView()
.withElement(findElement(Locator.NAME, "Passwd"))
.perform(DriverAtoms.webKeys(Credentials.PASSWORD))
.withElement(findElement(Locator.ID, "signIn"))
.perform(webClick());
waitTime();
onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(false)));
}
@Test public void _b2_Connected_Google() {
onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(true)));
onView(withId(R.id.bt_google)).perform(click());
waitTime();
onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(false)));
}
@Test public void _b3_Get_Token_Google() {
onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(true)));
onView(withId(R.id.bt_google_get_token)).perform(click());
waitTime();
onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(false)));
}
@Test public void _b4_Disconnect_Google() {
onView(withId(R.id.bt_google_disconnect)).perform(click());
waitTime();
}
@Test public void _b5_Get_Token_Error_Google() {
onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(true)));
onView(withId(R.id.bt_google_get_token)).perform(click());
waitTime();
onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(true)));
}
@Test public void _b6_Google_Does_Not_Store_Cookies() {
onView(withId(R.id.bt_google)).perform(click());
waitTime();
onView(withId(R.id.webview)).check(matches(isDisplayed()));
}
@Test public void _d1_Connect_With_LinkedIn() {
onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(true)));
onView(withId(R.id.bt_linkedin)).perform(click());
waitTime();
rotateDevice();
onWebView()
.withElement(findElement(Locator.NAME, "session_key"))
.perform(DriverAtoms.webKeys(Credentials.EMAIL))
.withElement(findElement(Locator.NAME, "session_password"))
.perform(DriverAtoms.webKeys(Credentials.PASSWORD))
.withElement(findElement(Locator.NAME, "authorize"))
.perform(webClick());
waitTime();
waitTime();
onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(false)));
}
@Test public void _d2_Connected_LinkedIn() {
onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(true)));
onView(withId(R.id.bt_linkedin)).perform(click());
waitTime();
onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(false)));
}
@Test public void _d3_Get_Token_LinkedIn() {
onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(true)));
onView(withId(R.id.bt_linkedin_get_token)).perform(click());
waitTime();
onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(false)));
}
@Test public void _d4_Disconnect_LinkedIn() {
onView(withId(R.id.bt_linkedin_disconnect)).perform(click());
waitTime();
}
@Test public void _d5_Get_Token_Error_LinkedIn() {
onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(true)));
onView(withId(R.id.bt_linkedin_get_token)).perform(click());
waitTime();
onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(true)));
}
@Test public void _d6_LinkedIn_Does_Not_Store_Cookies() {
onView(withId(R.id.bt_linkedin)).perform(click());
waitTime();
onView(withId(R.id.webview)).check(matches(isDisplayed()));
}
@Test public void _e1_Connect_With_Yahoo() {
onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(true)));
onView(withId(R.id.bt_yahoo)).perform(click());
waitTime();
rotateDevice();
onWebView()
.withElement(findElement(Locator.NAME, "username"))
.perform(DriverAtoms.webKeys(Credentials.EMAIL_YAHOO))
.withElement(findElement(Locator.NAME, "signin"))
.perform(webClick());
waitTime();
onWebView()
.withElement(findElement(Locator.NAME, "passwd"))
.perform(DriverAtoms.webKeys(Credentials.PASSWORD))
.withElement(findElement(Locator.NAME, "signin"))
.perform(webClick());
waitTime();
onWebView()
.withElement(findElement(Locator.NAME, "agree"))
.perform(webClick());
waitTime();
onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(false)));
}
@Test public void _e2_Connected_Yahoo() {
onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(true)));
onView(withId(R.id.bt_yahoo)).perform(click());
waitTime();
onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(false)));
}
@Test public void _e3_Get_Token_Yahoo() {
onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(true)));
onView(withId(R.id.bt_yahoo_get_token)).perform(click());
waitTime();
onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(false)));
}
@Test public void _e4_Disconnect_Yahoo() {
onView(withId(R.id.bt_yahoo_disconnect)).perform(click());
waitTime();
}
@Test public void _e5_Get_Token_Error_Yahoo() {
onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(true)));
onView(withId(R.id.bt_yahoo_get_token)).perform(click());
waitTime();
onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(true)));
}
@Test public void _e6_Yahoo_Does_Not_Store_Cookies() {
onView(withId(R.id.bt_yahoo)).perform(click());
waitTime();
onView(withId(R.id.webview)).check(matches(isDisplayed()));
}
//Twitter, github Can not be performed due to security restrictions.
//Exception: Caused by: java.lang.RuntimeException: Fatal exception checking document state: Evaluation: status: 13 value: {message=Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: "script-src https://abs.twimg.com https://abs-0.twimg.com https://twitter.com https://mobile.twitter.com".
//} hasMessage: true message: Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: "script-src https://abs.twimg.com https://abs-0.twimg.com https://twitter.com https://mobile.twitter.com".
private Matcher<View> shouldBeEmpty(boolean shouldBeEmpty) {
return new BoundedMatcher<View, TextView>(TextView.class) {
@Override public void describeTo(Description description) {
description.appendText("no empty text: ");
}
@Override public boolean matchesSafely(TextView textView) {
String text = textView.getText().toString();
if (shouldBeEmpty) return text.isEmpty();
else return !text.isEmpty();
}
};
}
private void waitTime() {
try {Thread.sleep(3500);}
catch (InterruptedException e) { e.printStackTrace();}
}
private void rotateDevice() {
UiDevice uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
try {
uiDevice.setOrientationLeft();
waitTime();
uiDevice.setOrientationNatural();
waitTime();
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
================================================
FILE: app/src/main/AndroidManifest.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.fuckboilerplate.rxsocialconnect">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:name=".SampleApp"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".StartActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".interceptors.InterceptorsActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar"/>
<activity
android:name=".connections.ChooseActivityOrFragment"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar"/>
<activity
android:name=".connections.ConnectionsActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar"/>
<activity
android:name=".connections.HostActivityFragment"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar"/>
</application>
</manifest>
================================================
FILE: app/src/main/java/org/fuckboilerplate/rxsocialconnect/SampleApp.java
================================================
package org.fuckboilerplate.rxsocialconnect;
import android.app.Application;
import io.victoralbertos.jolyglot.GsonSpeaker;
import org.fuckboilerplate.rx_social_connect.RxSocialConnect;
/**
* Created by victor on 17/05/16.
*/
public class SampleApp extends Application {
@Override public void onCreate() {
super.onCreate();
RxSocialConnect
.register(this, "myEncryptionKey")
.using(new GsonSpeaker());
}
}
================================================
FILE: app/src/main/java/org/fuckboilerplate/rxsocialconnect/StartActivity.java
================================================
package org.fuckboilerplate.rxsocialconnect;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import org.fuckboilerplate.rxsocialconnect.connections.ChooseActivityOrFragment;
import org.fuckboilerplate.rxsocialconnect.interceptors.InterceptorsActivity;
/**
* Created by victor on 24/05/16.
*/
public class StartActivity extends Activity {
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.start_activity);
findViewById(R.id.bt_connections).setOnClickListener(v ->
startActivity(new Intent(this, ChooseActivityOrFragment.class))
);
findViewById(R.id.bt_interceptors).setOnClickListener(v ->
startActivity(new Intent(this, InterceptorsActivity.class))
);
}
}
================================================
FILE: app/src/main/java/org/fuckboilerplate/rxsocialconnect/connections/ChooseActivityOrFragment.java
================================================
package org.fuckboilerplate.rxsocialconnect.connections;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import org.fuckboilerplate.rxsocialconnect.R;
/**
* Created by victor on 20/05/16.
*/
public class ChooseActivityOrFragment extends Activity {
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.choose_activity_or_fragment);
findViewById(R.id.bt_activity)
.setOnClickListener(v -> startActivity(new Intent(this, ConnectionsActivity.class)));
findViewById(R.id.bt_fragment)
.setOnClickListener(v -> startActivity(new Intent(this, HostActivityFragment.class)));
}
}
================================================
FILE: app/src/main/java/org/fuckboilerplate/rxsocialconnect/connections/ConnectionsActivity.java
================================================
package org.fuckboilerplate.rxsocialconnect.connections;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import com.github.scribejava.apis.FacebookApi;
import com.github.scribejava.apis.GitHubApi;
import com.github.scribejava.apis.GoogleApi20;
import com.github.scribejava.apis.LinkedInApi20;
import com.github.scribejava.apis.TwitterApi;
import com.github.scribejava.apis.YahooApi;
import org.fuckboilerplate.rx_social_connect.RxSocialConnect;
import org.fuckboilerplate.rxsocialconnect.R;
public class ConnectionsActivity extends AppCompatActivity {
private Helper helper;
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.connections);
helper = new Helper(this);
setUpTwitter();
setUpFacebook();
setUpGoogle();
setUpLinkedIn();
setUpYahoo();
setUpGithub();
findViewById(R.id.bt_all_disconnect).setOnClickListener(v -> helper.closeAllConnection());
}
private void setUpTwitter() {
findViewById(R.id.bt_twitter).setOnClickListener(v -> {
RxSocialConnect.with(ConnectionsActivity.this, helper.twitterService())
.subscribe(response -> response.targetUI().helper.showResponse(response.token()),
error -> helper.showError(error));
});
findViewById(R.id.bt_twitter_get_token).setOnClickListener(v -> helper.showTokenOAuth1(TwitterApi.class));
findViewById(R.id.bt_twitter_disconnect).setOnClickListener(v -> helper.closeConnection(TwitterApi.class));
}
private void setUpFacebook() {
findViewById(R.id.bt_facebook).setOnClickListener(v -> {
RxSocialConnect.with(ConnectionsActivity.this, helper.facebookService())
.subscribe(response -> response.targetUI().helper.showResponse(response.token()),
error -> helper.showError(error));
});
findViewById(R.id.bt_facebook_get_token).setOnClickListener(v -> helper.showTokenOAuth2(FacebookApi.class));
findViewById(R.id.bt_facebook_disconnect).setOnClickListener(v -> helper.closeConnection(FacebookApi.class));
}
private void setUpGoogle() {
findViewById(R.id.bt_google).setOnClickListener(v -> {
RxSocialConnect.with(ConnectionsActivity.this, helper.googleService())
.subscribe(response -> response.targetUI().helper.showResponse(response.token()),
error -> helper.showError(error));
});
findViewById(R.id.bt_google_get_token).setOnClickListener(v -> helper.showTokenOAuth2(GoogleApi20.class));
findViewById(R.id.bt_google_disconnect).setOnClickListener(v -> helper.closeConnection(GoogleApi20.class));
}
private void setUpLinkedIn() {
findViewById(R.id.bt_linkedin).setOnClickListener(v -> {
RxSocialConnect.with(ConnectionsActivity.this, helper.linkedinService())
.subscribe(response -> response.targetUI().helper.showResponse(response.token()),
error -> helper.showError(error));
});
findViewById(R.id.bt_linkedin_get_token).setOnClickListener(v -> helper.showTokenOAuth2(LinkedInApi20.class));
findViewById(R.id.bt_linkedin_disconnect).setOnClickListener(v -> helper.closeConnection(LinkedInApi20.class));
}
private void setUpYahoo() {
findViewById(R.id.bt_yahoo).setOnClickListener(v -> {
RxSocialConnect.with(ConnectionsActivity.this, helper.yahooService())
.subscribe(response -> response.targetUI().helper.showResponse(response.token()),
error -> helper.showError(error));
});
findViewById(R.id.bt_yahoo_get_token).setOnClickListener(v -> helper.showTokenOAuth1(YahooApi.class));
findViewById(R.id.bt_yahoo_disconnect).setOnClickListener(v -> helper.closeConnection(YahooApi.class));
}
private void setUpGithub() {
findViewById(R.id.bt_github).setOnClickListener(v -> {
RxSocialConnect.with(ConnectionsActivity.this, helper.githubService())
.subscribe(response -> response.targetUI().helper.showResponse(response.token()),
error -> helper.showError(error));
});
findViewById(R.id.bt_github_get_token).setOnClickListener(v -> helper.showTokenOAuth2(GitHubApi.class));
findViewById(R.id.bt_github_disconnect).setOnClickListener(v -> helper.closeConnection(GitHubApi.class));
}
}
================================================
FILE: app/src/main/java/org/fuckboilerplate/rxsocialconnect/connections/ConnectionsFragment.java
================================================
package org.fuckboilerplate.rxsocialconnect.connections;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.github.scribejava.apis.FacebookApi;
import com.github.scribejava.apis.GitHubApi;
import com.github.scribejava.apis.GoogleApi20;
import com.github.scribejava.apis.LinkedInApi20;
import com.github.scribejava.apis.TwitterApi;
import com.github.scribejava.apis.YahooApi;
import org.fuckboilerplate.rx_social_connect.RxSocialConnect;
import org.fuckboilerplate.rxsocialconnect.R;
public class ConnectionsFragment extends Fragment {
private Helper helper;
@Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.connections, container, false);
}
@Override public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
helper = new Helper(this);
setUpTwitter();
setUpFacebook();
setUpGoogle();
setUpLinkedIn();
setUpYahoo();
setUpGithub();
findViewById(R.id.bt_all_disconnect).setOnClickListener(v -> helper.closeAllConnection());
}
private void setUpTwitter() {
findViewById(R.id.bt_twitter).setOnClickListener(v -> {
RxSocialConnect.with(ConnectionsFragment.this, helper.twitterService())
.subscribe(response -> response.targetUI().helper.showResponse(response.token()),
error -> helper.showError(error));
});
findViewById(R.id.bt_twitter_get_token).setOnClickListener(v -> helper.showTokenOAuth1(TwitterApi.class));
findViewById(R.id.bt_twitter_disconnect).setOnClickListener(v -> helper.closeConnection(TwitterApi.class));
}
private void setUpFacebook() {
findViewById(R.id.bt_facebook).setOnClickListener(v -> {
RxSocialConnect.with(ConnectionsFragment.this, helper.facebookService())
.subscribe(response -> response.targetUI().helper.showResponse(response.token()),
error -> helper.showError(error));
});
findViewById(R.id.bt_facebook_get_token).setOnClickListener(v -> helper.showTokenOAuth2(FacebookApi.class));
findViewById(R.id.bt_facebook_disconnect).setOnClickListener(v -> helper.closeConnection(FacebookApi.class));
}
private void setUpGoogle() {
findViewById(R.id.bt_google).setOnClickListener(v -> {
RxSocialConnect.with(ConnectionsFragment.this, helper.googleService())
.subscribe(response -> response.targetUI().helper.showResponse(response.token()),
error -> helper.showError(error));
});
findViewById(R.id.bt_google_get_token).setOnClickListener(v -> helper.showTokenOAuth2(GoogleApi20.class));
findViewById(R.id.bt_google_disconnect).setOnClickListener(v -> helper.closeConnection(GoogleApi20.class));
}
private void setUpLinkedIn() {
findViewById(R.id.bt_linkedin).setOnClickListener(v -> {
RxSocialConnect.with(ConnectionsFragment.this, helper.linkedinService())
.subscribe(response -> response.targetUI().helper.showResponse(response.token()),
error -> helper.showError(error));
});
findViewById(R.id.bt_linkedin_get_token).setOnClickListener(v -> helper.showTokenOAuth2(LinkedInApi20.class));
findViewById(R.id.bt_linkedin_disconnect).setOnClickListener(v -> helper.closeConnection(LinkedInApi20.class));
}
private void setUpYahoo() {
findViewById(R.id.bt_yahoo).setOnClickListener(v -> {
RxSocialConnect.with(ConnectionsFragment.this, helper.yahooService())
.subscribe(response -> response.targetUI().helper.showResponse(response.token()),
error -> helper.showError(error));
});
findViewById(R.id.bt_yahoo_get_token).setOnClickListener(v -> helper.showTokenOAuth1(YahooApi.class));
findViewById(R.id.bt_yahoo_disconnect).setOnClickListener(v -> helper.closeConnection(YahooApi.class));
}
private void setUpGithub() {
findViewById(R.id.bt_github).setOnClickListener(v -> {
RxSocialConnect.with(ConnectionsFragment.this, helper.githubService())
.subscribe(response -> response.targetUI().helper.showResponse(response.token()),
error -> helper.showError(error));
});
findViewById(R.id.bt_github_get_token).setOnClickListener(v -> helper.showTokenOAuth2(GitHubApi.class));
findViewById(R.id.bt_github_disconnect).setOnClickListener(v -> helper.closeConnection(GitHubApi.class));
}
private View findViewById(int resId) {
return getView().findViewById(resId);
}
}
================================================
FILE: app/src/main/java/org/fuckboilerplate/rxsocialconnect/connections/Helper.java
================================================
package org.fuckboilerplate.rxsocialconnect.connections;
import android.app.Activity;
import android.content.Context;
import android.support.v4.app.Fragment;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import com.github.scribejava.apis.FacebookApi;
import com.github.scribejava.apis.GitHubApi;
import com.github.scribejava.apis.GoogleApi20;
import com.github.scribejava.apis.LinkedInApi20;
import com.github.scribejava.apis.TwitterApi;
import com.github.scribejava.apis.YahooApi;
import com.github.scribejava.core.builder.ServiceBuilder;
import com.github.scribejava.core.builder.api.BaseApi;
import com.github.scribejava.core.builder.api.DefaultApi10a;
import com.github.scribejava.core.builder.api.DefaultApi20;
import com.github.scribejava.core.model.OAuth1AccessToken;
import com.github.scribejava.core.model.OAuth2AccessToken;
import com.github.scribejava.core.oauth.OAuth10aService;
import com.github.scribejava.core.oauth.OAuth20Service;
import org.fuckboilerplate.rx_social_connect.RxSocialConnect;
import org.fuckboilerplate.rxsocialconnect.R;
public class Helper {
private final Object targetUI;
public Helper(Object targetUI) {
this.targetUI = targetUI;
}
OAuth10aService twitterService() {
String consumerKey = "3wEAwhjvJmBpJpUfIXiY9PQOg";
String consumerSecret = "8N47XdpE4GSlswMcBTOZFc3fDcil7WnK4RINfUyKf2d0rFrF2I";
String callbackUrl = "http://victoralbertos.com";
return new ServiceBuilder()
.apiKey(consumerKey)
.apiSecret(consumerSecret)
.callback(callbackUrl)
.build(TwitterApi.instance());
}
OAuth20Service facebookService() {
String appId = "452930454916873";
String appSecret = "4a643dd4c4537f01411ab7bb44736f1f";
String callbackUrl = "http://victoralbertos.com/";
String permissions = "public_profile, email";
return new ServiceBuilder()
.apiKey(appId)
.apiSecret(appSecret)
.callback(callbackUrl)
.scope(permissions)
.build(FacebookApi.instance());
}
OAuth20Service googleService() {
String clientId = "112202070176-3b8b2s85rtt39k6ga5f2001p937i57fq.apps.googleusercontent.com";
String clientSecret = "-zkjJwn3j_2JOyPSDHExJ6cO";
String callbackUrl = "http://victoralbertos.com/";
String permissions = "profile";
return new ServiceBuilder()
.apiKey(clientId)
.apiSecret(clientSecret)
.callback(callbackUrl)
.scope(permissions)
.build(GoogleApi20.instance());
}
OAuth20Service linkedinService() {
String clientId = "77u9plrpoq0g6t";
String clientSecret = "VlH229TNkzJysxbq";
String callbackUrl = "http://victoralbertos.com";
String permissions = "r_basicprofile";
return new ServiceBuilder()
.apiKey(clientId)
.apiSecret(clientSecret)
.callback(callbackUrl)
.scope(permissions)
.build(LinkedInApi20.instance());
}
OAuth10aService yahooService() {
String clientId = "dj0yJmk9Sk9NZUlPc0RaODVDJmQ9WVdrOVRubHlWMWRuTTJVbWNHbzlNQS0tJnM9Y29uc3VtZXJzZWNyZXQmeD0wNw--";
String clientSecret = "449b2d2f06d986297d65df7fc020544bf71eb10c";
String callbackUrl = "http://victoralbertos.com";
return new ServiceBuilder()
.apiKey(clientId)
.apiSecret(clientSecret)
.callback(callbackUrl)
.build(YahooApi.instance());
}
OAuth20Service githubService() {
String appId = "725a59980165855cc986";
String appSecret = "38733b4bf1c8646af86e38797f345847a0b61388";
String callbackUrl = "http://victoralbertos.com/";
return new ServiceBuilder()
.apiKey(appId)
.apiSecret(appSecret)
.callback(callbackUrl)
.build(GitHubApi.instance());
}
void showTokenOAuth1(Class<? extends DefaultApi10a> clazz) {
RxSocialConnect.getTokenOAuth1(clazz)
.subscribe(token -> showResponse(token),
error -> showError(error));
}
void showTokenOAuth2(Class<? extends DefaultApi20> clazz) {
RxSocialConnect.getTokenOAuth2(clazz)
.subscribe(token -> showResponse(token),
error -> showError(error));
}
void closeConnection(Class<? extends BaseApi> clazz) {
RxSocialConnect
.closeConnection(clazz)
.subscribe(_I -> {
showToast(clazz.getName() + " disconnected");
clearEditTexts();
}, error -> showError(error));
}
void closeAllConnection() {
RxSocialConnect
.closeConnections()
.subscribe(_I -> {
showToast("All disconnected");
clearEditTexts();
}, error -> showError(error));
}
void showResponse(OAuth1AccessToken token) {
clearEditTexts();
((TextView)findViewById(R.id.tv_token)).setText(token.getToken());
((TextView)findViewById(R.id.tv_secret)).setText(token.getTokenSecret());
}
void showResponse(OAuth2AccessToken token) {
clearEditTexts();
((TextView)findViewById(R.id.tv_token)).setText(token.getAccessToken());
}
private void clearEditTexts() {
((TextView)findViewById(R.id.tv_token)).setText("");
((TextView)findViewById(R.id.tv_secret)).setText("");
}
void showError(Throwable throwable) {
clearEditTexts();
showToast(throwable.getMessage());
}
private View findViewById(int resId) {
if (targetUI instanceof Activity) return ((Activity) targetUI).findViewById(resId);
else return ((Fragment) targetUI).getView().findViewById(resId);
}
private void showToast(String message) {
Toast.makeText(getContext(), message, Toast.LENGTH_LONG).show();
}
private Context getContext() {
if (targetUI instanceof Activity) return ((Activity) targetUI);
else return((Fragment) targetUI).getActivity();
}
}
================================================
FILE: app/src/main/java/org/fuckboilerplate/rxsocialconnect/connections/HostActivityFragment.java
================================================
package org.fuckboilerplate.rxsocialconnect.connections;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import org.fuckboilerplate.rxsocialconnect.R;
/**
* Created by victor on 20/05/16.
*/
public class HostActivityFragment extends AppCompatActivity {
@Override protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.host_activity_fragment);
}
}
================================================
FILE: app/src/main/java/org/fuckboilerplate/rxsocialconnect/interceptors/InterceptorsActivity.java
================================================
package org.fuckboilerplate.rxsocialconnect.interceptors;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
import android.widget.Toast;
import com.github.scribejava.core.model.OAuth1AccessToken;
import com.github.scribejava.core.model.OAuth2AccessToken;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import org.fuckboilerplate.rx_social_connect.RxSocialConnect;
import org.fuckboilerplate.rxsocialconnect.R;
public class InterceptorsActivity extends AppCompatActivity {
private Repository repository;
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.interceptors);
repository = new Repository();
setUpFacebook();
setUpYahoo();
}
private void setUpFacebook() {
findViewById(R.id.bt_connect_facebook).setOnClickListener(v ->
RxSocialConnect.with(this, repository.facebookService())
.subscribe(response -> response.targetUI().showToken(response.token()),
error -> showError(error))
);
findViewById(R.id.bt_show_profile_facebook).setOnClickListener(v ->
repository.getFacebookApi().me()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(user -> showUserProfile(user.toString()),
error -> showError(error))
);
}
private void setUpYahoo() {
findViewById(R.id.bt_connect_yahoo).setOnClickListener(v ->
RxSocialConnect.with(this, repository.yahooService())
.subscribe(response -> response.targetUI().showToken(response.token()),
error -> showError(error))
);
findViewById(R.id.bt_show_profile_yahoo).setOnClickListener(v ->
repository.getYahooApiRest().me()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(user -> showUserProfile(user.toString()),
error -> showError(error))
);
}
private void showUserProfile(String userProfileJSON) {
clearTextViewToken();
TextView tv_profile = (TextView) findViewById(R.id.tv_profile);
tv_profile.setText(userProfileJSON);
}
private void showToken(OAuth2AccessToken oAuth2AccessToken) {
clearTextViewToken();
Toast.makeText(this, oAuth2AccessToken.getAccessToken(), Toast.LENGTH_SHORT).show();
}
private void showToken(OAuth1AccessToken token) {
clearTextViewToken();
Toast.makeText(this, token.getToken(), Toast.LENGTH_SHORT).show();
}
private void showError(Throwable error) {
clearTextViewToken();
Toast.makeText(this, error.getMessage(), Toast.LENGTH_SHORT).show();
}
private void clearTextViewToken() {
((TextView) findViewById(R.id.tv_profile)).setText("");
}
}
================================================
FILE: app/src/main/java/org/fuckboilerplate/rxsocialconnect/interceptors/Repository.java
================================================
package org.fuckboilerplate.rxsocialconnect.interceptors;
import com.github.scribejava.apis.FacebookApi;
import com.github.scribejava.apis.YahooApi;
import com.github.scribejava.core.builder.ServiceBuilder;
import com.github.scribejava.core.oauth.OAuth10aService;
import com.github.scribejava.core.oauth.OAuth20Service;
import com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import io.reactivex.Observable;
import io.victoralbertos.rx_social_connect.OAuth1Interceptor;
import io.victoralbertos.rx_social_connect.OAuth2Interceptor;
import okhttp3.OkHttpClient;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.http.GET;
public class Repository {
private final YahooApiRest yahooApiRest;
private final FacebookApiRest facebookApi;
public Repository() {
yahooApiRest = initYahooApiRest();
facebookApi = initFacebookApiRest();
}
private FacebookApiRest initFacebookApiRest() {
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new OAuth2Interceptor(FacebookApi.class))
.build();
return new Retrofit.Builder()
.baseUrl(FacebookApiRest.URL_BASE)
.client(client)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build().create(FacebookApiRest.class);
}
private YahooApiRest initYahooApiRest() {
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new OAuth1Interceptor(yahooService()))
.build();
return new Retrofit.Builder()
.baseUrl(YahooApiRest.URL_BASE)
.client(client)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build().create(YahooApiRest.class);
}
FacebookApiRest getFacebookApi() {
return facebookApi;
}
YahooApiRest getYahooApiRest() {
return yahooApiRest;
}
interface YahooApiRest {
String URL_BASE = "https://social.yahooapis.com";
@GET("/v1/user/me/profile?format=json") Observable<Object> me();
}
interface FacebookApiRest {
String URL_BASE = "https://graph.facebook.com";
@GET("/v2.5/me")
Observable<Object> me();
}
OAuth20Service facebookService() {
String appId = "452930454916873";
String appSecret = "4a643dd4c4537f01411ab7bb44736f1f";
String callbackUrl = "http://victoralbertos.com/";
String permissions = "public_profile, email";
return new ServiceBuilder()
.apiKey(appId)
.apiSecret(appSecret)
.callback(callbackUrl)
.scope(permissions)
.build(FacebookApi.instance());
}
OAuth10aService yahooService() {
String clientId = "dj0yJmk9Sk9NZUlPc0RaODVDJmQ9WVdrOVRubHlWMWRuTTJVbWNHbzlNQS0tJnM9Y29uc3VtZXJzZWNyZXQmeD0wNw--";
String clientSecret = "449b2d2f06d986297d65df7fc020544bf71eb10c";
String callbackUrl = "http://victoralbertos.com";
return new ServiceBuilder()
.apiKey(clientId)
.apiSecret(clientSecret)
.callback(callbackUrl)
.build(YahooApi.instance());
}
}
================================================
FILE: app/src/main/res/layout/choose_activity_or_fragment.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/bt_activity"
android:text="Activity"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:id="@+id/bt_fragment"
android:text="Fragment"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
================================================
FILE: app/src/main/res/layout/connections.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
android:orientation="vertical">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Twitter: " />
<Button
android:id="@+id/bt_twitter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Connect" />
<Button
android:id="@+id/bt_twitter_get_token"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Get token" />
<Button
android:id="@+id/bt_twitter_disconnect"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Disconnect" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Facebook: " />
<Button
android:id="@+id/bt_facebook"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Connect" />
<Button
android:id="@+id/bt_facebook_get_token"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Get token" />
<Button
android:id="@+id/bt_facebook_disconnect"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Disconnect" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Google: " />
<Button
android:id="@+id/bt_google"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Connect" />
<Button
android:id="@+id/bt_google_get_token"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Get token" />
<Button
android:id="@+id/bt_google_disconnect"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Disconnect" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Linkedin: " />
<Button
android:id="@+id/bt_linkedin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Connect" />
<Button
android:id="@+id/bt_linkedin_get_token"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Get token" />
<Button
android:id="@+id/bt_linkedin_disconnect"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Disconnect" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Yahoo: " />
<Button
android:id="@+id/bt_yahoo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Connect" />
<Button
android:id="@+id/bt_yahoo_get_token"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Get token" />
<Button
android:id="@+id/bt_yahoo_disconnect"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Disconnect" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Github: " />
<Button
android:id="@+id/bt_github"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Connect" />
<Button
android:id="@+id/bt_github_get_token"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Get token" />
<Button
android:id="@+id/bt_github_disconnect"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Disconnect" />
</LinearLayout>
<TextView
android:id="@+id/tv_token"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tv_secret"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:id="@+id/bt_all_disconnect"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="All disconnect" />
</LinearLayout>
</ScrollView>
================================================
FILE: app/src/main/res/layout/host_activity_fragment.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="@+id/rxSocialConnectFragment"
android:name="org.fuckboilerplate.rxsocialconnect.connections.ConnectionsFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:layout="@layout/connections" />
</LinearLayout>
================================================
FILE: app/src/main/res/layout/interceptors.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Facebook" />
<Button
android:id="@+id/bt_connect_facebook"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Connect" />
<Button
android:id="@+id/bt_show_profile_facebook"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Show profile" />
</LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Yahoo" />
<Button
android:id="@+id/bt_connect_yahoo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Connect" />
<Button
android:id="@+id/bt_show_profile_yahoo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Show profile" />
</LinearLayout>
<TextView
android:id="@+id/tv_profile"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
================================================
FILE: app/src/main/res/layout/start_activity.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/bt_connections"
android:text="Connections"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:id="@+id/bt_interceptors"
android:text="Interceptors"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
================================================
FILE: app/src/main/res/values/colors.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#3F51B5</color>
<color name="colorPrimaryDark">#303F9F</color>
<color name="colorAccent">#FF4081</color>
</resources>
================================================
FILE: app/src/main/res/values/dimens.xml
================================================
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
<dimen name="fab_margin">16dp</dimen>
</resources>
================================================
FILE: app/src/main/res/values/strings.xml
================================================
<resources>
<string name="app_name">RxSocialConnect</string>
<string name="action_settings">Settings</string>
</resources>
================================================
FILE: app/src/main/res/values/styles.xml
================================================
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
<style name="AppTheme.NoActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
</resources>
================================================
FILE: app/src/main/res/values-v21/styles.xml
================================================
<resources>
<style name="AppTheme.NoActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:statusBarColor">@android:color/transparent</item>
</style>
</resources>
================================================
FILE: app/src/main/res/values-w820dp/dimens.xml
================================================
<resources>
<!-- Example customization of dimensions originally defined in res/values/dimens.xml
(such as screen margins) for screens with more than 820dp of available width. This
would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
<dimen name="activity_horizontal_margin">64dp</dimen>
</resources>
================================================
FILE: build.gradle
================================================
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.3'
classpath 'com.github.dcendents:android-maven-gradle-plugin:1.4.1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
jcenter()
maven { url "https://jitpack.io" }
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
================================================
FILE: core/.gitignore
================================================
/build
================================================
FILE: core/build.gradle
================================================
apply plugin: 'com.android.library'
apply plugin: 'com.github.dcendents.android-maven'
group='com.github.VictorAlbertos'
version='1.0.1-2.x'
android {
compileSdkVersion 25
buildToolsVersion "25.0.0"
defaultConfig {
minSdkVersion 16
targetSdkVersion 25
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
lintOptions {
abortOnError false
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:25.1.1'
compile 'com.github.scribejava:scribejava-apis:3.2.0'
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
compile 'io.reactivex.rxjava2:rxjava:2.0.6'
compile "com.github.VictorAlbertos:RxActivityResult:0.4.1-2.x"
compile 'com.github.VictorAlbertos.Jolyglot:api:0.0.3'
testCompile 'com.github.VictorAlbertos.Jolyglot:gson:0.0.3'
testCompile "org.mockito:mockito-core:1.10.19"
}
// build a jar with source files
task sourcesJar(type: Jar) {
from android.sourceSets.main.java.srcDirs
classifier = 'sources'
}
task javadoc(type: Javadoc) {
failOnError false
source = android.sourceSets.main.java.sourceFiles
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
classpath += configurations.compile
}
// build a jar with javadoc
task javadocJar(type: Jar, dependsOn: javadoc) {
classifier = 'javadoc'
from javadoc.destinationDir
}
artifacts {
archives sourcesJar
archives javadocJar
}
================================================
FILE: core/proguard-rules.pro
================================================
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /Users/victor/Documents/AndroidStudio/android_sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
================================================
FILE: core/src/main/AndroidManifest.xml
================================================
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.fuckboilerplate.rx_social_connect">
<application>
<activity
android:name=".internal.ActivityConnect"
android:label="@string/app_name"
android:theme="@style/Theme.AppCompat.NoActionBar"/>
</application>
</manifest>
================================================
FILE: core/src/main/java/org/fuckboilerplate/rx_social_connect/NotActiveTokenFoundException.java
================================================
/*
* Copyright 2016 FuckBoilerplate
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.fuckboilerplate.rx_social_connect;
public class NotActiveTokenFoundException extends RuntimeException {
public NotActiveTokenFoundException() {
super("There is no active token for the provider requested");
}
}
================================================
FILE: core/src/main/java/org/fuckboilerplate/rx_social_connect/Response.java
================================================
/*
* Copyright 2016 FuckBoilerplate
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.fuckboilerplate.rx_social_connect;
import com.github.scribejava.core.model.Token;
public final class Response<T, D extends Token> {
private final T targetUI;
private final D token;
public Response(T targetUI, D token) {
this.targetUI = targetUI;
this.token = token;
}
public T targetUI() {
return targetUI;
}
public D token() {
return token;
}
}
================================================
FILE: core/src/main/java/org/fuckboilerplate/rx_social_connect/RxSocialConnect.java
================================================
/*
* Copyright 2016 FuckBoilerplate
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.fuckboilerplate.rx_social_connect;
import android.app.Activity;
import android.app.Application;
import android.content.Intent;
import android.support.v4.app.Fragment;
import com.github.scribejava.core.builder.api.BaseApi;
import com.github.scribejava.core.builder.api.DefaultApi10a;
import com.github.scribejava.core.builder.api.DefaultApi20;
import com.github.scribejava.core.model.Token;
import com.github.scribejava.core.oauth.OAuth10aService;
import com.github.scribejava.core.oauth.OAuth20Service;
import com.github.scribejava.core.oauth.OAuthService;
import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.functions.Function;
import io.victoralbertos.jolyglot.Jolyglot;
import java.util.concurrent.Callable;
import org.fuckboilerplate.rx_social_connect.internal.ActivityConnect;
import org.fuckboilerplate.rx_social_connect.internal.persistence.OAuth1AccessToken;
import org.fuckboilerplate.rx_social_connect.internal.persistence.OAuth2AccessToken;
import org.fuckboilerplate.rx_social_connect.internal.persistence.TokenCache;
import org.fuckboilerplate.rx_social_connect.internal.services.OAuth1Service;
import org.fuckboilerplate.rx_social_connect.internal.services.OAuth2Service;
import org.fuckboilerplate.rx_social_connect.internal.services.Service;
import rx_activity_result2.Result;
import rx_activity_result2.RxActivityResult;
public final class RxSocialConnect {
private static final String ERROR_ENCRYPTION_KEY_IS_NULL = "Error encryption key must not be null";
/**
* Register RxSocialConnect calling this method on onCreate android application method.
*/
public static Builder register(Application application, String encryptionKey) {
if (encryptionKey == null) throw new RuntimeException(ERROR_ENCRYPTION_KEY_IS_NULL);
RxActivityResult.register(application);
return new Builder(application, encryptionKey);
}
public static class Builder {
private final Application application;
private final String encryptionKey;
public Builder(Application application, String encryptionKey) {
this.application = application;
this.encryptionKey = encryptionKey;
}
public void using(Jolyglot jolyglot) {
TokenCache.INSTANCE.init(application, encryptionKey, jolyglot);
}
}
/**
* Performs an oauth http call using oauth1 protocol and retrieve the associated token calling it from an activity.
* @param activity the activity calling
* @param oAuth10aService the oauth1 service containing the provider as long as the provider credentials.
* @param <A> the activity calling
* @return a response instance holding the OAuth1AccessToken and the current valid activity instance.
* @see com.github.scribejava.core.model.OAuth1AccessToken
*/
public static <A extends Activity> Observable<Response<A, com.github.scribejava.core.model.OAuth1AccessToken>> with(A activity, OAuth10aService oAuth10aService) {
return startActivity(activity, new OAuth1Service(oAuth10aService),
oAuth10aService.getApi().getClass().getSimpleName(), OAuth1AccessToken.class)
.map(new Function<Response<Object, OAuth1AccessToken>, Response<A, com.github.scribejava.core.model.OAuth1AccessToken>>() {
@Override public Response<A, com.github.scribejava.core.model.OAuth1AccessToken> apply(Response<Object, OAuth1AccessToken> response) {
return new Response(response.targetUI(), response.token());
}
});
}
/**
* Performs an oauth http call using oauth2 protocol and retrieve the associated token calling it from an activity.
* @param activity the activity calling
* @param oAuth20Service the oauth2 service containing the provider as long as the provider credentials.
* @param <A> the activity calling
* @return a response instance holding the OAuth1AccessToken and the current valid activity instance.
* @see com.github.scribejava.core.model.OAuth2AccessToken
*/
public static <A extends Activity> Observable<Response<A, com.github.scribejava.core.model.OAuth2AccessToken>> with(A activity, OAuth20Service oAuth20Service) {
return startActivity(activity, new OAuth2Service(oAuth20Service),
oAuth20Service.getApi().getClass().getSimpleName(), OAuth2AccessToken.class)
.map(new Function<Response<Object, OAuth2AccessToken>, Response<A, com.github.scribejava.core.model.OAuth2AccessToken>>() {
@Override public Response<A, com.github.scribejava.core.model.OAuth2AccessToken> apply(Response<Object, OAuth2AccessToken> response) {
return new Response(response.targetUI(), response.token());
}
});
}
/**
* Performs an oauth http call using oauth1 protocol and retrieve the associated token calling it from a fragment.
* @param fragment the fragment calling
* @param oAuth10aService the oauth1 service containing the provider as long as the provider credentials.
* @param <F> the fragment calling
* @return a response instance holding the OAuth1AccessToken and the current valid activity fragment.
* @see com.github.scribejava.core.model.OAuth1AccessToken
*/
public static <F extends Fragment> Observable<Response<F, com.github.scribejava.core.model.OAuth1AccessToken>> with(F fragment, OAuth10aService oAuth10aService) {
return startActivity(fragment, new OAuth1Service(oAuth10aService),
oAuth10aService.getApi().getClass().getSimpleName(), OAuth1AccessToken.class)
.map(new Function<Response<Object, OAuth1AccessToken>, Response<F, com.github.scribejava.core.model.OAuth1AccessToken>>() {
@Override public Response<F, com.github.scribejava.core.model.OAuth1AccessToken> apply(Response<Object, OAuth1AccessToken> response) {
return new Response(response.targetUI(), response.token());
}
});
}
/**
* Performs an oauth http call using oauth2 protocol and retrieve the associated token calling it from a fragment.
* @param fragment the fragment calling
* @param oAuth20Service the oauth2 service containing the provider as long as the provider credentials.
* @param <F> the fragment calling
* @return a response instance holding the OAuth2AccessToken and the current valid activity fragment.
* @see com.github.scribejava.core.model.OAuth2AccessToken
*/
public static <F extends Fragment> Observable<Response<F, com.github.scribejava.core.model.OAuth2AccessToken>> with(F fragment, OAuth20Service oAuth20Service) {
return startActivity(fragment, new OAuth2Service(oAuth20Service),
oAuth20Service.getApi().getClass().getSimpleName(), OAuth2AccessToken.class)
.map(new Function<Response<Object, OAuth2AccessToken>, Response<F, com.github.scribejava.core.model.OAuth2AccessToken>>() {
@Override public Response<F, com.github.scribejava.core.model.OAuth2AccessToken> apply(Response<Object, OAuth2AccessToken> response) {
return new Response(response.targetUI(), response.token());
}
});
}
/**
* Remove an stored token from a previous oauth authentication cached on disk.
* @see BaseApi
*/
public static Observable<Object> closeConnection(final Class<? extends BaseApi> classApi) {
return Observable.defer(new Callable<ObservableSource<? extends Object>>() {
@Override public ObservableSource<? extends Object> call() throws Exception {
String keyToken = classApi.getSimpleName();
TokenCache.INSTANCE.evict(keyToken);
return Observable.just(1);
}
});
}
/**
* Remove all stored tokens from previous oauth authentications cached on disk.
*/
public static Observable<Object> closeConnections() {
return Observable.defer(new Callable<ObservableSource<? extends Object>>() {
@Override public ObservableSource<? extends Object> call() throws Exception {
TokenCache.INSTANCE.evictAll();
return Observable.just(1);
}
});
}
/**
* Retrieve the token stored resulting from previous Oauth1 authentication.
* @param classApi a class provider which extends from DefaultApi10a. The same one used to build the OAuthService.
* @return observable containing an OAuth1AccessToken or if not token cached observable which throws NotTokenFoundException
*/
public static Observable<com.github.scribejava.core.model.OAuth1AccessToken> getTokenOAuth1(final Class<? extends DefaultApi10a> classApi) {
return Observable.defer(
new Callable<ObservableSource<? extends com.github.scribejava.core.model.OAuth1AccessToken>>() {
@Override public ObservableSource<? extends com.github.scribejava.core.model.OAuth1AccessToken> call()
throws Exception {
String keyToken = classApi.getSimpleName();
Observable<OAuth1AccessToken> token = (Observable<OAuth1AccessToken>) TokenCache.INSTANCE.get(keyToken, OAuth1AccessToken.class);
if (token != null) {
return token.map(new Function<OAuth1AccessToken, com.github.scribejava.core.model.OAuth1AccessToken>() {
@Override public com.github.scribejava.core.model.OAuth1AccessToken apply(OAuth1AccessToken token) {
return token.toOAuth1AccessTokenScribe();
}
});
}
return Observable.error(new NotActiveTokenFoundException());
}
});
}
/**
* Retrieve the token stored resulting from previous Oauth2 authentication.
* @param classApi a class provider which extends from DefaultApi20. The same one used to build the OAuthService.
* @return observable containing an OAuth2AccessToken or if not token cached observable which throws NotTokenFoundException
*/
public static Observable<com.github.scribejava.core.model.OAuth2AccessToken> getTokenOAuth2(final Class<? extends DefaultApi20> classApi) {
return Observable.defer(new Callable<ObservableSource<? extends com.github.scribejava.core.model.OAuth2AccessToken>>() {
@Override public ObservableSource<? extends com.github.scribejava.core.model.OAuth2AccessToken> call()
throws Exception {
String keyToken = classApi.getSimpleName();
Observable<OAuth2AccessToken> oToken = (Observable<OAuth2AccessToken>) TokenCache.INSTANCE.get(keyToken, OAuth2AccessToken.class);
if (oToken != null) {
return oToken.map(new Function<OAuth2AccessToken, com.github.scribejava.core.model.OAuth2AccessToken>() {
@Override public com.github.scribejava.core.model.OAuth2AccessToken apply(OAuth2AccessToken token) {
return token.toOAuth2AccessTokenScribe();
}
});
}
return Observable.error(new NotActiveTokenFoundException());
}
});
}
private static final String ERROR_RETRIEVING_TOKEN = "Error retrieving token";
private static <T extends Token> Observable<Response<Object, T>> startActivity(final Object targetUI, Service<T, ? extends OAuthService> service, final String keyToken, final Class<T> classToken) {
Activity activity = targetUI instanceof Activity ? (Activity) targetUI : ((Fragment) targetUI).getActivity();
Observable<T> response = (Observable<T>) TokenCache.INSTANCE.get(keyToken, classToken);
if (response != null) return response.map(new Function<T, Response<Object, T>>() {
@Override public Response<Object, T> apply(T token) {
return new Response(targetUI, token);
}
});
ActivityConnect.service = service;
Intent intent = new Intent(activity, ActivityConnect.class);
Observable oTempResponse;
if (targetUI instanceof Activity) {
oTempResponse = RxActivityResult.on((Activity) targetUI)
.startIntent(intent);
} else {
oTempResponse = RxActivityResult.on((Fragment) targetUI)
.startIntent(intent);
}
Observable<Result> oResponse = (Observable<Result>) oTempResponse;
return oResponse.map(new Function<Result, Response<Object, T>>() {
@Override public Response<Object, T> apply(Result result) {
ActivityConnect.service = null;
if (result.data() == null) throw new RuntimeException(ERROR_RETRIEVING_TOKEN);
if (result.resultCode() == Activity.RESULT_OK) {
T token = (T) result.data().getExtras().getSerializable(ActivityConnect.KEY_RESULT);
TokenCache.INSTANCE.save(keyToken, token);
return new Response(targetUI, token);
}
String errorMessage = result.data().getExtras().getString(ActivityConnect.KEY_RESULT, "");
if (!errorMessage.isEmpty()) throw new RuntimeException(errorMessage);
else throw new RuntimeException(ERROR_RETRIEVING_TOKEN);
}
});
}
}
================================================
FILE: core/src/main/java/org/fuckboilerplate/rx_social_connect/internal/ActivityConnect.java
================================================
/*
* Copyright 2016 FuckBoilerplate
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.fuckboilerplate.rx_social_connect.internal;
import android.app.Activity;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.webkit.CookieManager;
import android.webkit.CookieSyncManager;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import com.github.scribejava.core.model.Token;
import com.github.scribejava.core.oauth.OAuthService;
import org.fuckboilerplate.rx_social_connect.R;
import org.fuckboilerplate.rx_social_connect.internal.services.Service;
import io.reactivex.functions.Consumer;
public class ActivityConnect extends Activity {
public static final String KEY_RESULT = "key_result";
public static Service<? extends Token, ? extends OAuthService> service;
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.connection_activity);
initWebView();
}
protected void initWebView() {
final WebView webView = (WebView) findViewById(R.id.webview);
clearCookies(webView);
webView.setWebViewClient(new WebViewClient() {
@Override public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (service == null || !url.startsWith(service.callbackUrl())) return super.shouldOverrideUrlLoading(view, url);
webView.setVisibility(View.GONE);
service.oResponse(url).subscribe(new Consumer<Token>() {
@Override public void accept(Token token) throws Exception {
finishWithToken(token);
}
}, new Consumer<Throwable>() {
@Override public void accept(Throwable error) throws Exception {
finishWithError(error);
}
});
return true;
}
@Override public void onPageFinished(WebView view, String url) {}
});
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setDomStorageEnabled(true);
service.oAuthUrl().subscribe(new Consumer<String>() {
@Override public void accept(String url) throws Exception {
webView.loadUrl(url);
}
}, new Consumer<Throwable>() {
@Override public void accept(Throwable error) throws Exception {
finishWithError(error);
}
});
}
@SuppressWarnings("deprecation")
private void clearCookies(WebView webView) {
webView.clearCache(true);
webView.clearHistory();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
CookieManager.getInstance().removeAllCookies(null);
CookieManager.getInstance().flush();
} else {
CookieSyncManager cookieSyncManager = CookieSyncManager.createInstance(this);
cookieSyncManager.startSync();
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.removeAllCookie();
cookieManager.removeSessionCookie();
cookieSyncManager.stopSync();
cookieSyncManager.sync();
}
}
private void finishWithError(Throwable error) {
Intent intent = new Intent();
String message = error.getMessage();
if (message == null && error.getCause() != null) message = error.getCause().getMessage();
intent.putExtra(KEY_RESULT, message);
setResult(Activity.RESULT_CANCELED, intent);
finish();
}
private void finishWithToken(Token token) {
Intent intent = new Intent();
intent.putExtra(KEY_RESULT, token);
setResult(Activity.RESULT_OK, intent);
finish();
}
}
================================================
FILE: core/src/main/java/org/fuckboilerplate/rx_social_connect/internal/encryption/BuiltInEncryptor.java
================================================
/*
* Copyright 2015 Victor Albertos
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.fuckboilerplate.rx_social_connect.internal.encryption;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
/**
* Encrypt/Decrypt the file data
*/
public class BuiltInEncryptor implements Encryptor {
private static final int KEY_LENGTH = 128; // Max 128 bits by default. See http://stackoverflow.com/a/24907555/5502014
private static final int FILE_BUF = 1024;
private Cipher encryptCipher;
private Cipher decryptCipher;
public BuiltInEncryptor() {
}
@Override public void encrypt(String key, File decryptedFile, File encryptedFile) {
initCiphers(key);
try {
CipherInputStream cis = new CipherInputStream(new FileInputStream(decryptedFile), encryptCipher);
write(cis, new FileOutputStream(encryptedFile));
} catch (Exception e) {
e.printStackTrace();
}
}
@Override public void decrypt(String key, File encryptedFile, File decryptedFile) {
initCiphers(key);
try {
CipherOutputStream cos = new CipherOutputStream(new FileOutputStream(decryptedFile), decryptCipher);
write(new FileInputStream(encryptedFile), cos);
} catch (Exception e) {
e.printStackTrace();
}
}
private void initCiphers(String key) {
try {
SecretKeySpec secretKey = generateSecretKey(key);
encryptCipher = Cipher.getInstance("AES");
encryptCipher.init(Cipher.ENCRYPT_MODE, secretKey);
decryptCipher = Cipher.getInstance("AES");
decryptCipher.init(Cipher.DECRYPT_MODE, secretKey);
} catch (Exception e) {
e.printStackTrace();
}
}
private SecretKeySpec generateSecretKey(String key) throws Exception {
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
secureRandom.setSeed(key.getBytes("UTF-8"));
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(KEY_LENGTH, secureRandom);
SecretKey secretKey = keyGenerator.generateKey();
return new SecretKeySpec(secretKey.getEncoded(), "AES");
}
private void write(InputStream is, OutputStream os) {
byte[] bytes = new byte[FILE_BUF];
int numBytes;
try {
while ((numBytes = is.read(bytes)) != -1) {
os.write(bytes, 0, numBytes);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
is.close();
os.flush();
os.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
================================================
FILE: core/src/main/java/org/fuckboilerplate/rx_social_connect/internal/encryption/Encryptor.java
================================================
/*
* Copyright 2015 Victor Albertos
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.fuckboilerplate.rx_social_connect.internal.encryption;
import java.io.File;
/**
* Interface to Encrypt/Decrypt the file data
*/
public interface Encryptor {
/**
* Encrypts the {@code decryptedFile} data and saves it into {@code encryptedFile}
*
* @param key Key used by the algorithm to encrypt/decrypt the data
* @param decryptedFile Input file with the data to encrypt
* @param encryptedFile Output file with the encrypted data
*/
void encrypt(String key, File decryptedFile, File encryptedFile);
/**
* Decrypts the {@code encryptedFile} data and saves it into {@code decryptedFile}
*
* @param key Key used by the algorithm to encrypt/decrypt the data
* @param encryptedFile Input file with the encrypted data
* @param decryptedFile Output file with the data without encrypt
*/
void decrypt(String key, File encryptedFile, File decryptedFile);
}
================================================
FILE: core/src/main/java/org/fuckboilerplate/rx_social_connect/internal/encryption/FileEncryptor.java
================================================
/*
* Copyright 2016 Victor Albertos
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.fuckboilerplate.rx_social_connect.internal.encryption;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.channels.FileChannel;
public class FileEncryptor {
private static final String SUFFIX_TMP = "-tmp";
private final Encryptor encryptor;
public FileEncryptor(Encryptor encryptor) {
this.encryptor = encryptor;
}
public File encrypt(String key, File file) {
if (key == null || !file.exists()) return file;
String filenameInput = file.getAbsolutePath();
file = rename(file, new File(filenameInput + SUFFIX_TMP));
File fileOutput = new File(filenameInput);
encryptor.encrypt(key, file, fileOutput);
file.delete();
return fileOutput;
}
public File decrypt(String key, File file) {
if (key == null || !file.exists()) return file;
String filenameInput = file.getAbsolutePath();
File fileOutput = new File(filenameInput + SUFFIX_TMP);
encryptor.decrypt(key, file, fileOutput);
return fileOutput;
}
private File rename(File fileSrc, File fileDst) {
FileChannel inputChannel = null;
FileChannel outputChannel = null;
try {
inputChannel = new FileInputStream(fileSrc).getChannel();
outputChannel = new FileOutputStream(fileDst).getChannel();
inputChannel.transferTo(0, inputChannel.size(), outputChannel);
fileSrc.delete();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (inputChannel != null) {
inputChannel.close();
}
if (outputChannel != null) {
outputChannel.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
return fileDst;
}
}
================================================
FILE: core/src/main/java/org/fuckboilerplate/rx_social_connect/internal/persistence/Disk.java
================================================
/*
* Copyright 2016 FuckBoilerplate
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.fuckboilerplate.rx_social_connect.internal.persistence;
import com.github.scribejava.core.model.Token;
import io.reactivex.Observable;
import io.victoralbertos.jolyglot.Jolyglot;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import org.fuckboilerplate.rx_social_connect.internal.encryption.BuiltInEncryptor;
import org.fuckboilerplate.rx_social_connect.internal.encryption.FileEncryptor;
public class Disk<T extends Token> {
private final File cacheDirectory;
private static final String NAME_DIR = "RxSocialConnect";
private final Jolyglot jolyglot;
private final String encryptionKey;
private final FileEncryptor fileEncryptor;
public Disk(File file, String encryptionKey, Jolyglot jolyglot) {
this.fileEncryptor = new FileEncryptor(new BuiltInEncryptor());
this.encryptionKey = encryptionKey;
this.cacheDirectory = new File(file + File.separator + NAME_DIR);
if (!this.cacheDirectory.exists()) cacheDirectory.mkdir();
this.jolyglot = jolyglot;
}
public void save(String key, T data) {
String wrapperJSONSerialized = jolyglot.toJson(data);
FileWriter fileWriter = null;
try {
File file = new File(cacheDirectory, key);
fileWriter = new FileWriter(file, false);
fileWriter.write(wrapperJSONSerialized);
fileWriter.flush();
fileWriter.close();
fileWriter = null;
fileEncryptor.encrypt(encryptionKey, new File(cacheDirectory, key));
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
} finally {
try {
if (fileWriter != null) {
fileWriter.flush();
fileWriter.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public Observable<T> get(String keyToken, Class<T> classToken) {
T response = retrieve(keyToken, classToken);
if (response != null) {
if (response instanceof OAuth2AccessToken) {
if (!((OAuth2AccessToken)response).isExpired()) {
return Observable.just(response);
}
} else {
return Observable.just(response);
}
}
return null;
}
private T retrieve(String key, Class<T> clazz) {
File file = new File(cacheDirectory, key);
file = fileEncryptor.decrypt(encryptionKey, file);
try {
T data = jolyglot.fromJson(file, clazz);
file.delete();
return data;
} catch (Exception ignore) {
return null;
} finally {
file.delete();
}
}
public void evict(String key) {
File file = new File(cacheDirectory, key);
file.delete();
}
public void evictAll() {
File[] tokens = cacheDirectory.listFiles();
if (tokens == null) return;
for (File token : tokens) {
token.delete();
}
}
}
================================================
FILE: core/src/main/java/org/fuckboilerplate/rx_social_connect/internal/persistence/OAuth1AccessToken.java
================================================
package org.fuckboilerplate.rx_social_connect.internal.persistence;
public final class OAuth1AccessToken extends com.github.scribejava.core.model.OAuth1AccessToken {
/**
* Exists just to make happy some json providers
*/
public OAuth1AccessToken() {
super("stub", "stub", "stub");
}
public OAuth1AccessToken(com.github.scribejava.core.model.OAuth1AccessToken oAuth1AccessToken) {
super(oAuth1AccessToken.getToken(),
oAuth1AccessToken.getTokenSecret(),
oAuth1AccessToken.getRawResponse());
}
public com.github.scribejava.core.model.OAuth1AccessToken toOAuth1AccessTokenScribe() {
return this;
}
}
================================================
FILE: core/src/main/java/org/fuckboilerplate/rx_social_connect/internal/persistence/OAuth2AccessToken.java
================================================
/*
* Copyright 2016 FuckBoilerplate
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.fuckboilerplate.rx_social_connect.internal.persistence;
public final class OAuth2AccessToken extends com.github.scribejava.core.model.OAuth2AccessToken {
private final long expirationDate;
/**
* Exists just to make happy some json providers
*/
public OAuth2AccessToken() {
super("stub", "stub", 0, "stub", "stub", "stub");
expirationDate = 0;
}
public OAuth2AccessToken(com.github.scribejava.core.model.OAuth2AccessToken oAuth2AccessToken) {
super(oAuth2AccessToken.getAccessToken(), oAuth2AccessToken.getTokenType(), oAuth2AccessToken.getExpiresIn(),
oAuth2AccessToken.getRefreshToken(), oAuth2AccessToken.getScope(), oAuth2AccessToken.getRawResponse());
if (oAuth2AccessToken.getExpiresIn() == null) this.expirationDate = 0;
else this.expirationDate = System.currentTimeMillis() + (oAuth2AccessToken.getExpiresIn() * 1000);
}
public boolean isExpired() {
if (expirationDate == 0) return false;
return System.currentTimeMillis() > expirationDate;
}
public com.github.scribejava.core.model.OAuth2AccessToken toOAuth2AccessTokenScribe() {
return this;
}
}
================================================
FILE: core/src/main/java/org/fuckboilerplate/rx_social_connect/internal/persistence/TokenCache.java
================================================
/*
* Copyright 2016 FuckBoilerplate
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.fuckboilerplate.rx_social_connect.internal.persistence;
import android.content.Context;
import android.support.annotation.VisibleForTesting;
import com.github.scribejava.core.model.Token;
import io.reactivex.Observable;
import io.victoralbertos.jolyglot.Jolyglot;
import java.io.File;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
public enum TokenCache {
INSTANCE();
private Disk disk;
private ConcurrentMap<String, Observable<? extends Token>> memory;
public void init(Context context, String encryptionKey, Jolyglot jolyglot) {
disk = new Disk(context.getFilesDir(), encryptionKey, jolyglot);
memory = new ConcurrentHashMap();
}
@VisibleForTesting void init(File file, String encryptionKey, Jolyglot jolyglot) {
disk = new Disk(file, encryptionKey, jolyglot);
memory = new ConcurrentHashMap();
}
public <T extends Token> void save(String key, T data) {
memory.put(key, Observable.just(data));
disk.save(key, data);
}
public Observable<? extends Token> get(String keyToken, Class<? extends Token> classToken) {
Observable<? extends Token> token = memory.get(keyToken);
if (token == null) {
token = disk.get(keyToken, classToken);
if (token != null) memory.put(keyToken, token);
}
return token;
}
public void evict(String key) {
memory.remove(key);
disk.evict(key);
}
public void evictAll() {
for (String key : memory.keySet()) {
memory.remove(key);
}
disk.evictAll();
}
}
================================================
FILE: core/src/main/java/org/fuckboilerplate/rx_social_connect/internal/services/OAuth1Service.java
================================================
/*
* Copyright 2016 FuckBoilerplate
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.fuckboilerplate.rx_social_connect.internal.services;
import android.net.Uri;
import com.github.scribejava.core.model.OAuth1RequestToken;
import com.github.scribejava.core.oauth.OAuth10aService;
import org.fuckboilerplate.rx_social_connect.internal.persistence.OAuth1AccessToken;
import org.fuckboilerplate.rx_social_connect.query_string.QueryString;
import org.fuckboilerplate.rx_social_connect.query_string.QueryStringStrategy;
public final class OAuth1Service extends Service<OAuth1AccessToken, OAuth10aService> {
public OAuth1Service(OAuth10aService service) {
super(service);
}
@Override public OAuth1AccessToken token(String url) throws Exception {
Uri uri = Uri.parse(url);
QueryStringStrategy strategy = QueryString.PARSER.getStrategyOAuth1();
String error = strategy.extractError(uri);
if (error != null && !error.isEmpty()) throw new RuntimeException(error);
String verifier = strategy.extractCode(uri);
return new OAuth1AccessToken(
service.getAccessToken(oAuth1RequestToken, verifier)
);
}
private OAuth1RequestToken oAuth1RequestToken;
@Override protected String authUrl() throws Exception {
oAuth1RequestToken = service.getRequestToken();
return service.getAuthorizationUrl(oAuth1RequestToken);
}
@Override public String callbackUrl() {
return service.getConfig().getCallback();
}
}
================================================
FILE: core/src/main/java/org/fuckboilerplate/rx_social_connect/internal/services/OAuth2Service.java
================================================
/*
* Copyright 2016 FuckBoilerplate
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.fuckboilerplate.rx_social_connect.internal.services;
import android.net.Uri;
import com.github.scribejava.core.oauth.OAuth20Service;
import org.fuckboilerplate.rx_social_connect.internal.persistence.OAuth2AccessToken;
import org.fuckboilerplate.rx_social_connect.query_string.QueryString;
import org.fuckboilerplate.rx_social_connect.query_string.QueryStringStrategy;
public final class OAuth2Service extends Service<OAuth2AccessToken, OAuth20Service> {
public OAuth2Service(OAuth20Service service) {
super(service);
}
@Override public OAuth2AccessToken token(String url) throws Exception {
Uri uri = Uri.parse(url);
QueryStringStrategy strategy = QueryString.PARSER.getStrategyOAuth2();
String error = strategy.extractError(uri);
if (error != null && !error.isEmpty()) throw new RuntimeException(error);
String code = strategy.extractCode(uri);
com.github.scribejava.core.model.OAuth2AccessToken accessToken = service.getAccessToken(code);
return new OAuth2AccessToken(accessToken);
}
@Override protected String authUrl() throws Exception {
return service.getAuthorizationUrl();
}
@Override public String callbackUrl() {
return service.getConfig().getCallback();
}
}
================================================
FILE: core/src/main/java/org/fuckboilerplate/rx_social_connect/internal/services/Service.java
================================================
/*
* Copyright 2016 FuckBoilerplate
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.fuckboilerplate.rx_social_connect.internal.services;
import com.github.scribejava.core.model.Token;
import com.github.scribejava.core.oauth.OAuthService;
import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.schedulers.Schedulers;
import java.util.concurrent.Callable;
import io.reactivex.android.schedulers.AndroidSchedulers;
public abstract class Service<T extends Token, S extends OAuthService> {
protected final S service;
public Service(S service) {
this.service = service;
}
public Observable<T> oResponse(final String url) {
return Observable.defer(new Callable<ObservableSource<? extends T>>() {
@Override public ObservableSource<? extends T> call() throws Exception {
try {
return Observable.just(token(url));
} catch (Exception e) {
return Observable.error(e);
}
}
}).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
}
public abstract T token(String url) throws Exception;
public Observable<String> oAuthUrl() {
return Observable.defer(new Callable<ObservableSource<? extends String>>() {
@Override public ObservableSource<? extends String> call() throws Exception {
try {
return Observable.just(authUrl());
} catch (Exception e) {
return Observable.error(e);
}
}
}).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
}
protected abstract String authUrl() throws Exception;
public abstract String callbackUrl();
}
================================================
FILE: core/src/main/java/org/fuckboilerplate/rx_social_connect/query_string/QueryString.java
================================================
/*
* Copyright 2016 FuckBoilerplate
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.fuckboilerplate.rx_social_connect.query_string;
import android.net.Uri;
/**
* Handle the current QueryStringStrategy and provide and entry point for further customization.
*
* @see QueryStringStrategy
*/
public enum QueryString {
PARSER;
private QueryStringStrategy strategyOAuth1;
private QueryStringStrategy strategyOAuth2;
QueryString() {
strategyOAuth1 = defaultStrategyOAuth1();
strategyOAuth2 = defaultStrategyOAuth2();
}
/**
* Replace current QueryStringStrategy for OAuth1 providers
*/
public void replaceStrategyOAuth1(QueryStringStrategy strategyOauth1) {
this.strategyOAuth1 = strategyOauth1;
}
/**
* Replace current QueryStringStrategy for OAuth2 providers
*/
public void replaceStrategyOAuth2(QueryStringStrategy strategyOauth2) {
this.strategyOAuth2 = strategyOauth2;
}
/**
* Reset QueryStringStrategy for OAuth1 providers to default
*/
public void resetStrategyOAuth1() {
this.strategyOAuth1 = defaultStrategyOAuth1();
}
/**
* Reset QueryStringStrategy for OAuth2 providers to default
*/
public void resetStrategyOAuth2() {
this.strategyOAuth2 = defaultStrategyOAuth2();
}
public QueryStringStrategy getStrategyOAuth1() {
return strategyOAuth1;
}
public QueryStringStrategy getStrategyOAuth2() {
return strategyOAuth2;
}
private QueryStringStrategy defaultStrategyOAuth1() {
return new QueryStringStrategy() {
@Override public String extractCode(Uri uri) {
return uri.getQueryParameter("oauth_verifier");
}
@Override public String extractError(Uri uri) {
return uri.getQueryParameter("error");
}
};
}
private QueryStringStrategy defaultStrategyOAuth2() {
return new QueryStringStrategy() {
@Override public String extractCode(Uri uri) {
return uri.getQueryParameter("code");
}
@Override public String extractError(Uri uri) {
return uri.getQueryParameter("error");
}
};
}
}
================================================
FILE: core/src/main/java/org/fuckboilerplate/rx_social_connect/query_string/QueryStringStrategy.java
================================================
/*
* Copyright 2016 FuckBoilerplate
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.fuckboilerplate.rx_social_connect.query_string;
import android.net.Uri;
import android.support.annotation.Nullable;
/**
* Use it when some provider does not honor the standard query string formatter.
*/
public interface QueryStringStrategy {
/**
* Given an uri, parse the query string to extract the associated oauth code.
* @param uri the uri
* @return the param code
*/
String extractCode(Uri uri);
/**
* Given an uri, parse the query string to extract the associated error.
* @param uri the uri
* @return the error message
*/
@Nullable
String extractError(Uri uri);
}
================================================
FILE: core/src/main/res/layout/connection_activity.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<WebView
android:id="@+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
================================================
FILE: core/src/main/res/values/strings.xml
================================================
<resources>
<string name="app_name">rx_social_connect</string>
</resources>
================================================
FILE: core/src/test/java/org/fuckboilerplate/rx_social_connect/OAuth2AccessTokenTest.java
================================================
/*
* Copyright 2016 FuckBoilerplate
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.fuckboilerplate.rx_social_connect;
import org.fuckboilerplate.rx_social_connect.internal.persistence.OAuth2AccessToken;
import org.junit.Test;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
public class OAuth2AccessTokenTest {
@Test public void When_Token_Expires_Then_Expire() throws Exception {
Integer expiresInThreeSecond = 3;
OAuth2AccessToken oAuth2AccessToken = new OAuth2AccessToken(createToken(expiresInThreeSecond));
waitTime(3500);
assertThat(oAuth2AccessToken.isExpired(), is(true));
}
@Test public void When_Token_Not_Expire_Then_Not_Expire() throws Exception {
Integer expiresInOneSecond = 1;
OAuth2AccessToken oAuth2AccessToken = new OAuth2AccessToken(createToken(expiresInOneSecond));
waitTime(550);
assertThat(oAuth2AccessToken.isExpired(), is(false));
}
private com.github.scribejava.core.model.OAuth2AccessToken createToken(Integer expiresOnSeconds) {
return new com.github.scribejava.core.model.OAuth2AccessToken("", "", expiresOnSeconds, "", "", "");
}
private void waitTime(long time) {
try {Thread.sleep(time);}
catch (InterruptedException e) { e.printStackTrace();}
}
}
================================================
FILE: core/src/test/java/org/fuckboilerplate/rx_social_connect/QueryStringTest.java
================================================
/*
* Copyright 2016 FuckBoilerplate
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.fuckboilerplate.rx_social_connect;
import android.net.Uri;
import android.support.annotation.Nullable;
import org.fuckboilerplate.rx_social_connect.query_string.QueryString;
import org.fuckboilerplate.rx_social_connect.query_string.QueryStringStrategy;
import org.junit.FixMethodOrder;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runners.MethodSorters;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.when;
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public final class QueryStringTest {
@Rule public MockitoRule mockitoRule = MockitoJUnit.rule();
@Mock Uri uri;
@Test public void _1_Verify_Replace_OAuth1_Strategy() {
when(uri.getQueryParameter("oauth_verifier_custom")).thenReturn("success");
when(uri.getQueryParameter("error_custom")).thenReturn("error");
QueryString.PARSER.replaceStrategyOAuth1(new QueryStringStrategy() {
@Override public String extractCode(Uri uri) {
return uri.getQueryParameter("oauth_verifier_custom");
}
@Nullable @Override public String extractError(Uri uri) {
return uri.getQueryParameter("error_custom");
}
});
QueryStringStrategy strategy = QueryString.PARSER.getStrategyOAuth1();
assertThat(strategy.extractCode(uri), is("success"));
assertThat(strategy.extractError(uri), is("error"));
}
@Test public void _2_Verify_Replace_OAuth2_Strategy() {
when(uri.getQueryParameter("code_custom")).thenReturn("success");
when(uri.getQueryParameter("error_custom")).thenReturn("error");
QueryString.PARSER.replaceStrategyOAuth2(new QueryStringStrategy() {
@Override public String extractCode(Uri uri) {
return uri.getQueryParameter("code_custom");
}
@Nullable @Override public String extractError(Uri uri) {
return uri.getQueryParameter("error_custom");
}
});
QueryStringStrategy strategy = QueryString.PARSER.getStrategyOAuth2();
assertThat(strategy.extractCode(uri), is("success"));
assertThat(strategy.extractError(uri), is("error"));
}
@Test public void _3_Verify_Default_OAuth1_Strategy() {
QueryString.PARSER.resetStrategyOAuth1();
when(uri.getQueryParameter("oauth_verifier")).thenReturn("success");
when(uri.getQueryParameter("error")).thenReturn("error");
QueryStringStrategy strategy = QueryString.PARSER.getStrategyOAuth1();
assertThat(strategy.extractCode(uri), is("success"));
assertThat(strategy.extractError(uri), is("error"));
}
@Test public void _4_Verify_Default_OAuth2_Strategy() {
QueryString.PARSER.resetStrategyOAuth2();
when(uri.getQueryParameter("code")).thenReturn("success");
when(uri.getQueryParameter("error")).thenReturn("error");
QueryStringStrategy strategy = QueryString.PARSER.getStrategyOAuth2();
assertThat(strategy.extractCode(uri), is("success"));
assertThat(strategy.extractError(uri), is("error"));
}
}
================================================
FILE: core/src/test/java/org/fuckboilerplate/rx_social_connect/internal/persistence/TokenCacheTest.java
================================================
/*
* Copyright 2016 FuckBoilerplate
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.fuckboilerplate.rx_social_connect.internal.persistence;
import com.github.scribejava.apis.FacebookApi;
import com.github.scribejava.apis.TwitterApi;
import io.reactivex.Observable;
import io.reactivex.observers.TestObserver;
import io.victoralbertos.jolyglot.GsonSpeaker;
import io.victoralbertos.jolyglot.Jolyglot;
import org.junit.ClassRule;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runners.MethodSorters;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TokenCacheTest {
private static final String TOKEN_KEY = TwitterApi.class.getSimpleName(), TOKEN_KEY_2 = FacebookApi.class.getSimpleName(), TOKEN = "TOKEN", TOKEN_SECRET = "TOKEN_SECRET", RAW_RESPONSE = "RAW_RESPONSE";
private static final com.github.scribejava.core.model.OAuth1AccessToken OAUTH1_ACCESS_TOKEN = new com.github.scribejava.core.model.OAuth1AccessToken(TOKEN, TOKEN_SECRET, RAW_RESPONSE);
private static final com.github.scribejava.core.model.OAuth2AccessToken OAUTH2_ACCESS_TOKEN = new com.github.scribejava.core.model.OAuth2AccessToken(TOKEN, RAW_RESPONSE);
@ClassRule public static TemporaryFolder temporaryFolder = new TemporaryFolder();
@Test public void _1_When_Save_Token_And_Retrieve_It_Get_It() {
TokenCache.INSTANCE.init(temporaryFolder.getRoot(), "key", jsonConverter());
TokenCache.INSTANCE.save(TOKEN_KEY, OAUTH1_ACCESS_TOKEN);
TestObserver<com.github.scribejava.core.model.OAuth1AccessToken> testSubscriber = new TestObserver<>();
Observable<com.github.scribejava.core.model.OAuth1AccessToken> oToken = (Observable<com.github.scribejava.core.model.OAuth1AccessToken>) TokenCache.INSTANCE.get(TOKEN_KEY, OAuth1AccessToken.class);
oToken.subscribe(testSubscriber);
testSubscriber.awaitTerminalEvent();
assertThat(testSubscriber.values().get(0).getToken(), is(TOKEN));
}
@Test public void _2_When_Retrieve_After_Memory_Destroyed_Get_It() {
TokenCache.INSTANCE.init(temporaryFolder.getRoot(), "key", jsonConverter());
TestObserver<com.github.scribejava.core.model.OAuth1AccessToken> testSubscriber = new TestObserver<>();
Observable<com.github.scribejava.core.model.OAuth1AccessToken> oToken = (Observable<com.github.scribejava.core.model.OAuth1AccessToken>) TokenCache.INSTANCE.get(TOKEN_KEY, OAuth1AccessToken.class);
oToken.subscribe(testSubscriber);
testSubscriber.awaitTerminalEvent();
assertThat(testSubscriber.values().get(0).getToken(), is(TOKEN));
}
@Test public void _3_When_Evict_And_Retrieve_It_Get_Null() {
TokenCache.INSTANCE.init(temporaryFolder.getRoot(), "key", jsonConverter());
TokenCache.INSTANCE.evict(TOKEN_KEY);
Observable<com.github.scribejava.core.model.OAuth1AccessToken> oToken = (Observable<com.github.scribejava.core.model.OAuth1AccessToken>) TokenCache.INSTANCE.get(TOKEN_KEY, OAuth1AccessToken.class);
assertNull(oToken);
}
@Test public void _4_When_Evict_All_And_Retrieve_It_Get_Null() {
TokenCache.INSTANCE.init(temporaryFolder.getRoot(), "key", jsonConverter());
TokenCache.INSTANCE.save(TOKEN_KEY, OAUTH1_ACCESS_TOKEN);
TokenCache.INSTANCE.save(TOKEN_KEY_2, OAUTH2_ACCESS_TOKEN);
TestObserver<com.github.scribejava.core.model.OAuth1AccessToken> testSubscriberToken1 = new TestObserver<>();
Observable<com.github.scribejava.core.model.OAuth1AccessToken> oToken = (Observable<com.github.scribejava.core.model.OAuth1AccessToken>) TokenCache.INSTANCE.get(TOKEN_KEY, OAuth1AccessToken.class);
oToken.subscribe(testSubscriberToken1);
testSubscriberToken1.awaitTerminalEvent();
assertThat(testSubscriberToken1.values().get(0).getToken(), is(TOKEN));
TestObserver<com.github.scribejava.core.model.OAuth2AccessToken> testSubscriberToken2 = new TestObserver<>();
Observable<com.github.scribejava.core.model.OAuth2AccessToken> oToken2 = (Observable<com.github.scribejava.core.model.OAuth2AccessToken>) TokenCache.INSTANCE.get(TOKEN_KEY_2, OAuth2AccessToken.class);
oToken2.subscribe(testSubscriberToken2);
testSubscriberToken2.awaitTerminalEvent();
assertThat(testSubscriberToken2.values().get(0).getAccessToken(), is(TOKEN));
TokenCache.INSTANCE.evict(TOKEN_KEY);
TokenCache.INSTANCE.evict(TOKEN_KEY_2);
oToken = (Observable<com.github.scribejava.core.model.OAuth1AccessToken>) TokenCache.INSTANCE.get(TOKEN_KEY, OAuth1AccessToken.class);
assertNull(oToken);
oToken2 = (Observable<com.github.scribejava.core.model.OAuth2AccessToken>) TokenCache.INSTANCE.get(TOKEN_KEY_2, OAuth2AccessToken.class);
assertNull(oToken2);
}
private Jolyglot jsonConverter() {
return new GsonSpeaker();
}
}
================================================
FILE: gradle/wrapper/gradle-wrapper.properties
================================================
#Thu Sep 15 14:35:02 CEST 2016
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip
================================================
FILE: gradle.properties
================================================
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
# Default value: -Xmx10248m -XX:MaxPermSize=256m
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
================================================
FILE: gradlew
================================================
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
================================================
FILE: gradlew.bat
================================================
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
================================================
FILE: gson_converter/.gitignore
================================================
/build
================================================
FILE: gson_converter/build.gradle
================================================
apply plugin: 'com.android.library'
apply plugin: 'com.github.dcendents.android-maven'
group='com.github.FuckBoilerplate'
android {
compileSdkVersion 23
buildToolsVersion "25.0.2"
defaultConfig {
minSdkVersion 16
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:23.4.0'
compile 'com.google.code.gson:gson:2.6.2'
compile project(':core')
testCompile 'junit:junit:4.12'
}
// build a jar with source files
task sourcesJar(type: Jar) {
from android.sourceSets.main.java.srcDirs
classifier = 'sources'
}
task javadoc(type: Javadoc) {
failOnError false
source = android.sourceSets.main.java.sourceFiles
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
classpath += configurations.compile
}
// build a jar with javadoc
task javadocJar(type: Jar, dependsOn: javadoc) {
classifier = 'javadoc'
from javadoc.destinationDir
}
artifacts {
archives sourcesJar
archives javadocJar
}
================================================
FILE: gson_converter/proguard-rules.pro
================================================
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /Users/victor/Documents/AndroidStudio/android_sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
================================================
FILE: gson_converter/src/main/AndroidManifest.xml
================================================
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="io.victoralbertos.rx_social_connect_gson_converter">
<application
android:allowBackup="true"
android:label="@string/app_name"
android:supportsRtl="true">
</application>
</manifest>
================================================
FILE: gson_converter/src/main/java/io/victoralbertos/rx_social_connect/GsonConverter.java
================================================
package io.victoralbertos.rx_social_connect;
import com.google.gson.Gson;
import java.io.File;
import java.io.FileReader;
/**
* JSONConverter implementation using gson.
* @see JSONConverter
*/
public class GsonConverter implements JSONConverter {
public static GsonConverter create() {
return new GsonConverter();
}
private GsonConverter() {}
@Override public <T> T fromJson(File file, Class<T> clazz) throws Exception {
T data = new Gson().fromJson(new FileReader(file.getAbsoluteFile()), clazz);
return data;
}
@Override public String toJson(Object object) {
return new Gson().toJson(object);
}
}
================================================
FILE: gson_converter/src/main/res/values/strings.xml
================================================
<resources>
<string name="app_name">rx_social_connect_gson_converter</string>
</resources>
================================================
FILE: gson_converter/src/test/java/io/victoralbertos/rx_social_connect/ExampleUnitTest.java
================================================
package io.victoralbertos.rx_social_connect;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* To work on unit tests, switch the Test Artifact in the Build Variants view.
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() throws Exception {
assertEquals(4, 2 + 2);
}
}
================================================
FILE: okhttp_interceptors/.gitignore
================================================
/build
================================================
FILE: okhttp_interceptors/build.gradle
================================================
apply plugin: 'com.android.library'
apply plugin: 'com.github.dcendents.android-maven'
group='com.github.VictorAlbertos'
version='1.0.1-2.x'
android {
compileSdkVersion 25
buildToolsVersion "25.0.0"
defaultConfig {
minSdkVersion 16
targetSdkVersion 25
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile project(':core')
compile 'com.android.support:appcompat-v7:25.1.1'
compile 'com.squareup.okhttp3:okhttp:3.6.0'
testCompile 'junit:junit:4.12'
testCompile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'
testCompile "com.squareup.retrofit2:converter-gson:2.1.0"
}
// build a jar with source files
task sourcesJar(type: Jar) {
from android.sourceSets.main.java.srcDirs
classifier = 'sources'
}
task javadoc(type: Javadoc) {
failOnError false
source = android.sourceSets.main.java.sourceFiles
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
classpath += configurations.compile
}
// build a jar with javadoc
task javadocJar(type: Jar, dependsOn: javadoc) {
classifier = 'javadoc'
from javadoc.destinationDir
}
artifacts {
archives sourcesJar
archives javadocJar
}
================================================
FILE: okhttp_interceptors/proguard-rules.pro
================================================
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /Users/victor/Documents/AndroidStudio/android_sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
================================================
FILE: okhttp_interceptors/src/main/AndroidManifest.xml
================================================
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="io.victoralbertos.rx_social_connect_interceptors">
<application>
</application>
</manifest>
================================================
FILE: okhttp_interceptors/src/main/java/io/victoralbertos/rx_social_connect/OAuth1Interceptor.java
================================================
/*
* Copyright 2016 Copyright 2016 Víctor Albertos
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.victoralbertos.rx_social_connect;
import com.github.scribejava.core.model.OAuth1AccessToken;
import com.github.scribejava.core.model.OAuthRequest;
import com.github.scribejava.core.model.Verb;
import com.github.scribejava.core.oauth.OAuth10aService;
import io.reactivex.Observable;
import org.fuckboilerplate.rx_social_connect.NotActiveTokenFoundException;
import org.fuckboilerplate.rx_social_connect.RxSocialConnect;
import java.io.IOException;
import java.util.Map;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;
public class OAuth1Interceptor implements Interceptor {
protected final OAuth10aService service;
public OAuth1Interceptor(OAuth10aService service) {
this.service = service;
}
@Override public Response intercept(Chain chain) throws IOException, NotActiveTokenFoundException {
Request request = chain.request();
String url = request.url().toString();
Verb verb = apply(request.method());
OAuthRequest requestOAuth = new OAuthRequest(verb, url, service);
Request.Builder builderRequest = request.newBuilder();
OAuth1AccessToken token = getOToken().blockingFirst();
service.signRequest(token, requestOAuth);
Map<String, String> headers = requestOAuth.getHeaders();
for (Map.Entry<String, String> header : headers.entrySet()) {
builderRequest.addHeader(header.getKey(), header.getValue());
}
Response response = chain.proceed(builderRequest.build());
return response;
}
private Verb apply(String method) {
if (method.equalsIgnoreCase("GET")) return Verb.GET;
else if (method.equalsIgnoreCase("POST")) return Verb.POST;
else if (method.equalsIgnoreCase("PUT")) return Verb.PUT;
else if (method.equalsIgnoreCase("DELETE")) return Verb.DELETE;
else if (method.equalsIgnoreCase("HEAD")) return Verb.HEAD;
else if (method.equalsIgnoreCase("OPTIONS")) return Verb.OPTIONS;
else if (method.equalsIgnoreCase("TRACE")) return Verb.TRACE;
else if (method.equalsIgnoreCase("PATCH")) return Verb.PATCH;
return null;
}
//Exists for testing purposes
protected Observable<OAuth1AccessToken> getOToken() {
return RxSocialConnect.getTokenOAuth1(service.getApi().getClass());
}
}
================================================
FILE: okhttp_interceptors/src/main/java/io/victoralbertos/rx_social_connect/OAuth2Interceptor.java
================================================
/*
* Copyright 2016 Copyright 2016 Víctor Albertos
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.victoralbertos.rx_social_connect;
import com.github.scribejava.core.builder.api.DefaultApi20;
import com.github.scribejava.core.model.OAuth2AccessToken;
import io.reactivex.Observable;
import java.io.IOException;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;
import org.fuckboilerplate.rx_social_connect.NotActiveTokenFoundException;
import org.fuckboilerplate.rx_social_connect.RxSocialConnect;
public class OAuth2Interceptor implements Interceptor {
private final Class<? extends DefaultApi20> apiClass;
public OAuth2Interceptor(Class<? extends DefaultApi20> apiClass) {
this.apiClass = apiClass;
}
@Override public Response intercept(Chain chain) throws IOException, NotActiveTokenFoundException {
String token = getOToken().blockingFirst().getAccessToken();
Request request = chain.request();
Request.Builder builderRequest = request.newBuilder();
builderRequest.addHeader("Authorization", "Bearer " + token);
request = builderRequest.build();
Response response = chain.proceed(request);
return response;
}
//Exists for testing purposes
protected Observable<OAuth2AccessToken> getOToken() {
return RxSocialConnect.getTokenOAuth2(apiClass);
}
}
================================================
FILE: okhttp_interceptors/src/main/res/values/strings.xml
================================================
<resources>
<string name="app_name">rx_social_connect_interceptors</string>
</resources>
================================================
FILE: okhttp_interceptors/src/test/java/io/victoralbertos/rx_social_connect/OAuth1TwitterInterceptorTest.java
================================================
/*
* Copyright 2016 Copyright 2016 Víctor Albertos
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.victoralbertos.rx_social_connect;
import com.github.scribejava.apis.TwitterApi;
import com.github.scribejava.core.builder.ServiceBuilder;
import com.github.scribejava.core.model.OAuth1AccessToken;
import com.github.scribejava.core.oauth.OAuth10aService;
import com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import io.reactivex.Observable;
import io.victoralbertos.rx_social_connect.base.OAuth1InterceptorTest;
import okhttp3.OkHttpClient;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.http.GET;
public class OAuth1TwitterInterceptorTest extends OAuth1InterceptorTest {
@Override protected OAuth10aService getService() {
String consumerKey = "3wEAwhjvJmBpJpUfIXiY9PQOg";
String consumerSecret = "8N47XdpE4GSlswMcBTOZFc3fDcil7WnK4RINfUyKf2d0rFrF2I";
return new ServiceBuilder()
.apiKey(consumerKey)
.apiSecret(consumerSecret)
.build(TwitterApi.instance());
}
@Override protected OAuth1AccessToken getToken() {
String token = "732545483974053888-YD0xBTx9261ghVNRxTnxTqDd6feBF7h";
String tokenSecret = "kwXNB0IzLtH5aZA9T5Fvg5Gh1cLVjayAFWfDYWV3AtW1p";
OAuth1AccessToken twitterToken = new OAuth1AccessToken(token, tokenSecret);
return twitterToken;
}
@Override protected Observable<Object> getApiCallWithoutInterceptor() {
return new Retrofit.Builder()
.baseUrl(OAuth1Api.URL_BASE)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build().create(OAuth1Api.class)
.me();
}
@Override protected Observable<Object> getApiCallWithInterceptor(OAuth1Interceptor interceptor) {
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(interceptor)
.build();
return new Retrofit.Builder()
.baseUrl(OAuth1Api.URL_BASE)
.client(client)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build().create(OAuth1Api.class)
.me();
}
private interface OAuth1Api {
String URL_BASE = "https://api.twitter.com";
@GET("/1.1/account/verify_credentials.json")
Observable<Object> me();
}
}
================================================
FILE: okhttp_interceptors/src/test/java/io/victoralbertos/rx_social_connect/OAuth1YahooInterceptorTest.java
================================================
/*
* Copyright 2016 Copyright 2016 Víctor Albertos
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.victoralbertos.rx_social_connect;
import com.github.scribejava.apis.YahooApi;
import com.github.scribejava.core.builder.ServiceBuilder;
import com.github.scribejava.core.model.OAuth1AccessToken;
import com.github.scribejava.core.oauth.OAuth10aService;
import com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import io.reactivex.Observable;
import io.victoralbertos.rx_social_connect.base.OAuth1InterceptorTest;
import okhttp3.OkHttpClient;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.http.GET;
public class OAuth1YahooInterceptorTest extends OAuth1InterceptorTest {
@Override protected OAuth10aService getService() {
String clientId = "dj0yJmk9Sk9NZUlPc0RaODVDJmQ9WVdrOVRubHlWMWRuTTJVbWNHbzlNQS0tJnM9Y29uc3VtZXJzZWNyZXQmeD0wNw--";
String clientSecret = "449b2d2f06d986297d65df7fc020544bf71eb10c";
return new ServiceBuilder()
.apiKey(clientId)
.apiSecret(clientSecret)
.build(YahooApi.instance());
}
@Override protected OAuth1AccessToken getToken() {
String token = "A=bKGw61fClQst5jvXVpOpwRyYXz..2es7g7C7m5k2_HwuKSKfi6VTnJeJJdGnaRRuISwGZcCRQ3J4ldwcbezZL0giYmYZDIZb_OcPttEmpwYneb030se5gWj4yPIKhciYtwruba8CKk6B96MEtPKIfNZ7sdeAB0MPRAGEe_.gZl9k.4L72qFoWzStHpTd79Wg3r8M3ClfFIT64zajfIldkLatEesiE6mqdfWLbNlJ1Zp8QJ.WSJq_aSc.rHZQ_gCx6J6QMMImF9BzCuevhoYN75G9aGkE_28HnqZUm5mCozGGx4ILXTDp4V_CWAL02M5wq1qC.28k8d7z0HnbXx80Y6PeIayqfog0BKaaY1GeM4elGY7kVBVNu5BzlsLfKOUXzRYS3JfYHWYxB3B3fdixE1DKFItaJ3bukVlTksZkgS6oYp3cmXF9iBEIxkmYr0B9u33jAn9Rc3cLfMF9u8LqsTUdVVkCO46dMvGvNwFCW410VelgVvG6lYfaFNtNMluBtyaDYjpXf2XH1Fx7nQ65Ma7CVrKr5EK61rXGYc1OwhsCn88IDUTShdqWW0xTk1sAsdz75pmofw5iR9ehZEJNeHKoDNLxihhBSLT5HC8eRl_FOgA7yuePnJceJuM._Jhsdm6BB2ocLKDEU3s2h.Djk9KLq640s6KfTR.AjM.G9.4DVrHiTA0JA2VxYPXWqOkrbfidIKthITd0ffIsMi6Tghw2vxYSWsF2oe6NrHdtTU04ahAuY3sRsEII04R9YDO.GeTVAb915yL9mo7ELQ_wjddxfh38rdDOeEfNotsfgMaAZB2zsDvMPtmIX9123jkdSyRf19aMy7viifHdi0zN.HHew4QGD3p04DYuJ60VweMrXoHfCvw605D2gLjvEvmN";
String tokenSecret = "f021440f68b8d9141849df4c233d3524789eaca8";
OAuth1AccessToken twitterToken = new OAuth1AccessToken(token, tokenSecret);
return twitterToken;
}
@Override protected Observable<Object> getApiCallWithoutInterceptor() {
return new Retrofit.Builder()
.baseUrl(OAuth1Api.URL_BASE)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build().create(OAuth1Api.class)
.me();
}
@Override protected Observable<Object> getApiCallWithInterceptor(OAuth1Interceptor interceptor) {
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(interceptor)
.build();
return new Retrofit.Builder()
.baseUrl(OAuth1Api.URL_BASE)
.client(client)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build().create(OAuth1Api.class)
.me();
}
private interface OAuth1Api {
String URL_BASE = "https://social.yahooapis.com";
@GET("/v1/user/me/profile?format=json")
Observable<Object> me();
}
}
================================================
FILE: okhttp_interceptors/src/test/java/io/victoralbertos/rx_social_connect/OAuth2FacebookInterceptorTest.java
================================================
/*
* Copyright 2016 Copyright 2016 Víctor Albertos
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.victoralbertos.rx_social_connect;
import com.github.scribejava.core.model.OAuth2AccessToken;
import com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import io.reactivex.Observable;
import io.victoralbertos.rx_social_connect.base.OAuth2InterceptorTest;
import okhttp3.OkHttpClient;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.http.GET;
public class OAuth2FacebookInterceptorTest extends OAuth2InterceptorTest {
@Override protected Observable<Object> getApiCallWithoutInterceptor() {
return new Retrofit.Builder()
.baseUrl(OAuth2Api.URL_BASE)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build().create(OAuth2Api.class)
.me();
}
@Override protected Observable<Object> getApiCallWithInterceptor(OAuth2Interceptor oAuth2Interceptor) {
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(oAuth2Interceptor)
.build();
return new Retrofit.Builder()
.baseUrl(OAuth2Api.URL_BASE)
.client(client)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build().create(OAuth2Api.class)
.me();
}
@Override protected OAuth2AccessToken getToken() {
String accessToken = "EAAGb8BbfjwkBAO8n69r93IbiBkQTPwesBWbBmKFNAXPcDjhho7duR3LGr8DVp5DdeQ4T16VEWtrdS21cGpnbD52rqNV45lMPInmwdbQYdZBMnERANgUGkVGxNTbpbHBVpFR1JiZCU5TgNGxWNmU43jzD5AuZB6H7c2J72sHEQZDZD";
OAuth2AccessToken token = new OAuth2AccessToken(accessToken);
return token;
}
interface OAuth2Api {
String URL_BASE = "https://graph.facebook.com";
@GET("/v2.5/me")
Observable<Object> me();
}
}
================================================
FILE: okhttp_interceptors/src/test/java/io/victoralbertos/rx_social_connect/OAuth2GoogleInterceptorTest.java
================================================
/*
* Copyright 2016 Copyright 2016 Víctor Albertos
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.victoralbertos.rx_social_connect;
import com.github.scribejava.core.model.OAuth2AccessToken;
import com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import io.reactivex.Observable;
import io.victoralbertos.rx_social_connect.base.OAuth2InterceptorTest;
import okhttp3.OkHttpClient;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.http.GET;
public class OAuth2GoogleInterceptorTest extends OAuth2InterceptorTest {
@Override protected Observable<Object> getApiCallWithoutInterceptor() {
return new Retrofit.Builder()
.baseUrl(OAuth2Api.URL_BASE)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build().create(OAuth2Api.class)
.me();
}
@Override protected Observable<Object> getApiCallWithInterceptor(OAuth2Interceptor oAuth2Interceptor) {
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(oAuth2Interceptor)
.build();
return new Retrofit.Builder()
.baseUrl(OAuth2Api.URL_BASE)
.client(client)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build().create(OAuth2Api.class)
.me();
}
@Override protected OAuth2AccessToken getToken() {
String accessToken = "ya29.CjLsAkgBIih0ud7W_a82uKsm6nIWbjg4YuBnK0smznICod4npYiVwz08YB6jPznOHpC6Ig";
OAuth2AccessToken token = new OAuth2AccessToken(accessToken);
return token;
}
interface OAuth2Api {
String URL_BASE = "https://www.googleapis.com";
@GET("/plus/v1/people/me")
Observable<Object> me();
}
}
================================================
FILE: okhttp_interceptors/src/test/java/io/victoralbertos/rx_social_connect/OAuth2LinkedinInterceptorTest.java
================================================
/*
* Copyright 2016 Copyright 2016 Víctor Albertos
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.victoralbertos.rx_social_connect;
import com.github.scribejava.core.model.OAuth2AccessToken;
import com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import io.reactivex.Observable;
import io.victoralbertos.rx_social_connect.base.OAuth2InterceptorTest;
import okhttp3.OkHttpClient;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.http.GET;
public class OAuth2LinkedinInterceptorTest extends OAuth2InterceptorTest {
@Override protected Observable<Object> getApiCallWithoutInterceptor() {
return new Retrofit.Builder()
.baseUrl(OAuth2Api.URL_BASE)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build().create(OAuth2Api.class)
.me();
}
@Override protected Observable<Object> getApiCallWithInterceptor(OAuth2Interceptor oAuth2Interceptor) {
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(oAuth2Interceptor)
.build();
return new Retrofit.Builder()
.baseUrl(OAuth2Api.URL_BASE)
.client(client)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build().create(OAuth2Api.class)
.me();
}
@Override protected OAuth2AccessToken getToken() {
String accessToken = "AQXMnxg_nqVmTo9N5uSvnv-t0jZv6yTEwYPVrQrOZDBAaZPr6Sfltnnchy4C2UlYnjR4rVHjimkgftmEzdcbSIY6nGhh2f0XzkFuuvJWf1vRAf1dayYylobHtpjbSRFW4jCj9Au1mDYpOrLbtWPePnS3I4sSvvvP0MbwLtthYVFVC8jDl9I";
OAuth2AccessToken token = new OAuth2AccessToken(accessToken);
return token;
}
interface OAuth2Api {
String URL_BASE = "https://api.linkedin.com";
@GET("/v1/people/~?format=json")
Observable<Object> me();
}
}
================================================
FILE: okhttp_interceptors/src/test/java/io/victoralbertos/rx_social_connect/base/OAuth1InterceptorTest.java
================================================
/*
* Copyright 2016 Copyright 2016 Víctor Albertos
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.victoralbertos.rx_social_connect.base;
import com.github.scribejava.core.model.OAuth1AccessToken;
import com.github.scribejava.core.oauth.OAuth10aService;
import com.jakewharton.retrofit2.adapter.rxjava2.HttpException;
import io.reactivex.Observable;
import io.reactivex.observers.TestObserver;
import io.victoralbertos.rx_social_connect.OAuth1Interceptor;
import java.io.IOException;
import org.fuckboilerplate.rx_social_connect.NotActiveTokenFoundException;
import org.junit.Test;
public abstract class OAuth1InterceptorTest {
@Test public void Get_Method_Throws_HttpException_Without_Interceptor() throws IOException {
TestObserver<Object> testSubscriber = new TestObserver<>();
getApiCallWithoutInterceptor().subscribe(testSubscriber);
testSubscriber.awaitTerminalEvent();
testSubscriber.assertNoValues();
testSubscriber.assertError(HttpException.class);
}
@Test public void Get_Method_Throws_NotActiveTokenFoundException_With_Interceptor_With_Invalid_Token() throws IOException {
OAuth1Interceptor interceptor = new OAuthInterceptorInvalidToken(getService());
TestObserver<Object> testSubscriber = new TestObserver<>();
getApiCallWithInterceptor(interceptor).subscribe(testSubscriber);
testSubscriber.awaitTerminalEvent();
testSubscriber.assertNoValues();
testSubscriber.assertError(NotActiveTokenFoundException.class);
}
@Test public void Get_Method_Success_With_Interceptor_With_Valid_Token() throws IOException {
OAuth1Interceptor interceptor = new OAuthInterceptorValidToken(getService());
TestObserver<Object> testSubscriber = new TestObserver<>();
getApiCallWithInterceptor(interceptor).subscribe(testSubscriber);
testSubscriber.awaitTerminalEvent();
testSubscriber.assertValueCount(1);
testSubscriber.assertNoErrors();
}
private class OAuthInterceptorInvalidToken extends OAuth1Interceptor {
public OAuthInterceptorInvalidToken(OAuth10aService service) {
super(service);
}
@Override protected Observable<OAuth1AccessToken> getOToken() {
return Observable.error(new NotActiveTokenFoundException());
}
}
private class OAuthInterceptorValidToken extends OAuth1Interceptor {
public OAuthInterceptorValidToken(OAuth10aService service) {
super(service);
}
@Override protected Observable<OAuth1AccessToken> getOToken() {
return Observable.just(getToken());
}
}
protected abstract Observable<Object> getApiCallWithoutInterceptor();
protected abstract Observable<Object> getApiCallWithInterceptor(OAuth1Interceptor oAuth1Interceptor);
protected abstract OAuth10aService getService();
protected abstract OAuth1AccessToken getToken();
}
================================================
FILE: okhttp_interceptors/src/test/java/io/victoralbertos/rx_social_connect/base/OAuth2InterceptorTest.java
================================================
/*
* Copyright 2016 Copyright 2016 Víctor Albertos
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.victoralbertos.rx_social_connect.base;
import com.github.scribejava.core.builder.api.DefaultApi20;
import com.github.scribejava.core.model.OAuth2AccessToken;
import com.jakewharton.retrofit2.adapter.rxjava2.HttpException;
import io.reactivex.Observable;
import io.reactivex.observers.TestObserver;
import io.victoralbertos.rx_social_connect.OAuth2Interceptor;
import java.io.IOException;
import org.fuckboilerplate.rx_social_connect.NotActiveTokenFoundException;
import org.junit.Test;
public abstract class OAuth2InterceptorTest {
@Test public void Get_Method_Throws_HttpException_Without_Interceptor() throws IOException
gitextract_6_iuv5ls/ ├── .gitignore ├── LICENSE.txt ├── README.md ├── app/ │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src/ │ ├── androidTest/ │ │ └── java/ │ │ └── org/ │ │ └── fuckboilerplate/ │ │ └── rxsocialconnect/ │ │ ├── ActivityTest.java │ │ ├── FragmentTest.java │ │ ├── RxSocialConnectInterceptorsTest.java │ │ └── RxSocialConnectTest.java │ └── main/ │ ├── AndroidManifest.xml │ ├── java/ │ │ └── org/ │ │ └── fuckboilerplate/ │ │ └── rxsocialconnect/ │ │ ├── SampleApp.java │ │ ├── StartActivity.java │ │ ├── connections/ │ │ │ ├── ChooseActivityOrFragment.java │ │ │ ├── ConnectionsActivity.java │ │ │ ├── ConnectionsFragment.java │ │ │ ├── Helper.java │ │ │ └── HostActivityFragment.java │ │ └── interceptors/ │ │ ├── InterceptorsActivity.java │ │ └── Repository.java │ └── res/ │ ├── layout/ │ │ ├── choose_activity_or_fragment.xml │ │ ├── connections.xml │ │ ├── host_activity_fragment.xml │ │ ├── interceptors.xml │ │ └── start_activity.xml │ ├── values/ │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ ├── values-v21/ │ │ └── styles.xml │ └── values-w820dp/ │ └── dimens.xml ├── build.gradle ├── core/ │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src/ │ ├── main/ │ │ ├── AndroidManifest.xml │ │ ├── java/ │ │ │ └── org/ │ │ │ └── fuckboilerplate/ │ │ │ └── rx_social_connect/ │ │ │ ├── NotActiveTokenFoundException.java │ │ │ ├── Response.java │ │ │ ├── RxSocialConnect.java │ │ │ ├── internal/ │ │ │ │ ├── ActivityConnect.java │ │ │ │ ├── encryption/ │ │ │ │ │ ├── BuiltInEncryptor.java │ │ │ │ │ ├── Encryptor.java │ │ │ │ │ └── FileEncryptor.java │ │ │ │ ├── persistence/ │ │ │ │ │ ├── Disk.java │ │ │ │ │ ├── OAuth1AccessToken.java │ │ │ │ │ ├── OAuth2AccessToken.java │ │ │ │ │ └── TokenCache.java │ │ │ │ └── services/ │ │ │ │ ├── OAuth1Service.java │ │ │ │ ├── OAuth2Service.java │ │ │ │ └── Service.java │ │ │ └── query_string/ │ │ │ ├── QueryString.java │ │ │ └── QueryStringStrategy.java │ │ └── res/ │ │ ├── layout/ │ │ │ └── connection_activity.xml │ │ └── values/ │ │ └── strings.xml │ └── test/ │ └── java/ │ └── org/ │ └── fuckboilerplate/ │ └── rx_social_connect/ │ ├── OAuth2AccessTokenTest.java │ ├── QueryStringTest.java │ └── internal/ │ └── persistence/ │ └── TokenCacheTest.java ├── gradle/ │ └── wrapper/ │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradle.properties ├── gradlew ├── gradlew.bat ├── gson_converter/ │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src/ │ ├── main/ │ │ ├── AndroidManifest.xml │ │ ├── java/ │ │ │ └── io/ │ │ │ └── victoralbertos/ │ │ │ └── rx_social_connect/ │ │ │ └── GsonConverter.java │ │ └── res/ │ │ └── values/ │ │ └── strings.xml │ └── test/ │ └── java/ │ └── io/ │ └── victoralbertos/ │ └── rx_social_connect/ │ └── ExampleUnitTest.java ├── okhttp_interceptors/ │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src/ │ ├── main/ │ │ ├── AndroidManifest.xml │ │ ├── java/ │ │ │ └── io/ │ │ │ └── victoralbertos/ │ │ │ └── rx_social_connect/ │ │ │ ├── OAuth1Interceptor.java │ │ │ └── OAuth2Interceptor.java │ │ └── res/ │ │ └── values/ │ │ └── strings.xml │ └── test/ │ └── java/ │ └── io/ │ └── victoralbertos/ │ └── rx_social_connect/ │ ├── OAuth1TwitterInterceptorTest.java │ ├── OAuth1YahooInterceptorTest.java │ ├── OAuth2FacebookInterceptorTest.java │ ├── OAuth2GoogleInterceptorTest.java │ ├── OAuth2LinkedinInterceptorTest.java │ └── base/ │ ├── OAuth1InterceptorTest.java │ └── OAuth2InterceptorTest.java └── settings.gradle
SYMBOL INDEX (288 symbols across 43 files)
FILE: app/src/androidTest/java/org/fuckboilerplate/rxsocialconnect/ActivityTest.java
class ActivityTest (line 24) | public class ActivityTest extends RxSocialConnectTest {
FILE: app/src/androidTest/java/org/fuckboilerplate/rxsocialconnect/FragmentTest.java
class FragmentTest (line 24) | public class FragmentTest extends RxSocialConnectTest {
FILE: app/src/androidTest/java/org/fuckboilerplate/rxsocialconnect/RxSocialConnectInterceptorsTest.java
class RxSocialConnectInterceptorsTest (line 34) | @RunWith(AndroidJUnit4.class)
method _a1_Connect_With_Facebook (line 39) | @Test public void _a1_Connect_With_Facebook() {
method _a2_Show_Profile_Facebook (line 58) | @Test public void _a2_Show_Profile_Facebook() {
method _b1_Connect_With_Yahoo (line 65) | @Test public void _b1_Connect_With_Yahoo() {
method _b2_Show_Profile_Yahoo (line 89) | @Test public void _b2_Show_Profile_Yahoo() {
method shouldBeEmpty (line 96) | private Matcher<View> shouldBeEmpty(boolean shouldBeEmpty) {
method waitTime (line 110) | private void waitTime() {
FILE: app/src/androidTest/java/org/fuckboilerplate/rxsocialconnect/RxSocialConnectTest.java
class RxSocialConnectTest (line 48) | @RunWith(AndroidJUnit4.class)
method _a1_Connect_With_Facebook (line 52) | @Test public void _a1_Connect_With_Facebook() {
method _a2_Connected_Facebook (line 74) | @Test public void _a2_Connected_Facebook() {
method _a3_Get_Token_Facebook (line 81) | @Test public void _a3_Get_Token_Facebook() {
method _a4_Disconnect_Facebook (line 88) | @Test public void _a4_Disconnect_Facebook() {
method _a5_Get_Token_Error_Facebook (line 93) | @Test public void _a5_Get_Token_Error_Facebook() {
method _a6_Facebook_Does_Not_Store_Cookies (line 100) | @Test public void _a6_Facebook_Does_Not_Store_Cookies() {
method _b1_Connect_With_Google (line 106) | @Test public void _b1_Connect_With_Google() {
method _b2_Connected_Google (line 131) | @Test public void _b2_Connected_Google() {
method _b3_Get_Token_Google (line 138) | @Test public void _b3_Get_Token_Google() {
method _b4_Disconnect_Google (line 145) | @Test public void _b4_Disconnect_Google() {
method _b5_Get_Token_Error_Google (line 150) | @Test public void _b5_Get_Token_Error_Google() {
method _b6_Google_Does_Not_Store_Cookies (line 157) | @Test public void _b6_Google_Does_Not_Store_Cookies() {
method _d1_Connect_With_LinkedIn (line 163) | @Test public void _d1_Connect_With_LinkedIn() {
method _d2_Connected_LinkedIn (line 184) | @Test public void _d2_Connected_LinkedIn() {
method _d3_Get_Token_LinkedIn (line 191) | @Test public void _d3_Get_Token_LinkedIn() {
method _d4_Disconnect_LinkedIn (line 198) | @Test public void _d4_Disconnect_LinkedIn() {
method _d5_Get_Token_Error_LinkedIn (line 203) | @Test public void _d5_Get_Token_Error_LinkedIn() {
method _d6_LinkedIn_Does_Not_Store_Cookies (line 210) | @Test public void _d6_LinkedIn_Does_Not_Store_Cookies() {
method _e1_Connect_With_Yahoo (line 216) | @Test public void _e1_Connect_With_Yahoo() {
method _e2_Connected_Yahoo (line 248) | @Test public void _e2_Connected_Yahoo() {
method _e3_Get_Token_Yahoo (line 255) | @Test public void _e3_Get_Token_Yahoo() {
method _e4_Disconnect_Yahoo (line 262) | @Test public void _e4_Disconnect_Yahoo() {
method _e5_Get_Token_Error_Yahoo (line 267) | @Test public void _e5_Get_Token_Error_Yahoo() {
method _e6_Yahoo_Does_Not_Store_Cookies (line 274) | @Test public void _e6_Yahoo_Does_Not_Store_Cookies() {
method shouldBeEmpty (line 284) | private Matcher<View> shouldBeEmpty(boolean shouldBeEmpty) {
method waitTime (line 298) | private void waitTime() {
method rotateDevice (line 303) | private void rotateDevice() {
FILE: app/src/main/java/org/fuckboilerplate/rxsocialconnect/SampleApp.java
class SampleApp (line 10) | public class SampleApp extends Application {
method onCreate (line 12) | @Override public void onCreate() {
FILE: app/src/main/java/org/fuckboilerplate/rxsocialconnect/StartActivity.java
class StartActivity (line 13) | public class StartActivity extends Activity {
method onCreate (line 15) | @Override protected void onCreate(Bundle savedInstanceState) {
FILE: app/src/main/java/org/fuckboilerplate/rxsocialconnect/connections/ChooseActivityOrFragment.java
class ChooseActivityOrFragment (line 12) | public class ChooseActivityOrFragment extends Activity {
method onCreate (line 14) | @Override protected void onCreate(Bundle savedInstanceState) {
FILE: app/src/main/java/org/fuckboilerplate/rxsocialconnect/connections/ConnectionsActivity.java
class ConnectionsActivity (line 16) | public class ConnectionsActivity extends AppCompatActivity {
method onCreate (line 19) | @Override protected void onCreate(Bundle savedInstanceState) {
method setUpTwitter (line 35) | private void setUpTwitter() {
method setUpFacebook (line 47) | private void setUpFacebook() {
method setUpGoogle (line 59) | private void setUpGoogle() {
method setUpLinkedIn (line 71) | private void setUpLinkedIn() {
method setUpYahoo (line 83) | private void setUpYahoo() {
method setUpGithub (line 95) | private void setUpGithub() {
FILE: app/src/main/java/org/fuckboilerplate/rxsocialconnect/connections/ConnectionsFragment.java
class ConnectionsFragment (line 20) | public class ConnectionsFragment extends Fragment {
method onCreateView (line 23) | @Nullable @Override public View onCreateView(LayoutInflater inflater, ...
method onActivityCreated (line 27) | @Override public void onActivityCreated(@Nullable Bundle savedInstance...
method setUpTwitter (line 42) | private void setUpTwitter() {
method setUpFacebook (line 54) | private void setUpFacebook() {
method setUpGoogle (line 66) | private void setUpGoogle() {
method setUpLinkedIn (line 78) | private void setUpLinkedIn() {
method setUpYahoo (line 90) | private void setUpYahoo() {
method setUpGithub (line 102) | private void setUpGithub() {
method findViewById (line 114) | private View findViewById(int resId) {
FILE: app/src/main/java/org/fuckboilerplate/rxsocialconnect/connections/Helper.java
class Helper (line 28) | public class Helper {
method Helper (line 31) | public Helper(Object targetUI) {
method twitterService (line 35) | OAuth10aService twitterService() {
method facebookService (line 47) | OAuth20Service facebookService() {
method googleService (line 61) | OAuth20Service googleService() {
method linkedinService (line 75) | OAuth20Service linkedinService() {
method yahooService (line 89) | OAuth10aService yahooService() {
method githubService (line 101) | OAuth20Service githubService() {
method showTokenOAuth1 (line 113) | void showTokenOAuth1(Class<? extends DefaultApi10a> clazz) {
method showTokenOAuth2 (line 119) | void showTokenOAuth2(Class<? extends DefaultApi20> clazz) {
method closeConnection (line 125) | void closeConnection(Class<? extends BaseApi> clazz) {
method closeAllConnection (line 134) | void closeAllConnection() {
method showResponse (line 143) | void showResponse(OAuth1AccessToken token) {
method showResponse (line 149) | void showResponse(OAuth2AccessToken token) {
method clearEditTexts (line 154) | private void clearEditTexts() {
method showError (line 159) | void showError(Throwable throwable) {
method findViewById (line 164) | private View findViewById(int resId) {
method showToast (line 169) | private void showToast(String message) {
method getContext (line 173) | private Context getContext() {
FILE: app/src/main/java/org/fuckboilerplate/rxsocialconnect/connections/HostActivityFragment.java
class HostActivityFragment (line 12) | public class HostActivityFragment extends AppCompatActivity {
method onCreate (line 14) | @Override protected void onCreate(@Nullable Bundle savedInstanceState) {
FILE: app/src/main/java/org/fuckboilerplate/rxsocialconnect/interceptors/InterceptorsActivity.java
class InterceptorsActivity (line 14) | public class InterceptorsActivity extends AppCompatActivity {
method onCreate (line 17) | @Override protected void onCreate(Bundle savedInstanceState) {
method setUpFacebook (line 26) | private void setUpFacebook() {
method setUpYahoo (line 42) | private void setUpYahoo() {
method showUserProfile (line 58) | private void showUserProfile(String userProfileJSON) {
method showToken (line 64) | private void showToken(OAuth2AccessToken oAuth2AccessToken) {
method showToken (line 69) | private void showToken(OAuth1AccessToken token) {
method showError (line 74) | private void showError(Throwable error) {
method clearTextViewToken (line 79) | private void clearTextViewToken() {
FILE: app/src/main/java/org/fuckboilerplate/rxsocialconnect/interceptors/Repository.java
class Repository (line 17) | public class Repository {
method Repository (line 21) | public Repository() {
method initFacebookApiRest (line 26) | private FacebookApiRest initFacebookApiRest() {
method initYahooApiRest (line 39) | private YahooApiRest initYahooApiRest() {
method getFacebookApi (line 52) | FacebookApiRest getFacebookApi() {
method getYahooApiRest (line 56) | YahooApiRest getYahooApiRest() {
type YahooApiRest (line 60) | interface YahooApiRest {
method me (line 63) | @GET("/v1/user/me/profile?format=json") Observable<Object> me();
type FacebookApiRest (line 66) | interface FacebookApiRest {
method me (line 69) | @GET("/v2.5/me")
method facebookService (line 73) | OAuth20Service facebookService() {
method yahooService (line 87) | OAuth10aService yahooService() {
FILE: core/src/main/java/org/fuckboilerplate/rx_social_connect/NotActiveTokenFoundException.java
class NotActiveTokenFoundException (line 19) | public class NotActiveTokenFoundException extends RuntimeException {
method NotActiveTokenFoundException (line 21) | public NotActiveTokenFoundException() {
FILE: core/src/main/java/org/fuckboilerplate/rx_social_connect/Response.java
class Response (line 21) | public final class Response<T, D extends Token> {
method Response (line 25) | public Response(T targetUI, D token) {
method targetUI (line 30) | public T targetUI() {
method token (line 34) | public D token() {
FILE: core/src/main/java/org/fuckboilerplate/rx_social_connect/RxSocialConnect.java
class RxSocialConnect (line 45) | public final class RxSocialConnect {
method register (line 51) | public static Builder register(Application application, String encrypt...
class Builder (line 57) | public static class Builder {
method Builder (line 61) | public Builder(Application application, String encryptionKey) {
method using (line 66) | public void using(Jolyglot jolyglot) {
method with (line 79) | public static <A extends Activity> Observable<Response<A, com.github.s...
method with (line 97) | public static <A extends Activity> Observable<Response<A, com.github.s...
method with (line 115) | public static <F extends Fragment> Observable<Response<F, com.github.s...
method with (line 133) | public static <F extends Fragment> Observable<Response<F, com.github.s...
method closeConnection (line 147) | public static Observable<Object> closeConnection(final Class<? extends...
method closeConnections (line 160) | public static Observable<Object> closeConnections() {
method getTokenOAuth1 (line 174) | public static Observable<com.github.scribejava.core.model.OAuth1Access...
method getTokenOAuth2 (line 200) | public static Observable<com.github.scribejava.core.model.OAuth2Access...
method startActivity (line 221) | private static <T extends Token> Observable<Response<Object, T>> start...
FILE: core/src/main/java/org/fuckboilerplate/rx_social_connect/internal/ActivityConnect.java
class ActivityConnect (line 37) | public class ActivityConnect extends Activity {
method onCreate (line 41) | @Override protected void onCreate(Bundle savedInstanceState) {
method initWebView (line 47) | protected void initWebView() {
method clearCookies (line 87) | @SuppressWarnings("deprecation")
method finishWithError (line 108) | private void finishWithError(Throwable error) {
method finishWithToken (line 119) | private void finishWithToken(Token token) {
FILE: core/src/main/java/org/fuckboilerplate/rx_social_connect/internal/encryption/BuiltInEncryptor.java
class BuiltInEncryptor (line 37) | public class BuiltInEncryptor implements Encryptor {
method BuiltInEncryptor (line 44) | public BuiltInEncryptor() {
method encrypt (line 47) | @Override public void encrypt(String key, File decryptedFile, File enc...
method decrypt (line 58) | @Override public void decrypt(String key, File encryptedFile, File dec...
method initCiphers (line 69) | private void initCiphers(String key) {
method generateSecretKey (line 83) | private SecretKeySpec generateSecretKey(String key) throws Exception {
method write (line 93) | private void write(InputStream is, OutputStream os) {
FILE: core/src/main/java/org/fuckboilerplate/rx_social_connect/internal/encryption/Encryptor.java
type Encryptor (line 24) | public interface Encryptor {
method encrypt (line 33) | void encrypt(String key, File decryptedFile, File encryptedFile);
method decrypt (line 42) | void decrypt(String key, File encryptedFile, File decryptedFile);
FILE: core/src/main/java/org/fuckboilerplate/rx_social_connect/internal/encryption/FileEncryptor.java
class FileEncryptor (line 25) | public class FileEncryptor {
method FileEncryptor (line 29) | public FileEncryptor(Encryptor encryptor) {
method encrypt (line 33) | public File encrypt(String key, File file) {
method decrypt (line 46) | public File decrypt(String key, File file) {
method rename (line 56) | private File rename(File fileSrc, File fileDst) {
FILE: core/src/main/java/org/fuckboilerplate/rx_social_connect/internal/persistence/Disk.java
class Disk (line 28) | public class Disk<T extends Token> {
method Disk (line 35) | public Disk(File file, String encryptionKey, Jolyglot jolyglot) {
method save (line 43) | public void save(String key, T data) {
method get (line 71) | public Observable<T> get(String keyToken, Class<T> classToken) {
method retrieve (line 87) | private T retrieve(String key, Class<T> clazz) {
method evict (line 103) | public void evict(String key) {
method evictAll (line 108) | public void evictAll() {
FILE: core/src/main/java/org/fuckboilerplate/rx_social_connect/internal/persistence/OAuth1AccessToken.java
class OAuth1AccessToken (line 3) | public final class OAuth1AccessToken extends com.github.scribejava.core....
method OAuth1AccessToken (line 8) | public OAuth1AccessToken() {
method OAuth1AccessToken (line 12) | public OAuth1AccessToken(com.github.scribejava.core.model.OAuth1Access...
method toOAuth1AccessTokenScribe (line 18) | public com.github.scribejava.core.model.OAuth1AccessToken toOAuth1Acce...
FILE: core/src/main/java/org/fuckboilerplate/rx_social_connect/internal/persistence/OAuth2AccessToken.java
class OAuth2AccessToken (line 19) | public final class OAuth2AccessToken extends com.github.scribejava.core....
method OAuth2AccessToken (line 25) | public OAuth2AccessToken() {
method OAuth2AccessToken (line 30) | public OAuth2AccessToken(com.github.scribejava.core.model.OAuth2Access...
method isExpired (line 38) | public boolean isExpired() {
method toOAuth2AccessTokenScribe (line 43) | public com.github.scribejava.core.model.OAuth2AccessToken toOAuth2Acce...
FILE: core/src/main/java/org/fuckboilerplate/rx_social_connect/internal/persistence/TokenCache.java
type TokenCache (line 28) | public enum TokenCache {
method init (line 34) | public void init(Context context, String encryptionKey, Jolyglot jolyg...
method init (line 39) | @VisibleForTesting void init(File file, String encryptionKey, Jolyglot...
method save (line 44) | public <T extends Token> void save(String key, T data) {
method get (line 49) | public Observable<? extends Token> get(String keyToken, Class<? extend...
method evict (line 58) | public void evict(String key) {
method evictAll (line 63) | public void evictAll() {
FILE: core/src/main/java/org/fuckboilerplate/rx_social_connect/internal/services/OAuth1Service.java
class OAuth1Service (line 26) | public final class OAuth1Service extends Service<OAuth1AccessToken, OAut...
method OAuth1Service (line 28) | public OAuth1Service(OAuth10aService service) {
method token (line 32) | @Override public OAuth1AccessToken token(String url) throws Exception {
method authUrl (line 47) | @Override protected String authUrl() throws Exception {
method callbackUrl (line 52) | @Override public String callbackUrl() {
FILE: core/src/main/java/org/fuckboilerplate/rx_social_connect/internal/services/OAuth2Service.java
class OAuth2Service (line 25) | public final class OAuth2Service extends Service<OAuth2AccessToken, OAut...
method OAuth2Service (line 27) | public OAuth2Service(OAuth20Service service) {
method token (line 31) | @Override public OAuth2AccessToken token(String url) throws Exception {
method authUrl (line 44) | @Override protected String authUrl() throws Exception {
method callbackUrl (line 48) | @Override public String callbackUrl() {
FILE: core/src/main/java/org/fuckboilerplate/rx_social_connect/internal/services/Service.java
class Service (line 28) | public abstract class Service<T extends Token, S extends OAuthService> {
method Service (line 31) | public Service(S service) {
method oResponse (line 35) | public Observable<T> oResponse(final String url) {
method token (line 47) | public abstract T token(String url) throws Exception;
method oAuthUrl (line 49) | public Observable<String> oAuthUrl() {
method authUrl (line 61) | protected abstract String authUrl() throws Exception;
method callbackUrl (line 62) | public abstract String callbackUrl();
FILE: core/src/main/java/org/fuckboilerplate/rx_social_connect/query_string/QueryString.java
type QueryString (line 26) | public enum QueryString {
method QueryString (line 32) | QueryString() {
method replaceStrategyOAuth1 (line 40) | public void replaceStrategyOAuth1(QueryStringStrategy strategyOauth1) {
method replaceStrategyOAuth2 (line 47) | public void replaceStrategyOAuth2(QueryStringStrategy strategyOauth2) {
method resetStrategyOAuth1 (line 54) | public void resetStrategyOAuth1() {
method resetStrategyOAuth2 (line 61) | public void resetStrategyOAuth2() {
method getStrategyOAuth1 (line 65) | public QueryStringStrategy getStrategyOAuth1() {
method getStrategyOAuth2 (line 69) | public QueryStringStrategy getStrategyOAuth2() {
method defaultStrategyOAuth1 (line 73) | private QueryStringStrategy defaultStrategyOAuth1() {
method defaultStrategyOAuth2 (line 85) | private QueryStringStrategy defaultStrategyOAuth2() {
FILE: core/src/main/java/org/fuckboilerplate/rx_social_connect/query_string/QueryStringStrategy.java
type QueryStringStrategy (line 25) | public interface QueryStringStrategy {
method extractCode (line 31) | String extractCode(Uri uri);
method extractError (line 38) | @Nullable
FILE: core/src/test/java/org/fuckboilerplate/rx_social_connect/OAuth2AccessTokenTest.java
class OAuth2AccessTokenTest (line 26) | public class OAuth2AccessTokenTest {
method When_Token_Expires_Then_Expire (line 28) | @Test public void When_Token_Expires_Then_Expire() throws Exception {
method When_Token_Not_Expire_Then_Not_Expire (line 37) | @Test public void When_Token_Not_Expire_Then_Not_Expire() throws Excep...
method createToken (line 46) | private com.github.scribejava.core.model.OAuth2AccessToken createToken...
method waitTime (line 50) | private void waitTime(long time) {
FILE: core/src/test/java/org/fuckboilerplate/rx_social_connect/QueryStringTest.java
class QueryStringTest (line 35) | @FixMethodOrder(MethodSorters.NAME_ASCENDING)
method _1_Verify_Replace_OAuth1_Strategy (line 40) | @Test public void _1_Verify_Replace_OAuth1_Strategy() {
method _2_Verify_Replace_OAuth2_Strategy (line 59) | @Test public void _2_Verify_Replace_OAuth2_Strategy() {
method _3_Verify_Default_OAuth1_Strategy (line 78) | @Test public void _3_Verify_Default_OAuth1_Strategy() {
method _4_Verify_Default_OAuth2_Strategy (line 89) | @Test public void _4_Verify_Default_OAuth2_Strategy() {
FILE: core/src/test/java/org/fuckboilerplate/rx_social_connect/internal/persistence/TokenCacheTest.java
class TokenCacheTest (line 35) | @FixMethodOrder(MethodSorters.NAME_ASCENDING)
method _1_When_Save_Token_And_Retrieve_It_Get_It (line 43) | @Test public void _1_When_Save_Token_And_Retrieve_It_Get_It() {
method _2_When_Retrieve_After_Memory_Destroyed_Get_It (line 56) | @Test public void _2_When_Retrieve_After_Memory_Destroyed_Get_It() {
method _3_When_Evict_And_Retrieve_It_Get_Null (line 67) | @Test public void _3_When_Evict_And_Retrieve_It_Get_Null() {
method _4_When_Evict_All_And_Retrieve_It_Get_Null (line 75) | @Test public void _4_When_Evict_All_And_Retrieve_It_Get_Null() {
method jsonConverter (line 105) | private Jolyglot jsonConverter() {
FILE: gson_converter/src/main/java/io/victoralbertos/rx_social_connect/GsonConverter.java
class GsonConverter (line 12) | public class GsonConverter implements JSONConverter {
method create (line 14) | public static GsonConverter create() {
method GsonConverter (line 18) | private GsonConverter() {}
method fromJson (line 20) | @Override public <T> T fromJson(File file, Class<T> clazz) throws Exce...
method toJson (line 25) | @Override public String toJson(Object object) {
FILE: gson_converter/src/test/java/io/victoralbertos/rx_social_connect/ExampleUnitTest.java
class ExampleUnitTest (line 10) | public class ExampleUnitTest {
method addition_isCorrect (line 11) | @Test
FILE: okhttp_interceptors/src/main/java/io/victoralbertos/rx_social_connect/OAuth1Interceptor.java
class OAuth1Interceptor (line 35) | public class OAuth1Interceptor implements Interceptor {
method OAuth1Interceptor (line 38) | public OAuth1Interceptor(OAuth10aService service) {
method intercept (line 42) | @Override public Response intercept(Chain chain) throws IOException, N...
method apply (line 64) | private Verb apply(String method) {
method getOToken (line 77) | protected Observable<OAuth1AccessToken> getOToken() {
FILE: okhttp_interceptors/src/main/java/io/victoralbertos/rx_social_connect/OAuth2Interceptor.java
class OAuth2Interceptor (line 29) | public class OAuth2Interceptor implements Interceptor {
method OAuth2Interceptor (line 32) | public OAuth2Interceptor(Class<? extends DefaultApi20> apiClass) {
method intercept (line 36) | @Override public Response intercept(Chain chain) throws IOException, N...
method getOToken (line 50) | protected Observable<OAuth2AccessToken> getOToken() {
FILE: okhttp_interceptors/src/test/java/io/victoralbertos/rx_social_connect/OAuth1TwitterInterceptorTest.java
class OAuth1TwitterInterceptorTest (line 31) | public class OAuth1TwitterInterceptorTest extends OAuth1InterceptorTest {
method getService (line 33) | @Override protected OAuth10aService getService() {
method getToken (line 43) | @Override protected OAuth1AccessToken getToken() {
method getApiCallWithoutInterceptor (line 51) | @Override protected Observable<Object> getApiCallWithoutInterceptor() {
method getApiCallWithInterceptor (line 60) | @Override protected Observable<Object> getApiCallWithInterceptor(OAuth...
type OAuth1Api (line 74) | private interface OAuth1Api {
method me (line 77) | @GET("/1.1/account/verify_credentials.json")
FILE: okhttp_interceptors/src/test/java/io/victoralbertos/rx_social_connect/OAuth1YahooInterceptorTest.java
class OAuth1YahooInterceptorTest (line 31) | public class OAuth1YahooInterceptorTest extends OAuth1InterceptorTest {
method getService (line 33) | @Override protected OAuth10aService getService() {
method getToken (line 43) | @Override protected OAuth1AccessToken getToken() {
method getApiCallWithoutInterceptor (line 51) | @Override protected Observable<Object> getApiCallWithoutInterceptor() {
method getApiCallWithInterceptor (line 60) | @Override protected Observable<Object> getApiCallWithInterceptor(OAuth...
type OAuth1Api (line 74) | private interface OAuth1Api {
method me (line 77) | @GET("/v1/user/me/profile?format=json")
FILE: okhttp_interceptors/src/test/java/io/victoralbertos/rx_social_connect/OAuth2FacebookInterceptorTest.java
class OAuth2FacebookInterceptorTest (line 28) | public class OAuth2FacebookInterceptorTest extends OAuth2InterceptorTest {
method getApiCallWithoutInterceptor (line 30) | @Override protected Observable<Object> getApiCallWithoutInterceptor() {
method getApiCallWithInterceptor (line 39) | @Override protected Observable<Object> getApiCallWithInterceptor(OAuth...
method getToken (line 53) | @Override protected OAuth2AccessToken getToken() {
type OAuth2Api (line 59) | interface OAuth2Api {
method me (line 62) | @GET("/v2.5/me")
FILE: okhttp_interceptors/src/test/java/io/victoralbertos/rx_social_connect/OAuth2GoogleInterceptorTest.java
class OAuth2GoogleInterceptorTest (line 28) | public class OAuth2GoogleInterceptorTest extends OAuth2InterceptorTest {
method getApiCallWithoutInterceptor (line 30) | @Override protected Observable<Object> getApiCallWithoutInterceptor() {
method getApiCallWithInterceptor (line 39) | @Override protected Observable<Object> getApiCallWithInterceptor(OAuth...
method getToken (line 53) | @Override protected OAuth2AccessToken getToken() {
type OAuth2Api (line 60) | interface OAuth2Api {
method me (line 63) | @GET("/plus/v1/people/me")
FILE: okhttp_interceptors/src/test/java/io/victoralbertos/rx_social_connect/OAuth2LinkedinInterceptorTest.java
class OAuth2LinkedinInterceptorTest (line 28) | public class OAuth2LinkedinInterceptorTest extends OAuth2InterceptorTest {
method getApiCallWithoutInterceptor (line 30) | @Override protected Observable<Object> getApiCallWithoutInterceptor() {
method getApiCallWithInterceptor (line 39) | @Override protected Observable<Object> getApiCallWithInterceptor(OAuth...
method getToken (line 53) | @Override protected OAuth2AccessToken getToken() {
type OAuth2Api (line 59) | interface OAuth2Api {
method me (line 62) | @GET("/v1/people/~?format=json")
FILE: okhttp_interceptors/src/test/java/io/victoralbertos/rx_social_connect/base/OAuth1InterceptorTest.java
class OAuth1InterceptorTest (line 29) | public abstract class OAuth1InterceptorTest {
method Get_Method_Throws_HttpException_Without_Interceptor (line 31) | @Test public void Get_Method_Throws_HttpException_Without_Interceptor(...
method Get_Method_Throws_NotActiveTokenFoundException_With_Interceptor_With_Invalid_Token (line 40) | @Test public void Get_Method_Throws_NotActiveTokenFoundException_With_...
method Get_Method_Success_With_Interceptor_With_Valid_Token (line 51) | @Test public void Get_Method_Success_With_Interceptor_With_Valid_Token...
class OAuthInterceptorInvalidToken (line 61) | private class OAuthInterceptorInvalidToken extends OAuth1Interceptor {
method OAuthInterceptorInvalidToken (line 62) | public OAuthInterceptorInvalidToken(OAuth10aService service) {
method getOToken (line 66) | @Override protected Observable<OAuth1AccessToken> getOToken() {
class OAuthInterceptorValidToken (line 71) | private class OAuthInterceptorValidToken extends OAuth1Interceptor {
method OAuthInterceptorValidToken (line 73) | public OAuthInterceptorValidToken(OAuth10aService service) {
method getOToken (line 77) | @Override protected Observable<OAuth1AccessToken> getOToken() {
method getApiCallWithoutInterceptor (line 82) | protected abstract Observable<Object> getApiCallWithoutInterceptor();
method getApiCallWithInterceptor (line 83) | protected abstract Observable<Object> getApiCallWithInterceptor(OAuth1...
method getService (line 84) | protected abstract OAuth10aService getService();
method getToken (line 85) | protected abstract OAuth1AccessToken getToken();
FILE: okhttp_interceptors/src/test/java/io/victoralbertos/rx_social_connect/base/OAuth2InterceptorTest.java
class OAuth2InterceptorTest (line 29) | public abstract class OAuth2InterceptorTest {
method Get_Method_Throws_HttpException_Without_Interceptor (line 31) | @Test public void Get_Method_Throws_HttpException_Without_Interceptor(...
method Get_Method_Throws_NotActiveTokenFoundException_With_Interceptor_With_Invalid_Token (line 40) | @Test public void Get_Method_Throws_NotActiveTokenFoundException_With_...
method Get_Method_Success_With_Interceptor_With_Valid_Token (line 51) | @Test public void Get_Method_Success_With_Interceptor_With_Valid_Token...
class OAuthInterceptorInvalidToken (line 61) | private class OAuthInterceptorInvalidToken extends OAuth2Interceptor {
method OAuthInterceptorInvalidToken (line 62) | public OAuthInterceptorInvalidToken(Class<? extends DefaultApi20> ap...
method getOToken (line 66) | @Override protected Observable<OAuth2AccessToken> getOToken() {
class OAuthInterceptorValidToken (line 71) | private class OAuthInterceptorValidToken extends OAuth2Interceptor {
method OAuthInterceptorValidToken (line 73) | public OAuthInterceptorValidToken(Class<? extends DefaultApi20> apiC...
method getOToken (line 77) | @Override protected Observable<OAuth2AccessToken> getOToken() {
method getApiCallWithoutInterceptor (line 82) | protected abstract Observable<Object> getApiCallWithoutInterceptor();
method getApiCallWithInterceptor (line 83) | protected abstract Observable<Object> getApiCallWithInterceptor(OAuth2...
method getToken (line 84) | protected abstract OAuth2AccessToken getToken();
Condensed preview — 84 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (202K chars).
[
{
"path": ".gitignore",
"chars": 509,
"preview": "# Built application files\n*.apk\n*.ap_\n\n# Files for the Dalvik VM\n*.dex\n\n# Java class files\n*.class\n\n# Generated files\nbi"
},
{
"path": "LICENSE.txt",
"chars": 11345,
"preview": " Apache License\n Version 2.0, January 2004\n "
},
{
"path": "README.md",
"chars": 12124,
"preview": ":warning: Deprecated :warning:\n\nUse [SocialConnect](https://github.com/cookpad/SocialConnect) instead.\n\n[![Android Arsen"
},
{
"path": "app/.gitignore",
"chars": 7,
"preview": "/build\n"
},
{
"path": "app/build.gradle",
"chars": 2293,
"preview": "apply plugin: 'com.android.application'\napply plugin: 'me.tatarka.retrolambda'\n\nbuildscript {\n repositories {\n "
},
{
"path": "app/proguard-rules.pro",
"chars": 680,
"preview": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in /U"
},
{
"path": "app/src/androidTest/java/org/fuckboilerplate/rxsocialconnect/ActivityTest.java",
"chars": 976,
"preview": "/*\n * Copyright 2016 FuckBoilerplate\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
},
{
"path": "app/src/androidTest/java/org/fuckboilerplate/rxsocialconnect/FragmentTest.java",
"chars": 979,
"preview": "/*\n * Copyright 2016 FuckBoilerplate\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
},
{
"path": "app/src/androidTest/java/org/fuckboilerplate/rxsocialconnect/RxSocialConnectInterceptorsTest.java",
"chars": 4668,
"preview": "package org.fuckboilerplate.rxsocialconnect;\n\nimport android.support.test.espresso.matcher.BoundedMatcher;\nimport androi"
},
{
"path": "app/src/androidTest/java/org/fuckboilerplate/rxsocialconnect/RxSocialConnectTest.java",
"chars": 12301,
"preview": "/*\n * Copyright 2016 FuckBoilerplate\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
},
{
"path": "app/src/main/AndroidManifest.xml",
"chars": 1623,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n package="
},
{
"path": "app/src/main/java/org/fuckboilerplate/rxsocialconnect/SampleApp.java",
"chars": 468,
"preview": "package org.fuckboilerplate.rxsocialconnect;\n\nimport android.app.Application;\nimport io.victoralbertos.jolyglot.GsonSpea"
},
{
"path": "app/src/main/java/org/fuckboilerplate/rxsocialconnect/StartActivity.java",
"chars": 864,
"preview": "package org.fuckboilerplate.rxsocialconnect;\n\nimport android.app.Activity;\nimport android.content.Intent;\nimport android"
},
{
"path": "app/src/main/java/org/fuckboilerplate/rxsocialconnect/connections/ChooseActivityOrFragment.java",
"chars": 758,
"preview": "package org.fuckboilerplate.rxsocialconnect.connections;\n\nimport android.app.Activity;\nimport android.content.Intent;\nim"
},
{
"path": "app/src/main/java/org/fuckboilerplate/rxsocialconnect/connections/ConnectionsActivity.java",
"chars": 4631,
"preview": "package org.fuckboilerplate.rxsocialconnect.connections;\n\nimport android.os.Bundle;\nimport android.support.v7.app.AppCom"
},
{
"path": "app/src/main/java/org/fuckboilerplate/rxsocialconnect/connections/ConnectionsFragment.java",
"chars": 5049,
"preview": "package org.fuckboilerplate.rxsocialconnect.connections;\n\nimport android.os.Bundle;\nimport android.support.annotation.Nu"
},
{
"path": "app/src/main/java/org/fuckboilerplate/rxsocialconnect/connections/Helper.java",
"chars": 6327,
"preview": "package org.fuckboilerplate.rxsocialconnect.connections;\n\nimport android.app.Activity;\nimport android.content.Context;\ni"
},
{
"path": "app/src/main/java/org/fuckboilerplate/rxsocialconnect/connections/HostActivityFragment.java",
"chars": 517,
"preview": "package org.fuckboilerplate.rxsocialconnect.connections;\n\nimport android.os.Bundle;\nimport android.support.annotation.Nu"
},
{
"path": "app/src/main/java/org/fuckboilerplate/rxsocialconnect/interceptors/InterceptorsActivity.java",
"chars": 3193,
"preview": "package org.fuckboilerplate.rxsocialconnect.interceptors;\n\nimport android.os.Bundle;\nimport android.support.v7.app.AppCo"
},
{
"path": "app/src/main/java/org/fuckboilerplate/rxsocialconnect/interceptors/Repository.java",
"chars": 3447,
"preview": "package org.fuckboilerplate.rxsocialconnect.interceptors;\n\nimport com.github.scribejava.apis.FacebookApi;\nimport com.git"
},
{
"path": "app/src/main/res/layout/choose_activity_or_fragment.xml",
"chars": 594,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n andr"
},
{
"path": "app/src/main/res/layout/connections.xml",
"chars": 7098,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<ScrollView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n androi"
},
{
"path": "app/src/main/res/layout/host_activity_fragment.xml",
"chars": 552,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n xmln"
},
{
"path": "app/src/main/res/layout/interceptors.xml",
"chars": 1978,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n andr"
},
{
"path": "app/src/main/res/layout/start_activity.xml",
"chars": 604,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n andr"
},
{
"path": "app/src/main/res/values/colors.xml",
"chars": 208,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n <color name=\"colorPrimary\">#3F51B5</color>\n <color name=\"color"
},
{
"path": "app/src/main/res/values/dimens.xml",
"chars": 253,
"preview": "<resources>\n <!-- Default screen margins, per the Android Design guidelines. -->\n <dimen name=\"activity_horizontal"
},
{
"path": "app/src/main/res/values/strings.xml",
"chars": 131,
"preview": "<resources>\n <string name=\"app_name\">RxSocialConnect</string>\n <string name=\"action_settings\">Settings</string>\n</"
},
{
"path": "app/src/main/res/values/styles.xml",
"chars": 708,
"preview": "<resources>\n\n <!-- Base application theme. -->\n <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.DarkActionBar"
},
{
"path": "app/src/main/res/values-v21/styles.xml",
"chars": 327,
"preview": "<resources>\n\n <style name=\"AppTheme.NoActionBar\">\n <item name=\"windowActionBar\">false</item>\n <item nam"
},
{
"path": "app/src/main/res/values-w820dp/dimens.xml",
"chars": 358,
"preview": "<resources>\n <!-- Example customization of dimensions originally defined in res/values/dimens.xml\n (such as s"
},
{
"path": "build.gradle",
"chars": 615,
"preview": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\n\nbuildscript {\n r"
},
{
"path": "core/.gitignore",
"chars": 7,
"preview": "/build\n"
},
{
"path": "core/build.gradle",
"chars": 1702,
"preview": "apply plugin: 'com.android.library'\napply plugin: 'com.github.dcendents.android-maven'\ngroup='com.github.VictorAlbertos'"
},
{
"path": "core/proguard-rules.pro",
"chars": 680,
"preview": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in /U"
},
{
"path": "core/src/main/AndroidManifest.xml",
"chars": 356,
"preview": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n package=\"org.fuckboilerplate.rx_social_connect\""
},
{
"path": "core/src/main/java/org/fuckboilerplate/rx_social_connect/NotActiveTokenFoundException.java",
"chars": 841,
"preview": "/*\n * Copyright 2016 FuckBoilerplate\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
},
{
"path": "core/src/main/java/org/fuckboilerplate/rx_social_connect/Response.java",
"chars": 1027,
"preview": "/*\n * Copyright 2016 FuckBoilerplate\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
},
{
"path": "core/src/main/java/org/fuckboilerplate/rx_social_connect/RxSocialConnect.java",
"chars": 14345,
"preview": "/*\n * Copyright 2016 FuckBoilerplate\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
},
{
"path": "core/src/main/java/org/fuckboilerplate/rx_social_connect/internal/ActivityConnect.java",
"chars": 4434,
"preview": "/*\n * Copyright 2016 FuckBoilerplate\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
},
{
"path": "core/src/main/java/org/fuckboilerplate/rx_social_connect/internal/encryption/BuiltInEncryptor.java",
"chars": 3675,
"preview": "/*\n * Copyright 2015 Victor Albertos\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
},
{
"path": "core/src/main/java/org/fuckboilerplate/rx_social_connect/internal/encryption/Encryptor.java",
"chars": 1542,
"preview": "/*\n * Copyright 2015 Victor Albertos\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
},
{
"path": "core/src/main/java/org/fuckboilerplate/rx_social_connect/internal/encryption/FileEncryptor.java",
"chars": 2549,
"preview": "/*\n * Copyright 2016 Victor Albertos\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
},
{
"path": "core/src/main/java/org/fuckboilerplate/rx_social_connect/internal/persistence/Disk.java",
"chars": 3735,
"preview": "/*\n * Copyright 2016 FuckBoilerplate\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
},
{
"path": "core/src/main/java/org/fuckboilerplate/rx_social_connect/internal/persistence/OAuth1AccessToken.java",
"chars": 648,
"preview": "package org.fuckboilerplate.rx_social_connect.internal.persistence;\n\npublic final class OAuth1AccessToken extends com.gi"
},
{
"path": "core/src/main/java/org/fuckboilerplate/rx_social_connect/internal/persistence/OAuth2AccessToken.java",
"chars": 1803,
"preview": "/*\n * Copyright 2016 FuckBoilerplate\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
},
{
"path": "core/src/main/java/org/fuckboilerplate/rx_social_connect/internal/persistence/TokenCache.java",
"chars": 2256,
"preview": "/*\n * Copyright 2016 FuckBoilerplate\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
},
{
"path": "core/src/main/java/org/fuckboilerplate/rx_social_connect/internal/services/OAuth1Service.java",
"chars": 2053,
"preview": "/*\n * Copyright 2016 FuckBoilerplate\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
},
{
"path": "core/src/main/java/org/fuckboilerplate/rx_social_connect/internal/services/OAuth2Service.java",
"chars": 1901,
"preview": "/*\n * Copyright 2016 FuckBoilerplate\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
},
{
"path": "core/src/main/java/org/fuckboilerplate/rx_social_connect/internal/services/Service.java",
"chars": 2328,
"preview": "/*\n * Copyright 2016 FuckBoilerplate\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
},
{
"path": "core/src/main/java/org/fuckboilerplate/rx_social_connect/query_string/QueryString.java",
"chars": 2619,
"preview": "/*\n * Copyright 2016 FuckBoilerplate\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
},
{
"path": "core/src/main/java/org/fuckboilerplate/rx_social_connect/query_string/QueryStringStrategy.java",
"chars": 1221,
"preview": "/*\n * Copyright 2016 FuckBoilerplate\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
},
{
"path": "core/src/main/res/layout/connection_activity.xml",
"chars": 348,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<FrameLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n andro"
},
{
"path": "core/src/main/res/values/strings.xml",
"chars": 80,
"preview": "<resources>\n <string name=\"app_name\">rx_social_connect</string>\n</resources>\n"
},
{
"path": "core/src/test/java/org/fuckboilerplate/rx_social_connect/OAuth2AccessTokenTest.java",
"chars": 1873,
"preview": "/*\n * Copyright 2016 FuckBoilerplate\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
},
{
"path": "core/src/test/java/org/fuckboilerplate/rx_social_connect/QueryStringTest.java",
"chars": 3688,
"preview": "/*\n * Copyright 2016 FuckBoilerplate\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
},
{
"path": "core/src/test/java/org/fuckboilerplate/rx_social_connect/internal/persistence/TokenCacheTest.java",
"chars": 5591,
"preview": "/*\n * Copyright 2016 FuckBoilerplate\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
},
{
"path": "gradle/wrapper/gradle-wrapper.properties",
"chars": 234,
"preview": "#Thu Sep 15 14:35:02 CEST 2016\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER"
},
{
"path": "gradle.properties",
"chars": 855,
"preview": "# Project-wide Gradle settings.\n\n# IDE (e.g. Android Studio) users:\n# Gradle settings configured through the IDE *will o"
},
{
"path": "gradlew",
"chars": 4971,
"preview": "#!/usr/bin/env bash\n\n##############################################################################\n##\n## Gradle start "
},
{
"path": "gradlew.bat",
"chars": 2404,
"preview": "@if \"%DEBUG%\" == \"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@r"
},
{
"path": "gson_converter/.gitignore",
"chars": 7,
"preview": "/build\n"
},
{
"path": "gson_converter/build.gradle",
"chars": 1308,
"preview": "apply plugin: 'com.android.library'\napply plugin: 'com.github.dcendents.android-maven'\n\ngroup='com.github.FuckBoilerplat"
},
{
"path": "gson_converter/proguard-rules.pro",
"chars": 680,
"preview": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in /U"
},
{
"path": "gson_converter/src/main/AndroidManifest.xml",
"chars": 298,
"preview": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n package=\"io.victoralbertos.rx_social_connect_gs"
},
{
"path": "gson_converter/src/main/java/io/victoralbertos/rx_social_connect/GsonConverter.java",
"chars": 669,
"preview": "package io.victoralbertos.rx_social_connect;\n\nimport com.google.gson.Gson;\n\nimport java.io.File;\nimport java.io.FileRead"
},
{
"path": "gson_converter/src/main/res/values/strings.xml",
"chars": 95,
"preview": "<resources>\n <string name=\"app_name\">rx_social_connect_gson_converter</string>\n</resources>\n"
},
{
"path": "gson_converter/src/test/java/io/victoralbertos/rx_social_connect/ExampleUnitTest.java",
"chars": 328,
"preview": "package io.victoralbertos.rx_social_connect;\n\nimport org.junit.Test;\n\nimport static org.junit.Assert.*;\n\n/**\n * To work "
},
{
"path": "okhttp_interceptors/.gitignore",
"chars": 7,
"preview": "/build\n"
},
{
"path": "okhttp_interceptors/build.gradle",
"chars": 1467,
"preview": "apply plugin: 'com.android.library'\napply plugin: 'com.github.dcendents.android-maven'\ngroup='com.github.VictorAlbertos'"
},
{
"path": "okhttp_interceptors/proguard-rules.pro",
"chars": 680,
"preview": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in /U"
},
{
"path": "okhttp_interceptors/src/main/AndroidManifest.xml",
"chars": 185,
"preview": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n package=\"io.victoralbertos.rx_social_connect_in"
},
{
"path": "okhttp_interceptors/src/main/java/io/victoralbertos/rx_social_connect/OAuth1Interceptor.java",
"chars": 2980,
"preview": "/*\n * Copyright 2016 Copyright 2016 Víctor Albertos\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
},
{
"path": "okhttp_interceptors/src/main/java/io/victoralbertos/rx_social_connect/OAuth2Interceptor.java",
"chars": 1917,
"preview": "/*\n * Copyright 2016 Copyright 2016 Víctor Albertos\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
},
{
"path": "okhttp_interceptors/src/main/res/values/strings.xml",
"chars": 93,
"preview": "<resources>\n <string name=\"app_name\">rx_social_connect_interceptors</string>\n</resources>\n"
},
{
"path": "okhttp_interceptors/src/test/java/io/victoralbertos/rx_social_connect/OAuth1TwitterInterceptorTest.java",
"chars": 3105,
"preview": "/*\n * Copyright 2016 Copyright 2016 Víctor Albertos\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
},
{
"path": "okhttp_interceptors/src/test/java/io/victoralbertos/rx_social_connect/OAuth1YahooInterceptorTest.java",
"chars": 3991,
"preview": "/*\n * Copyright 2016 Copyright 2016 Víctor Albertos\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
},
{
"path": "okhttp_interceptors/src/test/java/io/victoralbertos/rx_social_connect/OAuth2FacebookInterceptorTest.java",
"chars": 2584,
"preview": "/*\n * Copyright 2016 Copyright 2016 Víctor Albertos\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
},
{
"path": "okhttp_interceptors/src/test/java/io/victoralbertos/rx_social_connect/OAuth2GoogleInterceptorTest.java",
"chars": 2494,
"preview": "/*\n * Copyright 2016 Copyright 2016 Víctor Albertos\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
},
{
"path": "okhttp_interceptors/src/test/java/io/victoralbertos/rx_social_connect/OAuth2LinkedinInterceptorTest.java",
"chars": 2603,
"preview": "/*\n * Copyright 2016 Copyright 2016 Víctor Albertos\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
},
{
"path": "okhttp_interceptors/src/test/java/io/victoralbertos/rx_social_connect/base/OAuth1InterceptorTest.java",
"chars": 3483,
"preview": "/*\n * Copyright 2016 Copyright 2016 Víctor Albertos\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
},
{
"path": "okhttp_interceptors/src/test/java/io/victoralbertos/rx_social_connect/base/OAuth2InterceptorTest.java",
"chars": 3449,
"preview": "/*\n * Copyright 2016 Copyright 2016 Víctor Albertos\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\")"
},
{
"path": "settings.gradle",
"chars": 48,
"preview": "include ':app', ':core', ':okhttp_interceptors'\n"
}
]
// ... and 1 more files (download for full content)
About this extraction
This page contains the full source code of the FuckBoilerplate/RxSocialConnect-Android GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 84 files (184.0 KB), approximately 45.2k tokens, and a symbol index with 288 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.