I'm having a issue uploading a file to Google Drive.
W/System.err: java.io.FileNotFoundException: /storage/emulated/0/Android/data/dev/files/backup/https:/i.picsum.photos/id/723/200/200.jpg? (No such file or directory)
This is my following code.
Source code from
https://www.section.io/engineering-education/backup-services-with-google-drive-api-in-android/
class GoogleDriveUtils(private val context: Context) {
fun initializeGoogleClient() {
val signInOptions = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail()
.requestScopes(Scope(DriveScopes.DRIVE_FILE), Scope(DriveScopes.DRIVE_APPDATA))
.build()
val client = GoogleSignIn.getClient(context, signInOptions)
(context as? Activity)?.startActivityForResult(
client.signInIntent,
SignUpFragment.RC_SIGN_IN
)
}
fun googleDriverIntegrate() {
GoogleSignIn.getLastSignedInAccount(context)?.let { googleAccount ->
val credential = GoogleAccountCredential.usingOAuth2(
context, listOf(DriveScopes.DRIVE_FILE)
)
credential.selectedAccount = googleAccount.account!!
}
}
fun getDriveService(): Drive? {
GoogleSignIn.getLastSignedInAccount(context)?.let { googleAccount ->
val credential = GoogleAccountCredential.usingOAuth2(
context, listOf(DriveScopes.DRIVE_FILE)
)
credential.selectedAccount = googleAccount.account!!
return Drive.Builder(
AndroidHttp.newCompatibleTransport(),
JacksonFactory.getDefaultInstance(),
credential
)
.setApplicationName(context.getString(R.string.app_name))
.build()
}
return null
}
fun accessDriveFiles(savePath: String?) {
getDriveService()?.let { googleDriveService ->
CoroutineScope(Dispatchers.IO).launch {
var pageToken: String?
do {
val result = googleDriveService.files().list().apply {
spaces = "drive"
fields = "nextPageToken, files(id, name)"
pageToken = this.pageToken
}.execute()
result.files.forEach { file ->
Log.d("FILE", ("name=${file.name} id=${file.id}"))
}
} while (pageToken != null)
}
val FILE_NAME_BACKUP="test.txt"
val localFileDirectory = File(context.getExternalFilesDir("backup")!!.toURI())
val actualFile = savePath?.let { File(it) }
val gFile = com.google.api.services.drive.model.File()
if (actualFile != null) {
gFile.name = actualFile.name
}
if (actualFile != null) {
Log.e("actualFile", actualFile.name)
}
val fileContent = FileContent("text/plain", actualFile)
googleDriveService.Files().create(gFile, fileContent).execute()
}
}
fun uploadFileToGDrive(path: String?) {
getDriveService()?.let { googleDriveService ->
CoroutineScope(Dispatchers.IO).launch {
try {
val localFileDirectory =
File(context.getExternalFilesDir("backup")!!.toURI())
val actualFile = File("${localFileDirectory}/$path")
val gFile = com.google.api.services.drive.model.File()
gFile.name = actualFile.name
val fileContent = FileContent("image/jpeg", actualFile)
googleDriveService.Files().create(gFile, fileContent).execute()
Log.e("File uploaded", "File uploaded")
} catch (exception: Exception) {
exception.printStackTrace()
}
}
} ?: Toast.makeText(context, "Please Log In first!", LENGTH_SHORT).show()
}
fun downloadFileFromGDrive(id: String) {
getDriveService()?.let { googleDriveService ->
CoroutineScope(Dispatchers.IO).launch {
googleDriveService.Files().get(id).execute()
}
} ?: Toast.makeText(context, "Please Log In first!", LENGTH_SHORT).show()
}
}
Related
I'm trying to get access token and refresh token from my app. I'm using one tap sign in but I cant seem to get the desired access and refresh tokens (for Oauth2) .One tap works just fine in both signIn/signUp. I tried using the following:
Module:
#Provides
fun provideOneTapClient(
context: Context
) = Identity.getSignInClient(context)
#Provides
#Named("signInRequest")
fun provideSignInRequest(
app: Application
) = BeginSignInRequest.builder()
.setGoogleIdTokenRequestOptions(
BeginSignInRequest.GoogleIdTokenRequestOptions.builder()
.setSupported(true)
.setServerClientId(app.getString(R.string.web_client_id))
.setFilterByAuthorizedAccounts(true)
.build()
)
.setAutoSelectEnabled(true)
.build()
#Provides
#Named("signUpRequest")
fun provideSignUpRequest(
app: Application
) = BeginSignInRequest.builder()
.setGoogleIdTokenRequestOptions(
BeginSignInRequest.GoogleIdTokenRequestOptions.builder()
.setSupported(true)
.setServerClientId(app.getString(R.string.web_client_id))
.setFilterByAuthorizedAccounts(false)
.build()
)
.build()
#Provides
fun provideGoogleSignInOptions(
app: Application
) = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(app.getString(R.string.web_client_id))
.requestScopes(Scope(CalendarScopes.CALENDAR))
.requestServerAuthCode(app.getString(R.string.web_client_id), true)
.requestEmail()
.build()
#Provides
fun provideGoogleSignInClient(
app: Application,
options: GoogleSignInOptions
) = GoogleSignIn.getClient(app, options)
#Provides
fun provideAuthRepository(
auth: FirebaseAuth,
oneTapClient: SignInClient,
#Named("signInRequest")
signInRequest: BeginSignInRequest,
#Named("signUpRequest")
signUpRequest: BeginSignInRequest,
signInClient: GoogleSignInClient,
usersRef: CollectionReference
): AuthRepository = AuthRepositoryImpl(
auth = auth,
oneTapClient = oneTapClient,
signInRequest = signInRequest,
signUpRequest = signUpRequest,
signInClient = signInClient,
usersRef = usersRef
)
AuthImpl:
override suspend fun oneTapSignInWithGoogle() = flow {
try {
emit(Loading)
val result = oneTapClient.beginSignIn(signInRequest).await()
emit(Success(result))
} catch (e: Exception) {
emit(Failure(e))
}
}
override suspend fun oneTapSignUpWithGoogle() = flow {
try {
emit(Loading)
val result = oneTapClient.beginSignIn(signUpRequest).await()
emit(Success(result))
} catch (e: Exception) {
emit(Failure(e))
}
}
override suspend fun firebaseSignInWithGoogle(googleCredential: AuthCredential) = flow {
try {
emit(Loading)
val authResult = auth.signInWithCredential(googleCredential).await()
val isNewUser = authResult.additionalUserInfo?.isNewUser
emit(Success(isNewUser))
} catch (e: Exception) {
emit(Failure(e))
}
}
viewmodel:
override suspend fun oneTapSignInWithGoogle() = flow {
try {
emit(Loading)
val result = oneTapClient.beginSignIn(signInRequest).await()
emit(Success(result))
} catch (e: Exception) {
emit(Failure(e))
}
}
override suspend fun oneTapSignUpWithGoogle() = flow {
try {
emit(Loading)
val result = oneTapClient.beginSignIn(signUpRequest).await()
emit(Success(result))
} catch (e: Exception) {
emit(Failure(e))
}
}
override suspend fun firebaseSignInWithGoogle(googleCredential: AuthCredential) = flow {
try {
emit(Loading)
val authResult = auth.signInWithCredential(googleCredential).await()
val isNewUser = authResult.additionalUserInfo?.isNewUser
emit(Success(isNewUser))
} catch (e: Exception) {
emit(Failure(e))
}
}
SignIn Screen:
val launcher = rememberLauncherForActivityResult(StartIntentSenderForResult()) { result ->
if (result.resultCode == RESULT_OK) {
try {
val credentials = viewModel.oneTapClient.getSignInCredentialFromIntent(result.data)
val googleIdToken = credentials.googleIdToken
val googleCredentials = getCredential(googleIdToken, null)
viewModel.signInWithGoogle(googleCredentials)
} catch (it: ApiException) {
print(it)
}
}
}
fun launch(signInResult: BeginSignInResult) {
val intent = IntentSenderRequest.Builder(signInResult.pendingIntent.intentSender).build()
launcher.launch(intent)
}
when (val oneTapSignInResponse = viewModel.oneTapSignInState.value) {
is Loading -> ProgressBar()
is Success -> oneTapSignInResponse.data?.let {
LaunchedEffect(it) {
launch(it)
}
}
is Failure -> oneTapSignInResponse.e?.let {
LaunchedEffect(Unit) {
print(it)
if (it.message == "16: Cannot find a matching credential.") {
viewModel.oneTapSignUp()
}
}
}
}
when (val oneTapSignUpResponse = viewModel.oneTapSignUpState.value) {
is Loading -> ProgressBar()
is Success -> oneTapSignUpResponse.data?.let {
LaunchedEffect(it) {
launch(it)
}
}
is Failure -> oneTapSignUpResponse.e?.let {
LaunchedEffect(Unit) {
print(it)
}
}
}
when (val signInResponse = viewModel.signInState.value) {
is Loading -> ProgressBar()
is Success -> signInResponse.data?.let { isNewUser ->
if (isNewUser) {
LaunchedEffect(isNewUser) {
viewModel.createUser()
}
} else {
LaunchedEffect(Unit) {
navController.navigate(EisenhowerScreens.EisenHomeScreen.name) {
popUpTo(EisenhowerScreens.LoginScreen.name) {
inclusive = true
}
}
}
}
}
is Failure -> signInResponse.e?.let {
LaunchedEffect(Unit) {
print(it)
}
}
}
I'm using jetpack compose for the app. and I'm not sure what I need to have Access and Refresh tokens.
Please assist,
I have upgraded my flutter to 3.0.1 • channel stable ,
dart sdk version to Dart SDK version: 2.17.1 (stable) (Tue May 17 17:58:21 2022 +0000) on "windows_x64".
kotlin version ext.kotlin_version = '1.6.20' in /android/build.gradle file.
When I try to start my app I get the following error
C:\Users\[MY_USER]\AppData\Local\Pub\Cache\hosted\pub.dartlang.org\photo_manager-
1.3.10\android\src\main\kotlin\top\kikt\imagescanner\core\PhotoManagerPlugin.kt: (128, 36): Type
mismatch: inferred type is Boolean? but Boolean was expected
e: C:\Users\[MY_USER]\AppData\Local\Pub\Cache\hosted\pub.dartlang.org\photo_manager-
1.3.10\android\src\main\kotlin\top\kikt\imagescanner\core\PhotoManagerPlugin.kt: (128, 41): Type
mismatch: inferred type is Boolean? but Boolean was expected
2
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':photo_manager:compileDebugKotlin'.
> A failure occurred while executing org.jetbrains.kotlin.compilerRunner.GradleCompilerRunnerWithWorkers$GradleKotlinCompilerWorkAction
> Compilation error. See log for more details
* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
* Get more help at https://help.gradle.org
BUILD FAILED in 6m 26s
Exception: Gradle task assembleDebug failed with exit code 1
Exited (sigterm)
I'm not sure what else is missing. I did not edit any kotlin code.
Kotlin MainActivity.kt
package com.company.app
import io.flutter.embedding.android.FlutterActivity
class MainActivity: FlutterActivity() {
}
PhotoManagerPlugin.kt code
package top.kikt.imagescanner.core
import android.Manifest
import android.app.Activity
import android.content.Context
import android.content.pm.PackageManager
import android.os.Build
import android.os.Handler
import androidx.annotation.RequiresApi
import com.bumptech.glide.Glide
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import top.kikt.imagescanner.core.entity.AssetEntity
import top.kikt.imagescanner.core.entity.FilterOption
import top.kikt.imagescanner.core.entity.PermissionResult
import top.kikt.imagescanner.core.entity.ThumbLoadOption
import top.kikt.imagescanner.core.utils.ConvertUtils
import top.kikt.imagescanner.core.utils.IDBUtils
import top.kikt.imagescanner.core.utils.belowSdk
import top.kikt.imagescanner.permission.PermissionsListener
import top.kikt.imagescanner.permission.PermissionsUtils
import top.kikt.imagescanner.util.LogUtils
import top.kikt.imagescanner.util.ResultHandler
import java.util.concurrent.ArrayBlockingQueue
import java.util.concurrent.ThreadPoolExecutor
import java.util.concurrent.TimeUnit
/// create 2019-09-05 by cai
class PhotoManagerPlugin(
private val applicationContext: Context,
messenger: BinaryMessenger,
private var activity: Activity?,
private val permissionsUtils: PermissionsUtils
) : MethodChannel.MethodCallHandler {
val deleteManager = PhotoManagerDeleteManager(applicationContext, activity)
fun bindActivity(activity: Activity?) {
this.activity = activity
deleteManager.bindActivity(activity)
}
companion object {
private const val poolSize = 8
private val threadPool: ThreadPoolExecutor = ThreadPoolExecutor(
poolSize + 3,
1000,
200,
TimeUnit.MINUTES,
ArrayBlockingQueue(poolSize + 3)
)
fun runOnBackground(runnable: () -> Unit) {
threadPool.execute(runnable)
}
var cacheOriginBytes = true
}
private val notifyChannel = PhotoManagerNotifyChannel(applicationContext, messenger, Handler())
init {
permissionsUtils.permissionsListener = object : PermissionsListener {
override fun onDenied(
deniedPermissions: MutableList<String>,
grantedPermissions: MutableList<String>
) {
}
override fun onGranted() {
}
}
}
private val photoManager = PhotoManager(applicationContext)
private var ignorePermissionCheck = false
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
val resultHandler = ResultHandler(result, call)
if (call.method == "ignorePermissionCheck") {
val ignore = call.argument<Boolean>("ignore")!!
ignorePermissionCheck = ignore
resultHandler.reply(ignore)
return
}
var needLocationPermissions = false
val handleResult = when (call.method) {
"releaseMemCache" -> {
photoManager.clearCache()
resultHandler.reply(1)
true
}
"log" -> {
LogUtils.isLog = call.arguments()
resultHandler.reply(1)
true
}
"openSetting" -> {
permissionsUtils.getAppDetailSettingIntent(activity)
resultHandler.reply(1)
true
}
"clearFileCache" -> {
Glide.get(applicationContext).clearMemory()
runOnBackground {
photoManager.clearFileCache()
resultHandler.reply(1)
}
true
}
"forceOldApi" -> {
photoManager.useOldApi = true
resultHandler.reply(1)
true
}
"systemVersion" -> {
resultHandler.reply(Build.VERSION.SDK_INT.toString())
true
}
"cacheOriginBytes" -> {
cacheOriginBytes = call.arguments()
resultHandler.reply(cacheOriginBytes)
true
}
"getLatLngAndroidQ" -> {
/// 这里不拦截, 然后额外添加gps权限
needLocationPermissions = true
false
}
"copyAsset" -> {
needLocationPermissions = true
false
}
"getFullFile" -> {
val isOrigin = call.argument<Boolean>("isOrigin")!!
if (isOrigin && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
needLocationPermissions = true
}
false
}
"getOriginBytes" -> {
needLocationPermissions = true
false
}
"getMediaUrl" -> {
false
}
else -> false
}
if (handleResult) {
return
}
if (ignorePermissionCheck) {
onHandlePermissionResult(call, resultHandler, true)
return
}
if (permissionsUtils.isRequesting) {
resultHandler.replyError(
"PERMISSION_REQUESTING",
"Another permission request is still ongoing. Please request after the existing one is done.",
null
)
return
}
val utils = permissionsUtils.apply {
withActivity(activity)
permissionsListener = object : PermissionsListener {
override fun onDenied(
deniedPermissions: MutableList<String>,
grantedPermissions: MutableList<String>
) {
LogUtils.info("onDenied call.method = ${call.method}")
if (call.method == "requestPermissionExtend") {
resultHandler.reply(PermissionResult.Denied.value)
return
}
if (grantedPermissions.containsAll(
arrayListOf(
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
)
)
) {
LogUtils.info("onGranted call.method = ${call.method}")
onHandlePermissionResult(call, resultHandler, false)
} else {
replyPermissionError(resultHandler)
}
}
override fun onGranted() {
LogUtils.info("onGranted call.method = ${call.method}")
onHandlePermissionResult(call, resultHandler, true)
}
}
}
val permissions = arrayListOf(
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
)
if (needLocationPermissions && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && haveManifestMediaLocation(
applicationContext
)
) {
permissions.add(Manifest.permission.ACCESS_MEDIA_LOCATION)
}
utils.getPermissions(3001, permissions)
}
#RequiresApi(Build.VERSION_CODES.Q)
private fun haveManifestMediaLocation(context: Context): Boolean {
// Debug.waitForDebugger()
val applicationInfo = context.applicationInfo
val packageInfo = context.packageManager.getPackageInfo(
applicationInfo.packageName,
PackageManager.GET_PERMISSIONS
)
return packageInfo.requestedPermissions.contains(Manifest.permission.ACCESS_MEDIA_LOCATION)
}
private fun replyPermissionError(resultHandler: ResultHandler) {
resultHandler.replyError("Request for permission failed.", "User denied permission.", null)
}
private fun onHandlePermissionResult(
call: MethodCall,
resultHandler: ResultHandler,
haveLocationPermission: Boolean
) {
when (call.method) {
"requestPermissionExtend" -> resultHandler.reply(PermissionResult.Authorized.value)
"getGalleryList" -> {
if (Build.VERSION.SDK_INT >= 29) {
notifyChannel.setAndroidQExperimental(true)
}
runOnBackground {
val type = call.argument<Int>("type")!!
val hasAll = call.argument<Boolean>("hasAll")!!
val option = call.getOption()
val onlyAll = call.argument<Boolean>("onlyAll")!!
val list = photoManager.getGalleryList(type, hasAll, onlyAll, option)
resultHandler.reply(ConvertUtils.convertToGalleryResult(list))
}
}
"getAssetWithGalleryId" -> {
runOnBackground {
val id = call.argument<String>("id")!!
val page = call.argument<Int>("page")!!
val pageCount = call.argument<Int>("pageCount")!!
val type = call.argument<Int>("type")!!
val option = call.getOption()
val list = photoManager.getAssetList(id, page, pageCount, type, option)
resultHandler.reply(ConvertUtils.convertToAssetResult(list))
}
}
"getAssetListWithRange" -> {
runOnBackground {
val galleryId = call.getString("galleryId")
val type = call.getInt("type")
val start = call.getInt("start")
val end = call.getInt("end")
val option = call.getOption()
val list: List<AssetEntity> =
photoManager.getAssetListWithRange(galleryId, type, start, end, option)
resultHandler.reply(ConvertUtils.convertToAssetResult(list))
}
}
"getThumb" -> {
runOnBackground {
val id = call.argument<String>("id")!!
val optionMap = call.argument<Map<*, *>>("option")!!
val option = ThumbLoadOption.fromMap(optionMap)
photoManager.getThumb(id, option, resultHandler)
}
}
"requestCacheAssetsThumb" -> {
runOnBackground {
val ids = call.argument<List<String>>("ids")!!
val optionMap = call.argument<Map<*, *>>("option")!!
val option = ThumbLoadOption.fromMap(optionMap)
photoManager.requestCache(ids, option, resultHandler)
}
}
"cancelCacheRequests" -> {
runOnBackground {
photoManager.cancelCacheRequests()
}
}
"assetExists" -> {
runOnBackground {
val id = call.argument<String>("id")!!
photoManager.assetExists(id, resultHandler)
}
}
"getFullFile" -> {
runOnBackground {
val id = call.argument<String>("id")!!
val isOrigin =
if (!haveLocationPermission) false else call.argument<Boolean>("isOrigin")!!
photoManager.getFile(id, isOrigin, resultHandler)
}
}
"getOriginBytes" -> {
runOnBackground {
val id = call.argument<String>("id")!!
photoManager.getOriginBytes(
id,
cacheOriginBytes,
haveLocationPermission,
resultHandler
)
}
}
"getMediaUrl" -> {
runOnBackground {
val id = call.argument<String>("id")!!
val type = call.argument<Int>("type")!!
val mediaUri = photoManager.getMediaUri(id, type)
resultHandler.reply(mediaUri)
}
}
"getPropertiesFromAssetEntity" -> {
runOnBackground {
val id = call.argument<String>("id")!!
val asset = photoManager.getAssetProperties(id)
val assetResult = if (asset != null) {
ConvertUtils.convertToAssetResult(asset)
} else {
null
}
resultHandler.reply(assetResult)
}
}
"fetchPathProperties" -> {
runOnBackground {
val id = call.argument<String>("id")!!
val type = call.argument<Int>("type")!!
val option = call.getOption()
val pathEntity = photoManager.getPathEntity(id, type, option)
if (pathEntity != null) {
val mapResult = ConvertUtils.convertToGalleryResult(listOf(pathEntity))
resultHandler.reply(mapResult)
} else {
resultHandler.reply(null)
}
}
}
"getLatLngAndroidQ" -> {
runOnBackground {
val id = call.argument<String>("id")!!
// 读取id
val location = photoManager.getLocation(id)
resultHandler.reply(location)
}
}
"notify" -> {
runOnBackground {
val notify = call.argument<Boolean>("notify")
if (notify == true) {
notifyChannel.startNotify()
} else {
notifyChannel.stopNotify()
}
}
}
"deleteWithIds" -> {
runOnBackground {
try {
val ids = call.argument<List<String>>("ids")!!
if (belowSdk(29)) {
deleteManager.deleteInApi28(ids)
resultHandler.reply(ids)
} else if (IDBUtils.isAndroidR) {
val uris = ids.map {
photoManager.getUri(it)
}.toList()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
deleteManager.deleteInApi30(uris, resultHandler)
}
} else {
val uris = ids.mapNotNull { photoManager.getUri(it) }
// for (id in ids) {
// val uri = photoManager.getUri(id)
// if (uri != null) {
// deleteManager.deleteWithUriInApi29(uri, false)
// }
// }
deleteManager.deleteWithUriInApi29(ids, uris, resultHandler, false)
}
} catch (e: Exception) {
LogUtils.error("deleteWithIds failed", e)
resultHandler.replyError("deleteWithIds failed")
}
}
}
"saveImage" -> {
runOnBackground {
try {
val image = call.argument<ByteArray>("image")!!
val title = call.argument<String>("title") ?: ""
val desc = call.argument<String>("desc") ?: ""
val relativePath = call.argument<String>("relativePath") ?: ""
val entity = photoManager.saveImage(image, title, desc, relativePath)
if (entity == null) {
resultHandler.reply(null)
return#runOnBackground
}
val map = ConvertUtils.convertToAssetResult(entity)
resultHandler.reply(map)
} catch (e: Exception) {
LogUtils.error("save image error", e)
resultHandler.reply(null)
}
}
}
"saveImageWithPath" -> {
runOnBackground {
try {
val imagePath = call.argument<String>("path")!!
val title = call.argument<String>("title") ?: ""
val desc = call.argument<String>("desc") ?: ""
val relativePath = call.argument<String>("relativePath") ?: ""
val entity = photoManager.saveImage(imagePath, title, desc, relativePath)
if (entity == null) {
resultHandler.reply(null)
return#runOnBackground
}
val map = ConvertUtils.convertToAssetResult(entity)
resultHandler.reply(map)
} catch (e: Exception) {
LogUtils.error("save image error", e)
resultHandler.reply(null)
}
}
}
"saveVideo" -> {
runOnBackground {
try {
val videoPath = call.argument<String>("path")!!
val title = call.argument<String>("title")!!
val desc = call.argument<String>("desc") ?: ""
val relativePath = call.argument<String>("relativePath") ?: ""
val entity = photoManager.saveVideo(videoPath, title, desc, relativePath)
if (entity == null) {
resultHandler.reply(null)
return#runOnBackground
}
val map = ConvertUtils.convertToAssetResult(entity)
resultHandler.reply(map)
} catch (e: Exception) {
LogUtils.error("save video error", e)
resultHandler.reply(null)
}
}
}
"copyAsset" -> {
runOnBackground {
val assetId = call.argument<String>("assetId")!!
val galleryId = call.argument<String>("galleryId")!!
photoManager.copyToGallery(assetId, galleryId, resultHandler)
}
}
"moveAssetToPath" -> {
runOnBackground {
val assetId = call.argument<String>("assetId")!!
val albumId = call.argument<String>("albumId")!!
photoManager.moveToGallery(assetId, albumId, resultHandler)
}
}
"removeNoExistsAssets" -> {
runOnBackground {
photoManager.removeAllExistsAssets(resultHandler)
}
}
else -> resultHandler.notImplemented()
}
}
private fun MethodCall.getString(key: String): String {
return this.argument<String>(key)!!
}
private fun MethodCall.getInt(key: String): Int {
return this.argument<Int>(key)!!
}
private fun MethodCall.getOption(): FilterOption {
val arguments = argument<Map<*, *>>("option")!!
return ConvertUtils.convertFilterOptionsFromMap(arguments)
}
}
The issue was due to the use of multi_crop_picker: ^0.0.5, commented it out and app compiled successfully.
I had the same exact problem.
Just check your dependencies versions and update the necessary ones.
In my case, my flutter SDK version was 3.3.6 , and I discovered that two of my dependencies versions were NOT compatible with the flutter version.
The dependencies were :
1- wechat_assets_picker 6.3.0
2-wechat_camera_picker 2.6
I'm trying to read a file from external storage /some/path/somefile.txt
In the manifest I have <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
When I click button to try to read file that was picked by ActivityResultContracts.OpenDocument() I am getting
java.io.FileNotFoundException: /document/primary:some/path/somefile.txt: open failed: ENOENT (No such file or directory)
Here is my code:
#OptIn(ExperimentalPermissionsApi::class)
#Composable
fun ReadFileScreen() {
val readPermissionState = rememberPermissionState(
android.Manifest.permission.READ_EXTERNAL_STORAGE
)
val pickedFileUriState = remember { mutableStateOf<Uri?>(null) }
val launcher =
rememberLauncherForActivityResult(contract = ActivityResultContracts.OpenDocument()) { result ->
pickedFileUriState.value = result
}
Column {
Button(onClick = readPermissionState::launchPermissionRequest) {
Text("request read permission")
}
PermissionRequired(readPermissionState, {}, {}) {
Button(onClick = { launcher.launch(arrayOf("*/*")) }
) {
Text("pick file")
}
if (pickedFileUriState.value != null) Button(onClick = { readTextFile(pickedFileUriState.value!!) }
) {
Text("read file")
}
}
}
}
fun readTextFile(uri: Uri) {
try {
val text = File(uri.path).readText()
println(text)
} catch (e: Exception) {
e.printStackTrace()
}
}
Thanks to #ianhanniballake the link taught me the correct way to access the file picked by user.
Here is the code I came up with:
#OptIn(ExperimentalPermissionsApi::class)
#Composable
fun ReadFileScreen() {
val context = LocalContext.current
val pickedFileUriState = remember { mutableStateOf<Uri?>(null) }
val launcher =
rememberLauncherForActivityResult(contract = ActivityResultContracts.OpenDocument()) { result ->
pickedFileUriState.value = result
}
Column {
Button(onClick = { launcher.launch(arrayOf("*/*")) }
) {
Text("pick file")
}
if (pickedFileUriState.value != null)
Button(onClick = {
readTextFromUri(context, pickedFileUriState.value!!)
}
) {
Text("read file")
}
}
}
private fun readTextFromUri(context: Context, uri: Uri) {
try {
val stringBuilder = StringBuilder()
context.contentResolver.openInputStream(uri)?.use { inputStream ->
BufferedReader(InputStreamReader(inputStream)).use { reader ->
var line: String? = reader.readLine()
while (line != null) {
stringBuilder.append(line)
line = reader.readLine()
}
}
}
val text = stringBuilder.toString()
Log.d("xxx", "text $text")
} catch (e: IOException) {
e.printStackTrace()
}
}
I am getting a class not found exception when trying to click an image from the camera or while fetching it from the directory. The code is in kotlin and has been given below.
This is the class which implements the functionality to capture an image or picks them from the gallery.
The methods _openCamera() and openFileSelector() are implemented.
The main motive was to capture the images and upload them in the server but the implemented methods doesn't give the proper results.
class MainActivity : AppCompatActivity() {
private var drawerResult: Drawer? = null
private var jobschedular: JobScheduler? = null
private var jobschedularCode: Int = 1
private var phoneNumber: String? = null
private var toolbar: Toolbar? = null
private var familyId: String? = null
val TAG: String? = "Activity_Name"
val REQUEST_IMAGE_CAPTURE = 1
val REQUEST_CODE_FOR_GALLERY_CAPTURE = 2
var photoFile: File? = null
var progressDialog: Dialog? = null
private var doubleBackToExitPressedOnce = false
#SuppressLint("PrivateResource")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
overridePendingTransition(R.anim.fade_in, R.anim.fade_out)
Log.d(TAG, "Inside MainActivity")
//onclick listener for open camera
onclickListenerForOpenCamera()
//starting the services here . .
val service_checkAddedtoFamily = Intent(this, checkAddedToFamily::class.java)
startService(service_checkAddedtoFamily)
val service_checkDocsToBeVerified = Intent(this, checkDocsToBeVerified::class.java)
startService(service_checkDocsToBeVerified)
/*findViewById<Button>(R.id.scan).setOnClickListener {
val i = Intent(this, Testers::class.java)
i.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
i.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
startActivity(i)
overridePendingTransition(R.anim.fade_in, R.anim.fade_out)
}*/
//onclick listener for select image button
attach_onclick_listener_to_add_photos_from_gallery()
//onclick listener for select pdf files
onclickListenerForSelectPdfFile()
//get toolbar for drawer
toolbar = findViewById(R.id.toolbar_tabs)
//get phone number
val loginInfo = applicationContext.getSharedPreferences("loginInfo", Context.MODE_PRIVATE)
phoneNumber = loginInfo.getString("phoneNumber", "")
//onclick listener for upload button
//onclickListenerForUploadButton()
//onclick listener for retrieve button
onclickListenerForRetrieveButton()
//on click permanent diseases button
//onclickPermanentDiseasesButtton()
//navigation drawer
left_drawer(this, this#MainActivity, toolbar!!).createNavigationDrawer()
//verify auto upload
verifyAutoLoginInformation()
//create Sqlite database
DB_HELPER(this#MainActivity).writableDatabase
//get job schedular service
jobschedular = applicationContext.getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler
schedulTheJobForHealthGoals()
schedulTheJobForHealthInsurance()
setPreferencesForNutrition()
schedulTheJobForNutrition()
schedulTheJobForSyncNutritionOnline()
}
/*override fun onBackPressed() {
if (doubleBackToExitPressedOnce) {
super.onBackPressed()
return
}
this.doubleBackToExitPressedOnce = true
Toast.makeText(this, "Press back again to exit", Toast.LENGTH_SHORT).show()
Handler().postDelayed(Runnable { doubleBackToExitPressedOnce = false }, 2000)
}*/
//job schedular
fun schedulTheJobForHealthGoals() {
val builder = JobInfo.Builder(jobschedularCode, ComponentName(this#MainActivity, health_goals_services::class.java))
.setPersisted(true)
.setPeriodic(5000)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
.setRequiresCharging(false)
.setRequiresDeviceIdle(false)
val bundle = PersistableBundle()
bundle.putString("key", "value")
builder.setExtras(bundle)
val s_response = jobschedular!!.schedule(builder.build())
if (s_response <= 0) {
//something goes wrong
}
}
fun schedulTheJobForHealthInsurance() {
val builder = JobInfo.Builder(jobschedularCode, ComponentName(this#MainActivity, health_insurance_service::class.java))
.setPersisted(true)
.setPeriodic(5000)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
.setRequiresCharging(false)
.setRequiresDeviceIdle(false)
val bundle = PersistableBundle()
bundle.putString("key", "value")
builder.setExtras(bundle)
val s_response = jobschedular!!.schedule(builder.build())
if (s_response <= 0) {
//something goes wrong
}
}
fun schedulTheJobForNutrition() {
val builder = JobInfo.Builder(jobschedularCode, ComponentName(this#MainActivity, nutrition_service::class.java))
.setPersisted(true)
.setPeriodic(5000) //change to 1 hour
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
.setRequiresCharging(false)
.setRequiresDeviceIdle(false)
val bundle = PersistableBundle()
bundle.putString("key", "value")
builder.setExtras(bundle)
val s_response = jobschedular!!.schedule(builder.build())
if (s_response <= 0) {
//something goes wrong
}
}
fun setPreferencesForNutrition() {
val nutritionInfo = getSharedPreferences("nutrition", Context.MODE_PRIVATE)
val editor = nutritionInfo.edit()
editor.putString("breakFastTime_Hour", "7")
editor.putString("lunchTime_Hour", "14") //TODO: change to 13
editor.putString("DinnerTime_Hour", "20")
editor.apply()
}
fun schedulTheJobForSyncNutritionOnline() {
val builder = JobInfo.Builder(jobschedularCode, ComponentName(this#MainActivity, sync_nutrition_online::class.java))
.setPersisted(true)
.setPeriodic(5000)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
.setRequiresCharging(false)
.setRequiresDeviceIdle(false)
val bundle = PersistableBundle()
bundle.putString("key", "value")
builder.setExtras(bundle)
val s_response = jobschedular!!.schedule(builder.build())
if (s_response <= 0) {
//something goes wrong
}
}
//buttons on home screen
/*fun onclickListenerForUploadButton(){
findViewById<ImageView>(R.id.uploadButton).setOnClickListener{
openModeOfUploadActivity()
}
}*/
fun onclickListenerForRetrieveButton() {
findViewById<Button>(R.id.retrieveButton).setOnClickListener {
openHistoryActivity()
}
}
/*fun onclickPermanentDiseasesButtton(){
findViewById<Button>(R.id.permanentDiseasesButton).setOnClickListener{
openPermanentDiseases()
}
}*/
/*fun openModeOfUploadActivity(){
val intent = Intent(this,MainActivity::class.java)
startActivity(intent)
}*/
fun openHistoryActivity() {
val intent = Intent(this, history_pickFamilyMember::class.java)
startActivity(intent)
overridePendingTransition(R.anim.fade_in, R.anim.fade_out)
}
/*fun openPermanentDiseases(){
val intent = Intent(this,permanentDiseaese::class.java)
startActivity(intent)
}
*/
//verify auto login information
fun verifyAutoLoginInformation() {
val loginInfo = applicationContext.getSharedPreferences("loginInfo", Context.MODE_PRIVATE)
if (loginInfo.contains("familyOrIndividual") == true) {
//for family
if (loginInfo.getString("familyOrIndividual", "").toString() == "f") {
if (loginInfo.contains("phoneNumber") == true && loginInfo.contains("password") == true) {
val phoneNumber = loginInfo.getString("phoneNumber", "")
val password = loginInfo.getString("password", "")
individual_family_login(this#MainActivity).makeFamilyLoginApiRequest(phoneNumber, password)
} else {
left_drawer(this, this#MainActivity, toolbar!!).makeUserLogOut()
}
}
//for individual
if (loginInfo.getString("familyOrIndividual", "").toString() == "i") {
if (loginInfo.contains("phoneNumber") == true && loginInfo.contains("password") == true) {
val phoneNumber = loginInfo.getString("phoneNumber", "")
val password = loginInfo.getString("password", "")
individual_family_login(this#MainActivity).makeLoginApiRequest(phoneNumber, password)
} else {
left_drawer(this, this#MainActivity, toolbar!!).makeUserLogOut()
}
}
//for security
if (loginInfo.getString("familyOrIndividual", "").toString() != "i" && loginInfo.getString("familyOrIndividual", "").toString() != "f") {
left_drawer(this, this#MainActivity, toolbar!!).makeUserLogOut()
}
} else {
left_drawer(this, this#MainActivity, toolbar!!).makeUserLogOut()
}
}
//camera scan
fun onclickListenerForOpenCamera() {
findViewById<ImageView>(R.id.openCamera).setOnClickListener {
get_permissions_camera()
}
}
fun _openCamera() {
Log.d("Errors__", "inside _openCamera()")
try {
val takePictureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
try {
photoFile = createImageFile()
} catch (ex: Exception) {
Log.d("Errors__", "inside: " + ex.toString())
}
if (photoFile != null) {
val builder: StrictMode.VmPolicy.Builder = StrictMode.VmPolicy.Builder()
StrictMode.setVmPolicy(builder.build())
val photoURI: Uri = Uri.fromFile(photoFile!!)
Log.d("Path__", "photoURI: $photoURI")
Log.d("Path__", "photoURI.path: " + photoURI.path)
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI)
takePictureIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE)
}
}
} catch (e: Exception) {
Log.d("Errors__", "_openCamera" + e.toString())
}
}
fun createImageFile(): File {
Log.d("Errors__", "inside createImageFile()")
val mCurrentPhotoPath: String
val imageFileName = "camera"
val storageDir: File = getExternalFilesDir(Environment.DIRECTORY_PICTURES)
val image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
)
// Save a file: path for use with ACTION_VIEW intents
mCurrentPhotoPath = image.getAbsolutePath()
Log.d("Path__", "Image: $image")
return image
}
//file selector
fun onclickListenerForSelectPdfFile() {
findViewById<ImageView>(R.id.selectPdfFile).setOnClickListener {
get_permissions_fileExplorer()
}
}
#SuppressLint("SdCardPath")
fun openFileSelector() {
val properties = DialogProperties()
properties.selection_mode = DialogConfigs.MULTI_MODE;
properties.selection_type = DialogConfigs.FILE_SELECT;
properties.root = File(DialogConfigs.DEFAULT_DIR);
properties.error_dir = File(DialogConfigs.DEFAULT_DIR);
properties.offset = File(DialogConfigs.DEFAULT_DIR);
properties.extensions = null;
val dialog: FilePickerDialog = FilePickerDialog(this#MainActivity, properties)
dialog.setTitle("Select a File")
dialog.setDialogSelectionListener(object : DialogSelectionListener {
override fun onSelectedFilePaths(files: Array<out String>?) {
convertPdfToImages(files!!)
}
})
dialog.show()
}
fun convertPdfToImages(files: Array<out String>) {
showProcessProgress()
doAsync {
var uriList: MutableList<Uri>? = mutableListOf()
val no_of_files = files.size
var counter = 0
while (counter < no_of_files) {
var pdfFile = File(files[counter])
val decodeService = DecodeServiceBase(PdfContext())
decodeService.setContentResolver(applicationContext.getContentResolver())
decodeService.open(Uri.fromFile(pdfFile))
val pageCount: Int = decodeService.getPageCount()
var i = 0
while (i < pageCount) {
val page: PdfPage = decodeService.getPage(i) as PdfPage
val rectF = RectF(0.toFloat(), 0.toFloat(), 1.toFloat(), 1.toFloat())
// do a fit center to 1920x1080
val scaleBy = 1
val with: Int = (page.getWidth() * scaleBy)
val height: Int = (page.getHeight() * scaleBy)
val bitmap: Bitmap = page.renderBitmap(with, height, rectF)
try {
val outputFile = File(applicationContext.externalCacheDir,
System.currentTimeMillis().toString() + ".jpg")
val outputStream = FileOutputStream(outputFile)
// a bit long running
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream)
uriList!!.add(Uri.fromFile(outputFile))
outputStream.close()
} catch (e: IOException) {
}
i++
}
counter++
}
uiThread {
progressDialog!!.hide()
openPreview(uriList!!)
Log.d("mess", "size: " + uriList.size + " " + uriList.toString())
}
}
}
//select image
fun attach_onclick_listener_to_add_photos_from_gallery() {
findViewById<ImageView>(R.id.selectImage).setOnClickListener {
get_permissions_gallery()
}
}
fun open_selector() {
Matisse.from(this)
.choose(MimeType.allOf())
.countable(true)
.maxSelectable(200)
.restrictOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
.thumbnailScale(0.85f)
.imageEngine(PicassoEngine())
.forResult(REQUEST_CODE_FOR_GALLERY_CAPTURE)
}
//activity results
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == Activity.RESULT_OK) {
var uriOfImage = Uri.fromFile(photoFile)
Log.d("fileCapturing__", "URI Image: $uriOfImage")
//start croper
CropImage.activity(uriOfImage)
.start(this)
}
if (requestCode == REQUEST_CODE_FOR_GALLERY_CAPTURE && resultCode == Activity.RESULT_OK) {
var selected_images = Matisse.obtainResult(data)
openPreview(selected_images!!)
}
//for croper
if (requestCode == CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE) {
val result: CropImage.ActivityResult = CropImage.getActivityResult(data)
if (resultCode == RESULT_OK) {
doAsync {
val builder: StrictMode.VmPolicy.Builder = StrictMode.VmPolicy.Builder()
StrictMode.setVmPolicy(builder.build())
var resultUri: Uri = result.getUri()
//save cropped image for persisitance
val croppedImage = createImageFile() //empty
val outputStream = FileOutputStream(croppedImage)
// a bit long running
(Picasso.with(this#MainActivity)
.load(resultUri)
.get()
).compress(Bitmap.CompressFormat.JPEG, 100, outputStream)
Log.d("fileCapturing__", "outputStream: $outputStream")
resultUri = Uri.fromFile(croppedImage)
outputStream.close()
uiThread {
//add to mu list
var mu_list = ArrayList<Uri>(1)
mu_list.add(resultUri)
Log.d("fileCapturing__", "camera uri" + resultUri.toString())
openPreview(mu_list)
}
}
} else if (resultCode == CropImage.CROP_IMAGE_ACTIVITY_RESULT_ERROR_CODE) {
val error: Exception = result.getError()
Log.d("fileCapturing__", "Error: $error")
}
}
}
//preview
fun openPreview(list: MutableList<Uri>) {
val _object = list
val i = Intent(this, typeOfDocument::class.java)
val args = Bundle()
args.putSerializable("ARRAYLIST", _object as java.io.Serializable)
i.putExtra("BUNDLE", args)
startActivity(i)
finish()
}
//get permissions
//Camera
fun get_permissions_camera() {
if (ContextCompat.checkSelfPermission(this#MainActivity, android.Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
MaterialDialog.Builder(this#MainActivity)
.title("Camera permission")
.content("Camera permissions are required for opening Camera")
.negativeText("Cancel")
.onNegative(object : MaterialDialog.SingleButtonCallback {
override fun onClick(dialog: MaterialDialog, which: DialogAction) {
}
})
.positiveText("Give Permissions")
.onPositive(object : MaterialDialog.SingleButtonCallback {
override fun onClick(dialog: MaterialDialog, which: DialogAction) {
getPermissionsUsingDexter_camera(
android.Manifest.permission.CAMERA
)
}
})
.show()
} else {
_openCamera()
}
}
fun getPermissionsUsingDexter_camera(permissionString: String) {
Dexter.withActivity(this)
.withPermissions(
permissionString
).withListener(object : MultiplePermissionsListener {
override fun onPermissionRationaleShouldBeShown(permissions: MutableList<PermissionRequest>?, token: PermissionToken?) {
}
override fun onPermissionsChecked(report: MultiplePermissionsReport?) {
if (report!!.areAllPermissionsGranted() == true) {
_openCamera()
Log.d("mess", "permission given")
} else {
Log.d("mess", "permission not granted")
}
}
})
.check()
}
//gallery
fun get_permissions_gallery() {
if (ContextCompat.checkSelfPermission(this#MainActivity, android.Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
MaterialDialog.Builder(this#MainActivity)
.title("Storage permission")
.content("Storage permissions are required for opening the Gallery")
.negativeText("Cancel")
.onNegative(object : MaterialDialog.SingleButtonCallback {
override fun onClick(dialog: MaterialDialog, which: DialogAction) {
}
})
.positiveText("Give Permissions")
.onPositive(object : MaterialDialog.SingleButtonCallback {
override fun onClick(dialog: MaterialDialog, which: DialogAction) {
getPermissionsUsingDexter_gallery(
android.Manifest.permission.READ_EXTERNAL_STORAGE
)
}
})
.show()
} else {
open_selector()
}
}
fun getPermissionsUsingDexter_gallery(permissionString: String) {
Dexter.withActivity(this)
.withPermissions(
permissionString
).withListener(object : MultiplePermissionsListener {
override fun onPermissionRationaleShouldBeShown(permissions: MutableList<PermissionRequest>?, token: PermissionToken?) {
}
override fun onPermissionsChecked(report: MultiplePermissionsReport?) {
if (report!!.areAllPermissionsGranted() == true) {
open_selector()
Log.d("mess", "permission given")
} else {
Log.d("mess", "permission not granted")
}
}
})
.check()
}
//file exploer
fun get_permissions_fileExplorer() {
if (ContextCompat.checkSelfPermission(this#MainActivity, android.Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
MaterialDialog.Builder(this#MainActivity)
.title("Storage permission")
.content("Storage access permissions are required for opening File Explorer")
.negativeText("Cancel")
.onNegative(object : MaterialDialog.SingleButtonCallback {
override fun onClick(dialog: MaterialDialog, which: DialogAction) {
}
})
.positiveText("Give Permissions")
.onPositive(object : MaterialDialog.SingleButtonCallback {
override fun onClick(dialog: MaterialDialog, which: DialogAction) {
getPermissionsUsingDexter_fileExplores(
android.Manifest.permission.READ_EXTERNAL_STORAGE
)
}
})
.show()
} else {
openFileSelector()
}
}
fun getPermissionsUsingDexter_fileExplores(permissionString: String) {
Dexter.withActivity(this)
.withPermissions(
permissionString
).withListener(object : MultiplePermissionsListener {
override fun onPermissionRationaleShouldBeShown(permissions: MutableList<PermissionRequest>?, token: PermissionToken?) {
}
override fun onPermissionsChecked(report: MultiplePermissionsReport?) {
if (report!!.areAllPermissionsGranted() == true) {
openFileSelector()
Log.d("mess", "permission given")
} else {
Log.d("mess", "permission not granted")
}
}
})
.check()
}
//progress bar
fun showProcessProgress() {
progressDialog = MaterialDialog.Builder(this)
.title("Please Wait")
.content("Converting Pdf to Images")
.progress(true, 0)
.show()
}
}
The error shows when I try to click an image or fetch from the library.
The provider path used is given below:
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path
name="external_files"
path="." />
</paths>
I have tried changing the path to "/" but it didn't work. The error wasn't showing earlier but the error exists now.
Here is the snapshot of the logs.
All suggestions are accepted. Thanks in advance.
I'm trying to get the user info with this code but is not showing on the activity
The profile picture and the name are not creating a new user on the base
What am I missing?
Does anyone had coded this using Kotlin?
private fun handleFacebookAccessToken(token: AccessToken) {
Log.d(TAG, "handleFacebookAccessToken:" + token)
val credential = FacebookAuthProvider.getCredential(token.token)
App.currentAuth.signInWithCredential(credential)
.addOnCompleteListener(this) { Log.d(TAG, "signInWithCredential:success") }
.addOnSuccessListener(this) { authResult ->
if (authResult != null) {
val firebaseUser = authResult.user
if (App.database_table_users.child(firebaseUser.uid) == null) {
var facebookId = ""
firebaseUser.providerData
.filter { it.providerId == FacebookAuthProvider.PROVIDER_ID }
.forEach { facebookId = it.uid }
val photoUrl = "https://graph.facebook.com/$facebookId/picture?width=1024&height=1024"
App.database_table_users.child(firebaseUser.uid).setValue(
User(firebaseUser.uid,
firebaseUser.email.orEmpty(),
firebaseUser.displayName.orEmpty(),
photoUrl,
false
)
)
}
}
}
.addOnFailureListener(this) { ex ->
if (ex is FirebaseAuthUserCollisionException) {
LoginManager.getInstance().logOut()
val ad = AlertDialog.Builder(this#LoginActivity)
ad.setMessage(getString(R.string.auth_user_collision))
ad.setPositiveButton(getString(R.string.ok), null)
ad.show()
} else {
ex.printStackTrace()
}
}
}
You must use FirebaseAuth.getInstance() instead of App.currentAuth.
For example;
val mAuth = FirebaseAuth.getInstance()
val credential = FacebookAuthProvider.getCredential(token)
mAuth.signInWithCredential(credential)
.addOnCompleteListener(this) { task ->
if (task.isSuccessful) {
val user = mAuth.currentUser
} else {
task.exception?.printStackTrace()
}
}
Try This it's work for me
private fun loginWithFaceBook()
{
LoginManager.getInstance().registerCallback(callbackManager, facebookCallBack)
LoginManager.getInstance().logInWithReadPermissions(this, Arrays.asList("public_profile","email"))
}
private val facebookCallBack = object : FacebookCallback<LoginResult> {
override fun onSuccess(result: LoginResult?) {
val graphRequest = GraphRequest.newMeRequest(result?.accessToken) { _, response ->
val graphObject = response.jsonObject
val id = if(graphObject.has("id")) graphObject.getString("id") else null
val email = if(graphObject.has("email")) graphObject.getString("email") else null
val firstName = if(graphObject.has("first_name")) graphObject.getString("first_name") else null
val lastName = if(graphObject.has("last_name")) graphObject.getString("last_name") else null
val photoUrl = if(graphObject.has("picture")) {
val picture : JSONObject = graphObject.getJSONObject("picture")
if(picture.has("data") && picture.has("url") && picture.getString("url").isNotBlank()) {
picture.getString("url")
}
else
null
}
else
val bundle = Bundle()
bundle.putString("fields", "id,first_name,last_name,name,picture,email,gender,birthday,link")
graphRequest.parameters = bundle
graphRequest.executeAsync()
}
override fun onError(error: FacebookException) {
when{
error.message != null -> showSnackbar(error.message.toString())
}
}
override fun onCancel() {
}
}