android - 在 Canvas 上绘制图像并保存到 SD 卡中

标签 android

我尝试使用以下代码

  1. 在 Canvas 上绘画
  2. 将 Canvas 保存在图像上

问题 - 当我尝试保存图像时,它显示类似权限被拒绝的错误。我的错误日志如下。

在 Canvas 上绘制的代码:

public MyDrawView(Context c, AttributeSet attrs) {
        super(c, attrs);
        mPath = new Path();
        mBitmapPaint = new Paint(Paint.DITHER_FLAG);
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setDither(true);
        mPaint.setColor(0xFF000000);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeJoin(Paint.Join.ROUND);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mPaint.setStrokeWidth(9);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        mCanvas = new Canvas(mBitmap);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
        canvas.drawPath(mPath, mPaint);    
    }

    private float mX, mY;
    private static final float TOUCH_TOLERANCE = 4;

    private void touch_start(float x, float y) {
        mPath.reset();
        mPath.moveTo(x, y);
        mX = x;
        mY = y;
    }
    private void touch_move(float x, float y) {
        float dx = Math.abs(x - mX);
        float dy = Math.abs(y - mY);
        if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
            mPath.quadTo(mX, mY, (x + mX)/2, (y + mY)/2);
            mX = x;
            mY = y;
        }
    }
    private void touch_up() {
        mPath.lineTo(mX, mY);
        // commit the path to our offscreen
        mCanvas.drawPath(mPath, mPaint);
        // kill this so we don't double draw
        mPath.reset();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float x = event.getX();
        float y = event.getY();

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                touch_start(x, y);
                invalidate();
                break;
            case MotionEvent.ACTION_MOVE:
                touch_move(x, y);
                invalidate();
                break;
            case MotionEvent.ACTION_UP:
                touch_up();
                invalidate();
                break;
        }
        return true;
    }

    public Bitmap getBitmap() {
        this.setDrawingCacheEnabled(true);  
        this.buildDrawingCache();
        Bitmap bmp = Bitmap.createBitmap(this.getDrawingCache());   
        this.setDrawingCacheEnabled(false);
    return bmp;
   }

    public void clear(){
        mBitmap.eraseColor(Color.GREEN);
        invalidate();
        System.gc();    
    }

}

将 Canvas 保存为图像的第二个代码位于主 Activity 中。 由于我是初学者,我感谢任何建议。

第二个代码MainActivity:

public class MainActivity extends Activity {
MyDrawView myDrawView;

@Override
protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    myDrawView = (MyDrawView) findViewById(R.id.draw);
    Button button1 = (Button) findViewById(R.id.button1);
    button1.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {

            File folder = new File(Environment
                    .getExternalStorageDirectory().getAbsolutePath()+"/Folder image");
            if (!folder.exists()) {
                folder.mkdirs();
            }

            File file = new File(folder,"sample.png");

            if (!file.exists()) {
                try {
                    file.createNewFile();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }


            FileOutputStream ostream = null;
            try {
                ostream = new FileOutputStream(file);

                System.out.println(ostream);
                View targetView = myDrawView;

                Bitmap well = myDrawView.getBitmap();
                Bitmap save = Bitmap.createBitmap(320, 480, Config.ARGB_8888);
                Paint paint = new Paint();
                paint.setColor(Color.WHITE);
                Canvas now = new Canvas(save);
                now.drawRect(new Rect(0, 0, 320, 480), paint);
                now.drawBitmap(well, new Rect(0, 0, well.getWidth(), well.getHeight()), new Rect(0, 0, 320, 480), null);

                if (save == null) {
                    System.out.println("NULL bitmap save\n");
                }
                save.compress(Bitmap.CompressFormat.PNG, 100, ostream);
            } catch (NullPointerException e) {
                e.printStackTrace();
                Toast.makeText(getApplicationContext(), "Null error", Toast.LENGTH_SHORT).show();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
                Toast.makeText(getApplicationContext(), "File error", Toast.LENGTH_SHORT).show();
            } catch (IOException e) {
                e.printStackTrace();
                Toast.makeText(getApplicationContext(), "IO error", Toast.LENGTH_SHORT).show();
            }

        }
    });

}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}
}

我的错误日志是:

12-16 13:12:13.848: W/System.err(2010): java.io.IOException: open failed: EACCES (Permission denied)
12-16 13:12:13.848: W/System.err(2010):     at java.io.File.createNewFile(File.java:940)
12-16 13:12:13.848: W/System.err(2010):     at com.example.drawimage.MainActivity$1.onClick(MainActivity.java:48)
12-16 13:12:13.848: W/System.err(2010):     at android.view.View.performClick(View.java:4084)
12-16 13:12:13.848: W/System.err(2010):     at android.view.View$PerformClick.run(View.java:16966)
12-16 13:12:13.848: W/System.err(2010):     at android.os.Handler.handleCallback(Handler.java:615)
12-16 13:12:13.848: W/System.err(2010):     at android.os.Handler.dispatchMessage(Handler.java:92)
12-16 13:12:13.848: W/System.err(2010):     at android.os.Looper.loop(Looper.java:137)
12-16 13:12:13.848: W/System.err(2010):     at android.app.ActivityThread.main(ActivityThread.java:4745)
12-16 13:12:13.848: W/System.err(2010):     at java.lang.reflect.Method.invokeNative(Native Method)
12-16 13:12:13.848: W/System.err(2010):     at java.lang.reflect.Method.invoke(Method.java:511)
12-16 13:12:13.848: W/System.err(2010):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
12-16 13:12:13.848: W/System.err(2010):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
12-16 13:12:13.848: W/System.err(2010):     at dalvik.system.NativeStart.main(Native Method)
12-16 13:12:13.848: W/System.err(2010): Caused by: libcore.io.ErrnoException: open failed: EACCES (Permission denied)
12-16 13:12:13.848: W/System.err(2010):     at libcore.io.Posix.open(Native Method)
12-16 13:12:13.848: W/System.err(2010):     at libcore.io.BlockGuardOs.open(BlockGuardOs.java:110)
12-16 13:12:13.848: W/System.err(2010):     at java.io.File.createNewFile(File.java:933)
12-16 13:12:13.848: W/System.err(2010):     ... 12 more
12-16 13:12:13.848: W/System.err(2010): java.io.FileNotFoundException: /mnt/sdcard/Folder image/sample.png: open failed: EACCES (Permission denied)
12-16 13:12:13.848: W/System.err(2010):     at libcore.io.IoBridge.open(IoBridge.java:416)
12-16 13:12:13.848: W/System.err(2010):     at java.io.FileOutputStream.<init>(FileOutputStream.java:88)
12-16 13:12:13.848: W/System.err(2010):     at java.io.FileOutputStream.<init>(FileOutputStream.java:73)
12-16 13:12:13.848: W/System.err(2010):     at com.example.drawimage.MainActivity$1.onClick(MainActivity.java:58)
12-16 13:12:13.848: W/System.err(2010):     at android.view.View.performClick(View.java:4084)
12-16 13:12:13.848: W/System.err(2010):     at android.view.View$PerformClick.run(View.java:16966)
12-16 13:12:13.848: W/System.err(2010):     at android.os.Handler.handleCallback(Handler.java:615)
12-16 13:12:13.848: W/System.err(2010):     at android.os.Handler.dispatchMessage(Handler.java:92)
12-16 13:12:13.848: W/System.err(2010):     at android.os.Looper.loop(Looper.java:137)
12-16 13:12:13.848: W/System.err(2010):     at android.app.ActivityThread.main(ActivityThread.java:4745)
12-16 13:12:13.848: W/System.err(2010):     at java.lang.reflect.Method.invokeNative(Native Method)
12-16 13:12:13.848: W/System.err(2010):     at java.lang.reflect.Method.invoke(Method.java:511)
12-16 13:12:13.848: W/System.err(2010):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
12-16 13:12:13.848: W/System.err(2010):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
12-16 13:12:13.848: W/System.err(2010):     at dalvik.system.NativeStart.main(Native Method)
12-16 13:12:13.848: W/System.err(2010): Caused by: libcore.io.ErrnoException: open failed: EACCES (Permission denied)
12-16 13:12:13.848: W/System.err(2010):     at libcore.io.Posix.open(Native Method)
12-16 13:12:13.848: W/System.err(2010):     at libcore.io.BlockGuardOs.open(BlockGuardOs.java:110)
12-16 13:12:13.848: W/System.err(2010):     at libcore.io.IoBridge.open(IoBridge.java:400)
12-16 13:12:13.848: W/System.err(2010):     ... 14 more

AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.drawimage"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="21" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

最佳答案

您不应该将文件夹命名为“/Folder image”,删除空格就可以了。

关于android - 在 Canvas 上绘制图像并保存到 SD 卡中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27501486/

相关文章:

java - 如何一次性构建多个 Android 项目

Android getTextBounds 尾随空格处理(也与 AndEngine Font.getStringWidth 相关)

android - 对于华为设备,isPowerSaveMode() 始终返回 false

android - 对 `cv::error(int, std::string const&, char const*, char const*, int)' 的 undefined reference

java - 在 volley 加载数据时向应用程序添加进度微调器

android - 如何在android中滑动图像+文本

android - 如何使用 Google Play 服务中的新 Barcode API 捕获条形码值?

android - 从另一个类调用 Activity 类中的公共(public)方法?

android - 获得额外 Intent 时的空指针

java - 通过蓝牙从 Arduino 获取奇怪的数据到 Android