Monthly Archives: August 2013

Android unique device identifiers, serial number and ANDROID_ID

There has been some discussions about unique device identifiers in Android.

Basically there are 3 main options (starting from the least recommended):

MAC Address or TelephonyManager –  not recomended

The mac address from WiFi or Bluetooth, however this is the best option as some devices does not have the specific hardware(wifi or bt), or depending on its status (off/disabled) mac cannot be obtained.

ANDROID_ID (from API 3) – can change after system update

Settings.Secure.ANDROID_ID is

A 64-bit number (as a hex string) that is randomly generated on the device’s first boot and should remain constant for the lifetime of the device. (The value may change if a factory reset is performed on the device.)

Constant Value: “android_id”
It can be obtained grammatically using this:
Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID)

 

Serial Number (from API 9) – recommended

android.os.Build.SERIAL  –

A hardware serial number, if available. Alphanumeric only, case-insensitive.

is the serial number you see in the DDMS view in Eclipse or from the command “adb devices”. This can be obtained pragmatically from

android.os.Build.SERIAL

Conclusion

Its simple if you do not care to identify hardware  but installation go for ANDROID_ID, otherwise use android.os.Build.SERIAL.

Example

Here is a simple example of serial number and ANDROID_ID before and after android update.

Executed command:

adb devices

Executed code:

Log.i("TEST","android.os.Build.SERIAL: " + android.os.Build.SERIAL);
Log.i("TEST","Settings.Secure.ANDROID_ID: " + Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID));

On Build: jwr66v

command:

List of devices attached
0039f663df121556        device

code:

I/TAG(8122): android.os.Build.SERIAL: 0039f663df121556
I/TAG(8122): Settings.Secure.ANDROID_ID: 5b79c0300c556842

On Build: jwr66y

command:

List of devices attached
0039f663df121556        device

code:

I/TAG(2861): android.os.Build.SERIAL: 0039f663df121556
I/TAG(2861): Settings.Secure.ANDROID_ID: 3dcc3d9765e7f1db

 

New OTA JWR66V->JWR66Y and JSS15J->JSS15Q for Nexus devices

Today I received a new ota update for my GN (maguro yakju): http://android.clients.google.com/packages/ota/google_maguro/1b0ac7dfb2907e5981f1af24b9e5b005712bd4ee.signed-yakju-JWR66Y-from-JWR66V.1b0ac7df.zip

for takju: http://android.clients.google.com/packages/ota/google_takju/8069c140a030f5fe6a6296743aab8c5a93971b79.signed-takju-JWR66Y-from-JWR66V.8069c140.zip

This is for version JWR66V to update to JWR66Y(android-4.3_r1.1) for Galaxy Nexus, Nexus 4/7/10 and for new Nexus 7 the update is from JSS15J to JSS15Q(android-4.3_r2.2).

of course all the full images can be found at https://developers.google.com/android/nexus/images

and of course those + deodexed and insecure/debug boot at http://web.djodjo.org/?p=download:android:ROM_images

all changelogs can be downloaded/browsed at http://web.djodjo.org/?p=download:android:changelog

Get packages from IProject in eclipse using IJavaProject

When working with Eclipse and especially when developing plug-ins you will deal with the org.eclipse.core.resources.IProject interface.

This however does not give you an option to get the packages used in the project. For that you will need org.eclipse.jdt.core.IJavaProject interface which is a completely different interface and cannot just get it from a cast from IProject, however you can:

IProject proj = (IProject)selectionResult;

IJavaProject jProj = JavaCore.create(proj);

then of course you can use jProj.getPackageFragments() to get app the package elements in the project.

You can also check if project is actually java project before creating the IJavaProject:

if(JavaProject.hasJavaNature(proj)) ...

 

 

Android Eclipse @Override error

Have you ever experienced multiple errors when you import a project into a new environment and all the errors are on @Override methods smth like:

The method Xxx(zz) of type AAA.BBB must override a superclass method

Also when you remove “@Override” all goes fine?

Well this might be if you are compiling with Java 5 (or setting the compiler’s -source option to expect Java 5 source) . In Java 5 you could not use the @Override annotation with methods that implemented an interface, only with actual overrides of methods from a super class. This changed in Java 6 so that you can now use it in both contexts.

So a solution is just to compile with java 6+.

To set this in eclipse:

Window->preferences->Java->Compiler

in “JDK Compliance” set “Compiler compliance level” to 1.6.

Install Eclipse Juno/Kepler on Ubuntu

If you use Ubuntu Software Center to install eclipse only 3.8 is available but not 4.X.

Here is how to install it manually by manually downloading the eclipse IDE package.

  •          Download the eclipse tar.gz package from here.
  •          Then righ-click the eclipse tar.gz and choose the extract here option to extract the tar.gz package. You can also use the command line to extract the tar.gz package.
# tar xzf eclipse-cpp-juno-linux-gtk.tar.gz
  •           Move the extracted eclipse in the  /opt/ folder.Before running the below command be sure that you are in the directory which contains extracted eclipse folder.
# mv eclipse /opt/
  •             Use sudo if the above command gives permission denied message.
# sudo mv eclipse /opt/
  •        Create a desktop file and place it into /usr/share/applications
# sudo gedit /usr/share/applications/eclipse.desktop
  • and copy the following to the eclipse.desktop file
[Desktop Entry]
Name=Eclipse 
Type=Application
Exec=/opt/eclipse/eclipse
Terminal=false
Icon=/opt/eclipse/icon.xpm
Comment=Integrated Development Environment
NoDisplay=false
Categories=Development;IDE
Name[en]=eclipse.desktop
  • Create a symlink in /usr/local/bin using
 # cd /usr/local/bin
 # sudo ln -s /opt/eclipse/eclipse
  •  launch eclipse.

# /opt/eclipse/eclipse  -clean  &

If your eclipse does not start then you need to make sure /opt/eclipse/eclipse is there and executable.

Programmatically inject input events on Android

This is a brief overview of 3 main ways how to inject keys/touches monitor for input events on Android.

1) using internal (and some public) APIs

internal apis before api16:

IBinder wmbinder = ServiceManager.getService( "window" );
IWindowManager wm = IWindowManager.Stub.asInterface( wmbinder );
//pointer
wm.injectPointerEvent(myMotionEvent, false);
//key
wm.injectKeyEvent(new KeyEvent( KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_A ), false);
wm.injectKeyEvent(new KeyEvent( KeyEvent.ACTION_UP, KeyEvent.KEYCODE_A ), false);
//trackball
wm.injectTrackballEvent(myMotionEvent, false);

after api 15 Input Manager was introduced and those methods were removed from the window manager service:

IBinder imBinder = ServiceManager.getService("input");
IInputManager im = IInputManager.Stub.asInterface(imBinder);

//inject key event
 final KeyEvent keyEvent = new KeyEvent(downTime, eventTime, action, code, repeatCount, metaState, deviceId, scancode, flags | KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_KEEP_TOUCH_MODE | KeyEvent.FLAG_SOFT_KEYBOARD, source);
 event.setSource(InputDevice.SOURCE_ANY)
im.injectInputEvent(keyEvent, 2);

//inject pointer event
motionEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN);
im.injectInputEvent(motionEvent, 2);

Starting from api 16 InputManager is introduced in the public api. It can be used to information about input devices and available key layouts. This however has other hidden methods as injectInputEvent method which is the main entry for injecting events for: android.app.Instrumentation, com.android.uiautomator.core.InteractionController, com.android.commands.input.Input, com.android.server.accessibility.AccessibilityManagerService.Service, com.android.systemui.statusbar.policy.KeyButtonView.

InputManager im = (InputManager) getSystemService(INPUT_SERVICE);

2) using Instrumentation

Instrumentation mInst = new Instrumentation();
mInst.sendKeyDownUpSync( KeyEvent.KEYCODE_A );
mInst.sendPointerSync(MotionEvent.obtain(SystemClock.uptimeMillis(),
SystemClock.uptimeMillis(),MotionEvent.ACTION_DOWN, x, y, 0);
mInst.sendPointerSync(MotionEvent.obtain(SystemClock.uptimeMillis(),
SystemClock.uptimeMillis(),MotionEvent.ACTION_UP, x, y, 0);

3) using shell command or native/jni calls

There are many entries here but all come to usage of the input devices in /dev/input

shell@mako:/dev/input $ ll
crw-rw---- root     input     13,  64 2013-08-11 18:00 event0
crw-rw---- root     input     13,  65 2013-08-11 18:00 event1
crw-rw---- root     input     13,  66 2013-08-11 18:00 event2
crw-rw---- root     input     13,  67 2013-08-11 18:00 event3
crw-rw---- root     input     13,  68 2013-08-11 18:00 event4
crw-rw---- root     input     13,  69 2013-08-11 18:00 event5

these are different for different devices. They also have different ways to be addressed check this for general info.

so we need to read and write those but as we can see we have some restrictions, so we have 3 options.

  1. use su/root from app
  2. chmod the events
  3. use adb shell to access the events, as adbd is in the input group

after figuring this out we have quite a few options:

  • command “input”
shell@mako:/dev/input $ input                                                  
usage: input ...
       input text <string>
       input keyevent <key code number or name>
       input [touchscreen|touchpad|touchnavigation] tap <x> <y>
       input [touchscreen|touchpad|touchnavigation] swipe <x1> <y1> <x2> <y2> [duration(ms)]
       input trackball press
       input trackball roll <dx> <dy>

this however is much limited on older Android line 2.3.X it has only text an keyevent options.

Also this simply starts the java class “com.android.commands.input.Input”

command getevent and sendevent

shell@mako:/dev/input $ getevent -h                                            
Usage: getevent [-t] [-n] [-s switchmask] [-S] [-v [mask]] [-d] [-p] [-i] [-l] [-q] [-c count] [-r] [device]
    -t: show time stamps
    -n: don't print newlines
    -s: print switch states for given bits
    -S: print all switch states
    -v: verbosity mask (errs=1, dev=2, name=4, info=8, vers=16, pos. events=32, props=64)
    -d: show HID descriptor, if available
    -p: show possible events (errs, dev, name, pos. events)
    -i: show all device info and possible events
    -l: label event types and names in plain text
    -q: quiet (clear verbosity mask)
    -c: print given number of events then exit
    -r: print rate events are received
shell@mako:/dev/input $ sendevent                                            
use: sendevent device type code value

you can always use native jni code to do all this. Here is an example project.

a little bit outdated but interesting post related to this topic : http://cjix.info/blog/misc/internal-input-event-handling-in-the-linux-kernel-and-the-android-userspace/

Android start new activity from launcher, code and shell command

Option 1: via launcher / home screen

This is easy just a click on the home screen or all apps lists.

the default behaviour of the launcher is to launch the activity with flags 0x10200000, something like that:

INFO/ActivityManager(XXXX): Starting activity: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=my.package/myActivity }

From the reference guide we have:

public static final int FLAG_ACTIVITY_NEW_TASK
Constant Value: 268435456 (0x10000000)

public static final int FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
Constant Value: 2097152 (0x00200000)

The interesting one is FLAG_ACTIVITY_RESET_TASK_IF_NEEDED

If set, and this activity is either being started in a new task or bringing to the top an existing task, then it will be launched as the front door of the task. This will result in the application of any affinities needed to have that task in the proper state (either moving activities to or from it), or simply resetting that task to its initial state if needed.

Which means that we come back to our activity as we left it… good launcher 🙂 Now lets do it ourselves.

Option 2: Do it from java code

Simple using Intent.

Example:

Intent myIntent = new Intent(Intent.ACTION_MAIN);
myIntent.setClassName("my.package.myMainActivity", "my.package");
myIntent.putExtra(EXTRA_KEY, "Some string data");
myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
myIntent.addFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
startActivity(myIntent);

Option 3: using Activity Manager (am) from the shell (or java code)

djodjo@android:/ # am
am
usage: am [subcommand] [options]
usage: am start [-D] [-W] [-P <FILE>] [--start-profiler <FILE>]
[--R COUNT] [-S] [--opengl-trace]
[--user <USER_ID> | current] <INTENT>

...

<INTENT> specifications include these flags and arguments:
[-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]
[-c <CATEGORY> [-c <CATEGORY>] …]
[-e|--es <EXTRA_KEY> <EXTRA_STRING_VALUE> ...]
[--esn <EXTRA_KEY> ...]
[--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE> ...]
[--ei <EXTRA_KEY> <EXTRA_INT_VALUE> ...]
[--el <EXTRA_KEY> <EXTRA_LONG_VALUE> ...]
[--ef <EXTRA_KEY> <EXTRA_FLOAT_VALUE> ...]
[--eu <EXTRA_KEY> <EXTRA_URI_VALUE> ...]
[--ecn <EXTRA_KEY> <EXTRA_COMPONENT_NAME_VALUE>]
[--eia <EXTRA_KEY> <EXTRA_INT_VALUE>[,<EXTRA_INT_VALUE...]]
[--ela <EXTRA_KEY> <EXTRA_LONG_VALUE>[,<EXTRA_LONG_VALUE...]]
[--efa <EXTRA_KEY> <EXTRA_FLOAT_VALUE>[,<EXTRA_FLOAT_VALUE...]]
[-n <COMPONENT>] [-f <FLAGS>]
[--grant-read-uri-permission] [--grant-write-uri-permission]
[--debug-log-resolution] [--exclude-stopped-packages]
[--include-stopped-packages]
[--activity-brought-to-front] [--activity-clear-top]
[--activity-clear-when-task-reset] [--activity-exclude-from-recents]
[--activity-launched-from-history] [--activity-multiple-task]
[--activity-no-animation] [--activity-no-history]
[--activity-no-user-action] [--activity-previous-is-top]
[--activity-reorder-to-front] [--activity-reset-task-if-needed]
[--activity-single-top] [--activity-clear-task]
[--activity-task-on-home]
[--receiver-registered-only] [--receiver-replace-pending]
[--selector]
[<URI> | <PACKAGE> | <COMPONENT>]

example:

am start --user 0 -f 0x10200000 -a android.intent.action.MAIN -c android.intent.category.LAUNCHER -n my.package/.myMainActivity

note that –user N is needed from api 17, when user management was introduced, even on phones where you dont see the UI for that actually so you have just one user(N=0).

Change Android system property

To change the a property temporarily:

you can use the command “setprop <key> <value>”, from the device shell or from command shell on the pc execute “adb shell setprop <key> <value>”, where key is the property name and the value is the value you would like to assign to it. To get the list of all properties you can use “getprop”.

The command “setprop” may not be usable by an unprivileged user, so you may need to execute “su” or “adb root” before. To check if there was an effect from “setprop” you can call “getprop <key>”, where the key is the name of the property you are trying to change.

For the changes to take effect you will need to restart the Android runtime(zygote process) you can do that by “adb shell stop; adb shell start”.

Read only properties(name starting with ro.) cannot be changed using setprop even if root.

There is a “setpropex” binary by xda member goroh_kun that can do that: http://t.co/mMtzylU7

To persist a change  of property after reboot:

you need to modify the file where the property is located and initialized from.

The places where you can find properties are (listed by the way they overwrite each other):

  • /default.prop (has to be edited from the boot image as it gets overwritten when the kernel reboots)
  • /system/build.prop
  • /data/local.prop

You can change those by:

  • using some file explorer app which uses root
  • “adb pull” and “adb push”, having thta you have write permission for those files or you run adb as root
  • using update script and update it with CWM