Greetings!

If any of the info on this website was useful for your projects or made your head spin with creative ideas, and you would like to share a token of your appreciation- a donation would be massively appreciated!

Your donation will go to my Robotics Fund, straight towards more sensors, actuators, books, and journeys. It takes a lot to continue building these robots, and I’m really thankful of everyone who helps encourage me along the way.


USD


CAD

“A wise robot once said to me through Serial.println- that robots teach us about ourselves.”

All posts in Android ADK

Android ADK Background Service

I was playing around with the ADK and wondering how it would be possible to make the connection work while the app was in the background. The first way I tried was to not close the connection in onPause(). This worked, since the file input and output streams were able to continue … until they were garbage collected. When other Android apps run in the background, they use a Service. I tried this out with the ADK, and it works! Check out the video demonstration below.



Watch video on YouTube

The initialization and opening of the ADK is still done in the main activity. We use the Application class as a friendly singleton to transfer the streams, file descriptor, and usb accessory over to the Service.

  1. private void enableControls(boolean b) {
  2.         ((ServiceADKApplication) getApplication()).setInputStream(mInputStream);
  3.         ((ServiceADKApplication) getApplication()).setOutputStream(mOutputStream);
  4.         ((ServiceADKApplication) getApplication()).setFileDescriptor(mFileDescriptor);
  5.         ((ServiceADKApplication) getApplication()).setUsbAccessory(mAccessory);
  6.         // … snip …
  7. }

Creating the Service is rather straight forward. In ServiceADKActivity:

onCreate()

  1. startService(new Intent(this, ADKService.class));

onPause()

  1. try {
  2.         ADKService.self.startUpdater();
  3. } catch(Exception e) {
  4.         Log.d(TAG, "Starting the updater failed");
  5. }

onResume()

  1. try {
  2.         ADKService.self.stopUpdater();
  3. } catch(Exception e) {
  4.         Log.d(TAG, "Stopping the updater failed");
  5. }

When the Service is started, it creates an Updater thread, which runs every second.

  1. if (!updater.isRunning()) {
  2.         Log.d(TAG, "updater not running");
  3.         updater = new Updater();
  4.         updater.start();
  5. } else {
  6.         Log.d(TAG, "updater running");
  7. }

In background, this can run for a very long time. I let it be for 12 hours before I stopped it.

However… there is a very bizarre bug. Sometimes when the app returns to foreground, it can’t reconnect to the ADK. The main problem is with the USB Manager trying to open the accessory for some reason. The app has permissions to the accessory, and it prints out the connected accessory correctly. Here is my trace of the bug:

  1. @Override
  2.         public void onResume() {
  3.        
  4.         Log.v(TAG, "onResume");
  5.  
  6. // —- onResume is called —-
  7.        
  8.                 super.onResume();
  9.                
  10.                 try {
  11.                         ADKService.self.stopUpdater();
  12.                 } catch(Exception e) {
  13.                         Log.d(TAG, "Stopping the updater failed");
  14.                 }
  15.                
  16. // —- updater is indeed stopped —-
  17.  
  18.                 Intent intent = getIntent();
  19.                
  20.                 if (mInputStream != null && mOutputStream != null) {
  21.                         Log.v(TAG, "input and output stream weren’t null!");
  22.                         enableControls(true);
  23.                         return;
  24.                 }
  25.  
  26. // —- the file i&o streams are null —-
  27.                
  28.                 UsbAccessory[] accessories = mUsbManager.getAccessoryList();
  29.                
  30.                 Log.v(TAG, "all the accessories: " + accessories);
  31.  
  32. // —- shows the connected accessory —-
  33.                
  34.                 UsbAccessory accessory = (accessories == null ? null : accessories[0]);
  35.                 if (accessory != null) {
  36.                         if (mUsbManager.hasPermission(accessory)) {
  37.  
  38. // —- there is permission, going to open the accessory —-
  39.  
  40.                                 Log.v(TAG, "mUsbManager does have permission");
  41.                                 openAccessory(accessory);
  42.                         } else {
  43.                                 Log.v(TAG, "mUsbManager did not have permission");
  44.                                 synchronized (mUsbReceiver) {
  45.                                         if (!mPermissionRequestPending) {
  46.                                                 mUsbManager.requestPermission(accessory,
  47.                                                                 mPermissionIntent);
  48.                                                 mPermissionRequestPending = true;
  49.                                         }
  50.                                 }
  51.                         }
  52.                 } else {
  53.                         Log.d(TAG, "mAccessory is null");
  54.                 }
  55.                
  56.                
  57.         }
  58.  
  59.  
  60. private void openAccessory(UsbAccessory accessory) {
  61.                
  62.                 Log.e(TAG, "openAccessory: " + accessory);
  63.                
  64.                 Log.d(TAG, "this is mUsbManager: " + mUsbManager);
  65.                
  66. // —- prints out the address of usb manager fine —-
  67.  
  68.                 mFileDescriptor = mUsbManager.openAccessory(accessory);
  69.                
  70. // —- Error in log from UsbService: E/UsbService( 110): could not open /dev/usb_accessory
  71.  
  72.                 Log.d(TAG, "Tried to open");
  73.                
  74.                 if (mFileDescriptor != null) {
  75.                         mAccessory = accessory;
  76.                         FileDescriptor fd = mFileDescriptor.getFileDescriptor();
  77.                         mInputStream = new FileInputStream(fd);
  78.                         mOutputStream = new FileOutputStream(fd);
  79.                         mThread = new Thread(null, this, "DemoKit"); // meep
  80.                         mThread.start(); // meep
  81.                         Log.d(TAG, "accessory opened");
  82.                         enableControls(true);
  83.                 } else {
  84.                         Log.d(TAG, "accessory open fail");
  85.                         enableControls(false);
  86.                 }
  87. }

Does anyone know why this may be? I have tried to work around it numerous times but to no luck yet.

You can grab the code off of my GitHub to play around and test it.

It would be great if we could fix this bug!

Learning Pet – Thanks for voting!

Thanks everyone who voted for Learning Pet in the Open Hardware Summit Scholarship! It was much appreciated! We didn’t place in the top 3.

Here was a fantastic interview by Ian Cole, thanks so much Ian!



The future of Learning Pet is that there will be time spent on apps4arduino to make some money in order to be able to purchase some laser cut parts, 3d parts, and boards.

Here are some stats of the contest that I collected from the webpage:

- 51.9% had a prototype
- 48.1% showed a demo in their video
- 51.9% had a website
- 3.7% released their hardware files under a license for the open hardware definition
- 22.2% had their hardware files available
- 14.8% had a bom
- 5.6% released their source code under an osi license
- 22.2% had their code available
- 40.7% had documentation
- 22.2% had additional videos
- 59.3% said what they would do with the prize if they won
- 18.5% demoed while at the ohs

You can check out all the documentation for Learning Pet here:
http://robotgrrl.com/learningpet

Thanks again!

Learning Pet will be at the Maker Faire this weekend, so be sure to say hi! (or whatever hi is in robobrrd language)

Learning Pet – VOTE! (Open Hardware Summit Scholarship)

VOTE FOR LEARNING PET IN THE OPEN HARDWARE SUMMIT SCHOLARSHIP!

Introducing Learning Pet, a mini RoboBrrd with a very large theme- education! Learning Pet enriches lessons by creating a physical interface to interact with the virtual world.



We demonstrate a number sorting game, where the student interacts with the robot to blast virtual UFO’s with the lowest value. Correct answers are celebrated with a wing flap, and each level-up with a dance. We use the Accessory Development Kit to interface with mobile devices while away from the computer.



On LearningPet’s webpage, it has all the detailed information about the hardware, software and design. There is also a handy checklist at the top, so that at a glance you can quickly see the important facts.

It would be awesome if you could vote for Learning Pet in the Open Hardware Summit Scholarship! VOTE here!

Here is a YouTube playlist of all the videos!