This example will show you how to capture user gesture as signature and save it to an image in the android emulator. Users just need to write the signature on the screen and click save then a png format image will be created in the SD card of the device. You can use the android device monitor to pull down the signature image to your PC.
1. Capture And Save Gesture Signature To Image Example.
If you can not watch the above video, you can see it on the youtube URL https://youtu.be/gIhXlOXEJ6A
1.1 Example Introduction.
- There are two Buttons and one GestureOverlayView widget on the screen.
- When you click the first REDRAW button, it will clear the user input gesture signature below it, you can redraw your signature again.
- When you click the second SAVE button, it will save the user input signature to a png format image and save it in the android sd card folder.
- Because this example will save the image to external storage, you should grant the permission android.permission.WRITE_EXTERNAL_STORAGE to the application when running it.
1.2 Pull Down The Signature Image From Emulator.
- When the image is created, you can click Tools —> Android —> Android Device Monitor menu item at the android studio top menu bar to open the android device monitor.
- Select one android emulator on the Android Device Monitor window left side, then click the File Explorer tab in the right panel and browse the image file in the storage directory.
- If you can not see the file or can not open the folder, you can execute the command
adb root
in a dos window to resolve it. Then you can click the pull-down icon at the Android Device Monitor —> android emulator —> File Explorer tab top right corner to pull it to your PC.
2. Capture Gesture Signature To Image Example Source Code.
2.1 Example Project Source Files.
- Below are this example’s project source files. The most important source files are MainActivity.java, CustomGestureListener.java, activity_main.xml, AndroidManifest.xml.
C:\WORKSPACE\WORK\DEV2QA.COM-EXAMPLE-CODE\ANDROIDEXAMPLEPROJECT\CAPTURESIGNATUREBYGESTURE │ .gitignore │ build.gradle │ gradle.properties │ gradlew │ gradlew.bat │ settings.gradle │ ├───.idea │ gradle.xml │ misc.xml │ modules.xml │ runConfigurations.xml │ ├───app │ │ .gitignore │ │ build.gradle │ │ proguard-rules.pro │ │ │ └───src │ │ │ ├───main │ │ │ AndroidManifest.xml │ │ │ │ │ ├───java │ │ │ └───com │ │ │ └───dev2qa │ │ │ └───android │ │ │ └───example │ │ │ └───capturesignaturebygesture │ │ │ CustomGestureListener.java │ │ │ MainActivity.java │ │ │ │ │ └───res │ │ ├───layout │ │ │ activity_main.xml
2.2 Main Activity Java File.
- MainActivity.java
package com.dev2qa.android.example.capturesignaturebygesture; import android.Manifest; import android.content.pm.PackageManager; import android.gesture.GestureOverlayView; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.os.Environment; import android.support.annotation.NonNull; import android.support.v4.app.ActivityCompat; import android.support.v4.content.ContextCompat; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.widget.Button; import android.widget.Toast; import java.io.File; import java.io.FileOutputStream; public class MainActivity extends AppCompatActivity { private static final int REQUEST_CODE_WRITE_EXTERNAL_STORAGE_PERMISSION = 1; private GestureOverlayView gestureOverlayView = null; private Button redrawButton = null; private Button saveButton = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); setTitle("dev2qa.com - Android Capture Signature By Gesture."); init(); gestureOverlayView.addOnGesturePerformedListener(new CustomGestureListener()); redrawButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { gestureOverlayView.clear(false); } }); saveButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { checkPermissionAndSaveSignature(); } }); } private void init() { if(gestureOverlayView==null) { gestureOverlayView = (GestureOverlayView)findViewById(R.id.sign_pad); } if(redrawButton==null) { redrawButton = (Button)findViewById(R.id.redraw_button); } if(saveButton==null) { saveButton = (Button)findViewById(R.id.save_button); } } private void checkPermissionAndSaveSignature() { try { // Check whether this app has write external storage permission or not. int writeExternalStoragePermission = ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE); // If do not grant write external storage permission. if(writeExternalStoragePermission!= PackageManager.PERMISSION_GRANTED) { // Request user to grant write external storage permission. ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE_WRITE_EXTERNAL_STORAGE_PERMISSION); }else { saveSignature(); } } catch (Exception e) { Log.v("Signature Gestures", e.getMessage()); e.printStackTrace(); } } private void saveSignature() { try { // First destroy cached image. gestureOverlayView.destroyDrawingCache(); // Enable drawing cache function. gestureOverlayView.setDrawingCacheEnabled(true); // Get drawing cache bitmap. Bitmap drawingCacheBitmap = gestureOverlayView.getDrawingCache(); // Create a new bitmap Bitmap bitmap = Bitmap.createBitmap(drawingCacheBitmap); // Get image file save path and name. String filePath = Environment.getExternalStorageDirectory().toString(); filePath += File.separator; filePath += "sign.png"; File file = new File(filePath); file.createNewFile(); FileOutputStream fileOutputStream = new FileOutputStream(file); // Compress bitmap to png image. bitmap.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream); // Flush bitmap to image file. fileOutputStream.flush(); // Close the output stream. fileOutputStream.close(); Toast.makeText(getApplicationContext(), "Signature file is saved to " + filePath, Toast.LENGTH_LONG).show(); } catch (Exception e) { Log.v("Signature Gestures", e.getMessage()); e.printStackTrace(); } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == REQUEST_CODE_WRITE_EXTERNAL_STORAGE_PERMISSION) { int grantResultsLength = grantResults.length; if (grantResultsLength > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { saveSignature(); } else { Toast.makeText(getApplicationContext(), "You denied write external storage permission.", Toast.LENGTH_LONG).show(); } } } }
2.3 Custom Gesture Listener.
- CustomGestureListener.java
package com.dev2qa.android.example.capturesignaturebygesture; import android.gesture.Gesture; import android.gesture.GestureOverlayView; import android.gesture.GestureOverlayView.OnGesturePerformedListener; public class CustomGestureListener implements OnGesturePerformedListener { @Override public void onGesturePerformed(GestureOverlayView gestureOverlayView, Gesture gesture) { } }
2.4 Main Activity Layout Xml File.
- activity_main.xml
<RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" > <Button android:id="@+id/redraw_button" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:text="Redraw" /> <Button android:id="@+id/save_button" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/redraw_button" android:text="Save" /> <android.gesture.GestureOverlayView android:id="@+id/sign_pad" android:layout_width="match_parent" android:layout_height="500dp" android:layout_below="@id/save_button" android:background="@android:color/holo_green_light" android:fadeEnabled="false" android:fadeOffset="10000" android:gestureColor="@color/colorPrimary" android:uncertainGestureColor="@android:color/holo_red_light" android:gestureStrokeLengthThreshold="0.1" android:gestureStrokeType="multiple" android:orientation="vertical" > </android.gesture.GestureOverlayView> </RelativeLayout>
2.5 Android Manifest Xml File.
- AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.dev2qa.android.example.capturesignaturebygesture"> <!-- Below permission is required for store gesture signature to image file. --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
Reference
- Android Read Write External Storage File Example
- Android RelativeLayout Example
- Android Implement And Recognize Custom Gesture Example