Kotlin:相机仅在模拟器上拍摄照片 (Android 8),并且错误地显示实时数据库中来自存储的照片链接
Kotlin: Camera takes photos only on emulator (Android 8) and incorrectly displays links to photos in Realtime Database from Storage
我正在以 instagram 的形式编写应用程序(我从 YouTube 学习课程,他们在 Android 8 上创建它,我正在尝试在 Android 10 上做同样的事情) ,我只认识 Kotlin 几个星期。已经实施了很多。但是问题出在 firebase 上。两个问题:
- 在应用程序中注册一个用户并将其文本数据保存在 firebase 中——我可以在任何设备上完成。通过 Android 上的模拟器 8 - 我可以拍照并且一切正常,即使 link 更改个人资料照片也能正确显示。还有一个
ShareActivity
文件,用户可以在“墙上”分享照片,问题是照片出现在 google firebase 的存储中,而在实时数据库中 link这张照片写成 "com.google.firebase.storage.UploadTask $TaskSnapshot@46529a6"
,但应该写成 link "https://firebasestorage.googleapis.com/v0/b/instapirate...
",而个人资料照片显示正确,即 posts - 不,照片是根本不可见。如何修复这个错误?我附上一张来自模拟器和数据库的照片:
- 还有一个问题,那就是在 Android 8 上,在 Instagram 模拟器中,我被要求获得使用相机的权限,我同意了,相机工作,拍照,一切都很好。而在 android 10 中,没有请求相机权限,因此相机打开,拍照,但无法保存照片(当我点击“保存”按钮时重新打开)。如果我快速按下按钮几次 - 有时它有助于保存照片,但这种情况发生在百万分之一的情况下。这并不是因为相机的分辨率。
我附上下面的代码:
AndroidManifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.instapirate">
<uses-feature android:name="android.hardware.camera"
android:required="true" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.INSTApirate" >
<activity
android:name=".activities.MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".activities.SearchActivity" />
<activity android:name=".activities.ShareActivity" />
<activity android:name=".activities.LikesActivity" />
<activity android:name=".activities.ProfileActivity" />
<activity
android:name=".activities.EditProfileActivity"
android:exported="true" />
<activity
android:name=".activities.LoginActivity"
android:windowSoftInputMode="stateVisible|adjustResize" >
</activity>
<activity
android:name=".activities.RegisterActivity"
android:windowSoftInputMode="stateVisible|adjustResize" >
</activity>
<activity android:name=".activities.ProfileSettingsActivity" />
<activity android:name=".activities.AddFriendsActivity"/>
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.example.instapirate.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths"></meta-data>
</provider>
</application>
</manifest>
配置文件是使用 EditProfileActivity
文件编辑的。下面有一段具体的代码,拍照和更改用户头像,这里的 link 可以正常工作并以正常形式加载到 Storage 和 RealtimeDatabase 中,但是在 Android 10 上照片也是未拍摄且相机已重置:
private lateinit var mUser: User
private lateinit var mFirebase: FirebaseHelper
private lateinit var mPendingUser: User
private lateinit var mCamera: CameraHelper
@SuppressLint("MissingSuperCall")
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode == mCamera.REQUEST_CODE && resultCode == RESULT_OK) {
mFirebase.uploadUserPhoto(mCamera.imageUri!!) {
mFirebase.storageUid().addOnCompleteListener {
val photoUrl = it.result.toString()
mFirebase.updateUserPhoto(photoUrl){
mUser = mUser.copy(photo = photoUrl)
profile_image.loadUserPhoto(mUser.photo)
}
}
}
}
}
loadUserPhoto
位于一个单独的 utils
文件中,其中存储了所有实用程序:
fun ImageView.loadUserPhoto(photoUrl: String?) =
ifNotDestroyed {
GlideApp.with(this).load(photoUrl).fallback(R.drawable.person).into(this)
}
参与以上代码的远程类:CameraHelper
import android.app.Activity
import android.content.Intent
import android.net.Uri
import android.os.Environment
import android.provider.MediaStore
import androidx.core.content.FileProvider
import java.io.File
import java.text.SimpleDateFormat
import java.util.*
class CameraHelper(private val activity: Activity) {
var imageUri: Uri? = null
val REQUEST_CODE = 1
private val simpleDateFormat = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US)
fun takeCameraPicture() {
val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
if (intent.resolveActivity(activity.packageManager) != null) {
val imageFile = createImageFile()
imageUri = FileProvider.getUriForFile(activity,
"com.example.instapirate.fileprovider",
imageFile)
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri)
activity.startActivityForResult(intent, REQUEST_CODE)
}
}
private fun createImageFile(): File {
val storageDir = activity.getExternalFilesDir(Environment.DIRECTORY_PICTURES)
return File.createTempFile(
"JPEG_${simpleDateFormat.format(Date())}_",
".jpg",
storageDir
)
}
}
FirebaseHelper
import android.app.Activity
import android.net.Uri
import com.example.instapirate.activities.showToast
import com.google.firebase.auth.AuthCredential
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.database.DatabaseReference
import com.google.firebase.database.FirebaseDatabase
import com.google.firebase.storage.FirebaseStorage
import com.google.firebase.storage.StorageReference
import com.google.firebase.storage.UploadTask
class FirebaseHelper(private val activity: Activity) {
val auth: FirebaseAuth = FirebaseAuth.getInstance()
val database: DatabaseReference = FirebaseDatabase.getInstance().reference
val storage: StorageReference = FirebaseStorage.getInstance().reference
fun storageUid() = storage.child("users/${auth.currentUser!!.uid}/photo/").downloadUrl
fun uploadUserPhoto(photo: Uri, onSuccess: (UploadTask.TaskSnapshot) -> Unit) {
storage.child("users/${currentUid()!!}/photo").putFile(photo)
.addOnCompleteListener {
if (it.isSuccessful) {
onSuccess(it.result!!)
} else {
activity.showToast(it.exception!!.message!!)
}
}
}
fun updateUserPhoto(photoUrl: String, onSuccess: () -> Unit) {
database.child("users/${currentUid()!!}/photo").setValue(photoUrl)
.addOnCompleteListener {
if (it.isSuccessful) {
onSuccess()
} else {
activity.showToast(it.exception!!.message!!)
}
}
}
fun updateUser(updates: Map<String, Any?>, onSuccess: () -> Unit) {
database.child("users").child(currentUid()!!).updateChildren(updates)
.addOnCompleteListener {
if (it.isSuccessful) {
onSuccess()
} else {
activity.showToast(it.exception!!.message!!)
}
}
}
fun updateEmail(email: String, onSuccess: () -> Unit) {
auth.currentUser!!.updateEmail(email).addOnCompleteListener {
if (it.isSuccessful) {
onSuccess()
} else {
activity.showToast(it.exception!!.message!!)
}
}
}
fun reauthenticate(credential: AuthCredential, onSuccess: () -> Unit) {
auth.currentUser!!.reauthenticate(credential).addOnCompleteListener {
if (it.isSuccessful) {
onSuccess()
} else {
activity.showToast(it.exception!!.message!!)
}
}
}
fun currentUserReference(): DatabaseReference =
database.child("users").child(currentUid()!!)
fun currentUid(): String? =
auth.currentUser?.uid
}
还有一个 ShareActivity
文件实现了将照片上传到 Feed,这就是 Firebase 出现问题的地方,因为 link 在这里以不正确的形式显示(提要的屏幕截图在上面)。如果照片是通过模拟器在 Android 8 上拍摄的,就会发生这种情况。 (在phone和Android10保存照片后相机重新打开,我必须重新拍照等等一圈)
class ShareActivity : BaseActivity(2) {
private val TAG = "ShareActivity"
private lateinit var mCamera: CameraHelper
private lateinit var mFirebase: FirebaseHelper
private lateinit var mUser: User
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_share)
Log.d(TAG, "onCreate")
mFirebase = FirebaseHelper(this)
mCamera = CameraHelper(this)
mCamera.takeCameraPicture()
back_image.setOnClickListener{finish()}
share_text.setOnClickListener{ share()}
mFirebase.currentUserReference().addValueEventListener(ValueEventListenerAdapter{
mUser = it.asUser()!!
})
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == mCamera.REQUEST_CODE) {
if (resultCode == RESULT_OK) {
GlideApp.with(this).load(mCamera.imageUri).centerCrop().into(post_image)
} else {
finish()
}
}
}
private fun share() {
val imageUri = mCamera. imageUri
if (imageUri != null) {
val uid = mFirebase.currentUid()!!
mFirebase.storage.child("users").child(uid).child("images")
.child(imageUri.lastPathSegment.toString()).putFile(imageUri).addOnCompleteListener{
if (it.isSuccessful){
val imageDownloadUrl = it.result!!.toString()
mFirebase.database.child("images").child(uid).push()
.setValue(imageDownloadUrl)
.addOnCompleteListener {
if (it.isSuccessful) {
mFirebase.database.child("feed-posts").child(uid)
.push()
.setValue(mkFeedPost(uid, imageDownloadUrl))
.addOnCompleteListener {
if (it.isSuccessful) {
startActivity(Intent(this,
ProfileActivity::class.java))
finish()
}
}
} else {
showToast(it.exception!!.message!!)
}
}
} else {
showToast(it.exception!!.message!!)
}
}
}
}
private fun mkFeedPost(uid: String, imageDownloadUrl: String): FeedPost {
return FeedPost(
uid = uid,
username = mUser.username,
image = imageDownloadUrl,
caption = caption_input.text.toString(),
photo = mUser.photo
)
}
}
在android10尝试保存照片时,Debug中出现如下文字(由于限制无法显示全部错误,但我认为这是错误的重要部分):
2022-03-20 19:05:55.711 29351-29351/? I/ple.instapirat: Late-enabling -Xcheck:jni
2022-03-20 19:05:55.855 29351-29351/? E/ple.instapirat: Unknown bits set in runtime_flags: 0x8000
2022-03-20 19:05:56.943 29351-29351/com.example.instapirate I/Perf: Connecting to perf service.
2022-03-20 19:05:57.016 29351-29351/com.example.instapirate I/FirebaseApp: Device unlocked: initializing all Firebase APIs for app [DEFAULT]
2022-03-20 19:05:57.126 29351-29351/com.example.instapirate D/FirebaseAuth: Notifying id token listeners about user ( PjHBujbeapTQxmLl4TgzhgOTzjo2 ).
2022-03-20 19:05:57.158 29351-29351/com.example.instapirate I/FirebaseInitProvider: FirebaseApp initialization successful
2022-03-20 19:05:57.194 29351-29422/com.example.instapirate I/DynamiteModule: Considering local module com.google.android.gms.measurement.dynamite:69 and remote module com.google.android.gms.measurement.dynamite:67
2022-03-20 19:05:57.194 29351-29422/com.example.instapirate I/DynamiteModule: Selected local version of com.google.android.gms.measurement.dynamite
2022-03-20 19:05:57.263 29351-29424/com.example.instapirate E/Perf: Fail to get file list com.example.instapirate
2022-03-20 19:05:57.264 29351-29424/com.example.instapirate E/Perf: getFolderSize() : Exception_1 = java.lang.NullPointerException: Attempt to get length of null array
2022-03-20 19:05:57.427 29351-29425/com.example.instapirate I/FA: App measurement initialized, version: 60000
2022-03-20 19:05:57.427 29351-29425/com.example.instapirate I/FA: To enable debug logging run: adb shell setprop log.tag.FA VERBOSE
2022-03-20 19:05:57.428 29351-29425/com.example.instapirate I/FA: To enable faster debug mode event logging run:
adb shell setprop debug.firebase.analytics.app com.example.instapirate
2022-03-20 19:05:57.428 29351-29425/com.example.instapirate D/FA: Debug-level message logging enabled
2022-03-20 19:05:57.554 29351-29351/com.example.instapirate W/ActivityThread: handleWindowVisibility: no activity for token android.os.BinderProxy@6dd3e0e
2022-03-20 19:05:57.825 29351-29351/com.example.instapirate W/ple.instapirat: Accessing hidden method Landroid/view/View;->computeFitSystemWindows(Landroid/graphics/Rect;Landroid/graphics/Rect;)Z (greylist, reflection, allowed)
2022-03-20 19:05:57.827 29351-29351/com.example.instapirate W/ple.instapirat: Accessing hidden method Landroid/view/ViewGroup;->makeOptionalFitsSystemWindows()V (greylist, reflection, allowed)
2022-03-20 19:05:58.076 29351-29351/com.example.instapirate D/ShareActivity: onCreate
2022-03-20 19:05:58.332 29351-29425/com.example.instapirate I/FA: Tag Manager is not found and thus will not be used
2022-03-20 19:05:58.417 29351-29511/com.example.instapirate D/skia: --- Failed to create image decoder with message 'unimplemented'
2022-03-20 19:05:58.441 29351-29511/com.example.instapirate D/skia: --- Failed to create image decoder with message 'unimplemented'
2022-03-20 19:05:58.443 29351-29511/com.example.instapirate I/chatty: uid=10260(com.example.instapirate) glide-source-th identical 1 line
2022-03-20 19:05:58.444 29351-29511/com.example.instapirate D/skia: --- Failed to create image decoder with message 'unimplemented'
2022-03-20 19:05:58.451 29351-29519/com.example.instapirate D/NetworkSecurityConfig: No Network Security Config specified, using platform default
2022-03-20 19:05:58.467 29351-29511/com.example.instapirate D/skia: --- Failed to create image decoder with message 'unimplemented'
2022-03-20 19:05:58.472 29351-29511/com.example.instapirate D/skia: --- Failed to create image decoder with message 'unimplemented'
2022-03-20 19:05:58.571 29351-29439/com.example.instapirate I/AdrenoGLES: QUALCOMM build : 7331a27, Ieeb4a86f7b
Build Date : 11/13/19
OpenGL ES Shader Compiler Version: EV031.27.05.02
Local Branch :
Remote Branch :
Remote Branch :
Reconstruct Branch :
2022-03-20 19:05:58.571 29351-29439/com.example.instapirate I/AdrenoGLES: Build Config : S L 8.0.12 AArch64
2022-03-20 19:05:58.608 29351-29439/com.example.instapirate I/AdrenoGLES: PFP: 0x005ff113, ME: 0x005ff066
2022-03-20 19:05:58.618 29351-29439/com.example.instapirate W/AdrenoUtils: <ReadGpuID_from_sysfs:194>: Failed to open /sys/class/kgsl/kgsl-3d0/gpu_model
2022-03-20 19:05:58.618 29351-29439/com.example.instapirate W/AdrenoUtils: <ReadGpuID:218>: Failed to read chip ID from gpu_model. Fallback to use the GSL path
2022-03-20 19:05:58.668 29351-29439/com.example.instapirate W/Gralloc3: mapper 3.x is not supported
2022-03-20 19:05:58.751 29351-29351/com.example.instapirate W/Glide: Load failed for content://com.example.instapirate.fileprovider/images/JPEG_20220320_190558_2535596221289941323.jpg with size [204x204]
class com.bumptech.glide.load.engine.GlideException: Failed to load resource
There were 3 causes:
java.io.IOException(java.lang.RuntimeException: setDataSource failed: status = 0xFFFFFFEA)
java.io.IOException(java.lang.RuntimeException: setDataSource failed: status = 0xFFFFFFEA)
java.io.IOException(java.lang.RuntimeException: setDataSource failed: status = 0xFFFFFFEA)
call GlideException#logRootCauses(String) for more detail
Cause (1 of 4): class com.bumptech.glide.load.engine.GlideException: Failed LoadPath{AutoCloseInputStream->Object->Drawable}, LOCAL
Cause (1 of 3): class com.bumptech.glide.load.engine.GlideException: Failed DecodePath{AutoCloseInputStream->GifDrawable->Drawable}
Cause (2 of 3): class com.bumptech.glide.load.engine.GlideException: Failed DecodePath{AutoCloseInputStream->Bitmap->Drawable}
Cause (3 of 3): class com.bumptech.glide.load.engine.GlideException: Failed DecodePath{AutoCloseInputStream->BitmapDrawable->Drawable}
Cause (2 of 4): class com.bumptech.glide.load.engine.GlideException: Failed LoadPath{ParcelFileDescriptorInner->Object->Drawable}, LOCAL
There were 2 causes:
java.io.IOException(java.lang.RuntimeException: setDataSource failed: status = 0xFFFFFFEA)
java.io.IOException(java.lang.RuntimeException: setDataSource failed: status = 0xFFFFFFEA)
call GlideException#logRootCauses(String) for more detail
Cause (1 of 2): class com.bumptech.glide.load.engine.GlideException: Failed DecodePath{ParcelFileDescriptorInner->Bitmap->Drawable}
There was 1 cause:
java.io.IOException(java.lang.RuntimeException: setDataSource failed: status = 0xFFFFFFEA)
call GlideException#logRootCauses(String) for more detail
Cause (1 of 1): class java.io.IOException: java.lang.RuntimeException: setDataSource failed: status = 0xFFFFFFEA
Cause (2 of 2): class com.bumptech.glide.load.engine.GlideException: Failed DecodePath{ParcelFileDescriptorInner->BitmapDrawable->Drawable}
There was 1 cause:
java.io.IOException(java.lang.RuntimeException: setDataSource failed: status = 0xFFFFFFEA)
call GlideException#logRootCauses(String) for more detail
Cause (1 of 1): class java.io.IOException: java.lang.RuntimeException: setDataSource failed: status = 0xFFFFFFEA
Cause (3 of 4): class com.bumptech.glide.load.engine.GlideException: Failed LoadPath{AssetFileDescriptor->Object->Drawable}, LOCAL
There was 1 cause:
java.io.IOException(java.lang.RuntimeException: setDataSource failed: status = 0xFFFFFFEA)
call GlideException#logRootCauses(String) for more detail
Cause (1 of 1): class com.bumptech.glide.load.engine.GlideException: Failed DecodePath{AssetFileDescriptor->Bitmap->Drawable}
There was 1 cause:
java.io.IOException(java.lang.RuntimeException: setDataSource failed: status = 0xFFFFFFEA)
call GlideException#logRootCauses(String) for more detail
Cause (1 of 1): class java.io.IOException: java.lang.RuntimeException: setDataSource failed: status = 0xFFFFFFEA
Cause (4 of 4): class com.bumptech.glide.load.engine.GlideException: Failed LoadPath{HierarchicalUri->Object->Drawable}, LOCAL
Cause (1 of 2): class com.bumptech.glide.load.engine.GlideException: Failed DecodePath{HierarchicalUri->Drawable->Drawable}
Cause (2 of 2): class com.bumptech.glide.load.engine.GlideException: Failed DecodePath{HierarchicalUri->Bitmap->Drawable}
2022-03-20 19:05:58.753 29351-29351/com.example.instapirate I/Glide: Root cause (1 of 3)
java.io.IOException: java.lang.RuntimeException: setDataSource failed: status = 0xFFFFFFEA
at com.bumptech.glide.load.resource.bitmap.VideoDecoder.decode(VideoDecoder.java:185)
at com.bumptech.glide.load.engine.DecodePath.decodeResourceWithList(DecodePath.java:92)
at com.bumptech.glide.load.engine.DecodePath.decodeResource(DecodePath.java:70)
at com.bumptech.glide.load.engine.DecodePath.decode(DecodePath.java:59)
at com.bumptech.glide.load.engine.LoadPath.loadWithExceptionList(LoadPath.java:76)
at com.bumptech.glide.load.engine.LoadPath.load(LoadPath.java:57)
at com.bumptech.glide.load.engine.DecodeJob.runLoadPath(DecodeJob.java:524)
at com.bumptech.glide.load.engine.DecodeJob.decodeFromFetcher(DecodeJob.java:488)
at com.bumptech.glide.load.engine.DecodeJob.decodeFromData(DecodeJob.java:474)
at com.bumptech.glide.load.engine.DecodeJob.decodeFromRetrievedData(DecodeJob.java:426)
at com.bumptech.glide.load.engine.DecodeJob.onDataFetcherReady(DecodeJob.java:390)
at com.bumptech.glide.load.engine.SourceGenerator.onDataReadyInternal(SourceGenerator.java:148)
at com.bumptech.glide.load.engine.SourceGenerator.onDataReady(SourceGenerator.java:76)
at com.bumptech.glide.load.data.LocalUriFetcher.loadData(LocalUriFetcher.java:52)
at com.bumptech.glide.load.engine.SourceGenerator.startNextLoad(SourceGenerator.java:70)
at com.bumptech.glide.load.engine.SourceGenerator.startNext(SourceGenerator.java:63)
at com.bumptech.glide.load.engine.DecodeJob.runGenerators(DecodeJob.java:310)
at com.bumptech.glide.load.engine.DecodeJob.decodeFromRetrievedData(DecodeJob.java:434)
at com.bumptech.glide.load.engine.DecodeJob.onDataFetcherReady(DecodeJob.java:390)
at com.bumptech.glide.load.engine.SourceGenerator.onDataReadyInternal(SourceGenerator.java:148)
at com.bumptech.glide.load.engine.SourceGenerator.onDataReady(SourceGenerator.java:76)
at com.bumptech.glide.load.data.LocalUriFetcher.loadData(LocalUriFetcher.java:52)
at com.bumptech.glide.load.engine.SourceGenerator.startNextLoad(SourceGenerator.java:70)
at com.bumptech.glide.load.engine.SourceGenerator.startNext(SourceGenerator.java:63)
at com.bumptech.glide.load.engine.DecodeJob.runGenerators(DecodeJob.java:310)
at com.bumptech.glide.load.engine.DecodeJob.runWrapped(DecodeJob.java:279)
at com.bumptech.glide.load.engine.DecodeJob.run(DecodeJob.java:234)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:919)
at com.bumptech.glide.load.engine.executor.GlideExecutor$DefaultThreadFactory.run(GlideExecutor.java:393)
Caused by: java.lang.RuntimeException: setDataSource failed: status = 0xFFFFFFEA
at android.media.MediaMetadataRetriever.setDataSource(Native Method)
at android.media.MediaMetadataRetriever.setDataSource(MediaMetadataRetriever.java:142)
at com.bumptech.glide.load.resource.bitmap.VideoDecoder$ParcelFileDescriptorInitializer.initialize(VideoDecoder.java:306)
at com.bumptech.glide.load.resource.bitmap.VideoDecoder$ParcelFileDescriptorInitializer.initialize(VideoDecoder.java:301)
at com.bumptech.glide.load.resource.bitmap.VideoDecoder.decode(VideoDecoder.java:173)
at com.bumptech.glide.load.engine.DecodePath.decodeResourceWithList(DecodePath.java:92)
at com.bumptech.glide.load.engine.DecodePath.decodeResource(DecodePath.java:70)
at com.bumptech.glide.load.engine.DecodePath.decode(DecodePath.java:59)
at com.bumptech.glide.load.engine.LoadPath.loadWithExceptionList(LoadPath.java:76)
at com.bumptech.glide.load.engine.LoadPath.load(LoadPath.java:57)
at com.bumptech.glide.load.engine.DecodeJob.runLoadPath(DecodeJob.java:524)
at com.bumptech.glide.load.engine.DecodeJob.decodeFromFetcher(DecodeJob.java:488)
at com.bumptech.glide.load.engine.DecodeJob.decodeFromData(DecodeJob.java:474)
如果需要代码中的更多必要数据,那么我可以编辑 post 并添加它们(在我看来,我已经附加了太多代码,对不起,但这很重要).我希望有人能帮我解决至少1个问题。
刚加入FirebaseHelper
此代码:
fun uploadSharePhoto(localPhotoUrl: Uri, onSuccess: (UploadTask.TaskSnapshot) -> Unit) =
storage.child("users/${auth.currentUser!!.uid}").child("images")
.child(localPhotoUrl.lastPathSegment!!)
.putFile(localPhotoUrl)
.addOnCompleteListener {
if (it.isSuccessful)
onSuccess(it.result!!)
else
activity.showToast(it.exception!!.message!!)
}
fun addSharePhoto(globalPhotoUrl: String, onSuccess: () -> Unit) =
database.child("images").child(auth.currentUser!!.uid)
.push().setValue(globalPhotoUrl)
.addOnComplete { onSuccess() }
private fun Task<Void>.addOnComplete(onSuccess: () -> Unit) {
addOnCompleteListener {
if (it.isSuccessful)
onSuccess()
else
activity.showToast(it.exception!!.message!!)
}
}
并且在 ShareActivity
中编辑了 share()
函数:
private fun share() {
val imageUri = mCamera.imageUri
if (imageUri != null) {
mFirebase.uploadSharePhoto(imageUri) {
it.metadata!!.reference!!.downloadUrl.addOnSuccessListener {
mFirebase.addSharePhoto(it.toString()) {
mFirebase.database.child("feed-posts").child(mFirebase.auth.currentUser!!.uid)
.push()
.setValue(mkFeedPost(mFirebase.auth.currentUser!!.uid, it.toString()))
.addOnCompleteListener {
if (it.isSuccessful) {
startActivity(Intent(this,
ProfileActivity::class.java))
finish()
}
}
}
}
}
}
}
现在所有链接都是正确的
我正在以 instagram 的形式编写应用程序(我从 YouTube 学习课程,他们在 Android 8 上创建它,我正在尝试在 Android 10 上做同样的事情) ,我只认识 Kotlin 几个星期。已经实施了很多。但是问题出在 firebase 上。两个问题:
- 在应用程序中注册一个用户并将其文本数据保存在 firebase 中——我可以在任何设备上完成。通过 Android 上的模拟器 8 - 我可以拍照并且一切正常,即使 link 更改个人资料照片也能正确显示。还有一个
ShareActivity
文件,用户可以在“墙上”分享照片,问题是照片出现在 google firebase 的存储中,而在实时数据库中 link这张照片写成"com.google.firebase.storage.UploadTask $TaskSnapshot@46529a6"
,但应该写成 link"https://firebasestorage.googleapis.com/v0/b/instapirate...
",而个人资料照片显示正确,即 posts - 不,照片是根本不可见。如何修复这个错误?我附上一张来自模拟器和数据库的照片: - 还有一个问题,那就是在 Android 8 上,在 Instagram 模拟器中,我被要求获得使用相机的权限,我同意了,相机工作,拍照,一切都很好。而在 android 10 中,没有请求相机权限,因此相机打开,拍照,但无法保存照片(当我点击“保存”按钮时重新打开)。如果我快速按下按钮几次 - 有时它有助于保存照片,但这种情况发生在百万分之一的情况下。这并不是因为相机的分辨率。
我附上下面的代码:
AndroidManifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.instapirate">
<uses-feature android:name="android.hardware.camera"
android:required="true" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.INSTApirate" >
<activity
android:name=".activities.MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".activities.SearchActivity" />
<activity android:name=".activities.ShareActivity" />
<activity android:name=".activities.LikesActivity" />
<activity android:name=".activities.ProfileActivity" />
<activity
android:name=".activities.EditProfileActivity"
android:exported="true" />
<activity
android:name=".activities.LoginActivity"
android:windowSoftInputMode="stateVisible|adjustResize" >
</activity>
<activity
android:name=".activities.RegisterActivity"
android:windowSoftInputMode="stateVisible|adjustResize" >
</activity>
<activity android:name=".activities.ProfileSettingsActivity" />
<activity android:name=".activities.AddFriendsActivity"/>
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.example.instapirate.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths"></meta-data>
</provider>
</application>
</manifest>
配置文件是使用 EditProfileActivity
文件编辑的。下面有一段具体的代码,拍照和更改用户头像,这里的 link 可以正常工作并以正常形式加载到 Storage 和 RealtimeDatabase 中,但是在 Android 10 上照片也是未拍摄且相机已重置:
private lateinit var mUser: User
private lateinit var mFirebase: FirebaseHelper
private lateinit var mPendingUser: User
private lateinit var mCamera: CameraHelper
@SuppressLint("MissingSuperCall")
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode == mCamera.REQUEST_CODE && resultCode == RESULT_OK) {
mFirebase.uploadUserPhoto(mCamera.imageUri!!) {
mFirebase.storageUid().addOnCompleteListener {
val photoUrl = it.result.toString()
mFirebase.updateUserPhoto(photoUrl){
mUser = mUser.copy(photo = photoUrl)
profile_image.loadUserPhoto(mUser.photo)
}
}
}
}
}
loadUserPhoto
位于一个单独的 utils
文件中,其中存储了所有实用程序:
fun ImageView.loadUserPhoto(photoUrl: String?) =
ifNotDestroyed {
GlideApp.with(this).load(photoUrl).fallback(R.drawable.person).into(this)
}
参与以上代码的远程类:CameraHelper
import android.app.Activity
import android.content.Intent
import android.net.Uri
import android.os.Environment
import android.provider.MediaStore
import androidx.core.content.FileProvider
import java.io.File
import java.text.SimpleDateFormat
import java.util.*
class CameraHelper(private val activity: Activity) {
var imageUri: Uri? = null
val REQUEST_CODE = 1
private val simpleDateFormat = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US)
fun takeCameraPicture() {
val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
if (intent.resolveActivity(activity.packageManager) != null) {
val imageFile = createImageFile()
imageUri = FileProvider.getUriForFile(activity,
"com.example.instapirate.fileprovider",
imageFile)
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri)
activity.startActivityForResult(intent, REQUEST_CODE)
}
}
private fun createImageFile(): File {
val storageDir = activity.getExternalFilesDir(Environment.DIRECTORY_PICTURES)
return File.createTempFile(
"JPEG_${simpleDateFormat.format(Date())}_",
".jpg",
storageDir
)
}
}
FirebaseHelper
import android.app.Activity
import android.net.Uri
import com.example.instapirate.activities.showToast
import com.google.firebase.auth.AuthCredential
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.database.DatabaseReference
import com.google.firebase.database.FirebaseDatabase
import com.google.firebase.storage.FirebaseStorage
import com.google.firebase.storage.StorageReference
import com.google.firebase.storage.UploadTask
class FirebaseHelper(private val activity: Activity) {
val auth: FirebaseAuth = FirebaseAuth.getInstance()
val database: DatabaseReference = FirebaseDatabase.getInstance().reference
val storage: StorageReference = FirebaseStorage.getInstance().reference
fun storageUid() = storage.child("users/${auth.currentUser!!.uid}/photo/").downloadUrl
fun uploadUserPhoto(photo: Uri, onSuccess: (UploadTask.TaskSnapshot) -> Unit) {
storage.child("users/${currentUid()!!}/photo").putFile(photo)
.addOnCompleteListener {
if (it.isSuccessful) {
onSuccess(it.result!!)
} else {
activity.showToast(it.exception!!.message!!)
}
}
}
fun updateUserPhoto(photoUrl: String, onSuccess: () -> Unit) {
database.child("users/${currentUid()!!}/photo").setValue(photoUrl)
.addOnCompleteListener {
if (it.isSuccessful) {
onSuccess()
} else {
activity.showToast(it.exception!!.message!!)
}
}
}
fun updateUser(updates: Map<String, Any?>, onSuccess: () -> Unit) {
database.child("users").child(currentUid()!!).updateChildren(updates)
.addOnCompleteListener {
if (it.isSuccessful) {
onSuccess()
} else {
activity.showToast(it.exception!!.message!!)
}
}
}
fun updateEmail(email: String, onSuccess: () -> Unit) {
auth.currentUser!!.updateEmail(email).addOnCompleteListener {
if (it.isSuccessful) {
onSuccess()
} else {
activity.showToast(it.exception!!.message!!)
}
}
}
fun reauthenticate(credential: AuthCredential, onSuccess: () -> Unit) {
auth.currentUser!!.reauthenticate(credential).addOnCompleteListener {
if (it.isSuccessful) {
onSuccess()
} else {
activity.showToast(it.exception!!.message!!)
}
}
}
fun currentUserReference(): DatabaseReference =
database.child("users").child(currentUid()!!)
fun currentUid(): String? =
auth.currentUser?.uid
}
还有一个 ShareActivity
文件实现了将照片上传到 Feed,这就是 Firebase 出现问题的地方,因为 link 在这里以不正确的形式显示(提要的屏幕截图在上面)。如果照片是通过模拟器在 Android 8 上拍摄的,就会发生这种情况。 (在phone和Android10保存照片后相机重新打开,我必须重新拍照等等一圈)
class ShareActivity : BaseActivity(2) {
private val TAG = "ShareActivity"
private lateinit var mCamera: CameraHelper
private lateinit var mFirebase: FirebaseHelper
private lateinit var mUser: User
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_share)
Log.d(TAG, "onCreate")
mFirebase = FirebaseHelper(this)
mCamera = CameraHelper(this)
mCamera.takeCameraPicture()
back_image.setOnClickListener{finish()}
share_text.setOnClickListener{ share()}
mFirebase.currentUserReference().addValueEventListener(ValueEventListenerAdapter{
mUser = it.asUser()!!
})
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == mCamera.REQUEST_CODE) {
if (resultCode == RESULT_OK) {
GlideApp.with(this).load(mCamera.imageUri).centerCrop().into(post_image)
} else {
finish()
}
}
}
private fun share() {
val imageUri = mCamera. imageUri
if (imageUri != null) {
val uid = mFirebase.currentUid()!!
mFirebase.storage.child("users").child(uid).child("images")
.child(imageUri.lastPathSegment.toString()).putFile(imageUri).addOnCompleteListener{
if (it.isSuccessful){
val imageDownloadUrl = it.result!!.toString()
mFirebase.database.child("images").child(uid).push()
.setValue(imageDownloadUrl)
.addOnCompleteListener {
if (it.isSuccessful) {
mFirebase.database.child("feed-posts").child(uid)
.push()
.setValue(mkFeedPost(uid, imageDownloadUrl))
.addOnCompleteListener {
if (it.isSuccessful) {
startActivity(Intent(this,
ProfileActivity::class.java))
finish()
}
}
} else {
showToast(it.exception!!.message!!)
}
}
} else {
showToast(it.exception!!.message!!)
}
}
}
}
private fun mkFeedPost(uid: String, imageDownloadUrl: String): FeedPost {
return FeedPost(
uid = uid,
username = mUser.username,
image = imageDownloadUrl,
caption = caption_input.text.toString(),
photo = mUser.photo
)
}
}
在android10尝试保存照片时,Debug中出现如下文字(由于限制无法显示全部错误,但我认为这是错误的重要部分):
2022-03-20 19:05:55.711 29351-29351/? I/ple.instapirat: Late-enabling -Xcheck:jni
2022-03-20 19:05:55.855 29351-29351/? E/ple.instapirat: Unknown bits set in runtime_flags: 0x8000
2022-03-20 19:05:56.943 29351-29351/com.example.instapirate I/Perf: Connecting to perf service.
2022-03-20 19:05:57.016 29351-29351/com.example.instapirate I/FirebaseApp: Device unlocked: initializing all Firebase APIs for app [DEFAULT]
2022-03-20 19:05:57.126 29351-29351/com.example.instapirate D/FirebaseAuth: Notifying id token listeners about user ( PjHBujbeapTQxmLl4TgzhgOTzjo2 ).
2022-03-20 19:05:57.158 29351-29351/com.example.instapirate I/FirebaseInitProvider: FirebaseApp initialization successful
2022-03-20 19:05:57.194 29351-29422/com.example.instapirate I/DynamiteModule: Considering local module com.google.android.gms.measurement.dynamite:69 and remote module com.google.android.gms.measurement.dynamite:67
2022-03-20 19:05:57.194 29351-29422/com.example.instapirate I/DynamiteModule: Selected local version of com.google.android.gms.measurement.dynamite
2022-03-20 19:05:57.263 29351-29424/com.example.instapirate E/Perf: Fail to get file list com.example.instapirate
2022-03-20 19:05:57.264 29351-29424/com.example.instapirate E/Perf: getFolderSize() : Exception_1 = java.lang.NullPointerException: Attempt to get length of null array
2022-03-20 19:05:57.427 29351-29425/com.example.instapirate I/FA: App measurement initialized, version: 60000
2022-03-20 19:05:57.427 29351-29425/com.example.instapirate I/FA: To enable debug logging run: adb shell setprop log.tag.FA VERBOSE
2022-03-20 19:05:57.428 29351-29425/com.example.instapirate I/FA: To enable faster debug mode event logging run:
adb shell setprop debug.firebase.analytics.app com.example.instapirate
2022-03-20 19:05:57.428 29351-29425/com.example.instapirate D/FA: Debug-level message logging enabled
2022-03-20 19:05:57.554 29351-29351/com.example.instapirate W/ActivityThread: handleWindowVisibility: no activity for token android.os.BinderProxy@6dd3e0e
2022-03-20 19:05:57.825 29351-29351/com.example.instapirate W/ple.instapirat: Accessing hidden method Landroid/view/View;->computeFitSystemWindows(Landroid/graphics/Rect;Landroid/graphics/Rect;)Z (greylist, reflection, allowed)
2022-03-20 19:05:57.827 29351-29351/com.example.instapirate W/ple.instapirat: Accessing hidden method Landroid/view/ViewGroup;->makeOptionalFitsSystemWindows()V (greylist, reflection, allowed)
2022-03-20 19:05:58.076 29351-29351/com.example.instapirate D/ShareActivity: onCreate
2022-03-20 19:05:58.332 29351-29425/com.example.instapirate I/FA: Tag Manager is not found and thus will not be used
2022-03-20 19:05:58.417 29351-29511/com.example.instapirate D/skia: --- Failed to create image decoder with message 'unimplemented'
2022-03-20 19:05:58.441 29351-29511/com.example.instapirate D/skia: --- Failed to create image decoder with message 'unimplemented'
2022-03-20 19:05:58.443 29351-29511/com.example.instapirate I/chatty: uid=10260(com.example.instapirate) glide-source-th identical 1 line
2022-03-20 19:05:58.444 29351-29511/com.example.instapirate D/skia: --- Failed to create image decoder with message 'unimplemented'
2022-03-20 19:05:58.451 29351-29519/com.example.instapirate D/NetworkSecurityConfig: No Network Security Config specified, using platform default
2022-03-20 19:05:58.467 29351-29511/com.example.instapirate D/skia: --- Failed to create image decoder with message 'unimplemented'
2022-03-20 19:05:58.472 29351-29511/com.example.instapirate D/skia: --- Failed to create image decoder with message 'unimplemented'
2022-03-20 19:05:58.571 29351-29439/com.example.instapirate I/AdrenoGLES: QUALCOMM build : 7331a27, Ieeb4a86f7b
Build Date : 11/13/19
OpenGL ES Shader Compiler Version: EV031.27.05.02
Local Branch :
Remote Branch :
Remote Branch :
Reconstruct Branch :
2022-03-20 19:05:58.571 29351-29439/com.example.instapirate I/AdrenoGLES: Build Config : S L 8.0.12 AArch64
2022-03-20 19:05:58.608 29351-29439/com.example.instapirate I/AdrenoGLES: PFP: 0x005ff113, ME: 0x005ff066
2022-03-20 19:05:58.618 29351-29439/com.example.instapirate W/AdrenoUtils: <ReadGpuID_from_sysfs:194>: Failed to open /sys/class/kgsl/kgsl-3d0/gpu_model
2022-03-20 19:05:58.618 29351-29439/com.example.instapirate W/AdrenoUtils: <ReadGpuID:218>: Failed to read chip ID from gpu_model. Fallback to use the GSL path
2022-03-20 19:05:58.668 29351-29439/com.example.instapirate W/Gralloc3: mapper 3.x is not supported
2022-03-20 19:05:58.751 29351-29351/com.example.instapirate W/Glide: Load failed for content://com.example.instapirate.fileprovider/images/JPEG_20220320_190558_2535596221289941323.jpg with size [204x204]
class com.bumptech.glide.load.engine.GlideException: Failed to load resource
There were 3 causes:
java.io.IOException(java.lang.RuntimeException: setDataSource failed: status = 0xFFFFFFEA)
java.io.IOException(java.lang.RuntimeException: setDataSource failed: status = 0xFFFFFFEA)
java.io.IOException(java.lang.RuntimeException: setDataSource failed: status = 0xFFFFFFEA)
call GlideException#logRootCauses(String) for more detail
Cause (1 of 4): class com.bumptech.glide.load.engine.GlideException: Failed LoadPath{AutoCloseInputStream->Object->Drawable}, LOCAL
Cause (1 of 3): class com.bumptech.glide.load.engine.GlideException: Failed DecodePath{AutoCloseInputStream->GifDrawable->Drawable}
Cause (2 of 3): class com.bumptech.glide.load.engine.GlideException: Failed DecodePath{AutoCloseInputStream->Bitmap->Drawable}
Cause (3 of 3): class com.bumptech.glide.load.engine.GlideException: Failed DecodePath{AutoCloseInputStream->BitmapDrawable->Drawable}
Cause (2 of 4): class com.bumptech.glide.load.engine.GlideException: Failed LoadPath{ParcelFileDescriptorInner->Object->Drawable}, LOCAL
There were 2 causes:
java.io.IOException(java.lang.RuntimeException: setDataSource failed: status = 0xFFFFFFEA)
java.io.IOException(java.lang.RuntimeException: setDataSource failed: status = 0xFFFFFFEA)
call GlideException#logRootCauses(String) for more detail
Cause (1 of 2): class com.bumptech.glide.load.engine.GlideException: Failed DecodePath{ParcelFileDescriptorInner->Bitmap->Drawable}
There was 1 cause:
java.io.IOException(java.lang.RuntimeException: setDataSource failed: status = 0xFFFFFFEA)
call GlideException#logRootCauses(String) for more detail
Cause (1 of 1): class java.io.IOException: java.lang.RuntimeException: setDataSource failed: status = 0xFFFFFFEA
Cause (2 of 2): class com.bumptech.glide.load.engine.GlideException: Failed DecodePath{ParcelFileDescriptorInner->BitmapDrawable->Drawable}
There was 1 cause:
java.io.IOException(java.lang.RuntimeException: setDataSource failed: status = 0xFFFFFFEA)
call GlideException#logRootCauses(String) for more detail
Cause (1 of 1): class java.io.IOException: java.lang.RuntimeException: setDataSource failed: status = 0xFFFFFFEA
Cause (3 of 4): class com.bumptech.glide.load.engine.GlideException: Failed LoadPath{AssetFileDescriptor->Object->Drawable}, LOCAL
There was 1 cause:
java.io.IOException(java.lang.RuntimeException: setDataSource failed: status = 0xFFFFFFEA)
call GlideException#logRootCauses(String) for more detail
Cause (1 of 1): class com.bumptech.glide.load.engine.GlideException: Failed DecodePath{AssetFileDescriptor->Bitmap->Drawable}
There was 1 cause:
java.io.IOException(java.lang.RuntimeException: setDataSource failed: status = 0xFFFFFFEA)
call GlideException#logRootCauses(String) for more detail
Cause (1 of 1): class java.io.IOException: java.lang.RuntimeException: setDataSource failed: status = 0xFFFFFFEA
Cause (4 of 4): class com.bumptech.glide.load.engine.GlideException: Failed LoadPath{HierarchicalUri->Object->Drawable}, LOCAL
Cause (1 of 2): class com.bumptech.glide.load.engine.GlideException: Failed DecodePath{HierarchicalUri->Drawable->Drawable}
Cause (2 of 2): class com.bumptech.glide.load.engine.GlideException: Failed DecodePath{HierarchicalUri->Bitmap->Drawable}
2022-03-20 19:05:58.753 29351-29351/com.example.instapirate I/Glide: Root cause (1 of 3)
java.io.IOException: java.lang.RuntimeException: setDataSource failed: status = 0xFFFFFFEA
at com.bumptech.glide.load.resource.bitmap.VideoDecoder.decode(VideoDecoder.java:185)
at com.bumptech.glide.load.engine.DecodePath.decodeResourceWithList(DecodePath.java:92)
at com.bumptech.glide.load.engine.DecodePath.decodeResource(DecodePath.java:70)
at com.bumptech.glide.load.engine.DecodePath.decode(DecodePath.java:59)
at com.bumptech.glide.load.engine.LoadPath.loadWithExceptionList(LoadPath.java:76)
at com.bumptech.glide.load.engine.LoadPath.load(LoadPath.java:57)
at com.bumptech.glide.load.engine.DecodeJob.runLoadPath(DecodeJob.java:524)
at com.bumptech.glide.load.engine.DecodeJob.decodeFromFetcher(DecodeJob.java:488)
at com.bumptech.glide.load.engine.DecodeJob.decodeFromData(DecodeJob.java:474)
at com.bumptech.glide.load.engine.DecodeJob.decodeFromRetrievedData(DecodeJob.java:426)
at com.bumptech.glide.load.engine.DecodeJob.onDataFetcherReady(DecodeJob.java:390)
at com.bumptech.glide.load.engine.SourceGenerator.onDataReadyInternal(SourceGenerator.java:148)
at com.bumptech.glide.load.engine.SourceGenerator.onDataReady(SourceGenerator.java:76)
at com.bumptech.glide.load.data.LocalUriFetcher.loadData(LocalUriFetcher.java:52)
at com.bumptech.glide.load.engine.SourceGenerator.startNextLoad(SourceGenerator.java:70)
at com.bumptech.glide.load.engine.SourceGenerator.startNext(SourceGenerator.java:63)
at com.bumptech.glide.load.engine.DecodeJob.runGenerators(DecodeJob.java:310)
at com.bumptech.glide.load.engine.DecodeJob.decodeFromRetrievedData(DecodeJob.java:434)
at com.bumptech.glide.load.engine.DecodeJob.onDataFetcherReady(DecodeJob.java:390)
at com.bumptech.glide.load.engine.SourceGenerator.onDataReadyInternal(SourceGenerator.java:148)
at com.bumptech.glide.load.engine.SourceGenerator.onDataReady(SourceGenerator.java:76)
at com.bumptech.glide.load.data.LocalUriFetcher.loadData(LocalUriFetcher.java:52)
at com.bumptech.glide.load.engine.SourceGenerator.startNextLoad(SourceGenerator.java:70)
at com.bumptech.glide.load.engine.SourceGenerator.startNext(SourceGenerator.java:63)
at com.bumptech.glide.load.engine.DecodeJob.runGenerators(DecodeJob.java:310)
at com.bumptech.glide.load.engine.DecodeJob.runWrapped(DecodeJob.java:279)
at com.bumptech.glide.load.engine.DecodeJob.run(DecodeJob.java:234)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:919)
at com.bumptech.glide.load.engine.executor.GlideExecutor$DefaultThreadFactory.run(GlideExecutor.java:393)
Caused by: java.lang.RuntimeException: setDataSource failed: status = 0xFFFFFFEA
at android.media.MediaMetadataRetriever.setDataSource(Native Method)
at android.media.MediaMetadataRetriever.setDataSource(MediaMetadataRetriever.java:142)
at com.bumptech.glide.load.resource.bitmap.VideoDecoder$ParcelFileDescriptorInitializer.initialize(VideoDecoder.java:306)
at com.bumptech.glide.load.resource.bitmap.VideoDecoder$ParcelFileDescriptorInitializer.initialize(VideoDecoder.java:301)
at com.bumptech.glide.load.resource.bitmap.VideoDecoder.decode(VideoDecoder.java:173)
at com.bumptech.glide.load.engine.DecodePath.decodeResourceWithList(DecodePath.java:92)
at com.bumptech.glide.load.engine.DecodePath.decodeResource(DecodePath.java:70)
at com.bumptech.glide.load.engine.DecodePath.decode(DecodePath.java:59)
at com.bumptech.glide.load.engine.LoadPath.loadWithExceptionList(LoadPath.java:76)
at com.bumptech.glide.load.engine.LoadPath.load(LoadPath.java:57)
at com.bumptech.glide.load.engine.DecodeJob.runLoadPath(DecodeJob.java:524)
at com.bumptech.glide.load.engine.DecodeJob.decodeFromFetcher(DecodeJob.java:488)
at com.bumptech.glide.load.engine.DecodeJob.decodeFromData(DecodeJob.java:474)
如果需要代码中的更多必要数据,那么我可以编辑 post 并添加它们(在我看来,我已经附加了太多代码,对不起,但这很重要).我希望有人能帮我解决至少1个问题。
刚加入FirebaseHelper
此代码:
fun uploadSharePhoto(localPhotoUrl: Uri, onSuccess: (UploadTask.TaskSnapshot) -> Unit) =
storage.child("users/${auth.currentUser!!.uid}").child("images")
.child(localPhotoUrl.lastPathSegment!!)
.putFile(localPhotoUrl)
.addOnCompleteListener {
if (it.isSuccessful)
onSuccess(it.result!!)
else
activity.showToast(it.exception!!.message!!)
}
fun addSharePhoto(globalPhotoUrl: String, onSuccess: () -> Unit) =
database.child("images").child(auth.currentUser!!.uid)
.push().setValue(globalPhotoUrl)
.addOnComplete { onSuccess() }
private fun Task<Void>.addOnComplete(onSuccess: () -> Unit) {
addOnCompleteListener {
if (it.isSuccessful)
onSuccess()
else
activity.showToast(it.exception!!.message!!)
}
}
并且在 ShareActivity
中编辑了 share()
函数:
private fun share() {
val imageUri = mCamera.imageUri
if (imageUri != null) {
mFirebase.uploadSharePhoto(imageUri) {
it.metadata!!.reference!!.downloadUrl.addOnSuccessListener {
mFirebase.addSharePhoto(it.toString()) {
mFirebase.database.child("feed-posts").child(mFirebase.auth.currentUser!!.uid)
.push()
.setValue(mkFeedPost(mFirebase.auth.currentUser!!.uid, it.toString()))
.addOnCompleteListener {
if (it.isSuccessful) {
startActivity(Intent(this,
ProfileActivity::class.java))
finish()
}
}
}
}
}
}
}
现在所有链接都是正确的