This commit is contained in:
parent
066400f700
commit
61f2af2cb9
687
Test Results - MainActivityTest.html
Normal file
687
Test Results - MainActivityTest.html
Normal file
File diff suppressed because one or more lines are too long
1010
Test Results - Tests_in_'pl_edu_amu_wmi_socialaggregator'.html
Normal file
1010
Test Results - Tests_in_'pl_edu_amu_wmi_socialaggregator'.html
Normal file
File diff suppressed because one or more lines are too long
@ -76,4 +76,9 @@ dependencies {
|
|||||||
implementation 'com.facebook.android:facebook-share:[5,6)'
|
implementation 'com.facebook.android:facebook-share:[5,6)'
|
||||||
|
|
||||||
implementation 'com.squareup.picasso:picasso:2.5.2'
|
implementation 'com.squareup.picasso:picasso:2.5.2'
|
||||||
|
|
||||||
|
implementation([
|
||||||
|
'com.snapchat.kit.sdk:creative:1.1.4',
|
||||||
|
'com.snapchat.kit.sdk:core:1.1.4'
|
||||||
|
])
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="pl.edu.amu.wmi.socialaggregator">
|
package="pl.edu.amu.wmi.socialaggregator">
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
@ -68,6 +69,24 @@
|
|||||||
android:name="com.facebook.FacebookContentProvider"
|
android:name="com.facebook.FacebookContentProvider"
|
||||||
android:exported="true"/>
|
android:exported="true"/>
|
||||||
|
|
||||||
|
|
||||||
|
<meta-data android:name="com.snapchat.kit.sdk.clientId" android:value="240836fb-b762-4be8-a42f-5472a22f2114" />
|
||||||
|
|
||||||
|
<!-- <meta-data android:name="com.snapchat.kit.sdk.clientId" android:value="your app’s client id" />-->
|
||||||
|
<!-- <meta-data android:name="com.snapchat.kit.sdk.redirectUrl" android:value="the url that will handle login completion" />-->
|
||||||
|
<!-- <meta-data android:name="com.snapchat.kit.sdk.scopes" android:resource="@array/snap_connect_scopes" />-->
|
||||||
|
|
||||||
|
<provider
|
||||||
|
android:authorities="${applicationId}.fileprovider,pl.edu.amu.wmi.socialaggregator.activity.NewPostActivity"
|
||||||
|
android:name="androidx.core.content.FileProvider"
|
||||||
|
android:exported="false"
|
||||||
|
android:grantUriPermissions="true">
|
||||||
|
<meta-data
|
||||||
|
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||||
|
android:resource="@xml/file_paths"
|
||||||
|
/>
|
||||||
|
</provider>
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
|
@ -2,24 +2,16 @@ package pl.edu.amu.wmi.socialaggregator.activity
|
|||||||
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import com.facebook.CallbackManager
|
|
||||||
import com.facebook.FacebookCallback
|
|
||||||
import com.facebook.FacebookException
|
|
||||||
import com.facebook.login.LoginResult
|
|
||||||
import com.jakewharton.rxbinding2.view.RxView
|
import com.jakewharton.rxbinding2.view.RxView
|
||||||
|
import io.reactivex.Observable
|
||||||
import io.reactivex.disposables.CompositeDisposable
|
import io.reactivex.disposables.CompositeDisposable
|
||||||
import kotlinx.android.synthetic.main.activity_main.*
|
import kotlinx.android.synthetic.main.activity_main.*
|
||||||
import pl.edu.amu.wmi.socialaggregator.R
|
import pl.edu.amu.wmi.socialaggregator.R
|
||||||
import pl.edu.amu.wmi.socialaggregator.utils.SocialPlatformsManager
|
import pl.edu.amu.wmi.socialaggregator.utils.SocialPlatformsManager
|
||||||
import pl.edu.amu.wmi.socialaggregator.viewholders.PostSummaryRecycler
|
import pl.edu.amu.wmi.socialaggregator.viewholders.PostSummaryRecycler
|
||||||
import pl.edu.amu.wmi.socialaggregator.viewholders.SocialWithButtonRecycler
|
import pl.edu.amu.wmi.socialaggregator.viewholders.SocialWithButtonRecycler
|
||||||
import com.facebook.AccessToken
|
|
||||||
import com.facebook.login.LoginManager
|
|
||||||
import com.facebook.share.widget.ShareDialog
|
|
||||||
import io.reactivex.Observable
|
|
||||||
|
|
||||||
|
|
||||||
class MainActivity : AppCompatActivity() {
|
class MainActivity : AppCompatActivity() {
|
||||||
@ -38,30 +30,6 @@ class MainActivity : AppCompatActivity() {
|
|||||||
val intent = Intent(this, NewPostActivity::class.java)
|
val intent = Intent(this, NewPostActivity::class.java)
|
||||||
startActivity(intent)
|
startActivity(intent)
|
||||||
},
|
},
|
||||||
// RxView.clicks(connectedSocialsButton)
|
|
||||||
// .subscribe {
|
|
||||||
// val accessToken = AccessToken.getCurrentAccessToken()
|
|
||||||
// val isLoggedIn = accessToken != null && !accessToken.isExpired
|
|
||||||
//
|
|
||||||
// Log.i(TAG, isLoggedIn.toString())
|
|
||||||
//
|
|
||||||
// LoginManager.getInstance().logInWithReadPermissions(this, listOf("public_profile"))
|
|
||||||
//
|
|
||||||
//// val request = GraphRequest.newMeRequest(
|
|
||||||
//// accessToken
|
|
||||||
//// ) { `object`, response ->
|
|
||||||
//// Log.v("LoginActivity", response.toString())
|
|
||||||
////
|
|
||||||
//// // Application code
|
|
||||||
//// }
|
|
||||||
//// val parameters = Bundle()
|
|
||||||
//// parameters.putString("fields", "id,name,email,gender,birthday")
|
|
||||||
//// request.parameters = parameters
|
|
||||||
//// request.executeAsync()
|
|
||||||
// ShareDialog(this).show()
|
|
||||||
//// val intent = Intent(this, AddSocialActivity::class.java)
|
|
||||||
//// startActivity(intent)
|
|
||||||
// },
|
|
||||||
RxView.clicks(previousPostsButton)
|
RxView.clicks(previousPostsButton)
|
||||||
.subscribe {
|
.subscribe {
|
||||||
val intent = Intent(this, PostHistoryActivity::class.java)
|
val intent = Intent(this, PostHistoryActivity::class.java)
|
||||||
@ -72,7 +40,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||||
SocialPlatformsManager.getAll()
|
SocialPlatformsManager.getAll()
|
||||||
.forEach { it.onActivityResult(requestCode, resultCode, data)}
|
.forEach { it.onActivityResult(requestCode, resultCode, data) }
|
||||||
super.onActivityResult(requestCode, resultCode, data)
|
super.onActivityResult(requestCode, resultCode, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,12 +56,13 @@ class MainActivity : AppCompatActivity() {
|
|||||||
previousPostsRecyclerView.apply {
|
previousPostsRecyclerView.apply {
|
||||||
layoutManager = LinearLayoutManager(this@MainActivity)
|
layoutManager = LinearLayoutManager(this@MainActivity)
|
||||||
adapter = PostSummaryRecycler(
|
adapter = PostSummaryRecycler(
|
||||||
Observable.fromIterable(SocialPlatformsManager.getLoggedIn(this@MainActivity))
|
Observable.merge(SocialPlatformsManager.getLoggedIn(this@MainActivity)
|
||||||
.flatMap { social ->
|
.map { social ->
|
||||||
return@flatMap social.getPosts(this@MainActivity)
|
social.getPosts(this@MainActivity)
|
||||||
.map { social to it }
|
.map { social to it }
|
||||||
.toObservable()
|
.toObservable()
|
||||||
})
|
})
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,12 +2,13 @@ package pl.edu.amu.wmi.socialaggregator.activity
|
|||||||
|
|
||||||
import android.Manifest
|
import android.Manifest
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.graphics.BitmapFactory
|
import android.graphics.BitmapFactory
|
||||||
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.provider.MediaStore
|
import android.provider.MediaStore
|
||||||
import android.widget.Toast
|
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.core.app.ActivityCompat
|
import androidx.core.app.ActivityCompat
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
@ -15,16 +16,25 @@ import androidx.recyclerview.widget.LinearLayoutManager
|
|||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import com.jakewharton.rxbinding2.view.RxView
|
import com.jakewharton.rxbinding2.view.RxView
|
||||||
import io.reactivex.Observable
|
import io.reactivex.Observable
|
||||||
|
import io.reactivex.functions.BiFunction
|
||||||
|
import io.reactivex.schedulers.Schedulers
|
||||||
|
import io.reactivex.subjects.PublishSubject
|
||||||
import kotlinx.android.synthetic.main.activity_new_post.*
|
import kotlinx.android.synthetic.main.activity_new_post.*
|
||||||
import kotlinx.android.synthetic.main.content_new_post.*
|
import kotlinx.android.synthetic.main.content_new_post.*
|
||||||
import pl.edu.amu.wmi.socialaggregator.R
|
import pl.edu.amu.wmi.socialaggregator.R
|
||||||
|
import pl.edu.amu.wmi.socialaggregator.socialplatforms.SocialPlatform
|
||||||
import pl.edu.amu.wmi.socialaggregator.utils.SocialPlatformsManager
|
import pl.edu.amu.wmi.socialaggregator.utils.SocialPlatformsManager
|
||||||
import pl.edu.amu.wmi.socialaggregator.viewholders.SocialWithToggleRecycler
|
import pl.edu.amu.wmi.socialaggregator.viewholders.SocialWithToggleRecycler
|
||||||
|
|
||||||
|
|
||||||
class NewPostActivity : AppCompatActivity() {
|
class NewPostActivity : AppCompatActivity() {
|
||||||
|
|
||||||
var file: String? = null
|
var file: String? = null
|
||||||
|
|
||||||
|
val postedSubject = PublishSubject.create<Any>()
|
||||||
|
|
||||||
|
val resumedSubject = PublishSubject.create<Any>()
|
||||||
|
|
||||||
@SuppressLint("CheckResult")
|
@SuppressLint("CheckResult")
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
@ -47,16 +57,48 @@ class NewPostActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
RxView.clicks(publishPost)
|
RxView.clicks(publishPost)
|
||||||
.filter { file != null }
|
.filter { file != null }
|
||||||
.subscribe {
|
.doOnNext {
|
||||||
availablesRecycler.chips.entries
|
val sdk = android.os.Build.VERSION.SDK_INT
|
||||||
.filter { (_, chip) -> chip.isChecked }
|
if (sdk < android.os.Build.VERSION_CODES.HONEYCOMB) {
|
||||||
.forEach { (social, _) ->
|
val clipboard =
|
||||||
|
getSystemService(Context.CLIPBOARD_SERVICE) as android.text.ClipboardManager
|
||||||
|
clipboard.text = postText.text?.toString() ?: ""
|
||||||
|
} else {
|
||||||
|
val clipboard =
|
||||||
|
getSystemService(Context.CLIPBOARD_SERVICE) as android.content.ClipboardManager
|
||||||
|
val clip = android.content.ClipData.newPlainText(
|
||||||
|
"text label",
|
||||||
|
postText.text?.toString() ?: ""
|
||||||
|
)
|
||||||
|
clipboard.primaryClip = clip
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.observeOn(Schedulers.io())
|
||||||
|
.doOnNext {
|
||||||
|
resumedSubject.zipWith(
|
||||||
|
Observable.fromIterable(availablesRecycler.chips.entries
|
||||||
|
.filter { (_, chip) -> chip.isChecked }
|
||||||
|
.map { it.key }),
|
||||||
|
BiFunction<Any, SocialPlatform, SocialPlatform> { _, t2 -> t2 }
|
||||||
|
)
|
||||||
|
.doOnNext {
|
||||||
val bitmap = BitmapFactory.decodeFile(file!!)
|
val bitmap = BitmapFactory.decodeFile(file!!)
|
||||||
social.addPost(this, postText.text?.toString() ?: "test", listOf(bitmap))
|
it.addPost(
|
||||||
.blockingSubscribe()
|
postedSubject, this,
|
||||||
Toast.makeText(this, "Posted to ${social.getName()}!", Toast.LENGTH_SHORT)
|
postText.text?.toString() ?: "",
|
||||||
.show()
|
listOf(bitmap),
|
||||||
|
listOf(file!!)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
.take(availablesRecycler.chips.count { it.value.isChecked }.toLong())
|
||||||
|
.toList()
|
||||||
|
.subscribe { _ ->
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
.subscribe {
|
||||||
|
resumedSubject.onNext(Any())
|
||||||
}
|
}
|
||||||
|
|
||||||
RxView.clicks(imageView2)
|
RxView.clicks(imageView2)
|
||||||
@ -86,18 +128,33 @@ class NewPostActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||||
|
SocialPlatformsManager.getAll()
|
||||||
|
.forEach { it.onActivityResult(requestCode, resultCode, data) }
|
||||||
super.onActivityResult(requestCode, resultCode, data)
|
super.onActivityResult(requestCode, resultCode, data)
|
||||||
|
|
||||||
if (requestCode == PICK_IMAGE_REQUEST_CODE) {
|
if (requestCode == PICK_IMAGE_REQUEST_CODE) {
|
||||||
data?.data?.let { uri ->
|
data?.data?.let { uri ->
|
||||||
uri.pathSegments?.last()?.let {
|
file = getPath(uri)
|
||||||
file = it
|
|
||||||
}
|
|
||||||
imageView2.setImageURI(uri)
|
imageView2.setImageURI(uri)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getPath(uri: Uri): String? {
|
||||||
|
val projection = arrayOf(MediaStore.Images.Media.DATA)
|
||||||
|
val cursor = contentResolver.query(uri, projection, null, null, null) ?: return null
|
||||||
|
val column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)
|
||||||
|
cursor.moveToFirst()
|
||||||
|
val s = cursor.getString(column_index)
|
||||||
|
cursor.close()
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
resumedSubject.onNext(Any())
|
||||||
|
}
|
||||||
|
|
||||||
private fun canAccessGallery() =
|
private fun canAccessGallery() =
|
||||||
(ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
|
(ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
|
||||||
|
@ -4,7 +4,6 @@ import android.app.Activity
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.icu.text.SimpleDateFormat
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.View
|
import android.view.View
|
||||||
@ -12,11 +11,9 @@ import android.view.ViewGroup
|
|||||||
import androidx.constraintlayout.widget.ConstraintLayout
|
import androidx.constraintlayout.widget.ConstraintLayout
|
||||||
import androidx.constraintlayout.widget.ConstraintSet
|
import androidx.constraintlayout.widget.ConstraintSet
|
||||||
import com.facebook.*
|
import com.facebook.*
|
||||||
|
import com.facebook.login.LoginManager
|
||||||
import com.facebook.login.LoginResult
|
import com.facebook.login.LoginResult
|
||||||
import com.facebook.login.widget.LoginButton
|
import com.facebook.login.widget.LoginButton
|
||||||
import pl.edu.amu.wmi.socialaggregator.utils.Utils
|
|
||||||
import pl.edu.amu.wmi.socialaggregator.viewholders.SocialWithButtonRecycler
|
|
||||||
import com.facebook.login.LoginManager
|
|
||||||
import com.facebook.share.Sharer
|
import com.facebook.share.Sharer
|
||||||
import com.facebook.share.model.ShareMediaContent
|
import com.facebook.share.model.ShareMediaContent
|
||||||
import com.facebook.share.model.SharePhoto
|
import com.facebook.share.model.SharePhoto
|
||||||
@ -28,7 +25,8 @@ import io.reactivex.subjects.PublishSubject
|
|||||||
import org.json.JSONArray
|
import org.json.JSONArray
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
import pl.edu.amu.wmi.socialaggregator.R
|
import pl.edu.amu.wmi.socialaggregator.R
|
||||||
import java.lang.Exception
|
import pl.edu.amu.wmi.socialaggregator.utils.Utils
|
||||||
|
import pl.edu.amu.wmi.socialaggregator.viewholders.SocialWithButtonRecycler
|
||||||
|
|
||||||
|
|
||||||
class Facebook : SocialPlatform {
|
class Facebook : SocialPlatform {
|
||||||
@ -52,15 +50,21 @@ class Facebook : SocialPlatform {
|
|||||||
return accessToken != null && !accessToken.isExpired
|
return accessToken != null && !accessToken.isExpired
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun addPost(context: Context, text: String, images: List<Bitmap>) : PublishSubject<Any> {
|
override fun addPost(
|
||||||
|
publishSubject: PublishSubject<Any>,
|
||||||
|
context: Context,
|
||||||
|
text: String,
|
||||||
|
images: List<Bitmap>,
|
||||||
|
imagePaths: List<String>
|
||||||
|
) {
|
||||||
val content = ShareMediaContent.Builder().apply {
|
val content = ShareMediaContent.Builder().apply {
|
||||||
images.forEach {addMedium(
|
images.forEach {
|
||||||
SharePhoto.Builder().setBitmap(it).build()
|
addMedium(
|
||||||
)}
|
SharePhoto.Builder().setBitmap(it).build()
|
||||||
|
)
|
||||||
|
}
|
||||||
}.build()
|
}.build()
|
||||||
|
|
||||||
val publishSubject = PublishSubject.create<Any>()
|
|
||||||
|
|
||||||
val shareDialog = ShareDialog(context as Activity)
|
val shareDialog = ShareDialog(context as Activity)
|
||||||
shareDialog.registerCallback(callbackManager, object : FacebookCallback<Sharer.Result?> {
|
shareDialog.registerCallback(callbackManager, object : FacebookCallback<Sharer.Result?> {
|
||||||
override fun onSuccess(result: Sharer.Result?) {
|
override fun onSuccess(result: Sharer.Result?) {
|
||||||
@ -68,7 +72,7 @@ class Facebook : SocialPlatform {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onCancel() {
|
override fun onCancel() {
|
||||||
publishSubject.onError(Exception("Cancelled"))
|
publishSubject.onNext(Any())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onError(error: FacebookException?) {
|
override fun onError(error: FacebookException?) {
|
||||||
@ -76,23 +80,26 @@ class Facebook : SocialPlatform {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
shareDialog.show(content, ShareDialog.Mode.AUTOMATIC)
|
shareDialog.show(content, ShareDialog.Mode.AUTOMATIC)
|
||||||
|
|
||||||
return publishSubject
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getPosts(context: Context): Single<List<Post>> {
|
override fun getPosts(context: Context): Single<List<Post>> {
|
||||||
return Single.just(AccessToken.getCurrentAccessToken())
|
return Single.just(AccessToken.getCurrentAccessToken())
|
||||||
|
.observeOn(Schedulers.io())
|
||||||
.map { token ->
|
.map { token ->
|
||||||
if (token.isExpired) {
|
if (token.isExpired) {
|
||||||
return@map emptyList<Post>()
|
return@map emptyList<Post>()
|
||||||
} else {
|
} else {
|
||||||
val request = GraphRequest.newGraphPathRequest(
|
val request = GraphRequest.newGraphPathRequest(
|
||||||
AccessToken.getCurrentAccessToken(),
|
AccessToken.getCurrentAccessToken(),
|
||||||
"/me/posts") {
|
"/me/posts"
|
||||||
|
) {
|
||||||
Log.i(getName(), it.toString())
|
Log.i(getName(), it.toString())
|
||||||
}
|
}
|
||||||
val parameters = Bundle()
|
val parameters = Bundle()
|
||||||
parameters.putString("fields", "likes.summary(true),created_time,message,attachments{url,unshimmed_url,media,subattachments}")
|
parameters.putString(
|
||||||
|
"fields",
|
||||||
|
"likes.summary(true),created_time,message,attachments{url,unshimmed_url,media,subattachments}"
|
||||||
|
)
|
||||||
request.parameters = parameters
|
request.parameters = parameters
|
||||||
val res = request.executeAndWait()
|
val res = request.executeAndWait()
|
||||||
|
|
||||||
@ -100,14 +107,14 @@ class Facebook : SocialPlatform {
|
|||||||
val size = data.length()
|
val size = data.length()
|
||||||
return@map (0 until size).map {
|
return@map (0 until size).map {
|
||||||
val obj = data[it] as JSONObject
|
val obj = data[it] as JSONObject
|
||||||
val msg = if(obj.has("message")) obj.getString("message") else ""
|
val msg = if (obj.has("message")) obj.getString("message") else ""
|
||||||
val date = if(obj.has("created_time")) obj.getString("created_time") else ""
|
val date =
|
||||||
|
if (obj.has("created_time")) obj.getString("created_time") else ""
|
||||||
// SimpleDateFormat("YYYY-MM-DD\'T\'hh:mm:ssZ").parse(date)
|
// SimpleDateFormat("YYYY-MM-DD\'T\'hh:mm:ssZ").parse(date)
|
||||||
Post(this, msg, date, getImages(obj))
|
Post(this, msg, date, getImages(obj))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -122,12 +129,15 @@ class Facebook : SocialPlatform {
|
|||||||
.flatMap {
|
.flatMap {
|
||||||
val urls = mutableListOf<String>()
|
val urls = mutableListOf<String>()
|
||||||
if (it.has("media")) {
|
if (it.has("media")) {
|
||||||
urls.add(it.getJSONObject("media")
|
urls.add(
|
||||||
.getJSONObject("image")
|
it.getJSONObject("media")
|
||||||
.getString("src"))
|
.getJSONObject("image")
|
||||||
|
.getString("src")
|
||||||
|
)
|
||||||
}
|
}
|
||||||
if (it.has("subattachments")) {
|
if (it.has("subattachments")) {
|
||||||
val subattachments = it.getJSONObject("subattachments").getJSONArray("data")
|
val subattachments =
|
||||||
|
it.getJSONObject("subattachments").getJSONArray("data")
|
||||||
urls.addAll((0 until subattachments.length())
|
urls.addAll((0 until subattachments.length())
|
||||||
.map { subattachments[it] as JSONObject }
|
.map { subattachments[it] as JSONObject }
|
||||||
.map {
|
.map {
|
||||||
@ -158,21 +168,35 @@ class Facebook : SocialPlatform {
|
|||||||
parent.addView(button)
|
parent.addView(button)
|
||||||
|
|
||||||
constraintSet.clone(parent as ConstraintLayout)
|
constraintSet.clone(parent as ConstraintLayout)
|
||||||
constraintSet.connect(button.id, ConstraintSet.TOP,
|
constraintSet.connect(
|
||||||
parent.id, ConstraintSet.TOP, 8.toPx(context))
|
button.id, ConstraintSet.TOP,
|
||||||
constraintSet.connect(button.id, ConstraintSet.END,
|
parent.id, ConstraintSet.TOP, 8.toPx(context)
|
||||||
parent.id, ConstraintSet.END)
|
)
|
||||||
constraintSet.connect(button.id, ConstraintSet.BOTTOM,
|
constraintSet.connect(
|
||||||
parent.id, ConstraintSet.BOTTOM, 8.toPx(context))
|
button.id, ConstraintSet.END,
|
||||||
|
parent.id, ConstraintSet.END
|
||||||
|
)
|
||||||
|
constraintSet.connect(
|
||||||
|
button.id, ConstraintSet.BOTTOM,
|
||||||
|
parent.id, ConstraintSet.BOTTOM, 8.toPx(context)
|
||||||
|
)
|
||||||
|
|
||||||
constraintSet.connect(viewHolder.textView.id, ConstraintSet.BOTTOM,
|
constraintSet.connect(
|
||||||
button.id, ConstraintSet.BOTTOM)
|
viewHolder.textView.id, ConstraintSet.BOTTOM,
|
||||||
constraintSet.connect(viewHolder.textView.id, ConstraintSet.END,
|
button.id, ConstraintSet.BOTTOM
|
||||||
button.id, ConstraintSet.START, 8.toPx(context))
|
)
|
||||||
constraintSet.connect(viewHolder.textView.id, ConstraintSet.START,
|
constraintSet.connect(
|
||||||
parent.id, ConstraintSet.START)
|
viewHolder.textView.id, ConstraintSet.END,
|
||||||
constraintSet.connect(viewHolder.textView.id, ConstraintSet.TOP,
|
button.id, ConstraintSet.START, 8.toPx(context)
|
||||||
button.id, ConstraintSet.TOP)
|
)
|
||||||
|
constraintSet.connect(
|
||||||
|
viewHolder.textView.id, ConstraintSet.START,
|
||||||
|
parent.id, ConstraintSet.START
|
||||||
|
)
|
||||||
|
constraintSet.connect(
|
||||||
|
viewHolder.textView.id, ConstraintSet.TOP,
|
||||||
|
button.id, ConstraintSet.TOP
|
||||||
|
)
|
||||||
constraintSet.setHorizontalBias(viewHolder.textView.id, 0.toFloat())
|
constraintSet.setHorizontalBias(viewHolder.textView.id, 0.toFloat())
|
||||||
constraintSet.applyTo(parent)
|
constraintSet.applyTo(parent)
|
||||||
|
|
||||||
@ -180,8 +204,10 @@ class Facebook : SocialPlatform {
|
|||||||
val callback = object : FacebookCallback<LoginResult> {
|
val callback = object : FacebookCallback<LoginResult> {
|
||||||
override fun onSuccess(result: LoginResult?) {
|
override fun onSuccess(result: LoginResult?) {
|
||||||
Log.i(getName(), "SUCCESS!")
|
Log.i(getName(), "SUCCESS!")
|
||||||
LoginManager.getInstance().logInWithReadPermissions(context as Activity,
|
LoginManager.getInstance().logInWithReadPermissions(
|
||||||
listOf("email"))
|
context as Activity,
|
||||||
|
listOf("email")
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCancel() {
|
override fun onCancel() {
|
||||||
|
@ -1,84 +0,0 @@
|
|||||||
package pl.edu.amu.wmi.socialaggregator.socialplatforms
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.graphics.Bitmap
|
|
||||||
import android.util.Log
|
|
||||||
import io.reactivex.Single
|
|
||||||
import io.reactivex.subjects.PublishSubject
|
|
||||||
import pl.edu.amu.wmi.socialaggregator.R
|
|
||||||
import pl.edu.amu.wmi.socialaggregator.utils.InternalStorage
|
|
||||||
import java.io.ByteArrayOutputStream
|
|
||||||
import java.io.File
|
|
||||||
import java.text.DateFormat
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
abstract class FacebookMock : SocialPlatform {
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
val TAG = FacebookMock::class.java.canonicalName
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getName(): String = "Facebook Mock"
|
|
||||||
|
|
||||||
override fun getLogo(): Int = R.mipmap.ic_logo_facebook
|
|
||||||
|
|
||||||
override fun login(context: Context) {
|
|
||||||
val loginsDir = InternalStorage.getFileOrDir(context, "logins")
|
|
||||||
loginsDir?.mkdir()
|
|
||||||
if (loginsDir != null) {
|
|
||||||
val loginFile = File(loginsDir, "facebook")
|
|
||||||
loginFile.createNewFile()
|
|
||||||
} else {
|
|
||||||
Log.e(TAG, "Could not create logins directory")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun logout(context: Context) {
|
|
||||||
InternalStorage.getFileOrDir(context, "logins/facebook")?.delete()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun isLoggedIn(context: Context): Boolean {
|
|
||||||
return InternalStorage.getFileOrDir(context, "logins/facebook")?.exists() ?: false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun addPost(context: Context, text: String, images: List<Bitmap>): PublishSubject<Any> {
|
|
||||||
val postsDir = InternalStorage.getFileOrDir(context, "posts/facebook")
|
|
||||||
if (postsDir != null) {
|
|
||||||
val postDir = File(postsDir, System.currentTimeMillis().toString())
|
|
||||||
postDir.mkdirs()
|
|
||||||
|
|
||||||
val textFile = File(postDir, "content")
|
|
||||||
textFile.createNewFile()
|
|
||||||
textFile.writeText(text)
|
|
||||||
|
|
||||||
images.forEachIndexed { index, image ->
|
|
||||||
val imageFile = File(postDir, "image$index")
|
|
||||||
imageFile.createNewFile()
|
|
||||||
|
|
||||||
ByteArrayOutputStream().use { stream ->
|
|
||||||
image.compress(Bitmap.CompressFormat.JPEG, 100, stream)
|
|
||||||
imageFile.writeBytes(stream.toByteArray())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
Log.e(TAG, "Could not create posts directory")
|
|
||||||
}
|
|
||||||
return PublishSubject.create()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getPosts(context: Context): Single<List<Post>> {
|
|
||||||
val postsDir = InternalStorage.getFileOrDir(context, "posts/facebook")
|
|
||||||
return Single.just(postsDir?.listFiles()?.flatMap {
|
|
||||||
it.listFiles().map {
|
|
||||||
val dt = Date(it.lastModified())
|
|
||||||
Post(
|
|
||||||
this,
|
|
||||||
it.readText(),
|
|
||||||
DateFormat.getDateTimeInstance().format(dt),
|
|
||||||
emptyList()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}?.toList() ?: emptyList())
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,5 @@
|
|||||||
|
package pl.edu.amu.wmi.socialaggregator.socialplatforms
|
||||||
|
|
||||||
|
import java.lang.Exception
|
||||||
|
|
||||||
|
class NotApplicableException(val socialPlatform: SocialPlatform) : Exception()
|
@ -0,0 +1,79 @@
|
|||||||
|
package pl.edu.amu.wmi.socialaggregator.socialplatforms
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.graphics.Bitmap
|
||||||
|
import android.util.Log
|
||||||
|
import com.snapchat.kit.sdk.SnapCreative
|
||||||
|
import com.snapchat.kit.sdk.creative.api.SnapCreativeKitCompletionCallback
|
||||||
|
import com.snapchat.kit.sdk.creative.api.SnapCreativeKitSendError
|
||||||
|
import com.snapchat.kit.sdk.creative.exceptions.SnapMediaSizeException
|
||||||
|
import com.snapchat.kit.sdk.creative.models.SnapPhotoContent
|
||||||
|
import io.reactivex.Single
|
||||||
|
import io.reactivex.subjects.PublishSubject
|
||||||
|
import pl.edu.amu.wmi.socialaggregator.R
|
||||||
|
import pl.edu.amu.wmi.socialaggregator.viewholders.SocialWithButtonRecycler
|
||||||
|
import java.io.File
|
||||||
|
import java.lang.Exception
|
||||||
|
|
||||||
|
class Snapchat : SocialPlatform {
|
||||||
|
override fun getName(): String = "Snapchat"
|
||||||
|
|
||||||
|
override fun login(context: Context) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun logout(context: Context) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isLoggedIn(context: Context): Boolean = true
|
||||||
|
|
||||||
|
override fun addPost(
|
||||||
|
publishSubject: PublishSubject<Any>,
|
||||||
|
context: Context,
|
||||||
|
text: String,
|
||||||
|
images: List<Bitmap>,
|
||||||
|
imagePaths: List<String>
|
||||||
|
) {
|
||||||
|
val snapCreativeKitApi = SnapCreative.getApi(context)
|
||||||
|
|
||||||
|
val content = imagePaths.map {
|
||||||
|
val snapMediaFactory = SnapCreative.getMediaFactory(context)
|
||||||
|
val photoFile = try {
|
||||||
|
snapMediaFactory.getSnapPhotoFromFile(File(it))
|
||||||
|
} catch (e: SnapMediaSizeException) {
|
||||||
|
Log.e(getName(), e.toString())
|
||||||
|
null
|
||||||
|
}
|
||||||
|
SnapPhotoContent(photoFile!!)
|
||||||
|
}.first()
|
||||||
|
|
||||||
|
snapCreativeKitApi.sendWithCompletionHandler(
|
||||||
|
content,
|
||||||
|
object : SnapCreativeKitCompletionCallback {
|
||||||
|
override fun onSendSuccess() {
|
||||||
|
publishSubject.onNext(Any())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSendFailed(p0: SnapCreativeKitSendError?) {
|
||||||
|
publishSubject.onError(Exception("Snapchat error"))
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getPosts(context: Context): Single<List<Post>> {
|
||||||
|
return Single.just(emptyList())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getLogo(): Int = R.drawable.ic_icon_snapchat
|
||||||
|
|
||||||
|
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||||
|
super.onActivityResult(requestCode, resultCode, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun handleButtonView(context: Context): (SocialWithButtonRecycler.ViewHolder) -> Unit =
|
||||||
|
{
|
||||||
|
it.image.setImageResource(getLogo())
|
||||||
|
it.textView.text = getName()
|
||||||
|
}
|
||||||
|
}
|
@ -13,7 +13,10 @@ interface SocialPlatform {
|
|||||||
fun login(context: Context)
|
fun login(context: Context)
|
||||||
fun logout(context: Context)
|
fun logout(context: Context)
|
||||||
fun isLoggedIn(context: Context): Boolean
|
fun isLoggedIn(context: Context): Boolean
|
||||||
fun addPost(context: Context, text: String, images: List<Bitmap>): PublishSubject<Any>
|
fun addPost(publishSubject: PublishSubject<Any>,
|
||||||
|
context: Context, text: String, images: List<Bitmap>,
|
||||||
|
imagePaths: List<String>)
|
||||||
|
|
||||||
fun getPosts(context: Context): Single<List<Post>>
|
fun getPosts(context: Context): Single<List<Post>>
|
||||||
fun getLogo(): Int
|
fun getLogo(): Int
|
||||||
fun handleButtonView(context: Context): (SocialWithButtonRecycler.ViewHolder) -> Unit = {}
|
fun handleButtonView(context: Context): (SocialWithButtonRecycler.ViewHolder) -> Unit = {}
|
||||||
|
@ -2,13 +2,14 @@ package pl.edu.amu.wmi.socialaggregator.utils
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import pl.edu.amu.wmi.socialaggregator.socialplatforms.Facebook
|
import pl.edu.amu.wmi.socialaggregator.socialplatforms.Facebook
|
||||||
import pl.edu.amu.wmi.socialaggregator.socialplatforms.FacebookMock
|
import pl.edu.amu.wmi.socialaggregator.socialplatforms.Snapchat
|
||||||
import pl.edu.amu.wmi.socialaggregator.socialplatforms.SocialPlatform
|
import pl.edu.amu.wmi.socialaggregator.socialplatforms.SocialPlatform
|
||||||
|
|
||||||
object SocialPlatformsManager {
|
object SocialPlatformsManager {
|
||||||
private val IMPLEMENTED_PLATFORMS = listOf<SocialPlatform>(
|
private val IMPLEMENTED_PLATFORMS = listOf(
|
||||||
// FacebookMock()
|
// FacebookMock()
|
||||||
Facebook()
|
Facebook(),
|
||||||
|
Snapchat()
|
||||||
)
|
)
|
||||||
|
|
||||||
fun getAll() = IMPLEMENTED_PLATFORMS
|
fun getAll() = IMPLEMENTED_PLATFORMS
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package pl.edu.amu.wmi.socialaggregator.viewholders
|
package pl.edu.amu.wmi.socialaggregator.viewholders
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
@ -11,8 +12,11 @@ import androidx.recyclerview.widget.RecyclerView
|
|||||||
import com.squareup.picasso.Picasso
|
import com.squareup.picasso.Picasso
|
||||||
import io.reactivex.Observable
|
import io.reactivex.Observable
|
||||||
import pl.edu.amu.wmi.socialaggregator.R
|
import pl.edu.amu.wmi.socialaggregator.R
|
||||||
|
import pl.edu.amu.wmi.socialaggregator.socialplatforms.NotApplicableException
|
||||||
import pl.edu.amu.wmi.socialaggregator.socialplatforms.Post
|
import pl.edu.amu.wmi.socialaggregator.socialplatforms.Post
|
||||||
|
import pl.edu.amu.wmi.socialaggregator.socialplatforms.SocialPlatform
|
||||||
|
|
||||||
|
@SuppressLint("CheckResult")
|
||||||
class PostDetailsRecycler(
|
class PostDetailsRecycler(
|
||||||
postsObservable: Observable<List<Post>>
|
postsObservable: Observable<List<Post>>
|
||||||
) : RecyclerView.Adapter<PostDetailsRecycler.ViewHolder>() {
|
) : RecyclerView.Adapter<PostDetailsRecycler.ViewHolder>() {
|
||||||
@ -20,10 +24,11 @@ class PostDetailsRecycler(
|
|||||||
val posts = emptyList<Post>().toMutableList()
|
val posts = emptyList<Post>().toMutableList()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
postsObservable.subscribe {
|
postsObservable
|
||||||
posts.addAll(it)
|
.subscribe {
|
||||||
notifyDataSetChanged()
|
posts.addAll(it)
|
||||||
}
|
notifyDataSetChanged()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package pl.edu.amu.wmi.socialaggregator.viewholders
|
package pl.edu.amu.wmi.socialaggregator.viewholders
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
@ -7,22 +8,27 @@ import android.widget.TextView
|
|||||||
import androidx.constraintlayout.widget.ConstraintLayout
|
import androidx.constraintlayout.widget.ConstraintLayout
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import io.reactivex.Observable
|
import io.reactivex.Observable
|
||||||
|
import io.reactivex.Single
|
||||||
import pl.edu.amu.wmi.socialaggregator.R
|
import pl.edu.amu.wmi.socialaggregator.R
|
||||||
|
import pl.edu.amu.wmi.socialaggregator.socialplatforms.NotApplicableException
|
||||||
import pl.edu.amu.wmi.socialaggregator.socialplatforms.Post
|
import pl.edu.amu.wmi.socialaggregator.socialplatforms.Post
|
||||||
import pl.edu.amu.wmi.socialaggregator.socialplatforms.SocialPlatform
|
import pl.edu.amu.wmi.socialaggregator.socialplatforms.SocialPlatform
|
||||||
|
|
||||||
|
@SuppressLint("CheckResult")
|
||||||
class PostSummaryRecycler(
|
class PostSummaryRecycler(
|
||||||
socialsObservable: Observable<Pair<SocialPlatform, List<Post>>>
|
socialsObservable: Observable<Pair<SocialPlatform, List<Post>?>>
|
||||||
) : RecyclerView.Adapter<PostSummaryRecycler.ViewHolder>() {
|
) : RecyclerView.Adapter<PostSummaryRecycler.ViewHolder>() {
|
||||||
|
|
||||||
init {
|
private val socials = mutableListOf<Pair<SocialPlatform, List<Post>?>>()
|
||||||
socialsObservable.subscribe {
|
|
||||||
socials.add(it)
|
|
||||||
notifyDataSetChanged()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val socials = emptyList<Pair<SocialPlatform, List<Post>>>().toMutableList()
|
init {
|
||||||
|
socialsObservable
|
||||||
|
.doOnNext {
|
||||||
|
socials.add(it)
|
||||||
|
notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
.subscribe()
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||||
val layout = LayoutInflater.from(parent.context)
|
val layout = LayoutInflater.from(parent.context)
|
||||||
@ -41,9 +47,11 @@ class PostSummaryRecycler(
|
|||||||
|
|
||||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||||
val (social, posts) = socials[position]
|
val (social, posts) = socials[position]
|
||||||
val count = posts.size
|
val count = posts?.size
|
||||||
holder.socialName.text = social.getName()
|
holder.socialName.text = social.getName()
|
||||||
holder.postCount.text = count.toString() + if (count > 1) " posts" else " post"
|
holder.postCount.text = count?.let {
|
||||||
|
count.toString() + if (count > 1) " posts" else " post"
|
||||||
|
} ?: "Not applicable"
|
||||||
holder.imageView.setImageResource(social.getLogo())
|
holder.imageView.setImageResource(social.getLogo())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BIN
app/src/main/res/drawable-hdpi/ic_icon_snapchat.png
Normal file
BIN
app/src/main/res/drawable-hdpi/ic_icon_snapchat.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.3 KiB |
BIN
app/src/main/res/drawable-mdpi/ic_icon_snapchat.png
Normal file
BIN
app/src/main/res/drawable-mdpi/ic_icon_snapchat.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 725 B |
BIN
app/src/main/res/drawable-xhdpi/ic_icon_snapchat.png
Normal file
BIN
app/src/main/res/drawable-xhdpi/ic_icon_snapchat.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
BIN
app/src/main/res/drawable-xxhdpi/ic_icon_snapchat.png
Normal file
BIN
app/src/main/res/drawable-xxhdpi/ic_icon_snapchat.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.8 KiB |
BIN
app/src/main/res/drawable-xxxhdpi/ic_icon_snapchat.png
Normal file
BIN
app/src/main/res/drawable-xxxhdpi/ic_icon_snapchat.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.1 KiB |
@ -6,4 +6,10 @@
|
|||||||
|
|
||||||
<string name="facebook_app_id">2437098899888167</string>
|
<string name="facebook_app_id">2437098899888167</string>
|
||||||
<string name="fb_login_protocol_scheme">fb2437098899888167</string>
|
<string name="fb_login_protocol_scheme">fb2437098899888167</string>
|
||||||
|
|
||||||
|
<!-- <key>SCSDKScopes</key>-->
|
||||||
|
<!-- <array name="snap_connect_scopes">-->
|
||||||
|
<!-- <string>https://auth.snapchat.com/oauth2/api/user.bitmoji.avatar</string>-->
|
||||||
|
<!-- <!– other scopes you might have... –>-->
|
||||||
|
<!-- </array>-->
|
||||||
</resources>
|
</resources>
|
||||||
|
7
app/src/main/res/xml/file_paths.xml
Normal file
7
app/src/main/res/xml/file_paths.xml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<paths>
|
||||||
|
<root-path name="root" path="." />
|
||||||
|
|
||||||
|
<external-cache-path name="external_files" path="."/>
|
||||||
|
<external-path name="external_files" path="."/>
|
||||||
|
</paths>
|
@ -19,7 +19,10 @@ allprojects {
|
|||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
jcenter()
|
jcenter()
|
||||||
|
|
||||||
|
maven {
|
||||||
|
url "https://storage.googleapis.com/snap-kit-build/maven"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user