Dienstag, 22. April 2014

Forget Android Emulator, forget VirtualBox use Genymotion

For those who still struggle to debug & develop with Android Emulators, are tired of its bugs and crashes, its limitations and don't want to setup android-x86 on their own: Use Genymotion. It is awesome! 
All you need to do is: 

  1. Install VirtualBox (just install nothing else)
  2. Install & Run Genymotion
Thats it! Genymotion also supports WiFi (hurray), screen orientation and has currently about 20 preconfigured devices (from Xoom, Samsung's flagships to Nexus, ...). It is free for personal use, but also worth to spend 99€ (w/o support) / 299€ (w/ support) a year to get additional features like PixelPerfect and custom sensor values with Genymotion API for advanced testing.

I tried at is incredibly fast & stable - way faster than (Intel HAX) Android. Also it comes with cool ROMs that already have a FileManager for example. That is of course easy to add to the default Android Emu, but it is still nice to have.

Another thing I really loved is it's fullscreen mode. It keeps your device setup but adopts your screen size. On a Retina MacBook I was able to let Android run at 3840x2400. But I'd recommend to use a really high density for that! Also it perfectly reacts to Mac Touchpads (unlike Android Emu).

Downside: I haven't found a way yet to setup heap-size in settings. Though it should be possible through adb shell.


Get Genymotion

The time widget is located at the most right position. Stock Launcher is not made for high res ;)

... Neither is the drawer

Montag, 21. April 2014

Boosting Android Emulator on Intel Chips

Good news for all Android Devs with Intel Processors (AMD not supported): you can speed up the laggy and buggy Android Emulator by nearly 10x! 

The following steps are tested on Mac OS, Windows might behave differently. Check the link below to get details for Windows.


  1. Update ADT, make sure to update Eclipse afterwards as well. Download the Intel x86 Image for your API Level.
  2. Download Intel HAXM
  3. Install HAXM. I decided to give it 2 / 16 GB RAM, however this might be overkill for Android.
  4. Reboot once HAXM has been installed.
  5. Create an Emulator Image, make sure to select Intel x86 as Architecture and to tick "Use Host-GPU". Keep in mind: Google Api's Emu Image is not configured for Intel (as of now) and will not show Intel's Atom image!
  6. Run. The Console Window should show HAXM support not. If it is showing failed: check for other running instances of Emulator (which consume HAXMs RAM) or increase total RAM for HAXM / decrease allowed RAM for Android.





Have a look at a more detailed instruction with explanations about QEMU & HAXM.

Sonntag, 20. April 2014

Hidden Unix 101: SL

Ever mistyped "sl" instead of "ls" ? Here is what you will see (for Ubuntu Users: sudo apt-get install sl). However chances are low to see the directory.


Mittwoch, 16. April 2014

Android Renderscript: Gaussian Blur

Some of you might have stumbled upon problems with bluring in Android. Before Honeycomb (3.x) this was implemented "somewhat efficient by hardware" (quote from Android framework Engineer) and you could blur at least behind dialogs. Unfortunately you no longer have that option, gladly there is a solution (at least unless you want to blur dynamic content).

So here is a very basic and straight forward method to blur a Bitmap with API 17 and above (4.2.2+). Radius is a value between 0 and 25.

ATTENTION: It seems like there is a bug (currently Android 4.4.2) that forces apps to crash when using RenderScript on devices with a width of 2048 and bigger (like Nexus 10 ...). You can read more on that in the official Google Issue


private Bitmap  createBlurredImage (Bitmap originalBitmap, int radius)
 {
     // Create another bitmap that will hold the results of the filter.
     Bitmap blurredBitmap;
     blurredBitmap = Bitmap.createBitmap (originalBitmap);

     // Create the Renderscript instance that will do the work.
     RenderScript rs = RenderScript.create (this);

     // Allocate memory for Renderscript to work with
     Allocation input = Allocation.createFromBitmap (rs, originalBitmap, Allocation.MipmapControl.MIPMAP_FULL, Allocation.USAGE_SCRIPT);
     Allocation output = Allocation.createTyped (rs, input.getType());

     // Load up an instance of the specific script that we want to use.
     ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create (rs, Element.U8_4 (rs));
     script.setInput (input);

     // Set the blur radius
     script.setRadius (radius);

     // Start the ScriptIntrinisicBlur
     script.forEach (output);

     // Copy the output to the blurred bitmap
     output.copyTo (blurredBitmap);

     return blurredBitmap;
 }
Based on Xamarins tutorial.

Sonntag, 6. April 2014

How to remove Beats Audio drivers from your Android Smartphone

Today I want to tell you how to remove all files placed by Beats Audio Installer (com.motioncoding.beats) from your device, in case it corrupts your audio or you simply don't like it.

First of: BAI is given root access and places files to your system directory. After a successful installation these drivers work entirely standalone. The app is only required for the notification. That means: Removing the app and or deleting its cache/data will not remove the drivers. 


So how do you do it?


There are several ways, nevertheless I'd recommend to go with step 3.

  1. Have a backup of your /system partition? Great! Just reflash and and you are done.
  2. Don't have a backup (even though the app told you to do one for at least 3 times ...)? Inside the app is an uninstaller (depending on the app version there might be no one or an outdated one). It might already remove everything but unfortunately this uninstaller does not always work.
  3. Uninstaller not working? Reflash your ROM. Google for your stock ROM or install a Custom ROM. For some devices there are no ROMs online, those could try step 4.
  4. Removing all files manually. That one is a bit complex and you should really be careful what you are removing. Not all files listed might exist!
    Manual & list of files can be found here.


Freitag, 4. April 2014

Android System / Platform signed privileges for actions like Instrumentation

Attention: Using a high-level signature will not work in every ROM, so it only should be considered if there is absolutely no other way of doing this. Also it shall only be used for dedicated devices. I don't recommend putting it public on Google Play. However it should not violate Googles Developer TOS!

Sometimes you need to dig deeper into Android. Especially if you are an OEM or if you make a custom ROM in which you want to add additional features. 
Personally, I used system-signatures to send Key Syncs to foreign Activities i.e. Activities not developed / signed by me. I used that in the moui control remote app. If you are trying this without valid signatures you will end up in SecurityExceptions. 

 So how do you get rid of them?


  1. Obtain Platform Key (pk8 and x509)
  2. Modify AndroidManifest.xml
  3. Export unsigned
  4. Sign with signtools and platformkey
  5. Put to /system/app
Unfortunately Step #1 is the most problematic one, since typically the platform key is not distributed. However most ROMs use the default Google key which is inside the linked zip file. ROM developers who build Android from scratch will have their key inside one of the build directories.

2. Edit AndroidManifest.xml

<manifest 
xmlns:android="http://schemas.android.com/apk/res/android"

android:shareduserid="android.uid.system"

android:versioncode="1" 
android:versionname="Analog Adam" 
package="com.company.app"> ...

3. Should be clear ;-) 
Unsigned Export

4. Signing with Sign+ (Scroll below)

Just select the right keys (both platform) and drag 'n drop the apk, press sign and everything should be fine. A new apk will be created with the suffix _signed. 

Sign+


5. Put to /system/app

Put it there and check logcat for possible errors. Restarting your device should make the app visible.


Link to the Tool and keys: Click.



Steganography: How to store data in Images

Yesterday I came across an interesting question on stackexchange. The idea was to store data in an avatar image, so you could easily send the avatar, which would display you and store your game data. 


How can we achieve this?

There are many ways, but I would like to introduce a fairly easy to implement solution. We use the PNG image datatype, where every pixel contains of 4 values: alpha red green blue.


ARGB from least significant order bit on


So for our method we will use the alpha channel and will take the loss of a possible transparency.

Implementation details


  • The stored data is limited by the number of pixels we have. We will use 1 pixel for one number, so we have space for width(image) * height(image) number of characters.
  • The alpha value of each pixel that is not used will be set to 255 (non-transparent)
  • We limit our data input to lowercase letters, numbers and blanks. However you might easily adapt the algorithm for other inputs.
  • We will subtract a number between 0 .. 37 from the alpha channel
  • The encoding is done like that:
    A blank is represented by 0
    A number is represented by it's successor, such as 0 will be 1, .. , 5 will be 6, ..., 9 will be 10
    A letter is represented by 11 .. 37, so 'a' will be 11, ... , 'z' will be 37.
 I wrote the code for Java SE, since Android implementation would be even easier here. 


KEEP IN MIND: modifying the image, by applying filters or cropping, scaling ... might destroy or corrupt data!

Example

Let's say we want to store the given gamedata in the users avatar.
User:    bluewhile
Score:  99452
Date:    2014-04-01 12:04:33


We wrap it up in one string: bluewhile 999452 20140401 120433

When decoding, we can use String.split(" "); to get 4 values: name, score, date, time.


Original
Encoded

First let's look at turning a given String into a int array:



public int[] makeCode(String s) {
  if (s == null || !s.matches("[A-Za-z0-9 ]+")) // alphanumeric and blank
   return null;
  String work = s.toLowerCase().trim() + " ";
  int[] array = new int[work.length()];

  for (int i = 0; i < work.length(); i++) {
   array[i] = work.charAt(i);
   if (array[i] == 32) { // blank -> 0
    array[i] = 0;
   } else if (array[i] <= 57) { // number -> 1..9
    array[i] -= 47;
   } else { // letter -> 10..36
    array[i] -= 86;
   }
  }
  return array;
 }

It should be straight forward what happens here. Initially we check if all chars are valid, then the array is populated. An additional blank is added to the String, but don't worry it will be deleted later by trim().


Next up: Encoding



public void encodeAndSave(String s, File input, File output) {
  System.out.println("Encoding: "+s);
  try {
   BufferedImage cache = ImageIO.read(input);
   BufferedImage b = new BufferedImage(cache.getWidth(),
     cache.getHeight(), BufferedImage.TYPE_INT_ARGB);
   b.getGraphics().drawImage(cache, 0, 0, null);

   int i = 0;
   int[] data = makeCode(s);

   System.out.println("Code: " + Arrays.toString(data));

   for (int y = 0; y < b.getHeight(); y++)
    for (int x = 0; x < b.getWidth(); x++) {
     Color c = new Color(b.getRGB(x, y));
     int alpha = (255 - 37) + (i < data.length ? data[i] : 37);
     int col = (alpha << 24) | (c.getRed() << 16) | (c.getGreen() << 8) | c.getBlue();
     b.setRGB(x, y, col);
     i++;
    }
   ImageIO.write(b, "png", output);
  } catch (Exception e) {
   e.printStackTrace();
  }
 }


At the beginning we copy the image over to make sure it has an alpha channel, then we iterate through all pixels and write our encoded array from left to right, from top to bottom. Pixels that are off our data are set to 255. Also keep in mind that we can't use JPG because it has no alpha channel.


Decoding

public String decode(File input) {
  try {
   BufferedImage b = ImageIO.read(input);
   String s = "";
   for (int y = 0; y < b.getHeight(); y++) {
    for (int x = 0; x < b.getWidth(); x++) {
     int alpha = (b.getRGB(x, y) >>> 24);
     if (alpha != 255 && alpha != 0) {
      int n = (37 - (255 - alpha));
      if (n == 0) {
       s += " ";
      } else if (n <= 10) {
       s += n - 1;
      } else {
       s += ((char) (n + 86));
      }
     }
    }
   }
   return s.trim();
  } catch (Exception e) {
   e.printStackTrace();
  }
  return null;
 }

Decoding is like Encoding, just reversed ;-) 

Calling methods should look like:

encodeAndSave("bluewhile 999452 20140401120433", new File(
    "/Users/paul/Downloads/avatar.png"), new File(
    "/Users/paul/Downloads/avatar2.png"));

System.out.println(decode(new File(
    "/Users/paul/Downloads/avatar2.png")));

Donnerstag, 3. April 2014

Finally a blogger !

So who am I and why should you read my comments?
Starting with 15 years I was taught Java at my high school and developed more and more apps.
With 18 I founded a company and began distributing apps at Google Play. Believing in my projects and getting pushed by friends and family I achieved one milestone after another. Let's have abrief look at them:

  • 2012: Beats Audio Installer (Android) claims 1,000,000 unique downloads
  • Q4 2012: Stepping into hardware business by offering one of Germanys first Android TV sticks "nova" with own UI "moui"

This is a kinda big decision for someone who has just left high-school and earned some dollars but I thought it was worth it.

  • 2013: Multiple wins with "nova"
  • Q2 2013: moui - entirely written by me - is updated with Speech Recognition, autodiscovery, streaming features and so on.

By now I had to stop offering Android sticks, it is just too hard to survive in this business being a small company. I had a few other reasons as well, which I might blog about some day.

  • 2014: Beats is unstoppable: Though it has been kicked out of Play for more than a year now, I get still hundreds of downloads daily (can't tell you the real number, since my database implementation was a bit too sloppy and ended up crashing my providers server). By now Beats has over 5,000,000 downloads.