操作sdcar的图片oom 问题

本文介绍了一种在Android应用中处理从SD卡加载图片时出现的内存溢出(OOM)问题的方法。通过使用异步任务加载图片并适当调整图片大小来避免内存溢出。
最近在做一个小的应用,里面有处理从sdcard 中取得图片的的操作,但是发现会oom(out of memory )异常。于是google 看到了一篇帖子引用过来做个备份以后也有一个好的经验和总结
package cn.gridview;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;

import android.app.Activity;
import android.content.Context;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.MediaStore;
import android.view.Display;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;

public class GridviewTestActivity extends Activity implements  OnItemClickListener {
	      
	    /** 
	     * Grid view holding the images. 
	     */  
	    private GridView sdcardImages;  
	    /** 
	     * Image adapter for the grid view. 
	     */  
	    private ImageAdapter imageAdapter;  
	    /** 
	     * Display used for getting the width of the screen.  
	     */  
	    private Display display;  
	  
	    /** 
	     * Creates the content view, sets up the grid, the adapter, and the click listener. 
	     *  
	     * @see android.app.Activity#onCreate(android.os.Bundle) 
	     */  
	    @Override  
	    public void onCreate(Bundle savedInstanceState) {  
	        super.onCreate(savedInstanceState);          
	        // Request progress bar  
	        requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);  
	        setContentView(R.layout.main);  
	  
	        display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();  
	  
	        setupViews();  
	        setProgressBarIndeterminateVisibility(true);   
	        loadImages();  
	    }  
	  
	    /** 
	     * Free up bitmap related resources. 
	     */  
	    protected void onDestroy() {  
	        super.onDestroy();  
	        final GridView grid = sdcardImages;  
	        final int count = grid.getChildCount();  
	        ImageView v = null;  
	        for (int i = 0; i < count; i++) {  
	            v = (ImageView) grid.getChildAt(i);  
	            ((BitmapDrawable) v.getDrawable()).setCallback(null);  
	        }  
	    }  
	    /** 
	     * Setup the grid view. 
	     */  
	    private void setupViews() {  
	        sdcardImages = (GridView) findViewById(R.id.sdcard);  
	        sdcardImages.setNumColumns(display.getWidth()/95);  
	        sdcardImages.setClipToPadding(false);  
	        sdcardImages.setOnItemClickListener(GridviewTestActivity.this);  
	        imageAdapter = new ImageAdapter(getApplicationContext());   
	        sdcardImages.setAdapter(imageAdapter);  
	    }  
	    /** 
	     * Load images. 
	     */  
	    private void loadImages() {  
	        final Object data = getLastNonConfigurationInstance();  
	        if (data == null) {  
	            new LoadImagesFromSDCard().execute();  
	        } else {  
	            final LoadedImage[] photos = (LoadedImage[]) data;  
	            if (photos.length == 0) {  
	                new LoadImagesFromSDCard().execute();  
	            }  
	            for (LoadedImage photo : photos) {  
	                addImage(photo);  
	            }  
	        }  
	    }  
	    /** 
	     * Add image(s) to the grid view adapter. 
	     *  
	     * @param value Array of LoadedImages references 
	     */  
	    private void addImage(LoadedImage... value) {  
	        for (LoadedImage image : value) {  
	            imageAdapter.addPhoto(image);  
	            imageAdapter.notifyDataSetChanged();  
	        }  
	    }  
	      
	    /** 
	     * Save bitmap images into a list and return that list.  
	     *  
	     * @see android.app.Activity#onRetainNonConfigurationInstance() 
	     */  
	    @Override  
	    public Object onRetainNonConfigurationInstance() {  
	        final GridView grid = sdcardImages;  
	        final int count = grid.getChildCount();  
	        final LoadedImage[] list = new LoadedImage[count];  
	  
	        for (int i = 0; i < count; i++) {  
	            final ImageView v = (ImageView) grid.getChildAt(i);  
	            list[i] = new LoadedImage(((BitmapDrawable) v.getDrawable()).getBitmap());  
	        }  
	  
	        return list;  
	    }  
	    /** 
	     * Async task for loading the images from the SD card.  
	     *  
	     * @author Mihai Fonoage 
	     * 
	     */  
	    class LoadImagesFromSDCard extends AsyncTask<Object, LoadedImage, Object> {  
	          
	        /** 
	         * Load images from SD Card in the background, and display each image on the screen.  
	         *   
	         * @see android.os.AsyncTask#doInBackground(Params[]) 
	         */  
	        @Override  
	        protected Object doInBackground(Object... params) {  
	            //setProgressBarIndeterminateVisibility(true);   
	            Bitmap bitmap = null;  
	            Bitmap newBitmap = null;  
	            Uri uri = null;              
	  
	            // Set up an array of the Thumbnail Image ID column we want  
	            String[] projection = {MediaStore.Images.Thumbnails._ID};  
	            // Create the cursor pointing to the SDCard  
	            Cursor cursor = managedQuery( MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI,  
	                    projection, // Which columns to return  
	                    null,       // Return all rows  
	                    null,         
	                    null);   
	            int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Thumbnails._ID);  
	            int size = cursor.getCount();  
	            // If size is 0, there are no images on the SD Card.  
	            if (size == 0) {  
	                //No Images available, post some message to the user  
	            }  
	            int imageID = 0;  
	            for (int i = 0; i < size; i++) {  
	                cursor.moveToPosition(i);  
	                imageID = cursor.getInt(columnIndex);  
	                uri = Uri.withAppendedPath(MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, "" + imageID);  
	                try {  
	                    bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));  
	                    if (bitmap != null) {  
	                        newBitmap = Bitmap.createScaledBitmap(bitmap, 70, 70, true);  
	                        bitmap.recycle();  
	                        if (newBitmap != null) {  
	                            publishProgress(new LoadedImage(newBitmap));  
	                        }  
	                    }  
	                } catch (IOException e) {  
	                    //Error fetching image, try to recover  
	                }  
	            }  
	            cursor.close();  
	            return null;  
	        }  
	        /** 
	         * Add a new LoadedImage in the images grid. 
	         * 
	         * @param value The image. 
	         */  
	        @Override  
	        public void onProgressUpdate(LoadedImage... value) {  
	            addImage(value);  
	        }  
	        /** 
	         * Set the visibility of the progress bar to false. 
	         *  
	         * @see android.os.AsyncTask#onPostExecute(java.lang.Object) 
	         */  
	        @Override  
	        protected void onPostExecute(Object result) {  
	            setProgressBarIndeterminateVisibility(false);  
	        }  
	    }  
	  
	    /** 
	     * Adapter for our image files.  
	     *  
	     * @author Mihai Fonoage 
	     * 
	     */  
	    class ImageAdapter extends BaseAdapter {  
	  
	        private Context mContext;   
	        private ArrayList<LoadedImage> photos = new ArrayList<LoadedImage>();  
	  
	        public ImageAdapter(Context context) {   
	            mContext = context;   
	        }   
	  
	        public void addPhoto(LoadedImage photo) {   
	            photos.add(photo);   
	        }   
	  
	        public int getCount() {   
	            return photos.size();   
	        }   
	  
	        public Object getItem(int position) {   
	            return photos.get(position);   
	        }   
	  
	        public long getItemId(int position) {   
	            return position;   
	        }   
	  
	        public View getView(int position, View convertView, ViewGroup parent) {   
	            final ImageView imageView;   
	            if (convertView == null) {   
	                imageView = new ImageView(mContext);   
	            } else {   
	                imageView = (ImageView) convertView;   
	            }   
	            imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);  
	            imageView.setPadding(8, 8, 8, 8);  
	            imageView.setImageBitmap(photos.get(position).getBitmap());  
	            return imageView;   
	        }   
	    }  
	  
	    /** 
	     * A LoadedImage contains the Bitmap loaded for the image. 
	     */  
	    private static class LoadedImage {  
	        Bitmap mBitmap;  
	  
	        LoadedImage(Bitmap bitmap) {  
	            mBitmap = bitmap;  
	        }  
	  
	        public Bitmap getBitmap() {  
	            return mBitmap;  
	        }  
	    }  
	    /** 
	     * When an image is clicked, load that image as a puzzle.  
	     */  
	    public void onItemClick(AdapterView<?> parent, View v, int position, long id) {          
	        int columnIndex = 0;  
	        String[] projection = {MediaStore.Images.Media.DATA};  
	        Cursor cursor = managedQuery( MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI,  
	                projection,  
	                null,   
	                null,   
	                null);  
	        if (cursor != null) {  
	            columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);  
	            cursor.moveToPosition(position);  
	            String imagePath = cursor.getString(columnIndex);   
	  
	            FileInputStream is = null;  
	            BufferedInputStream bis = null;  
	            try {  
	                is = new FileInputStream(new File(imagePath));  
	                bis = new BufferedInputStream(is);  
	                Bitmap bitmap = BitmapFactory.decodeStream(bis);  
	                Bitmap useThisBitmap = Bitmap.createScaledBitmap(bitmap, parent.getWidth(), parent.getHeight(), true);  
	                bitmap.recycle();  
	                //Display bitmap (useThisBitmap)  
	            }   
	            catch (Exception e) {  
	                //Try to recover  
	            }  
	            finally {  
	                try {  
	                    if (bis != null) {  
	                        bis.close();  
	                    }  
	                    if (is != null) {  
	                        is.close();  
	                    }  
	                    cursor.close();  
	                    projection = null;  
	                } catch (Exception e) {  
	                }  
	            }  
	        }  
	    }  
	  
	}  
 main.xml的写法
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="vertical" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    > 
<GridView 
         android:id="@+id/sdcard" 
         android:layout_width="fill_parent" 
         android:layout_height="fill_parent" 
         android:columnWidth="90dp" 
         android:numColumns="auto_fit" 
         android:verticalSpacing="10dp" 
         android:horizontalSpacing="10dp" 
         android:stretchMode="columnWidth" 
         android:gravity="center" 
         />   
</LinearLayout> 
转自: http://wang-peng1.iteye.com/blog/676010

<think>好的,我需要解决用户的问题:如何通过命令行重复推送视频文件到安卓设备的SD卡。首先,用户提到之前遇到的错误是只读文件系统,所以权限和路径正确性很重要。根据用户提供的引用,特别是引用[1]和[2],他们可能尝试过adb push命令,但遇到了权限问题。 首先,确认设备连接。用户需要使用adb devices检查设备是否被识别,确保设备处于可调试模式。如果设备未列出,可能需要重新连接或检查USB调试设置。 接下来,确定正确的SD卡路径。引用[1]提到在AVD中,/mnt/media_rw/sdcard是可写入的目录。但实际设备可能路径不同,通常外部存储的路径是/sdcard/或/storage/emulated/0/。需要用户确认目标设备的正确路径,可以通过adb shell ls /sdcard/来测试是否有写入权限。 然后,使用adb push命令推送文件。基本命令是adb push local_file.mp4 /sdcard/目标路径/。但用户需要重复推送,可能需要覆盖现有文件。默认情况下,adb push会覆盖同名文件,但可能需要添加参数确保覆盖。例如,adb push -p 可能保留时间戳,但不确定是否影响覆盖行为,可能需要检查adb版本。 如果遇到权限被拒绝,可能需要重新挂载文件系统为可读写。在adb shell中使用su切换到root,然后执行mount -o remount,rw /sdcard,但这需要设备已root。如果设备未root,可能需要使用其他可写目录,如/sdcard/Download/,或者通过Android API请求权限。 另外,引用[2]中的示例使用的是pull命令,但用户需要push,所以命令结构类似,方向相反。用户需要确保目标目录存在,可以使用adb shell mkdir -p /sdcard/videos/来创建目录。 总结步骤:检查设备连接,确认目标路径可写,使用adb push推送,处理权限问题。如果仍然遇到只读错误,可能需要使用adb root或更改目录权限,但这取决于设备是否解锁了root权限。</think>要通过命令行重复推送视频文件到安卓设备的SD卡,需按以下步骤操作: ### 一、确认设备连接状态 1. 使用命令检查设备是否被识别: ```bash adb devices ``` 输出应包含设备序列号和`device`状态,如: ```bash JVROGMW8CQZXLZW8 device ``` 2. 若设备未列出: - 开启手机的**USB调试模式** - 重新插拔USB线 - 使用`adb kill-server && adb start-server`重启ADB服务 --- ### 二、确定SD卡可写路径 1. **通过ADB Shell验证路径权限**: ```bash adb shell ls -l /sdcard/ ``` 若返回`Permission denied`,尝试改用标准可写目录: ```bash adb shell ls -l /sdcard/Download/ ``` 2. **推荐使用系统预设目录**: - `/sdcard/Download/`(系统下载目录) - `/sdcard/DCIM/`(相册目录) - `/sdcard/Movies/`(视频目录)[^1] --- ### 三、执行重复推送命令 1. **基础推送命令**(覆盖已有文件): ```bash adb push -p D:\本地视频.mp4 /sdcard/Movies/ ``` - `-p`参数保留文件修改时间戳 - 默认行为会直接覆盖同名文件 2. **批量推送示例**: ```bash adb push D:\video_folder\*.mp4 /sdcard/Movies/ ``` --- ### 四、处理只读文件系统错误 若出现`Read-only file system`错误: 1. **重新挂载为可写**(需root): ```bash adb root adb shell mount -o remount,rw /sdcard ``` 2. **通过Android API写入**: ```java // 在APP中请求MANAGE_EXTERNAL_STORAGE权限 Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION); startActivity(intent); ``` --- ### 五、验证文件传输 1. **检查文件大小**: ```bash adb shell ls -l /sdcard/Movies/视频文件名.mp4 ``` 2. **直接播放测试**: ```bash adb shell am start -a android.intent.action.VIEW -d file:///sdcard/Movies/视频文件名.mp4 -t video/mp4 ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值