10

**THIS QUESTION WAS SUCCESSFULLY ANSWERED AND HAS BECOME A BLOG POST <- click **

Hi I am a PHP developer I want to do a simple thing - I want to draw something drawn on a blank page on an Android Phone (with a finger with a largeish "emulated pen nib") and store the bitmap as a jpeg on a server by http post.

Here is what I have so far but this is taken from a tutorial that is involved with writing sprites for a game.. And I cant' adapt it

package com.my.example;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnTouchListener;

public class DrawCapture extends Activity implements OnTouchListener{

    OurView v;
    Bitmap ball;
    float x,y;

    @Override
    protected void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        setContentView(R.layout.draw_capture);
        v = new OurView(this);
        v.setOnTouchListener(this);
        ball = BitmapFactory.decodeResource(getResources(), R.drawable.blueball);
        x = y = 0;
        setContentView(v);
    }

    @Override
    protected void onPause(){
        super.onPause();
        v.pause();
    }

    protected void onResume(){
        super.onResume();
        v.resume();
    }

    public class OurView extends SurfaceView implements Runnable{
        Thread t = null;
        SurfaceHolder holder;
        boolean isItOK = false;

        public OurView(Context context) {
            super(context);
            holder = getHolder();
        }

        public void run() {
            while (isItOK == true){

                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                //perform canvas drawing
                if (!holder.getSurface().isValid()){
                    continue;
                }
                Canvas c = holder.lockCanvas();
                onDraw(c);
                holder.unlockCanvasAndPost(c);
            }       
        }

        public void onDraw(Canvas c){
            c.drawARGB(255, 210, 210, 210);
            c.drawBitmap(ball, x - (ball.getWidth()/2), y - (ball.getHeight()/2), null);
        }

        public void pause(){
            isItOK = false;
            while(true){
                try{
                    t.join();
                } catch(InterruptedException e){
                    e.printStackTrace();
                }
                break;
            }
            t = null;
        }

        public void resume(){
            isItOK = true;
            t = new Thread(this);
            t.start();
        }
    }

    public boolean onTouch(View v, MotionEvent me){

        switch (me.getAction()){
            case MotionEvent.ACTION_DOWN : 
                x = me.getX();
                y = me.getY();              
                break;
            case MotionEvent.ACTION_UP : 
                x = me.getX();
                y = me.getY();              
                break;
            case MotionEvent.ACTION_MOVE : 
                x = me.getX();
                y = me.getY();              
                break;
        }
        return true;
    }
}

and here is the XML

<?xml version="1.0" encoding="utf-8"?>
<SurfaceView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >


</SurfaceView>

Can someone please help me? I feel I am close - I use the blueball as a pen nib I just want to "save" this and possibly I'll need to have a button (or menu) on the XML page to do this ? I know it's a bit of a beg but there are a lot of people online asking how to draw with your finger and save something to the "cloud" if people could respond with examples of the code (not references) I promise I will compile this into a proper tutorial piece of code for the eventual benefit of all. Including the PHP server side code that I already am really happy with.

conners
  • 1,420
  • 4
  • 18
  • 28

2 Answers2

10

You can try to use the Gesture Object proposed by Google, try to execute my following code :

Activity1 xml :

<?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#FFFFFF" >

        <android.gesture.GestureOverlayView
            android:id="@+id/gestures"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:fadeEnabled="false"
            android:fadeOffset="5000000000"
            android:gestureColor="#000000"
            android:gestureStrokeType="multiple"
            android:gestureStrokeWidth="1"
            android:uncertainGestureColor="#000000"
            android:layout_above="@+id/save_button" />

        <Button
            android:id="@id/save_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_centerHorizontal="true"
            android:layout_marginBottom="20sp"
            android:paddingLeft="20sp"
            android:paddingRight="20sp"
            android:text="Save"
            android:textSize="22sp" />

    </RelativeLayout>

Activity1 java :

 package com.testandroidproject;

import java.io.ByteArrayOutputStream;

import android.app.Activity;
import android.content.Intent;
import android.gesture.GestureOverlayView;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

public class Activity1 extends Activity {

    private Button button_save;
    private GestureOverlayView gesture;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.main);

        gesture = (GestureOverlayView) findViewById(R.id.gestures);
        button_save = (Button) findViewById(R.id.save_button);

        button_save.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View arg0) {
                try {
                    Bitmap gestureImg = gesture.getGesture().toBitmap(100, 100,
                            8, Color.BLACK);

                    ByteArrayOutputStream bos = new ByteArrayOutputStream();
                    gestureImg.compress(Bitmap.CompressFormat.PNG, 100, bos);
                    byte[] bArray = bos.toByteArray();

                    Intent intent = new Intent(Activity1.this, Activity2.class);

                    intent.putExtra("draw", bArray);
                    startActivity(intent);

                } catch (Exception e) {
                    e.printStackTrace();
                    Toast.makeText(Activity1.this, "No draw on the string",
                            3000).show();
                }
            }
        });
    }

}

Activity2 xml :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FFFFFF"
    android:orientation="vertical" >

    <ImageView
        android:id="@+id/image_saved"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal" />

</LinearLayout>

Activity2 java :

package com.testandroidproject;

import java.io.ByteArrayInputStream;

import android.app.Activity;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.widget.ImageView;


public class Activity2 extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.display_image);

        ImageView image = (ImageView) findViewById(R.id.image_saved);

        ByteArrayInputStream imageStreamClient = new ByteArrayInputStream(
                getIntent().getExtras().getByteArray("draw"));
        image.setImageBitmap(BitmapFactory.decodeStream(imageStreamClient));
    }

}

Hope you will find this helpful.

grattmandu03
  • 1,266
  • 2
  • 13
  • 32
  • thank you I will look into this tomorrow and get back to you - looks like you are suggesting I rewrite, but that's ok. I will update you soon. (~24 hours) – conners Jul 24 '12 at 14:43
  • I don't have the time to try your code to check what is wrong, but I know that I have used my solution to save client signature in an Android app and it works like a charm :). So I share it to you if it can be useful. – grattmandu03 Jul 24 '12 at 14:49
  • *STOP*PRESS* I have it working as I need it to (with substantial changes but basically using your code still) I was able to remove "Activity2" completely and use the click listener to do a post of the gesture image via internal storage. I will post the "howto" once I have tidied it up. – conners Jul 25 '12 at 15:08
  • hi I have uploaded the answer I derived from this here at this blog http://wiki.nofolder.com/how-to-draw-something-with-your-finger-in-an-android-app-and-save-it-to-the-web – conners Jul 26 '12 at 09:04
2

I'm not sure what part of the "save" you are trying to accomplish, but I'll assume you're asking how to store what you've drawn on the canvas to a bitmap.

First, make yourself a bitmap to draw into. Say, canvasBitmap. Then:

c.setBitmap(canvasBitmap);

This will store everything that has been drawn into 'canvasBitmap.' Then, when the user presses a button to save:

savedBitmap = Bitmap.copy(canvasBitmap.getConfig(), true);

Now, take savedBitmap and fire it off into the cloud. Hope that helps.

TerryTate
  • 414
  • 3
  • 14
  • Yes, this looks excellent I will look at it tomorrow with a proper response - I need to apologise there is also an issue with the onTouch MotionEvent - it doesn't "DRAW" it simply drags the "cursor `blueball`" around the canvas - I also need it to "leave a trail" – conners Jul 24 '12 at 14:42
  • @conners The reason you are only dragging the cursor around the screen is that you are redrawing the background of the canvas every frame. What you need to do is call `c.drawARGB(255, 210, 210, 210);` only once, not every frame. If you remove that line of code you should see the drawing result you are looking for. – TerryTate Jul 24 '12 at 15:06