【问题标题】:How to Save Internet Image with url in SD card (Android Kotlin)如何在 SD 卡中保存带有 URL 的 Internet 图像(Android Kotlin)
【发布时间】:2020-05-03 02:55:06
【问题描述】:

我在这段代码中有错误(

java.lang.IllegalArgumentException: Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull, parameter result)

并且没有保存图片 我会给你所有的代码:

MainActivity 代码:

package com.masreta87.backhussian

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.View
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.masreta87.backhussian.models.BlogPost
import com.masreta87.backhussian.models.DataSource
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {
private lateinit var blogAdapter:BlogRecyclerAdapter
    lateinit var data: List<BlogPost>
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        initRecyclerView()
        addDataSet()

    }
    private fun addDataSet(){
        data=DataSource.createDataSet()
        blogAdapter.submitList(data)
    }
    private fun initRecyclerView(){
        recycler_view.apply {
            layoutManager=LinearLayoutManager(this@MainActivity)
            blogAdapter=BlogRecyclerAdapter()
            adapter=blogAdapter
        }

    }
}

和 BlogRecyclerAdapter.kt

    package com.masreta87.backhussian

import android.content.Context
import android.graphics.Bitmap
import android.os.AsyncTask
import android.os.Environment
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions
import com.masreta87.backhussian.models.BlogPost
import kotlinx.android.synthetic.main.layout_blog_list_item.view.*
import java.net.URL
import android.os.Environment.getExternalStorageDirectory
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.load.resource.bitmap.DownsampleStrategy
import java.io.File
import java.io.FileOutputStream
import java.lang.ref.WeakReference
import android.widget.Toast
import android.content.Intent
import android.annotation.SuppressLint
import android.app.ProgressDialog
import android.net.Uri
import com.squareup.picasso.Picasso
import java.io.IOException


class BlogRecyclerAdapter :RecyclerView.Adapter<RecyclerView.ViewHolder>(){
    private  var items:List <BlogPost> = ArrayList()

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        return  BlogViewHolder(
            LayoutInflater.from(parent.context).inflate(R.layout.layout_blog_list_item,parent,false)

        )
    }

    override fun getItemCount(): Int {
        return items.size
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        when(holder){

            is BlogViewHolder ->{
                holder.bind(items.get(position))
            }
        }
    }
    fun submitList(blogList: List<BlogPost>){
        items = blogList
    }
    class BlogViewHolder constructor(
        itemView:View

    ):RecyclerView.ViewHolder(itemView){
        val blogImage:ImageView =itemView.blog_image
        fun bind(blogPost:BlogPost){
            val requestOptions =RequestOptions()
                .placeholder(R.drawable.ic_launcher_background)
                .error(R.drawable.ic_launcher_background)
            Glide.with(itemView.context)
                .applyDefaultRequestOptions(requestOptions)
                .load(blogPost.image)
                .into(blogImage)
            itemView.setOnClickListener{
                SaveImage(itemView.context,blogPost.image.toString() );
            }

        }

    }


}

private fun SaveImage(context: Context, MyUrl: String) {
    val progress = ProgressDialog(context)

    class SaveThisImage : AsyncTask<Void, Void, Void>() {
        override fun onPreExecute() {
            super.onPreExecute()
            progress.setTitle("Processing")
            progress.setMessage("Please Wait...")
            progress.setCancelable(false)
            progress.show()
        }

        override fun doInBackground(vararg arg0: Void): Void? {
            try {

                val sdCard = Environment.getExternalStorageDirectory()
                @SuppressLint("DefaultLocale") val fileName =
                    String.format("%dm.png", System.currentTimeMillis())
                val dir = File(sdCard.absolutePath + "/Image")
                dir.mkdirs()
                val myImageFile = File(dir,fileName) // Create image file
                **var fos:FileOutputStream? = null**
                try {
                    Log.d("ala",myImageFile.toString())
                    **fos = FileOutputStream(myImageFile)**

                    val bitmap = Picasso.get().load(MyUrl).get()
                    bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos)

                    val intent = Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE)
                    intent.data = Uri.fromFile(myImageFile)
                    context.sendBroadcast(intent)
                } catch (e: IOException) {
                    e.printStackTrace()
                } finally {
                    try {
                        fos!!.close()
                    } catch (e: IOException) {
                        e.printStackTrace()
                    }

                }
            } catch (e: Exception) {
            }

            return null
        }

        override fun onPostExecute(result: Void) {
            super.onPostExecute(result)
            if (progress.isShowing) {
                progress.dismiss()
            }
            Toast.makeText(context, "Saved", Toast.LENGTH_SHORT).show()
        }
    }

    val shareimg = SaveThisImage()
    shareimg.execute()
}

还有 BlogPost.class

    package com.masreta87.backhussian.models

data class BlogPost(

                  var image:String

)

{

}

AND DataStore.class

    package com.masreta87.backhussian.models


class DataSource{

    companion object{

        fun createDataSet(): ArrayList<BlogPost>{
            val list = ArrayList<BlogPost>()
            list.add(
                BlogPost(
                    "https://firebasestorage.googleapis.com/v0/b/databaseim-56ef5.appspot.com/o/rpic%20(2).jpg?alt=media&token=138c2c3b-33ce-4a96-a7f5-74816af21809"
                )
            )
            list.add(
                BlogPost(
                    "https://firebasestorage.googleapis.com/v0/b/databaseim-56ef5.appspot.com/o/v1.png?alt=media&token=2e80d218-eb48-4c51-b51a-0fac43f76da7"
                )
            )

            list.add(
                BlogPost(
                    "https://firebasestorage.googleapis.com/v0/b/databaseim-56ef5.appspot.com/o/v10.jpg?alt=media&token=5e7207eb-1dac-41c0-bb3b-95abf9a54a2e"
                )
            )
            list.add(
                BlogPost(
                    "https://firebasestorage.googleapis.com/v0/b/databaseim-56ef5.appspot.com/o/v11.jpg?alt=media&token=2ab2b0c4-5ca1-4042-85c5-6d3e58181f45"
                )
            )

            return list
        }
    }
}

还有主播

<uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

还有activity_main.xml

    <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.recyclerview.widget.RecyclerView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:id="@+id/recycler_view"/>

</androidx.constraintlayout.widget.ConstraintLayout>

还有 layout_blog_list_item.xml

   <?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    app:cardElevation="10dp"
    app:cardCornerRadius="2dp"
    app:cardPreventCornerOverlap="false"
    >

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        >

        <ImageView
            android:layout_width="match_parent"
            android:layout_height="610dp"
            app:layout_constraintTop_toTopOf="parent"
            android:id="@+id/blog_image"
            android:background="@drawable/boder_image"
            android:padding="10dp"
            android:layout_margin="0dp"
            android:adjustViewBounds="true"
            android:scaleType="fitXY"
            />






    </androidx.constraintlayout.widget.ConstraintLayout>


</androidx.cardview.widget.CardView>

完全错误:

2020-01-15 21:34:36.509 32083-32083/? E/Android运行时:致命 例外:主要 进程:com.masreta87.backhussian,PID:32083 java.lang.IllegalArgumentException:指定为非空的参数为空:方法 kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull,参数 结果 在 com.masreta87.backhussian.BlogRecyclerAdapterKt$SaveImage$SaveThisImage.onPostExecute(未知 来源:2) 在 com.masreta87.backhussian.BlogRecyclerAdapterKt$SaveImage$SaveThisImage.onPostExecute(BlogRecyclerAdapter.kt:86) 在 android.os.AsyncTask.finish(AsyncTask.java:695) 在 android.os.AsyncTask.-wrap1(未知来源:0) 在 android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:712) 在 android.os.Handler.dispatchMessage(Handler.java:105) 在 android.os.Looper.loop(Looper.java:164) 在 android.app.ActivityThread.main(ActivityThread.java:6541) 在 java.lang.reflect.Method.invoke(本机方法) 在 com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)

这是应用程序中的完整错误

【问题讨论】:

  • 你能发布一份堆栈跟踪的副本吗?
  • 由于你还没有发布所有的堆栈跟踪,我想你应该将方法 doInBackground 的参数标记为可为空。
  • 我现在添加了堆栈跟踪
  • doInBackground 返回的类型必须与onPostExecute 方法中的参数类型相同,在您的情况下是不同的。尝试将onPostExecute 参数更改为Void? 并检查。还要确保在 AsyncTask 类头中将第三个参数类型 Void 更改为 Void?
  • 错误隐藏,但图片没有保存到SD卡!!

标签: android kotlin


【解决方案1】:

改变参数类型

override fun onPostExecute(result: Void)

override fun onPostExecute(result: Void?).

作为Akhilesh Kumar mentioned here,你也应该改变

class SaveThisImage : AsyncTask&lt;Void, Void, Void&gt;()

class SaveThisImage : AsyncTask&lt;Void, Void, Void?&gt;()

这是因为您的代码中的doInBackground 返回一个可为空的类型Void?doInBackground 的返回值作为参数传递给 onPostExcecute,但您的 onPostExecute 接受非空值 Void 而不是可空值 Void?

作为旁注,您应该在 Kotlin 中使用 Unit 而不是 Void

编辑

要显示您保存的图像,需要更新媒体数据库。当您重新启动设备或经过一段时间后,媒体数据库会更新,它将显示在保存位置。要立即更新媒体数据库,您可以使用MediaScannerConnection 对象。

尝试在bitmap.compress 之后将您保存的文件传递给此函数并传递您的myImageFile

/**
 * Updates the Pictures gallery to include the newly created file.
 * @param fileObj: file path to be scanned so that the new file will appear in the gallery
 */
private fun refreshPhoneGallery(fileObj: File)
{

    /* Scan the specified file path so that the new file will appear in gallery */
    MediaScannerConnection.scanFile(
        yourContext,
        arrayOf(fileObj.path),
        null,
        object : MediaScannerConnection.OnScanCompletedListener
        {
            override fun onScanCompleted(scannedFilePath: String?, p1: Uri?)
            {
                // Do whatever
            }
        }
    )
}

【讨论】:

  • 错误隐藏,但图片没有保存在SD卡中
  • 这可能是因为Android需要重新扫描你的设备来更新媒体数据库,你可以使用MediaScannerConnection来实现。我已经更新了我的答案以包含您可以使用的功能。
  • 代码:fos = FileOutputStream(myImageFile) return null 这里有错误
  • 你能调试你的代码看看myImageFile是否为空吗?
  • 不,myImageFile="/Storage/emulated/0/savedImageName/157959992357m.png"
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-23
  • 2014-08-17
  • 1970-01-01
相关资源
最近更新 更多