Thursday, 15 January 2015

Enable detection of USB Devices on Ubuntu


You just connected your android device to the system to begin debugging and found nothing but ????? under the Devices window in your IDE. Now what ?

To get the device running on the Ubuntu we will need to register all the devices with a udev file which contains usb configuration for each device connecting to the system.
In the udev rules file each device manufacturer is identified by a unique vendor id as specified by ATTR{idVendor}.

Main steps :
1. Open terminal, assuming you are at home directory
    write command to change directory i.e. <cd ..> {without arrows} twice.
    Now change directory to <cd etc/udev/rules.d/> {without arrows}

2. Write command with root access to create a file
    $ sudo gedit 51-android.rules
    It will prompt for password : enter your system's root password
    It will create and open up the file with gedit (or you can use the editor of your choice too).

3. Now you will need to add entries corresponding to each device you are going to connect to your system.
And the format for those entries is as follows :
   SUBSYSTEM=="usb", ATTR{idVendor}=="0bb4", MODE="0666", GROUP="plugdev"
   where "0bb4" is the vendor id for HTC found along side more other manufacturers in the list at
   http://developer.android.com/tools/device.html#VendorIds

   Also the MODE assignment specifies read/write permissions, and GROUP defines which Unix group owns the device node.

4. Once you are done with the above step, close the gedit or the editor you were using to edit the file.

5. Now we will change the permissions for the new created rules file as follows:
  $ chmod a+r /etc/udev/rules.d/51-android.rules

Really! In what world ? 
  If in any case you had restarted your terminal just after editing the file and hence getting the Operation not permitted error for the above 5th step,
  then you got to run the above command with sudo at the first place and again entering password when prompted for.
  $ sudo chmod a+r /etc/udev/rules.d/51-android.rules

6. Once done, you are good to go to play with your device connected to your machine.


Connect your device with usb debugging ON to the machine. And here you are annoyed one more time by a prompt on the device to check the Allow USB debugging dialog box.
But don't worry this will be last time you will be bugged.

Here is the sample file 51-android.rules file containing most vendor details about most used devices in the world. If you didn't found your device, please match with the above given vendor id's
and add one for yours.

Above list contains vendor Id's for Samsung, Motorola, Sony, Google, LG, Lenovo, Acer, Asus, Intel, Huawei etc.

Monday, 1 December 2014

Resolving Last ShutDown State (Normal or Abrupt)

This blog post is about how to resolve if the last device shutdown happened normally or abruptly.

Actually the problem with which this post was started was to check in an application whether the last shutdown happened abruptly with a battery detachment.

But since there is no broadcast intent available to check for the  battery detachments. It means there is no direct way to deduce whether the last shutdown was caused by detaching battery from the device.

So we started to reduce the problem firstly to check if the last state was simply normal or abrupt. And then in later posts if possible finding the reason for the abrupt shutdown was due to the detaching of battery.

The two parts are :
1. First part mainly deals with the checking of the app that whether the last shutdown was successful or not.
2. Second part mainly deals with checking if last shutdown was abrupt and was due to battery detachment

Here in this post we will only deal with the first part.

Important point :
This investigative implementation is totally based upon the fact that the intent with action ACTION_SHUTDOWN is never called by the system before going dead when it happens abruptly.

We can accomplish the first problem of resolving reason of shutdown by implementing BroadcastReceiver that listens for two broadcast intents with actions namely ACTION_SHUTDOWN and BOOT_COMPLETED.

We will be achieving our this task by saving a value (currently in Preferences) when system sends broadcast for ACTION_SHUTDOWN and checking its value when device is rebooted and system send a broadcast for BOOT_COMPLETED.

Implemented classes are :

BroadcastReceiver

public class DisconnectReceiver extends BroadcastReceiver
{
 @Override
 public void onReceive(Context context, Intent intent)
 {
  if (intent.getAction().equalsIgnoreCase(Intent.ACTION_BOOT_COMPLETED))
  {
   int shutDownCode = PreferenceManager.getDefaultSharedPreferences(DroidApplication.getsContext()).getInt(
     DisconnectConstants.KEY_NORMAL, 0);

   // Checking for the last shutdown value (1 = Normal ShutDown and 0 = Abrupt ShutDown )
   if (shutDownCode == 1)
   {
    // Reset the last value
    Editor editor = PreferenceManager.getDefaultSharedPreferences(DroidApplication.getsContext()).edit();
    editor.putInt(DisconnectConstants.KEY_NORMAL, 0);
    editor.commit();

    // TODO Here goes the user code to be implemented 
    
   }
   else if (shutDownCode == 0)
   {
    // TODO Here goes the user code to be implemented 
    
   }
  }
  else if (intent.getAction().equalsIgnoreCase(Intent.ACTION_SHUTDOWN))
  {
   // Saving value in Preferences for ShutDown broadcast
   Editor editor = PreferenceManager.getDefaultSharedPreferences(DroidApplication.getsContext()).edit();
   editor.putInt(DisconnectConstants.KEY_NORMAL, 1);
   editor.commit();
  }
 }
}

Changes in AndroidManifest.xml

Under <manifest> tag

<!-- Permission for getting RECEIVE_BOOT_COMPLETED -->
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

Under <application> tag

<!-- Receiver to checks for broadcast for ACTIONs : ACTION_SHUTDOWN and ACTION_BOOT_COMPLETED -->
 <receiver android:name="com.droidutility.disconnect.utils.DisconnectReceiver" >
  <intent-filter>
   <action android:name="android.intent.action.ACTION_SHUTDOWN" />
   <action android:name="android.intent.action.BOOT_COMPLETED" />
  </intent-filter>
 </receiver>


 
 
Please check here the code added in a library project with usage instructions in README.md.
 

Thursday, 27 November 2014

Android project import error for source-set with updated gradle tools


This blog post is about a very frequent error occurring with the updated version of gradle tools in Android Studio and its resolution.


This issue mainly occurs while importing an android project in android studio with updated gradle tools.

When we create a gradle based project in android studio, it generates the project with a defined structure, so that build.gradle can access all the source sets while building project. 

In other words, a gradle based android project  when created in the Android Studio IDE represents a particular hierarchy in which various components(various modules, library modules, directories containing generated code, gradle system specific directories and files) of a particular project is defined.

Or more precisely we are talking about the SourceSets.

SourceSet
A source-set in a gradle build system is a logical grouping of sources and resources and that confirms/corresponds to a hierarchy when a new project is created in android IDE.

As long as the source-set is defined according to the default structure, it will never complain for the build failed due to missing source sets.

Well this logical grouping could be changed as per the development requirements but then it would require some changes in the build.gradle to provide the proper path for the source sets required for proper build. An example of modified SourceSets is as follows :


Now if a project was created with updated source-sets using the older gradle (0.9.1) the only change in build.gradle that got it working was :


android {

  sourceSets {
   main {
    manifest.srcFile 'AndroidManifest.xml'
    res.srcDirs = ['res']
    assets.srcDirs = ['assets']
    java.srcDirs = ['src']
   }

  .........
  }
  
  .........
}


Project use to get imported successfully and so did the build process.

But the same project when was imported into studio with the updated gradle (0.13.2 [at time of writing]) was failing with the following error for the source-set paths. To get the project imported and build successfully we were required to provide source-set path accurately.

android {

   sourceSets {
    main {
     // Complete path to the source was required here.
     
     manifest.srcFile 'AndroidManifest.xml'
     java.srcDirs = ['src/main/java']
     assets.srcDirs = ['assets']
     res.srcDirs = ['res']
    }
  
  .........
  }
  
  ..........
}

Just this change got the project imported and later build successfully. 

References :
http://www.gradle.org/docs/current/dsl/index.html