如何在Android中将图像保存在共享首选项中 | Android中的共享首选项问题与图像

14

在我的应用程序中,登录后我必须将用户名和图片保存在共享首选项中以供其他页面使用。我已经能够将名称保存在首选项中,但不知道如何保存图像。

我正在尝试类似于以下内容-

SharedPreferences myPrefrence;
    String namePreferance="name";

    String imagePreferance="image";

SharedPreferences.Editor editor = myPrefrence.edit();
                editor.putString("namePreferance", itemNAme);
                editor.putString("imagePreferance", itemImagePreferance);
                editor.commit();
我试图将图像转换为对象后保存为字符串。但是当我重新将其转换为位图时,我没有得到任何东西。

为什么要将它存储在SharedPreferences中?那不是存储图像的正确位置。如果有外部存储器,则应将它们缓存在外部存储器上,如果没有,则应尝试将它们存储在内部存储器上,但是当使用内部存储器时要小心,因为通常不会像外部存储器那样拥有太多空间。请查看此链接,了解如何使用外部存储器:http://developer.android.com/guide/topics/data/data-storage.html#filesExternal - Chetna
@Chetna 谢谢,但我有点困惑,如果用户更改了个人资料图片或使用另一个帐户登录会发生什么? - user2652878
你试过谷歌搜索你的问题吗?因为如果你这样做了,你就会找到解决方案。这个是其中之一。 - Chetna
谢谢,我认为更好的选择是将其转换为base64字符串并存储在首选项中,对吧? - user2652878
谢谢!如果有任何问题,我会通知您的。 感谢您的帮助! - user2652878
显示剩余5条评论
4个回答

56

我已经解决了你的问题,做类似于这样的事情:

  1. Write Method to encode your bitmap into string base64-

    // method for bitmap to base64
    public static String encodeTobase64(Bitmap image) {
        Bitmap immage = image;
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        immage.compress(Bitmap.CompressFormat.PNG, 100, baos);
        byte[] b = baos.toByteArray();
        String imageEncoded = Base64.encodeToString(b, Base64.DEFAULT);
    
        Log.d("Image Log:", imageEncoded);
        return imageEncoded;
    }
    
  2. Pass your bitmap inside this method like something in your preference:

    SharedPreferences.Editor editor = myPrefrence.edit();
    editor.putString("namePreferance", itemNAme);
    editor.putString("imagePreferance", encodeTobase64(yourbitmap));
    editor.commit();
    
  3. And when you want to display your image just anywhere, convert it into a bitmap again using the decode method:

    // method for base64 to bitmap
    public static Bitmap decodeBase64(String input) {
        byte[] decodedByte = Base64.decode(input, 0);
        return BitmapFactory
                .decodeByteArray(decodedByte, 0, decodedByte.length);
    }
    
  4. Please pass your string inside this method and do what you want.


1
嗨,Manish,首先感谢您的回复!我已经在Chetna的帮助下解决了我的问题。感谢您花费时间并逐行解释。希望将来它能帮助其他人,所以我给您点赞。 - user2652878
干得好,继续保持! - user2652878
因为我的积分不够,所以我无法给你点赞。你能给我一些积分吗? - user2652878
你是怎么获取图片的名称的?当你将它放入sharedPref中时。 - RoCkDevstack
你在执行此操作时是否保留图像质量? - portfoliobuilder

6
Finally I solved this problem.

步骤: 1. 我在onCreate()中编写了一些代码,以获取来自前一个活动的意图数据。
 private  Bitmap bitmap;

 Intent intent = getIntent();

        if (getIntent().getExtras() != null)
        {
            // for get data from intent

            bitmap = intent.getParcelableExtra("PRODUCT_PHOTO");

            // for set this picture to imageview

            your_imageView.setImageBitmap(bitmap);

             sharedPreferences();

        }else
        {
            retrivesharedPreferences();
        }

创建sharedPreferences()并放入以下代码。
 private void sharedPreferences()
    {
        SharedPreferences shared = getSharedPreferences("App_settings", MODE_PRIVATE);
        SharedPreferences.Editor editor = shared.edit();
        editor.putString("PRODUCT_PHOTO", encodeTobase64(bitmap));
        editor.commit();
    }

创建 retrivesharedPreferences() 方法并放入以下代码:
private void retrivesharedPreferences()
    {
      SharedPreferences shared = getSharedPreferences("MyApp_Settings", MODE_PRIVATE);
        String photo = shared.getString("PRODUCT_PHOTO", "photo");
        assert photo != null;
        if(!photo.equals("photo"))
        {
            byte[] b = Base64.decode(photo, Base64.DEFAULT);
            InputStream is = new ByteArrayInputStream(b);
            bitmap = BitmapFactory.decodeStream(is);
            your_imageview.setImageBitmap(bitmap);
        }

    }

4. 编写encodeToBase64()方法,将您的位图编码为字符串base64,并将代码放入此方法中。
 public static String encodeTobase64(Bitmap image) {
        Bitmap bitmap_image = image;
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bitmap_image.compress(Bitmap.CompressFormat.PNG, 100, baos);
        byte[] b = baos.toByteArray();
        String imageEncoded = Base64.encodeToString(b, Base64.DEFAULT);

        return imageEncoded;
    }

我希望这对你有所帮助。

美丽的第一行 - Alireza Jamali

4

编码为Base64?!这简直是疯话!你将太多的信息存储到共享首选项中了。你应该采取的策略是保存图像URI文件路径,并按此方式检索它。这样,当解码图像时,你的应用程序不会存储太多信息并变成内存占用过高的问题。

我在Github上制作了一个简单的应用程序来演示这个想法,如果你想跟随:

1. 声明变量:

private ImageView mImage;
private Uri mImageUri;

2. 选择图像:

public void imageSelect() {
     Intent intent;
     if (Build.VERSION.SDK_INT < 19) {
         intent = new Intent(Intent.ACTION_GET_CONTENT);
     } else {
         intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
         intent.addCategory(Intent.CATEGORY_OPENABLE);
     }
     intent.setType("image/*");
     startActivityForResult(Intent.createChooser(intent, "Select Picture"),
         PICK_IMAGE_REQUEST);
 }

3. 保存图像 URI:

@Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
     // Check which request we're responding to
     if (requestCode == PICK_IMAGE_REQUEST) {
         // Make sure the request was successful
         if (resultCode == RESULT_OK) {
             // The user picked a image.
             // The Intent's data Uri identifies which item was selected.
            if (data != null) {

                // This is the key line item, URI specifies the name of the data
                mImageUri = data.getData();

                // Removes Uri Permission so that when you restart the device, it will be allowed to reload. 
                this.grantUriPermission(this.getPackageName(), mImageUri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
                final int takeFlags = Intent.FLAG_GRANT_READ_URI_PERMISSION;
                this.getContentResolver().takePersistableUriPermission(mImageUri, takeFlags);

                // Saves image URI as string to Default Shared Preferences
                SharedPreferences preferences = 
                     PreferenceManager.getDefaultSharedPreferences(this);
                SharedPreferences.Editor editor = preferences.edit();
                editor.putString("image", String.valueOf(mImageUri));
                editor.commit();

                // Sets the ImageView with the Image URI
                mImage.setImageURI(mImageUri);
                mImage.invalidate();
             }
         }
     }
 }

4. 需要时检索图像URI:

SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
String mImageUri = preferences.getString("image", null);
mImage.setImageURI(Uri.parse(mImageUri));

完成了!我们已经干净地将图像的URI路径保存到共享首选项中,并没有浪费宝贵的系统资源对图像进行编码并将其保存到SharedPreferences。


当图像不再在设备中时,它还能工作吗? - Ed_
不,这样行不通。如果你只有几张图片并且想要保护它们,那么第一种方法是更可取的选择! - m.i.n.a.r.

0
//Thanks Maish srivastava 
// i will do complete code just copy past and run it sure worked it
//
public class MainActivity extends Activity  implements OnClickListener
{
    private static int RESULT_LOAD_IMAGE = 1;
    public static final String MyPREFERENCES = "MyPre" ;//file name
       public static final String  key = "nameKey"; 
       SharedPreferences sharedpreferences ;
       Bitmap btmap;
    @Override
    protected void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

         sharedpreferences =  getSharedPreferences(MyPREFERENCES, Context.MODE_PRIVATE);
         if (sharedpreferences.contains(key))
          {
                String u=sharedpreferences.getString(key, "");
                btmap=decodeBase64(u); 
                ImageView iv = (ImageView) findViewById(R.id.imageView1);
                iv.setImageBitmap(btmap);
          }
       ImageButton imgbtn=(ImageButton) findViewById(R.id.imageButton1);
       imgbtn.setOnClickListener(this);
    }

public void onClick(View  v) 
{
    // TODO Auto-generated method stub
    switch (v.getId())
     {
             case R.id.imageButton1: 
                  try 
                  { //go to image library and pick the image
                   Intent i=newIntent(ntent.ACTION_PICK,
                   android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                   startActivityForResult(i, RESULT_LOAD_IMAGE);      
                  } 
                  catch (Exception e) 
                  {
                   e.printStackTrace();
                  }
                  break;
     }  
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == RESULT_LOAD_IMAGE && resultCode == RESULT_OK && null != data) 
    {
        Uri selectedImage = data.getData();
        String[] filePathColumn = { MediaStore.Images.Media.DATA };
        Cursor cursor = getContentResolver().query(selectedImage, filePathColumn, null, null, null);
        cursor.moveToFirst();

        int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
        String picturePath = cursor.getString(columnIndex);
        cursor.close();

        ImageView iv = (ImageView) findViewById(R.id.imageView1);
        iv.setImageBitmap(BitmapFactory.decodeFile(picturePath));
        btmap=BitmapFactory.decodeFile(picturePath);//decode method called

        Editor editor = sharedpreferences.edit();
        editor.putString(key,  encodeTobase64(btmap));
        editor.commit();   
    }


}
public static String encodeTobase64(Bitmap image)
     {
    Bitmap immage = image;
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    immage.compress(Bitmap.CompressFormat.PNG, 100, baos);
    byte[] b = baos.toByteArray();
    String imageEncoded = Base64.encodeToString(b, Base64.DEFAULT);

    Log.d("Image Log:", imageEncoded);
    return imageEncoded;

     }
public static Bitmap decodeBase64(String input) 
{
    byte[] decodedByte = Base64.decode(input, 0);
    return BitmapFactory
            .decodeByteArray(decodedByte, 0, decodedByte.length);
}
@Override
    public boolean onCreateOptionsMenu(Menu menu)
    {
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
}

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