{"id":2217,"date":"2013-05-07T23:10:42","date_gmt":"2013-05-07T14:28:15","guid":{"rendered":"https:\/\/programresource.net\/?p=2217"},"modified":"2014-05-09T19:41:15","modified_gmt":"2014-05-09T10:41:15","slug":"handle-stylus-eraser-and-pressure-with-supported-device-android-4-0-support","status":"publish","type":"post","link":"https:\/\/programresource.net\/en\/2013\/05\/07\/2217.html","title":{"rendered":"Handle stylus, eraser, and pressure with supported device (Android 4.0 support)"},"content":{"rendered":"<p>Device like Samsung Galaxy Note, some Android device supports stylus input. Those stylus uses\u00a0Electro-Magnetic Resonance technology, and able to distinguish stylus and finger, and also provides pressure info, and some pen supports eraser mode.<\/p>\n<p>If you have stylus supported device, you can try <a href=\"https:\/\/play.google.com\/store\/apps\/details?id=net.nefastudio.android.nftesttpinput&amp;feature=search_result#?t=W251bGwsMSwyLDEsIm5ldC5uZWZhc3R1ZGlvLmFuZHJvaWQubmZ0ZXN0dHBpbnB1dCJd\">Stylus Tester for Android<\/a>\u00a0to see what kind of data it gives (as 05\/07\/2013, app is not Android 4.0 ready).<\/p>\n<p>It isn&#8217;t hard for app to support stylus; you just need to add some flag checker in onTouchEvent function.<\/p>\n<p>Below is simple sample code.<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">@SuppressLint(&amp;quot;NewApi&amp;quot;)\r\n@Override\r\npublic boolean onTouchEvent(MotionEvent e) {\r\n\r\n\tboolean sw_androidoverfour;\r\n\tif (Build.VERSION.SDK_INT &lt; Build.VERSION_CODES.ICE_CREAM_SANDWICH)\r\n\t\tsw_androidoverfour = false;\r\n\telse\r\n\t\tsw_androidoverfour = true;\r\n\r\n\tif (e.getAction() == MotionEvent.ACTION_DOWN) {\r\n\t\tif (sw_androidoverfour){ \/\/for android 4.0+\r\n\t\t\tif (e.getToolType(0) == MotionEvent.TOOL_TYPE_STYLUS){ \/\/stylus\r\n\t\t\t\t\/\/e.getPressure() for pressure, range 0 to 1, float\r\n\t\t\telse if (e.getToolType(0) == MotionEvent.TOOL_TYPE_ERASER){ \/\/stylus eraser\r\n\t\t\t}else{ \/\/finger\r\n\t\t\t}\r\n\t\t}else{\r\n\t\t\tif (e.getMetaState() == 512){ \/\/stylus\r\n\t\t\t}else if (e.getMetaState() == 1024){ \/\/stylus eraser\r\n\t\t\t}else{ \/\/finger\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn true;\r\n\t} else if (e.getAction() == MotionEvent.ACTION_UP) {\r\n\t\tif (sw_androidoverfour){ \/\/for android 4.0+\r\n\t\t\tif (e.getToolType(0) == MotionEvent.TOOL_TYPE_STYLUS){ \/\/stylus\r\n\t\t\t}else if (e.getToolType(0) == MotionEvent.TOOL_TYPE_ERASER){ \/\/stylus eraser\r\n\t\t\t}else{ \/\/finger\r\n\t\t\t}\r\n\t\t}else{\r\n\t\t\tif (e.getMetaState() == 512){ \/\/stylus\r\n\t\t\t}else if (e.getMetaState() == 1024){ \/\/stylus eraser\r\n\t\t\t}else{ \/\/finger\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn true;\r\n\t} else if (e.getAction() == MotionEvent.ACTION_MOVE) {\r\n\t\tif (\/*use history for higher density input*\/){\r\n\t\t\tint N = e.getHistorySize();\r\n\t\t\tfor (int i=0; i&lt;=N; i++) {\r\n\t\t\t\tint ex,ey;\r\n\t\t\t\tif (i == N){\r\n\t\t\t\t\tex = (int)e.getX();\r\n\t\t\t\t\tey = (int)e.getY();\r\n\t\t\t\t}else{\r\n\t\t\t\t\tex = (int)e.getHistoricalX(i);\r\n\t\t\t\t\tey = (int)e.getHistoricalY(i);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t\/\/use ex and ey for position\r\n\t\t\tif (sw_androidoverfour){ \/\/for android 4.0+\r\n\t\t\t\tif (e.getToolType(0) == MotionEvent.TOOL_TYPE_STYLUS){ \/\/stylus\r\n\t\t\t\t}else if (e.getToolType(0) == MotionEvent.TOOL_TYPE_ERASER){ \/\/stylus eraser\r\n\t\t\t\t}else{ \/\/finger\r\n\t\t\t\t}\r\n\t\t\t}else{\r\n\t\t\t\tif (e.getMetaState() == 512){ \/\/stylus\r\n\t\t\t\t}else if (e.getMetaState() == 1024){ \/\/stylus eraser\r\n\t\t\t\t}else{ \/\/finger\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}else{\r\n\t\t\tif (sw_androidoverfour){ \/\/for android 4.0+\r\n\t\t\t\tif (e.getToolType(0) == MotionEvent.TOOL_TYPE_STYLUS){ \/\/stylus\r\n\t\t\t\t}else if (e.getToolType(0) == MotionEvent.TOOL_TYPE_ERASER){ \/\/stylus eraser\r\n\t\t\t\t}else{ \/\/finger\r\n\t\t\t\t}\r\n\t\t\t}else{\r\n\t\t\t\tif (e.getMetaState() == 512){ \/\/stylus\r\n\t\t\t\t}else if (e.getMetaState() == 1024){ \/\/stylus eraser\r\n\t\t\t\t}else{ \/\/finger\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn true;\r\n\t}\r\n}<\/pre>\n<p>For android after 4.0, e.getToolType is used to check stylus, and e.getMetaState for older android version. Build.VERSION.SDK_INT is used to check OS version.<\/p>\n<p>e.getToolType will cause unknown function when building target with older android platform, so SuppressLint is added before function to suppress error.<\/p>\n<p>If e.getToolType is TOOL_TYPE_STYLUS then stylus, TOOL_TYPE_ERASER for erasor, and else, finger. e.getMetaState is 512 for stylus, 1024 for eraser, and else, finger. When stylus or eraser, e.getPressure returns pressure.<\/p>\n<p>Pressure is floating value between 0 to 1, but this varies depending on device or stylus used. As I checked, Galaxy Note with attached stylus pen returns pressure between 0 to 0.6, and other compatible stylus pen returned 0 to 1.0. When developing drawing app, it would be better to give calibration option by letting user to test write, like Photoshop or Painter.<\/p>\n<p>In above sample code, e.getHistorySize code is included. This is, if more detailed stylus coordinate path info is available than ACTION_MOVE interval, you can get them by calling getHistoricalX or getHistoricalY.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Device like Samsung Galaxy Note, some Android device supports stylus input. Those stylus uses\u00a0Electro-Magnetic Resonance technology, and able to distinguish stylus and finger, and also provides pressure info, and some pen supports eraser mode. If you have stylus supported device, you can try Stylus Tester for Android\u00a0to see what kind of data it gives (as 05\/07\/2013, app is not Android 4.0 ready). It isn&#8217;t hard for app to support stylus; you just need to add some flag checker in onTouchEvent function. Below is simple sample code. For android after 4.0, e.getToolType is used to check stylus, and e.getMetaState for older android version. Build.VERSION.SDK_INT is used to check OS version. e.getToolType &#8230;<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"ngg_post_thumbnail":0,"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","footnotes":"","jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false}}},"categories":[330],"tags":[],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p3pJyQ-zL","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/programresource.net\/en\/wp-json\/wp\/v2\/posts\/2217"}],"collection":[{"href":"https:\/\/programresource.net\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/programresource.net\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/programresource.net\/en\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/programresource.net\/en\/wp-json\/wp\/v2\/comments?post=2217"}],"version-history":[{"count":2,"href":"https:\/\/programresource.net\/en\/wp-json\/wp\/v2\/posts\/2217\/revisions"}],"predecessor-version":[{"id":2484,"href":"https:\/\/programresource.net\/en\/wp-json\/wp\/v2\/posts\/2217\/revisions\/2484"}],"wp:attachment":[{"href":"https:\/\/programresource.net\/en\/wp-json\/wp\/v2\/media?parent=2217"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/programresource.net\/en\/wp-json\/wp\/v2\/categories?post=2217"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/programresource.net\/en\/wp-json\/wp\/v2\/tags?post=2217"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}