Android


Monkey Problems

Recently, we tried to user monkeyrunner on an Ubuntu 18.04 LTS. We installed Android Studio through snap and we setup the Android SDK in ~/Andoid. monkeyrunner was installed in ~/Android/Sdk/tools/bin. To our immeasurable disappointment we found out that when we tried to execute monkeyrunner, it would give the following error:

$ ./monkeyrunner
-Djava.ext.dirs=/home/tux/Android/Sdk/tools/lib:/home/tux/Android/Sdk/tools/lib/x86_64 is not supported. Use -classpath instead.
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.

At first, we had no idea what that meant, so we used file command on monkeyrunner and we found out that monkeyrunner is a bash script.

$ file monkeyrunner
monkeyrunner: POSIX shell script, ASCII text executable

After reading the code, we read the following at the last lines:

#need to use "java.ext.dirs" because "-jar" causes classpath to be ignored
#might need more memory, e.g. -Xmx128M
exec java -Xmx128M $os_opts $java_debug -Djava.ext.dirs="$frameworkdir:$swtpath" -Djava.library.path="$libdir" -Dcom.android.monkeyrunner.bindir="$progdir" -jar "$jarpath" "[email protected]"

First thing we did was to find the java version that was used, since the command that was giving the problem was that. We found out that we had version 11.

$ java -version
openjdk version "11.0.6" 2020-01-14
OpenJDK Runtime Environment (build 11.0.6+10-post-Ubuntu-1ubuntu118.04.1)
OpenJDK 64-Bit Server VM (build 11.0.6+10-post-Ubuntu-1ubuntu118.04.1, mixed mode, sharing)

After reading a bit, we found out that after Java version 8 the command line directive -Djava.ext.dirs it was deprecated and the recommendation to use -classpath was added. In the past, java.ext.dirs was used to instruct the JRE from where to load additional class and jar files. Since we had Java version 11 we had to try the recommendation to remove the -Djava.ext.dirs directive and use -classpath instead. So, we edited the file monkeyrunner and changed the last line as follows:

exec java -Xmx128M $os_opts $java_debug -classpath "$frameworkdir/*:$swtpath" -Djava.library.path="$libdir" -Dcom.android.monkeyrunner.bindir="$progdir" -jar "$jarpath" "[email protected]"

We tried executing the newly updated monkeyrunner again, only to hit another wall!

$ ./monkeyrunner
Exception in thread "main" java.lang.NoClassDefFoundError: com/android/chimpchat/ChimpChat
at com.android.monkeyrunner.MonkeyRunnerStarter.(MonkeyRunnerStarter.java:60)
at com.android.monkeyrunner.MonkeyRunnerStarter.main(MonkeyRunnerStarter.java:188)
Caused by: java.lang.ClassNotFoundException: com.android.chimpchat.ChimpChat
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
… 2 more

It turns out that when you use the -jar directive, JRE will ignore the -classpath directive and so it will again not be able to load any external class or jar files…

Solution

Instead of reinventing the wheel (We tried, we failed, it was painful. Still worth the shot!) we decided to install Java version 8 on Ubuntu 18.04 LTS side by side with Java version 11 and just used that.

First, we checked the list of installed jvm on our machine using the following command:

update-java-alternatives --list;

Where we got the following:

$ update-java-alternatives --list
java-1.11.0-openjdk-amd64 1111 /usr/lib/jvm/java-1.11.0-openjdk-amd64
java-1.8.0-openjdk-amd64 1081 /usr/lib/jvm/java-1.8.0-openjdk-amd64

It turned out we already had Java version 8 but if we didn’t we would install it as follows:

sudo apt install openjdk-8-jdk;

and then it would again appear in the list mentioned above.

Then, we switched to the Java version 8 using the following command and selecting the appropriate option:

sudo update-alternatives --config java;

$ sudo update-alternatives --config java
[sudo] password for tux:
There are 2 choices for the alternative java (providing /usr/bin/java).
Selection Path Priority Status
0 /usr/lib/jvm/java-11-openjdk-amd64/bin/java 1111 auto mode
1 /usr/lib/jvm/java-11-openjdk-amd64/bin/java 1111 manual mode
2 /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java 1081 manual mode
Press to keep the current choice[*], or type selection number: 2
update-alternatives: using /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java to provide /usr/bin/java (java) in manual mode

After switching Java to Version 8 monkeyrunner was working as expected!!


Android get GSF ID (Google Services Framework Identifier)

The Google Services Framework Identifier (GSF ID) is a unique 16 character hexadecimal number that your device automatically requests from Google as soon as you log to your Google Account for the first time. For a specific device, the GSF ID will change only after a factory reset. To get this information programmatically, you need to do two steps.

A) Add the following to your manifest

<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />

B) Execute the following code

private static final Uri sUri = Uri.parse("content://com.google.android.gsf.gservices");
public static String getGSFID(Context context) {
 try {
  Cursor query = context.getContentResolver().query(sUri, null, null, new String[] { "android_id" }, null);
  if (query == null) {
   return "Not found";
  }
  if (!query.moveToFirst() || query.getColumnCount() < 2) {
   query.close();
   return "Not found";
  }
  final String toHexString = Long.toHexString(Long.parseLong(query.getString(1)));
  query.close();
  return toHexString.toUpperCase().trim();
 } catch (SecurityException e) {
  e.printStackTrace();
  return null;
 } catch (Exception e2) {
  e2.printStackTrace();
  return null;
 }
}


[Video] Android OpenCV – Face Detection and Recognition Demo

Android OpenCV – Face Detection and Recognition Demo using Android NDK/JNI to load OpenCV library.

Google Play: https://play.google.com/store/apps/details?id=net.bytefreaks.opencvfacerecognition

Get it on Google Play

Our application is based on the ‘Face Detection’ sample of OpenCV. The sample that is available for download from http://sourceforge.net/projects/opencvlibrary/files/opencv-android/, you will notice that there are many versions there, we used version opencv-2.4.13.6-android-sdk. Refer to this (http://docs.opencv.org/2.4/doc/tutorials/introduction/android_binary_package/O4A_SDK.html) introduction for more information.


Fedora Configure Hardware Acceleration for the Android Emulator 1

While setting up Android Studio on a Fedora 27 x64, we got the following message from the Android Studio Setup Wizard:

We have detected that your system can run the Android emulator in an accelerated performance mode.
Linux-based systems support virtual machine acceleration through the KVM (Kernel-mode Virtual Machine) software package.

Search for install instructions for your particular Linux configuration (Android KVM Linux Installation) that KVM is enabled for faster Android emulator performance.

After going through the website mentioned in the message we noticed that there were no instructions for Fedora so we decided to write our own.

Below are the steps we followed to enable hardware acceleration for the Android emulator.

Step 1: Verify that your CPU has virtualization extensions.

Execute the following in a terminal:

egrep '^flags.*(vmx|svm)' /proc/cpuinfo;

if you get ANY output then it would mean that your CPU supports either VMX or SVM which is good.
If it does not print anything then the emulator will fall back to software virtualization, which is extremely slow.

Step 2: Install the virtualization packages

sudo dnf group install --with-optional virtualization;

Step 3: Start the service

sudo systemctl start libvirtd;

Step 4: Automatically start the service on boot:

sudo systemctl enable libvirtd;

Step 5: Verify that the kvm kernel modules were loaded

lsmod | grep kvm

If the above command does not print kvm_intel or kvm_amd, it would mean that KVM is not properly configured.


Android Studio – No space left on device 10

Recently we tried to install some packages from the Android SDK through Android Studio 3.0.1 and we got the error that the PC ran out of space while downloading the necessary packages and could not perform the operation.

Full Error Log:

To install:
- Google APIs Intel x86 Atom System Image (system-images;android-27;google_apis;x86)
Preparing "Install Google APIs Intel x86 Atom System Image (revision: 2)".
Downloading https://dl.google.com/android/repository/sys-img/google_apis/x86-27_r02.zip
An error occurred while preparing SDK package Google APIs Intel x86 Atom System Image: Cannot download 'https://dl.google.com/android/repository/sys-img/google_apis/x86-27_r02.zip': No space left on device
, response: 200 OK.
"Install Google APIs Intel x86 Atom System Image (revision: 2)" failed.
Failed packages:
- Google APIs Intel x86 Atom System Image (system-images;android-27;google_apis;x86)

Although the disk had a lot of free space, we got this error because the /tmp partition on our GNU/Linux Fedora 27 workstation was too small (~4GB).

$ df -h;
Filesystem Size Used Avail Use% Mounted on
devtmpfs 3.9G 0 3.9G 0% /dev
tmpfs 3.9G 107M 3.8G 3% /dev/shm
tmpfs 3.9G 1.9M 3.9G 1% /run
tmpfs 3.9G 0 3.9G 0% /sys/fs/cgroup
/dev/mapper/fedora-root 50G 35G 12G 75% /
tmpfs 3.9G 2.1M 3.9G 1% /tmp
/dev/sdb1 477M 179M 269M 41% /boot
/dev/mapper/fedora-home 178G 37G 132G 22% /home
tmpfs 794M 16K 794M 1% /run/user/42
tmpfs 794M 9.2M 785M 2% /run/user/1000

/tmp was not explicitly set so it was automatically configured to have half of the size of the RAM.
We didn’t not want to change the download path for the Java environment (and hence Android Studio and Android SDK tools) as after leaving the tmpfs folder it could mean that we would have to manually maintain the new path and clean it up. So we ended up in temporarily increasing the size of /tmp partition which did the trick and the virtual device was installed successfully.

Solution – temporarily increase the size of the /tmp partition:

The command we used to increase the size of the /tmp partition on Fedora 27 was the following:

sudo mount -o remount,size=8G,noatime /tmp;

After executing we, it we immediately saw that the results were applied without the need for a restart or any other operation and we could proceed to use the PC as normal.

$ df -h
Filesystem Size Used Avail Use% Mounted on
devtmpfs 3.9G 0 3.9G 0% /dev
tmpfs 3.9G 89M 3.8G 3% /dev/shm
tmpfs 3.9G 1.9M 3.9G 1% /run
tmpfs 3.9G 0 3.9G 0% /sys/fs/cgroup
/dev/mapper/fedora-root 50G 35G 12G 75% /
tmpfs 8.0G 2.0M 8.0G 1% /tmp
/dev/sdb1 477M 179M 269M 41% /boot
/dev/mapper/fedora-home 178G 37G 132G 22% /home
tmpfs 794M 16K 794M 1% /run/user/42
tmpfs 794M 6.9M 787M 1% /run/user/1000

The information for tmpfs we got it from: https://wiki.archlinux.org/index.php/Tmpfs

Full Correct Execution Log:

To install:
- Google APIs Intel x86 Atom System Image (system-images;android-27;google_apis;x86)
Preparing "Install Google APIs Intel x86 Atom System Image (revision: 2)".
Downloading https://dl.google.com/android/repository/sys-img/google_apis/x86-27_r02.zip
"Install Google APIs Intel x86 Atom System Image (revision: 2)" ready.
Installing Google APIs Intel x86 Atom System Image in /home/xeirwn/Android/Sdk/system-images/android-27/google_apis/x86
"Install Google APIs Intel x86 Atom System Image (revision: 2)" complete.
"Install Google APIs Intel x86 Atom System Image (revision: 2)" finished.