如何将图片保存到内部存储并在另一个活动中显示?

4
我正在使用Xamarin.Android。我有两个活动,需要在它们上面显示相同的图像。在第一个屏幕上,我从Web URL下载并显示它,但我不想在第二个屏幕上重复这样做。我想在第一个屏幕上下载时将其保存到内部存储,并从那里简单地检索它以在第二个活动中显示。我该怎么做?
这是我在第一个活动中使用的代码:
protected override void OnCreate (Bundle bundle)
{
    base.OnCreate (bundle);

    this.SetContentView (Resource.Layout.Main);

    String uriString = this.GetUriString();
    WebClient web = new WebClient ();
    web.DownloadDataCompleted += new DownloadDataCompletedEventHandler(web_DownloadDataCompleted);
    web.DownloadDataAsync (new Uri(uriString));
}

void web_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e)
{
    if (e.Error != null)
    {
        RunOnUiThread(() =>
            Toast.MakeText(this, e.Error.Message, ToastLength.Short).Show());
    }
    else
    {
        Bitmap bm = BitmapFactory.DecodeByteArray(e.Result, 0, e.Result.Length);

        // THIS IS WHERE I NEED TO SAVE THE IMAGE IN INTERNAL STORAGE //

        RunOnUiThread(() =>
            {
                ProgressBar pb = this.FindViewById<ProgressBar> (Resource.Id.custLogoProgressBar);
                pb.Visibility = ViewStates.Gone;

                ImageView imgCustLogo = FindViewById<ImageView>(Resource.Id.imgCustLogo);
                imgCustLogo.SetImageBitmap(bm);
            });
    }
}

现在要保存图像,这是我受到这个启发所做的事情:
        Bitmap bm = BitmapFactory.DecodeByteArray(e.Result, 0, e.Result.Length);

        ContextWrapper cw = new ContextWrapper(this.ApplicationContext);
        File directory = cw.GetDir("imgDir", FileCreationMode.Private);
        File myPath = new File(directory, "test.png");

        FileOutputStream fos = null;
        try 
        {
            fos = new FileOutputStream(myPath);
            bm.Compress(Bitmap.CompressFormat.Png, 100, fos);
            fos.Close();
        }
        catch (Exception ex) 
        {
            System.Console.Write(ex.Message);
        }

然而,这段代码无法编译,当我调用bm.Compress()时会出现异常。它提示:
Error CS1503: Argument 3: cannot convert from 'Java.IO.FileOutputStream' to 'System.IO.Stream'

我想知道是否有人能够从通用的角度回答这个问题?假设我已经创建了一个Image对象,它已经从URI加载了一个任意文件(例如可以是JPG、PNG等)。在PCL项目中,我该如何将其保存到本地文件系统中?我猜为了简化事情,我愿意将文件保存为常量文件类型,例如始终保存为PNG,而不管原始源格式如何。 - Andrew Jens
4个回答

3

好的,这是我让它正常工作的方法:

    Bitmap bm = BitmapFactory.DecodeByteArray(e.Result, 0, e.Result.Length);

    ContextWrapper cw = new ContextWrapper(this.ApplicationContext);
    File directory = cw.GetDir("imgDir", FileCreationMode.Private);
    File myPath = new File(directory, "test.png");

    try 
    {
        using (var os = new System.IO.FileStream(myPath.AbsolutePath, System.IO.FileMode.Create))
        {
            bm.Compress(Bitmap.CompressFormat.Png, 100, os);
        }
    }
    catch (Exception ex) 
    {
        System.Console.Write(ex.Message);
    }

1

如果您想将其保存到内部存储器中,并且不会在图库中显示

public static void SaveBitmapToInternalStorage(this Context context, Bitmap bitmap, string filename, string directory)
    {
        //can change directory as per need
        if (directory != null || directory != "") directory = "/" + directory;
        var imagesDir = context.GetExternalFilesDir(Android.OS.Environment.DirectoryPictures+ directory);
        if (!imagesDir.Exists()) imagesDir.Mkdirs();
        var jFile = new Java.IO.File(imagesDir, filename);
        var filePath = jFile.AbsoluteFile.ToString();

        System.IO.FileStream output = null;
        using (output = new System.IO.FileStream(filePath, System.IO.FileMode.Create))
        {
            bitmap.Compress(Bitmap.CompressFormat.Jpeg, 90, output);
        }
        output.Close();            
    }

要检索已保存的图像 注意:为了检索相同的文件,文件名和目录应该相同

public static Drawable GetDrawableFromInternalStorage(this Context context, string fileName, string directory)
    {
        //return drawable for imagename from internal storage
        if (directory != null || directory != "") directory = "/" + directory;
        var imagesDir = context.GetExternalFilesDir(Android.OS.Environment.DirectoryPictures + directory);
        if (!imagesDir.Exists()) return null;
        var jFile = new Java.IO.File(imagesDir, fileName);

        if (jFile.Exists())
        {
            var img = Drawable.CreateFromPath(jFile.ToString());
            return img;
        }
        return null;
    }

并将图片保存到相册中

public static bool SaveImageToGallery(this Context context, Bitmap bmp, string directory)
    {
        // First save the picture
        string storePath = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath + File.Separator + directory;
        File imgDir = new File(storePath);
        if (!imgDir.Exists()) imgDir.Mkdir();
        string fileName = System.DateTime.Today.ToLongDateString() + ".jpg";
        File file = new File(imgDir, fileName);
        try
        {
            var uri = Android.Net.Uri.FromFile(file);
            var os = context.ContentResolver.OpenOutputStream(uri);
            //Compress and save pictures by io stream
            bool isSuccess = bmp.Compress(Bitmap.CompressFormat.Jpeg, 60, os);
            os.Flush();
            os.Close();

            //Update the database by sending broadcast notifications after saving pictures                
            context.SendBroadcast(new Intent(Intent.ActionMediaScannerScanFile, uri));
            return isSuccess;
        }
        catch (IOException e) { }
        return false;
    }

如果您想要创建独特的文件名以保存到画廊中,则
File file = File.CreateTempFile(
                "Img_",  /* prefix */
                ".jpg",         /* suffix */
                imgDir    /* directory */);

0

我认为这是如何进行前后转换的:

using (var stream = new Java.Net.URL(uriString).OpenConnection().InputStream)
{
     bitmap = await BitmapFactory.DecodeStreamAsync(stream);
}

using (var stream = new Java.Net.URL(myPath.Path).OpenConnection().OutputStream)
{
    await bitmap.CompressAsync(Bitmap.CompressFormat.Png, 80, stream);
}

0

Bitmap 的 compress 方法需要一个 OutputStream 对象作为第三个参数,而你传递的是一个从 OutputStream 继承而来的 FileOutputStream。你可以尝试传递一个 OutputStream 对象来看看是否解决了问题。


OutputStream 实际上是 Java.IO.OutputStream,因此我仍然会收到错误提示:无法从 Java.IO.OutputStream 转换为 System.IO.Stream - Ahmed Salman Tahir

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接