Accelerometer in Android OS 2.x and deprecated API

Quickly share your Android Code Snippets here...

Accelerometer in Android OS 2.x and deprecated API

Postby ivomania » Fri Feb 05, 2010 1:23 am

Hi all.

This is my first post so sorry if I make any etiquette mistake... I'm a newbie. I've seen a lot of examples on how to use the accelerometer but at the end I read the documentation and created my own in order to supply the deprecation changes done after OS 1.6. Here is my first implementation of a shaker based on the new API for accelerometer. Basically this is a controller class for the shaking movement. It just consider to the x axis accelerometer changes but can be improved.

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2.  
  3.  
  4.  
  5.  
  6. /**
  7.  
  8.  * ShakeController: provide a vibration when the user shake the device
  9.  
  10.  * Copyright (C) 2010  Ivomania
  11.  
  12.  * This program is free software: you can redistribute it and/or modify
  13.  
  14.  * it under the terms of the GNU Affero General Public License as
  15.  
  16.  * published by the Free Software Foundation, either version 3 of the
  17.  
  18.  * License, or (at your option) any later version.
  19.  
  20.  *
  21.  
  22.  * This program is distributed in the hope that it will be useful,
  23.  
  24.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  25.  
  26.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  27.  
  28.  * GNU Affero General Public License for more details.
  29.  
  30.  *
  31.  
  32.  * You should have received a copy of the GNU Affero General Public License
  33.  
  34.  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  35.  
  36.  */
  37.  
  38.  
  39.  
  40. package com.ivomania.controller;
  41.  
  42.  
  43.  
  44. import android.content.Context;
  45.  
  46. import android.hardware.Sensor;
  47.  
  48. import android.hardware.SensorEvent;
  49.  
  50. import android.hardware.SensorEventListener;
  51.  
  52. import android.hardware.SensorManager;
  53.  
  54. import android.os.Vibrator;
  55.  
  56.  
  57.  
  58. /**
  59.  
  60.  * Controls the shaking movement. Calibration made on Google Nexus One
  61.  
  62.  */
  63.  
  64. public class ShakeController {
  65.  
  66.     /** Gravity threshold module set to 1,33 G */
  67.  
  68.     public static final float GRAVITY_MODULE = SensorManager.GRAVITY_EARTH + SensorManager.GRAVITY_EARTH/3;
  69.  
  70.     //Application context
  71.  
  72.     Context context;
  73.  
  74.     Vibrator vibrator;
  75.  
  76.     SensorManager sm;
  77.  
  78.     Sensor accelerometer;
  79.  
  80.     IvomaniaSensorListener accelerometerListener;
  81.  
  82.  
  83.  
  84.     private static ShakeController instance;
  85.  
  86.  
  87.  
  88.     /**
  89.  
  90.      * Singleton Implementation for this class (private constructor)
  91.  
  92.      * @param context the application context
  93.  
  94.      */
  95.  
  96.     private ShakeController(Context context) {
  97.  
  98.         this.context = context;
  99.  
  100.         //init the listener
  101.  
  102.         accelerometerListener = new IvomaniaSensorListener();
  103.  
  104.         //init the accelerometer
  105.  
  106.         initAccelerometer();
  107.  
  108.         //init the vibrator
  109.  
  110.         initVibrator();
  111.  
  112.     }
  113.  
  114.  
  115.  
  116.  
  117.  
  118.     /**
  119.  
  120.      * Singleton Implementation for this class
  121.  
  122.      * @param context the application context
  123.  
  124.      * @return ShakeController this class unique instance
  125.  
  126.      */
  127.  
  128.     public static ShakeController getInstance(Context context) {
  129.  
  130.         if (instance == null) {
  131.  
  132.             instance = new ShakeController(context);
  133.  
  134.         }
  135.  
  136.         return instance;
  137.  
  138.     }
  139.  
  140.  
  141.  
  142.     /**
  143.  
  144.      * System call to initialize the vibrator service
  145.  
  146.      * needs "android.permission.VIBRATION" on the AndroidManifest.xml
  147.  
  148.      */
  149.  
  150.     private void initVibrator() {
  151.  
  152.         vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
  153.  
  154.     }
  155.  
  156.  
  157.  
  158.     /**
  159.  
  160.      * System call to initialize the accelerometer service
  161.  
  162.      */
  163.  
  164.     private void initAccelerometer() {
  165.  
  166.         sm = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
  167.  
  168.         this.accelerometer = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
  169.  
  170.     }
  171.  
  172.  
  173.  
  174.     /**
  175.  
  176.      * External call to start sensor the service
  177.  
  178.      */
  179.  
  180.     public void startService() {
  181.  
  182.         sm.registerListener(accelerometerListener, accelerometer, SensorManager.SENSOR_DELAY_GAME);
  183.  
  184.     }
  185.  
  186.  
  187.  
  188.     /**
  189.  
  190.      * External call to stop sensor the service
  191.  
  192.      */
  193.  
  194.     public void stopService() {
  195.  
  196.         sm.unregisterListener(accelerometerListener, accelerometer);
  197.  
  198.  
  199.  
  200.     }
  201.  
  202.  
  203.  
  204.     /**
  205.  
  206.      * The accelerometer listener implementation
  207.  
  208.      */
  209.  
  210.     class IvomaniaSensorListener implements SensorEventListener {
  211.  
  212.  
  213.  
  214.         private static final int SCROLL_TO_VIBE = 2;
  215.  
  216.  
  217.  
  218.         //Counter for the left shake
  219.  
  220.         int rightCounter = 0;
  221.  
  222.         //Counter for the right shake
  223.  
  224.         int leftCounter = 0;
  225.  
  226.  
  227.  
  228.         protected IvomaniaSensorListener() {
  229.  
  230.         }
  231.  
  232.  
  233.  
  234.         /**
  235.  
  236.          * Use the x value to understand how much the scroll took place
  237.  
  238.          * After 4 intense scrolls left and right this method produces a vibration
  239.  
  240.          * @param sensorEvent
  241.  
  242.          */
  243.  
  244.         public void onSensorChanged(SensorEvent sensorEvent) {
  245.  
  246.            
  247.  
  248.             float[] coord = sensorEvent.values;
  249.  
  250.             if (coord[0] > GRAVITY_MODULE) {
  251.  
  252.                 leftCounter++;
  253.  
  254.             } else if (coord[0] < - GRAVITY_MODULE) {
  255.  
  256.                 rightCounter++;
  257.  
  258.             }
  259.  
  260.  
  261.  
  262.             if (rightCounter > SCROLL_TO_VIBE || leftCounter > 4) {
  263.  
  264.                 leftCounter = 0;
  265.  
  266.                 rightCounter = 0;
  267.  
  268.             }
  269.  
  270.  
  271.  
  272.             if (leftCounter == SCROLL_TO_VIBE && rightCounter == SCROLL_TO_VIBE) {
  273.  
  274.                 vibrator.vibrate(500);
  275.  
  276.                 leftCounter = 0;
  277.  
  278.                 rightCounter = 0;
  279.  
  280.             }
  281.  
  282.         }
  283.  
  284.  
  285.  
  286.         /**
  287.  
  288.          * Not implemented
  289.  
  290.          * @param se
  291.  
  292.          * @param accuracy
  293.  
  294.          */
  295.  
  296.         public void onAccuracyChanged(Sensor se, int accuracy) {
  297.  
  298.             //Log.error("Accuracy = " + accuracy);
  299.  
  300.         }
  301.  
  302.     }
  303.  
  304. }
  305.  
  306.  
  307.  
  308.  
Parsed in 0.044 seconds, using GeSHi 1.0.8.4


This controller can be used in external classes passing a context, for example:

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2. import com.ivomania.controller.ShakeController;
  3.  
  4. public MyClass extends Activity {
  5.  
  6.     public void onCreate(Bundle bundle) {
  7.  
  8.         ...
  9.  
  10.         ShakeController.getInstance(this).startService();
  11.  
  12.     }
  13.  
  14.  
  15.  
  16.     public void onDestroy() {
  17.  
  18.         ShakeController.getInstance(this).stopService();
  19.  
  20.  
  21.  
  22.         super.onDestroy();
  23.  
  24.     }
  25.  
  26. }
  27.  
  28.  
  29.  
  30.  
Parsed in 0.031 seconds, using GeSHi 1.0.8.4


This way the registration of the listener will be managed by the app lifecyle in order to avoid fast battery drain leaving the sensors up and running. The start and stop methods are the ones addressed to register and unregister the listener whenever the app opens and close (in this case).

Feel free to use the above code as you wish (If you wish :) ).

Thanks in advance for any comment or suggestion.

Ivomania
Mobile 2.0 - see my blog at:

http://superivomania.blogspot.com/

Or keep in sync with Funambol:

http://www.funambol.com
ivomania
Freshman
Freshman
 
Posts: 2
Joined: Thu Feb 04, 2010 10:19 am
Location: Italy - Milan

Top

No vibration

Postby wrightrocket » Fri May 07, 2010 6:20 pm

I implemented your class as you suggested. The app builds and runs, but my phone doesn't vibrate when I shake it. I'm using the HTC Droid Incredible. Any suggestions?
wrightrocket
Once Poster
Once Poster
 
Posts: 1
Joined: Fri May 07, 2010 6:16 pm

AndoridManifest Pemission check or sensor accuracy problem

Postby ivomania » Mon May 10, 2010 4:17 pm

Hi wrightrocket,


What you say is really strange as I tried it both on Motorola DROID Milestone and Google Nexus One and it was working. I think your problem could be due to a lack of permission in the manifest: I experienced the same behavior but all went fine when I finally added the VIBRATE permission on the manifest. The permission name is:

android.permission.VIBRATE

I omitted to attach the manifest code, but in order to use vibration in your app you should add the following lines of code:

<uses-permission android:name="android.permission.VIBRATE"/>

into the AndroidManifest.xml file.

If this doesn't work, can you see what the device log says using for example the ddms tool?

If my previous suggestion is not right I'd suggest to change the accuracy of the sensors and try again understanding using Log.d() calls if it is a calibration problem. If you can't finally solve the problem, please post here what is the situation and let's try together to solve the issue.

Please, let me know if the suggestion was right.

NOTE:
Let me also add that I integrated the code in this post to the application I made with my team in my company (Funambol Android sync client) that let you keep your contacs and picture in sync with our service. I tried it on nexus and droid and it was working (the sensor is enabled using the phisical arrow key on the left side of the device). The code is open source and released under GPL v3 so if you want to download it you can check out the svn repo from the funambol repo:

svn checkout https://android-client.forge.funambol.o ... _shakesync shakesync_read_only

You can also browse the code online if you just want to check the manifest or the sensor classes.

for any eventual problem with the funambol application itself refer to the funambol forum, please.

Thank you very much for your reply.
Mobile 2.0 - see my blog at:

http://superivomania.blogspot.com/

Or keep in sync with Funambol:

http://www.funambol.com
ivomania
Freshman
Freshman
 
Posts: 2
Joined: Thu Feb 04, 2010 10:19 am
Location: Italy - Milan

Re: Accelerometer in Android OS 2.x and deprecated API

Postby quaesitum » Thu Jul 22, 2010 8:16 pm

Hi Ivomania,

I just wanted to give a big thanks for sharing your particular implementation of a shake sensor.

The code is very clean.

Best Regards,
Glenn
quaesitum
Once Poster
Once Poster
 
Posts: 1
Joined: Thu Jul 22, 2010 8:13 pm

Top

Return to Code Snippets for Android

Who is online

Users browsing this forum: No registered users and 5 guests