We recommend you download the latest version of Android Studio, but it isn't required to implement the Predictive Touch API. If you're using another IDE, make sure you have the Android SDK (30 or higher) installed and meet all other system requirements necessary for Android development. This documentation assumes you're using Android Studio.
Download the Amazon Stylus SDK for Fire Tablets
This download allows you to implement Predictive Touch in your Stylus enabled Apps. Extract the SDK contents to a location of your choice.
Add the SDK to Android Studio
Download the SDK, save it to a preferred folder, and extract the zip file.
Open your existing project or make a new project in Android Studio.
Change the folder structure from Android to Project.
If not already created, inside of the app (old Android Studio) or Application (newer Android Studio), create a libs folder.
Copy the StylusSDKSupportLibrary-1.0.aar extracted in step 1 to the libs folder you created.
In your app's build.gradle file, reference the AAR file in the dependencies object:
Add the implementation files (libs/StylusSDKSupportLibrary-1.0.aar) in the build.gradle file's dependency section.
AmazonPredictiveTouch
This class is to carry out all the tasks like registering/deregistering for Predictive Touches. It also helps in getting the predicted points, so that apps can ask for them. Always call isFeatureRuntimeAvailable(Context) to know if the Predictive Touches are supported at runtime on device. If not supported, apps can refrain from calling other API's as those won't be useful. The App then needs to initialize AmazonPredictiveTouch using init(Context) in order to use predictions.
AmazonPredictiveTouch
This class contains the predicted coordinates. An instance of this is supplied to the app it is using AmazonPredictiveTouch#getLatestPredictions(long).
/**
* To initialize the Predictive Touch engine.
* An app/process should call it only once, unless they deregistered explicitly earlier.
* Calling it multiple times will not be useful and may result in non-delivery of
* predictions to the app due to duplicate registrations from same process.
* @param context the context of the application.
*/publicstaticvoidinit(Contextctx);/**
* Always call this method to know if the Predictive Touches are supported at runtime
* on device. If not supported, apps can refrain from calling other
* API's as those won't be useful
* @param context the context of the application.
* @return true if feature is supported in this device, else false
*/publicstaticbooleanisFeatureRuntimeAvailable(Contextctx);/**
* To manually register for getting Predictive Touches in case app deregistered earlier
* and want to re-register
* @return true if feature supported and either we are already registered or register
* is successful, else false
*/publicstaticbooleanregisterPredictiveTouches();/**
* To manually deregister with Predictive Touches in case app doesn't want predictions
* @return true if feature supported and either we are not registered or deregister
* is successful, else false
*/publicstaticbooleanderegisterPredictiveTouches();/**
* To let app check if it has registered for predictions or not
* @return true if registered else false
*/publicstaticbooleanisPredictiveTouchesRegistered();/**
* To let the app set the view for which it needs predictions
* @param view the view in which app will use predictions, should be non null
*/publicstaticvoidsetCurrentView(Viewv);/**
* To get the latest prediction stored in PredictiveTouchManager it received from algorithm
* If the feature is not supported or we don't have any predictions, this returns null
* @param t latest event timestamp the app has, to get predictions after t
* @return an {@link AmazonPredictedEvents} object containing predictions or null if
* there isn't any predictions received.
*/publicstaticAmazonPredictedEventsgetLatestPredictions(longt);}
/**
* To get the number of predictions in this {@link AmazonPredictedEvents} instance
* @return Number of predictions
*/publicintgetNumberOfPredictions();/**
* To get the x coordinate of predicted point at passed index. Apps should check
* if -1.0f is returned,then don't use it to draw
* @param index the index of predicted point
* @return x coordinate of the predicted point at passed index if index is valid, else -1.0f
*/publicfloatgetXAt(intindex);/**
* To get the y coordinate of predicted point at passed index. Apps should check
* if -1.0f is returned, then don't use it to draw
* @param index the index of predicted point
* @return y coordinate of the predicted point at passed index if index is valid, else -1.0f
*/publicfloatgetYAt(intindex);/**
* To get the timestamp of predicted point at passed index. Apps should check
* if -1L is returned, then don't use it as it indicates invalid.
* @param index the index of predicted point
* @return timestamp of the predicted point at passed index if index is valid, else -1L
*/publiclonggetEventTimeAt(intindex);}
Implementing the Amazon Stylus SDK
Overview
Check for feature availability using AmazonPredictiveTouch.isFeatureRuntimeAvailable().
Initialize the AmazonPredictiveTouch using AmazonPredictiveTouch.init().
Check if PredictiveTouches is registered using public static boolean isPredictiveTouchesRegistered().
Register for predictions using AmazonPredictiveTouch.registerPredictiveTouches().
Set the view for which you will use predictions using AmazonPredictiveTouch.setCurrentView().
Identify if it's a MOVE event in onTouchEvent and note its timestamp and coordinates.
Get predictions using AmazonPredictiveTouch.getLatestPredictions() and draw using AmazonPredictedEvents.
Deregister predictions using AmazonPredictiveTouch.deregisterPredictiveTouches().
See the following sections for details on each of these.
Step 1: Check for Amazon Predictive Touch availability
Use the AmazonPredictiveTouch.isFeatureRuntimeAvailable(android.content.Context context) method to know whether the feature is available on the device.
If the feature is not available or supported, this method returns false. Otherwise, it returns true.
importcom.amazon.stylussupportsdk.predictedtouches.AmazonPredictiveTouch;privatebooleanisPredictiveTouchesSupported(){/* sample implementation */returnAmazonPredictiveTouch.isFeatureRuntimeAvailable(this)==true;}@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);....................if(isPredictiveTouchesSupported()){// PredictiveTouches should be available. Code// to init and register for predictions goes here}else{// PredictiveTouches not available. Write it in a log messageLog.w(TAG,"PredictiveTouches is not supported");}}
importcom.amazon.stylussupportsdk.predictedtouches.AmazonPredictiveTouchprivatefunisPredictiveTouchesSupported():Boolean{/* sample implementation */returnAmazonPredictiveTouch.isFeatureRuntimeAvailable(this)}overridefunonCreate(savedInstanceState:Bundle?){super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)if(isPredictiveTouchesSupported()){// PredictiveTouches should be available. Code
// to init and register for predictions goes here
}else{// PredictiveTouches not available. Write it in a log message
Log.w(TAG,"PredictiveTouches is not supported")}}
Step 2: Initialize the AmazonPredictiveTouch
Use the AmazonPredictiveTouch.init(android.content.Context context) method to initialize.
This should be done using the onCreate() method of an Activity or during View creation (if needed only for that view).
Initialization also registers with the PredictionService by default, so you can skip calling AmazonPredictiveTouch.registerPredictiveTouches() after this step.
Now, predictive touch APIs can be used in all app processes.
Note: Don’t call init() more than once in the same App process. Predictive Service is designed to be used as one instance per process, so calling init() again is ignored.
importcom.amazon.stylussupportsdk.predictedtouches.AmazonPredictiveTouch;publicclassMainActivityextendsActivity{@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);....................if(isPredictiveTouchesSupported()){// PredictiveTouches should be available. Code// to init and register for predictions goes hereAmazonPredictiveTouch.init(MainActivity.this);}else{// PredictiveTouches not available. Write it in a log messageLog.w(TAG,"PredictiveTouches is not supported");}}}
importcom.amazon.stylussupportsdk.predictedtouches.AmazonPredictiveTouchclassMainActivity:Activity(){overridefunonCreate(savedInstanceState:Bundle?){super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)....................if(isPredictiveTouchesSupported()){// PredictiveTouches should be available. Code
// to init and register for predictions goes here
AmazonPredictiveTouch.init(this@MainActivity)}else{// PredictiveTouches not available. Write it in a log message
Log.w(TAG,"PredictiveTouches is not supported")}}}
Step 3: Check if PredictiveTouches is registered
Use the utility method isPredictiveTouchesRegistered() to check if PredictiveTouches is registered. This returns a boolean value.
For the App to receive predictive points, you must initialize or register the listener with either init() or registerPredictiveTouches(). You only need to use registerPredictiveTouches() in the cases where you have called deregisterPredictiveTouches() on certain views where you do not want the prediction and then come back to the view where the prediction is needed.
Step 4: Register for predictions
This is required when you used AmazonPredictiveTouch.deregisterPredictiveTouches() earlier to save compute/memory resources as you didn't need predictions, but now you again need predictions to be enabled.
In order to start receiving predictions again, use the AmazonPredictiveTouch.registerPredictiveTouches() method. This is an idempotent API, so calling it multiple times is not needed and won't result in different behavior. It returns true if registration is successful, otherwise it returns false.
importcom.amazon.stylussupportsdk.predictedtouches.AmazonPredictiveTouch;publicclassMainActivityextendsActivity{@OverrideprotectedvoidonResume(){super.onResume();// Assuming that at resume, user will be writing/drawing, etc. and we deregistered earlier,// so need to register for predictions.AmazonPredictiveTouch.registerPredictiveTouches();..........................}}
importcom.amazon.stylussupportsdk.predictedtouches.AmazonPredictiveTouchclassMainActivity:Activity(){overridefunonResume(){super.onResume()// Assuming that at resume, user will be writing/drawing, etc. and we deregistered earlier,
// so need to register for predictions.
AmazonPredictiveTouch.registerPredictiveTouches()}}
Step 5: Set the view for which you will use predictions
Each view has its own geometrical transform. For instance, its position on the screen, possible rotation, or scaling effects. The touch points need to be transformed accordingly.
In order to provide accurate predicted events to the current view where you will use predictions, set your current view. This can be done by switching to a new view that uses predictions. Use the method setCurrentView(android.view.View view).
Call this method before drawing in onTouchEvent() for MotionEvent.ACTION_DOWN for each view, which gets called every time a view is touched.
Step 6: Identify if it's a MOVE event using TouchEvent and note its timestamp and coordinates
Only use predictions for MOVE events. You can identify if it’s a MOVE event using the onTouchEvent() method. Make note of its timestamp and coordinates. To predict points for the latest MOVE event, use the timestamp. Also, we want to draw predicted points after the latest touch points X, Y coordinates, so we need the coordinates for it.
This can be done using onTouchEvent() with variables such as mLatestX, mLatestY, and mCurrentMoveTime. See the following sample code.
importcom.amazon.stylussupportsdk.predictedtouches.AmazonPredictiveTouch;publicclassTouchDisplayViewextendsView{privatelongmCurrentMoveTime=-1;privatefloatmLatestX,mLatestY;privatePathmCurrentStroke=newPath();// Path to store stroke data@OverridepublicbooleanonTouchEvent(MotionEventevent){............// Set the timestamp -1mCurrentMoveTime=-1;switch(event.getAction()&MotionEvent.ACTION_MASK){.............caseMotionEvent.ACTION_MOVE:{// Get the timestamp, X, Y values of current move eventmCurrentMoveTime=event.getEventTime();mLatestX=event.getX();mLatestY=event.getY();for(iin0untilevent.historySize){// add history points to current strokemCurrentStroke.lineTo(event.getHistoricalX(0,i),event.getHistoricalY(0,i))}// We are using lineTo for the sake of example, please use custom draw logic as requiredmCurrentStroke.lineTo(mLatestX,mLatestY);// add point to current strokethis.invalidate();break;}.............}}}
importcom.amazon.stylussupportsdk.predictedtouches.AmazonPredictiveTouchclassTouchDisplayView:View(){privatevarmCurrentMoveTime:Long=-1privatevarmLatestX=0fprivatevarmLatestY=0fprivatevalmCurrentStroke:Path=Path()// Path to store stroke data
overridefunonTouchEvent(event:MotionEvent):Boolean{// Set the timestamp -1
mCurrentMoveTime=-1when(event.actionandMotionEvent.ACTION_MASK){MotionEvent.ACTION_MOVE->{// Get the timestamp, X, Y values of current move event
mCurrentMoveTime=event.eventTimemLatestX=event.xmLatestY=event.yfor(iin0untilevent.historySize){// add history points to current stroke
mCurrentStroke.lineTo(event.getHistoricalX(0,i),event.getHistoricalY(0,i))}// We are using lineTo for the sake of example, please use custom draw logic as required
mCurrentStroke.lineTo(mLatestX,mLatestY)// add point to current stroke
this.invalidate()}}}}
Step 7: Get the predictions and draw
Now that we know it's a MOVE event and have its timestamp and its coordinates, we need to get the predictions corresponding to this timestamp.
Use getLatestPredictions(long t) to get the predictions.
This gives the AmazonPredictedEvents object. You can use this object to find the following:
The number of predictions using the getNumberOfPredictions() method. This returns an integer.
Event time using getEventTimeAt(int index). This returns a timestamp of type long.
X / Y coordinates using the getXAt(int index) and getYAt(int index) methods. These return float values.
Add the predictions to the current path or separate path for predictions to draw.
Important: Clear the canvas. Otherwise the predictions from the last draw are also visible.
importcom.amazon.stylussupportsdk.predictedtouches.AmazonPredictiveTouch;importcom.amazon.stylussupportsdk.predictedtouches.AmazonPredictedEvents;publicclassTouchDisplayViewextendsView{@OverrideprotectedvoidonDraw(Canvascanvas){// Get the latest predictions corresponding to mCurrentMoveTimeAmazonPredictedEventslatestPred=AmazonPredictiveTouch.getLatestPredictions(mCurrentMoveTime);Pathpredicted=newPath();// Add the predictions to Path if latest predictions are availableif(mCurrentMoveTime!=-1/*valid move*/&&latestPred!=null&&latestPred.getNumberOfPredictions()!=0){Log.i(TAG,"DRAWSTART EVENTTIME: "+mCurrentMoveTime+" currentTime "+SystemClock.uptimeMillis()+" latestPredTime "+latestPred.getEventTimeAt(latestPred.getNumberOfPredictions()-1));predicted.moveTo(mLatestX,mLatestY);for(inti=0;i<latestPred.getNumberOfPredictions();i++){// We are using lineTo for the sake of example, please use custom draw logic as requiredif(latestPred.getXAt(i)>-1.0f&&latestPred.getYAt(i)>-1.0f)predicted.lineTo(latestPred.getXAt(i),latestPred.getYAt(i));}}// Clear the canvas first, so that last predicted points get erased and we don't have unwanted artifactscanvas.drawColor(Color.WHITE);// Draw the actual pointscanvas.drawPath(mCurrentStroke,mPaint);// Draw the path containing predictions with another Paint object, to confirmif(!predicted.isEmpty())canvas.drawPath(predicted,mPaintPred);if(mCurrentMoveTime!=-1){Log.i(TAG,"DRAWEND EVENTTIME: "+mCurrentMoveTime+" currentTime "+SystemClock.uptimeMillis());}super.onDraw(canvas);}}
importcom.amazon.stylussupportsdk.predictedtouches.AmazonPredictiveTouchimportcom.amazon.stylussupportsdk.predictedtouches.AmazonPredictedEventsclassTouchDisplayView():View(){overridefunonDraw(canvas:Canvas){// Get the latest predictions corresponding to mCurrentMoveTime
vallatestPred:AmazonPredictedEvents=AmazonPredictiveTouch.getLatestPredictions(mCurrentMoveTime)valpredicted=Path()// Add the predictions to Path if latest predictions are available
if(mCurrentMoveTime!==-1/*valid move*/&&latestPred!=null&&latestPred.getNumberOfPredictions()!==0){Log.i(TAG,"DRAWSTART EVENTTIME: "+mCurrentMoveTime.toString()+" currentTime "+SystemClock.uptimeMillis().toString()+" latestPredTime "+latestPred.getEventTimeAt(latestPred.getNumberOfPredictions()-1))predicted.moveTo(mLatestX,mLatestY)for(iin0untillatestPred.getNumberOfPredictions()){// We are using lineTo for the sake of example, please use custom draw logic as required
if(latestPred.getXAt(i)>-1.0f&&latestPred.getYAt(i)>-1.0f)predicted.lineTo(latestPred.getXAt(i),latestPred.getYAt(i))}}// Clear the canvas first, so that last predicted points get erased and we don't have unwanted artifacts
canvas.drawColor(Color.WHITE)// Draw the actual points
canvas.drawPath(mCurrentStroke,mPaint)// Draw the path containing predictions with another Paint object, to confirm
if(!predicted.isEmpty())canvas.drawPath(predicted,mPaintPred)if(mCurrentMoveTime!==-1){Log.i(TAG,"DRAWEND EVENTTIME: "+mCurrentMoveTime.toString()+" currentTime "+SystemClock.uptimeMillis())}super.onDraw(canvas)}}
Step 8: Deregister predictions
Call the deregisterPredictiveTouches() method to deregister PredictiveTouches. You may consider doing this when the app moves to an Activity or View that does not need predictions, or your app goes into the background, to reduce CPU/Memory usage.
It is important that you link deregisterPredictiveTouches() of PredictiveTouches with the lifecycle of the Activity/View where it was initialized.
For example, for an activity, use init() in the onCreate() method and use deregisterPredictiveTouches() in the onDestroy() method. In scenarios where the process is not terminated but the Activity or View is destroyed, you won't be able re-initialize PredictiveTouches in the onCreate() method if it was not deregistered earlier. Display rotation is an example where the process is not killed (the process is still registered with the service), but the activity is re-created (which tries to create a new instance).
On a successful deregister, the method returns true, otherwise it returns false.
importcom.amazon.stylussupportsdk.predictedtouches.AmazonPredictiveTouch;publicclassMainActivityextendsActivity{// OPTIONAL: can do this when you want to stop for predictions while your app in background to save the predictive touches memory footprint.@OverrideprotectedvoidonPause(){AmazonPredictiveTouch.deregisterPredictiveTouches();super.onPause();}// This is a must for components who can die while the process is still alive (like activity, view, etc)@OverrideprotectedvoidonDestroy(){AmazonPredictiveTouch.deregisterPredictiveTouches();super.onDestroy();}}
importcom.amazon.stylussupportsdk.predictedtouches.AmazonPredictiveTouchclassMainActivity:Activity(){// OPTIONAL: can do this when you want to stop for predictions while your app in background to save the predictive touches memory footprint.
overridefunonPause(){AmazonPredictiveTouch.deregisterPredictiveTouches()super.onPause()}// This is a must for components who can die while the process is still alive (like activity, view, etc)
overridefunonDestroy(){AmazonPredictiveTouch.deregisterPredictiveTouches()super.onDestroy()}}
Troubleshooting
If you are having trouble getting or drawing predictions, check the following:
Is the feature available on the device?
Solution: Update Fire OS to latest version and call AmazonPredictiveTouch.isFeatureRuntimeAvailable() to check if your device supports this feature. Refer to Step 1 for details.
Do I need to maintain two APKs if my app will also be available on devices that don’t support Predictive Touch?
Solution: No, there is no need to maintain two different APKs. Use AmazonPredictiveTouch.isFeatureRuntimeAvailable() to determine if the device supports Predictive Touch before initializing AmazonPredictiveTouch.
Can I draw the predictions with a separate paint object (like a different color) and see that the predictions are being drawn?
You are visitor 01402503 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.