麻烦写入内存的android [英] Trouble writing internal memory android

查看:272
本文介绍了麻烦写入内存的android的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

void launchImageCapture(Activity context) {
    Uri imageFileUri = context.getContentResolver()
        .insert(Media.INTERNAL_CONTENT_URI, new ContentValues());
    m_queue.add(imageFileUri);
    Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);

    i.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, imageFileUri); 
    context.startActivityForResult(i, ImportActivity.CAMERA_REQUEST); 
}

以上code,它一直致力于,现在对我来说,在插入产生这种异常()。

The above code, which has always worked, is now generating this exception for me at insert().

java.lang.UnsupportedOperationException: Writing to internal storage is not supported.
     at com.android.providers.media.MediaProvider.generateFileName(MediaProvider.java:2336)
     at com.android.providers.media.MediaProvider.ensureFile(MediaProvider.java:1851)
     at com.android.providers.media.MediaProvider.insertInternal(MediaProvider.java:2006)
     at com.android.providers.media.MediaProvider.insert(MediaProvider.java:1974)
     at android.content.ContentProvider$Transport.insert(ContentProvider.java:150)
     at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:140)
     at android.os.Binder.execTransact(Binder.java:287)
     at dalvik.system.NativeStart.run(Native Method)

这不是一个空间的问题,而我唯一改变的是一个不相关的类的包一起。另外,我重新启动我的电话。

It is not a space issue, and the only thing I changed was the package of an unrelated class all together. Also, I restarted my phone.

推荐答案

在这里面对同样的问题,我很高兴找到这个线程。尽管两件事情是在这种解决方法缠着我,这个帖子让我看在正确的方向。我想与大家分享我自己的解决方法/解决方案。

Facing same problem here, I was happy to find this thread. Even though two things were bugging me in this workaround, this post had me looking in the right direction. I'd like to share my own workaround/solution.

首先,我要声明,我没有看到自己生活在什么样。

Let me begin by stating what I did not see myself living with.

首先,我不想离开应用程序专用文件MODE_WORLD_WRITEABLE。这看起来像无感对我来说,虽然我不明白的完全的另一个应用程序将如何访问该文件,除非知道到哪里寻找它的全名和路径。我不是说这一定是坏了你的情况,但它仍然缠着我莫名其妙。我想preFER覆盖所有我的基地由具有图片文件真正的私有我的应用程序。在我的业务案例,图片是没有用的应用程序之外,绝不应该是可删除的经,说,Android的画廊。我的应用程序将触发清除在适当的时间,以便不vampirize德罗伊德设备的存储空间。

First, I did not want to leave the application private file as MODE_WORLD_WRITEABLE. This looks like non-sense to me, although I cannot figure exactly how another application could access this file unless knowing where to look for it with complete name and path. I'm not saying it is necessarily bad for your scenario, but it is still bugging me somehow. I would prefer to cover all my bases by having picture files really private to my app. In my business case, pictures are of no use outside of the application and by no means should they be deleteable via, say, the Android Gallery. My app will trigger cleanup at an appropriate time so as to not vampirize Droid device storage space.

其次, openFileOutput()不留任何选项,但所得到的文件保存在 getFilesDir()根。如果我需要一些目录结构来保持对事物的顺序?此外,我的应用程序必须处理多张图片,所以我想有文件名中产生,所以我可以参考它以后。

Second, openFileOutput() do not leave any option but to save the resulting file in the root of getFilesDir(). What if I need some directory structure to keep things in order? In addition, my application must handle more than one picture, so I would like to have the filename generated so I can refer to it later on.

见,很容易捕捉相机中的照片,并把它保存到公众形象区(通过MediaStore)Droid手机设备上。这也很容易操作(查询,更新,删除)从MediaStore媒体。有趣的是,插入照相机图片来MediaStore genreates这似乎是唯一的文件名。这也很容易创建私有文件与目录结构的应用程序。中的关键Capturea摄像头的画面并将其保存到内部存储器问题是,你不能这样做,直接由于Android prevents ContentResolver的使用Media.INTERNAL_CONTENT_URI,因为私人的应用程序文件根据定义通过(外)摄像头活动不可访问。

See, it is easy to capture a photo with the camera and save it to public image area (via MediaStore) on the Droid device. It is also easy to manipulate (query, update, delete) media from MediaStore. Interestingly, inserting camera picture to MediaStore genreates a filename which appears to be unique. It is also easy to create private File for an application with a directory structure. The crux of the "Capturea camera picture and save it to internal memory" problem is that you can't do so directly because Android prevents ContentResolver to use Media.INTERNAL_CONTENT_URI, and because private app files are by definition not accessible via the (outside) Camera activity.

最后,我采取了以下策略:

Finally I adopted the following strategy:

  1. 的意图开始为结果的摄像头活动,从我的应用程序来捕捉图像。
  2. 当返回到我的应用程序,将捕捉到MediaStore。
  3. 查询MediaStore获得生成的图像文件名。
  4. 使用 Context.getDir()创建一个真正的内部文件路径相对于私有应用程序数据文件夹不管到。
  5. 使用的OutputStream写入位图数据,这个​​私人文件。
  6. 从MediaStore删除捕捉。
  7. 可选)显示捕获的ImageView的我的应用程序。
  1. Start the Camera activity for result from my app with the Intent to capture image.
  2. When returning to my app, insert capture to the MediaStore.
  3. Query the MediaStore to obtain generated image file name.
  4. Create a truly internal file onto whatever path relative to private application data folder using Context.getDir().
  5. Use an OutputStream to write Bitmap data to this private file.
  6. Delete capture from MediaStore.
  7. (Optional) show an ImageView of the capture in my app.

下面是code开始凸轮:

Here is the code starting the cam:

public void onClick (View v)
{
    ContentValues values = new ContentValues ();

    values.put (Media.IS_PRIVATE, 1);
    values.put (Media.TITLE, "Xenios Mobile Private Image");
    values.put (Media.DESCRIPTION, "Classification Picture taken via Xenios Mobile.");

    Uri picUri = getActivity ().getContentResolver ().insert (Media.EXTERNAL_CONTENT_URI, values);

    //Keep a reference in app for now, we might need it later.
    ((XeniosMob) getActivity ().getApplication ()).setCamPicUri (picUri);

    Intent takePicture = new Intent (MediaStore.ACTION_IMAGE_CAPTURE);

    //May or may not be populated depending on devices.
    takePicture.putExtra (MediaStore.EXTRA_OUTPUT, picUri);

    getActivity ().startActivityForResult (takePicture, R.id.action_camera_start);
}

这里是我的活动越来越凸轮结果:

And here is my activity getting cam result:

@Override
protected void onActivityResult (int requestCode, int resultCode, Intent data)
{
    super.onActivityResult (requestCode, resultCode, data);
    if (requestCode == R.id.action_camera_start)
    {
        if (resultCode == RESULT_OK)
        {
            Bitmap pic = null;
            Uri picUri = null;

            //Some Droid devices (as mine: Acer 500 tablet) leave data Intent null.
            if (data == null) {
                picUri = ((XeniosMob) getApplication ()).getCamPicUri ();
            } else
            {
                Bundle extras = data.getExtras ();
                picUri = (Uri) extras.get (MediaStore.EXTRA_OUTPUT);
            }

            try
            {
                pic = Media.getBitmap (getContentResolver (), picUri);
            } catch (FileNotFoundException ex)
            {
                Logger.getLogger (getClass ().getName ()).log (Level.SEVERE, null, ex);
            } catch (IOException ex)
            {
                Logger.getLogger (getClass ().getName ()).log (Level.SEVERE, null, ex);
            }

            //Getting (creating it if necessary) a private directory named app_Pictures
            //Using MODE_PRIVATE seems to prefix the directory name provided with "app_".
            File dir = getDir (Environment.DIRECTORY_PICTURES, Context.MODE_PRIVATE);

            //Query the MediaStore to retrieve generated filename for the capture.
            Cursor query = getContentResolver ().query (
                        picUri,
                        new String [] {
                            Media.DISPLAY_NAME,
                            Media.TITLE
                        },
                        null, null, null
                    );
            boolean gotOne = query.moveToFirst ();
            File internalFile = null;
            if (gotOne)
            {
                String dn = query.getString (query.getColumnIndexOrThrow (Media.DISPLAY_NAME));
                String title = query.getString (query.getColumnIndexOrThrow (Media.TITLE));
                query.close ();

                //Generated name is a ".jpg" on my device (tablet Acer 500).
                //I prefer to work with ".png".
                internalFile = new File (dir, dn.subSequence (0, dn.lastIndexOf (".")).toString () + ".png");
                internalFile.setReadable (true);
                internalFile.setWritable (true);
                internalFile.setExecutable (true);
                try
                {
                    internalFile.createNewFile ();

                    //Use an output stream to write picture data to internal file.
                    FileOutputStream fos = new FileOutputStream (internalFile);
                    BufferedOutputStream bos = new BufferedOutputStream (fos);

                    //Use lossless compression.
                    pic.compress (Bitmap.CompressFormat.PNG, 100, bos);

                    bos.flush ();
                    bos.close ();
                } catch (FileNotFoundException ex)
                {
                    Logger.getLogger (EvaluationActivity.class.getName()).log (Level.SEVERE, null, ex);
                } catch (IOException ex)
                {
                    Logger.getLogger (EvaluationActivity.class.getName()).log (Level.SEVERE, null, ex);
                }
            }

            //Update picture Uri to that of internal file.
            ((XeniosMob) getApplication ()).setCamPicUri (Uri.fromFile (internalFile));

            //Don't keep capture in public storage space (no Android Gallery use)
            int delete = getContentResolver ().delete (picUri, null, null);

            //rather just keep Uri references here
            //visit.add (pic);

            //Show the picture in app!
            ViewGroup photoLayout = (ViewGroup) findViewById (R.id.layout_photo_area);
            ImageView iv = new ImageView (photoLayout.getContext ());
            iv.setImageBitmap (pic);
            photoLayout.addView (iv, 120, 120);
        }
        else if (resultCode == RESULT_CANCELED)
        {
            Toast toast = Toast.makeText (this, "Picture capture has been cancelled.", Toast.LENGTH_LONG);
            toast.show ();
        }
    }
}

瞧!现在,我们有一个真正的应用私人图像文件,该文件名已经由德罗伊德装置产生。并没有被保持在公共存储区,从而$ ​​P $ pventing偶然图片操作

Voila! Now we have a truly application private picture file, which name has been generated by the Droid device. And nothing is kept in the public storage area, thus preventing accidental picture manipulation.

这篇关于麻烦写入内存的android的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆