Pages

Showing posts with label Informative. Show all posts
Showing posts with label Informative. Show all posts

Tuesday, April 7, 2015

Check if current user is owner

One would think that this is a simple task in Android, especially since one would expect Google to have added some kind of tool for it, like something to return the current user id. Well they have, but they also decided to hide it. Android actually has a very pore collection of tools when it comes to working with multi-users. Like many things in the framework, Google did not think that apps had any reason to access to any information regarding the users. Android's sources might be fully open, but the framework is more closed than boot loaders on HTC devices.

The user id is normally not a very important information since it is nothing more than a number from 10 and up, except for the owner which have 00. The only thing that this number can tell you, is which user was created first. But checking for the 00 id to identify the owner can be very helpful. You may be working on an app that should have certain restrictions when not used by the device owner. Maybe your app should not be used by other users at all. In any case identifying the owner is useful enough that Google should have added something like isOwner() to the UserManager service.

Searching the web, it seams like people are using a lot of reflection to access some of the hidden classes in order to identify the device owner. However reflection is not really needed, and it should be avoided if possible, simply because hidden classes are not official and might change over time. If this happens, apps need to be updated or they will be broken on future versions of Android.

Even though Android did not directly provide any access to the current user id, they did indirectly do this in one way, namely the app data folder. In Android 4.1 and below, all app data was placed in /data/data, but in newer versions they are placed in /data/user/[userid] and all apps have access to their own data folder. So to get the current user id from within an app, you only need to get the name of the parent folder to your apps data location. This is very simple.

MainActivity.java:
public class Utils {
 public static boolean isOwner(Context context) {
  /* 
   * Get the parent location. 
   * This can either be /data/user/[userid] or /data/data depending on Android version.
   */
  File file = new File(context.getApplicationInfo().dataDir).getParentFile();
  
  /*
   * Get the name of the folder in the parent location. 
   * This can either be [userid] or data
   */
  String user = file.getName();
  
  try {
   /*
    * Returns TRUE if this user has the id 0 (device owner)
    */
   return Integer.valueOf(user) == 0;
   
  } catch (NumberFormatException e) {
   /*
    * The user variable contained "data". 
    * This is not an multi-user environment, which means that we only have the device owner available.
    */
   return true;
  }
 }
}

The above code is even backward compatible with Android version without multi-user support, without any need to check the current API level. And we did not use any reflection or unsupported classes/methods.

Friday, March 20, 2015

JNI / Android NDK

If you visit the Android developer page and read about Android's NDK, it will seam as if Google is trying to scare people from using it and just stick with Java. In most cases this will properly be the best idea. Java is a great language and does a good job for most tasks. However JNI is not as dangerous as Google is trying to make it. Most of Android is build on JNI and IPC. Information is being parsed in and out of JVM and between processes constantly, so why should applications not take advantage of this as well?

One thing to remember about JNI is that it creates a bit of overload to parse in and out of JVM. But depending on the task, this is not necessarily enough downside to keep away from it. The best way to figure out whether or not to use C/C++ or Java, is to test your task in both and then compare the result.

One good example of a task better suited for JNI could be some extensive file operations. For this example we will collect the content of the stat file for all currently running processes on a device. On my device running Android 5, we are talking about rounded 300 files. We add this to a loop which will run 100 times which in turn will create 3000 file read operations.

The first thing we need, is a basic activity to run our examples in.

MainActivity.java:
public class MainActivity extends Activity {
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  
  setContentView(R.layout.activity_main);
  
  StringBuilder builder = new StringBuilder();
  
  for (int i=0; i < 2; i++) {
   double start = System.nanoTime();
   int files = 0;
   
   for (int x=0; x < 100; x++) {
    String[] list = null;
    
    switch (i) {
     case 0: list = JavaCollector.collect(); break;
     case 1: list = NativeCollector.collect();
    }
    
    files += list.length;
   }
   
   double end = System.nanoTime();
   
   builder.append(i == 0 ? "JavaCollector" : "NativeCollector\n");
   builder.append("Files = " + files + "\n");
   builder.append("Time = " + ((end - start) * Math.pow(10, -9)) + " seconds\n");
   builder.append("\n");
  }
  
  TextView view = (TextView) findViewById(R.id.textview);
  view.setText(builder.toString());
 }
}

We also need a Java method to do the collection work. We will separate the native method and the Java method into two files in this example. It makes it easier to keep an overview.

JavaCollector.java:
public class JavaCollector {
 
 /*
  * Re-defined regexp to match directories in /proc with process id's
  */
 protected static final Pattern REFEXP_PID = Pattern.compile("^[0-9]+$");
 
 /*
  * The method that collects all the file data
  */
 public static String[] collect() {
  /*
   * Get a listing from the /proc directory
   */
  String[] procListing = new File("/proc").list();
  
  /*
   * Define our input stream
   */
  BufferedReader in = null;
  
  /*
   * Create a temp container for the file output
   */
  ArrayList<String> lines = new ArrayList<String>();
  
  /*
   * Handle each entity in /proc
   */
  for (String procEntity : procListing) {
   /*
    * We only want the pid directories
    */
   if (REFEXP_PID.matcher(procEntity).matches()) {
    try {
     /*
      * Open the sub directory stat file
      */
     in = new BufferedReader(new FileReader("/proc/" + procEntity + "/stat"));
     
     /*
      * Get the content of the stat file
      */
     lines.add(in.readLine());
     
    } catch (IOException e) {} finally {
     if (in != null) {
      try {
       /*
        * Close the file
        */
       in.close();
       in = null;
       
      } catch (IOException e) {}
     }
    }
   }
  }
  
  /*
   * Create and return a string array
   */
  return lines.toArray( new String[ lines.size() ] );
 }
}

And we cannot compare the above Java class to JNI without a native example as well.

NativeCollector.java:
public class NativeCollector {
 
 /*
  * Load our collector library
  */
 static {
  System.loadLibrary("collector");
 }
 
 /*
  * This is really a call to Java_com_example_NativeCollector_collect() in collector.cpp
  */
 public static native String[] collect();
}


collector.cpp:
JNIEXPORT jobjectArray JNICALL Java_com_example_NativeCollector_collect(JNIEnv *env, jobject thisObj) {
 /*
  * Open /proc
  */
 DIR* procDirectory = opendir("/proc");

 if (procDirectory != NULL) {
  /*
   * Create a temp container with minimum 100 indexes pre-allocated
   */
  std::vector<std::string> lines(100);

  /*
   * Create an input stream
   */
  std::ifstream in;

  /*
   * Create a variable for the proc entities
   */
  struct dirent* procEntity;

  /*
   * Handle each entity in /proc
   */
  while ((procEntity = readdir(procDirectory)) != NULL) {
   /*
    * We only want the pid directories
    */
   if (std::regex_match (procEntity->d_name, std::regex("^[0-9]+$") )) {
    /*
     * Open the sub directory stat file
     */
    std::string path = std::string("/proc/") + procEntity->d_name + "/stat";
    in.open( path.c_str() );

    if (in && in.good()) {
     /*
      * Get the content of the stat file
      */
     std::string line;
     std::getline(in, line);

     lines.push_back(line);
    }

    /*
     * Close the file
     */
    if (in) {
     in.close();
    }
   }
  }

  /*
   * Create Java return data
   */
  if (lines.size() > 0) {
   /*
    * Create a Java array
    */
   jobjectArray ret = env->NewObjectArray(lines.size(), env->FindClass("java/lang/String"), NULL);

   for (int i=0; i < lines.size(); i++) {
    /*
     * Place the line in a Java String
     */
    jstring stringObject = env->NewStringUTF( lines[i].c_str() );

    /*
     * Add the Java String to the Java Array
     */
    env->SetObjectArrayElement(ret, i, stringObject);

    /*
     * Release the Java String reference.
     *
     * Note: This is important. We can only have a limited ammount of Java objects
     * at a time and they are not auto released until we return to the JVM. And since we
     * are looping an unknown, but large, number of files, we could end up with a memory overflow.
     */
    env->DeleteLocalRef(stringObject);
   }

   /*
    * Return the array to JVM
    */
   return ret;
  }
 }

 /*
  * Return an empty array
  */
 return env->NewObjectArray(0, env->FindClass("java/lang/String"), NULL);;
}

If we compile and run this application, we will get the following result:
  • JavaCollector$collect: 21.2 seconds
  • NativeCollector$collect: 2.7 seconds

    This is not just slightly faster than Java, this is 87% faster. 
This is only a simple example. If it should be used in a real application, then depending on the amount of files and amount of data, it might be a good idea to make some sort of iteration mechanism to avoid memory overflow. But as the result shows, it is sometimes a good idea to check whether or not a JNI solution might be better. Java is not always the correct solution. 

So get started with:

Friday, October 31, 2014

How does Hacklang work

I must admit that I am not a fan of Facebook. Unlike 90% of the world, I do not, and have no intention of, ever owning an account. The list of reasons are long, and some of the things on that list have more to do with the people using it, rather than the service itself. Something just happens to normal people when entering the website, it's like watching one of the many talk-shows and reality programs on TV.

But although this article is about Facebook, it is not about the service that they are most famous for. This article is about a small extension to the PHP programming language, created by Facebook, called Hack, and the related Virtual Machine called HHVM. If you are a PHP programmer and either do not know about this or if you have not yet tried it, then I'll suggest you have a look at it. This extension provides features that PHP should have had ages ago. This article will not get into what Hack and HHVM is, I'll suggest that you visit the website http://hhvm.com if you are not already familiar with it.

What this article will focus on, is how HHVM/Hack acts. PHP is normally a dynamic typed language, but Hack introduces static typed features, and at the same time keeps compatibility with regular PHP. It's like mixing oil and water, and actually making them mix. The way it works, is that the VM mostly upholds the rules of PHP while the type checker upholds the rules of Hack. In other words, you can without any issues execute code that is not acceptable by the rules of static typing, but you will get errors when parsing it through the optional type checker. The errors from the type checker can also be removed by changing how strict it should be, which can be set pr. file. This allows you to mix dynamic typing and static typing, and still be able to use the type checker on the strict files.

class MyClass {
    public function test1(): void {
        $this->internal( Map{"key"=>1} );
    }

    public function test2(): void {
        $this->internal( Vector{true} );
    }

    private function internal(Map<string, bool> $param): void {
        // Code ...
    }
}

If we execute test1() from a browser, HHVM would not generate any errors. It would simply allow it. If we execute test2(), HHVM would break the request with an error. The reason for this is that HHVM follows PHP rules, which does not provide any generics. PHP however does allow one to define parameter type, which is the only thing that is being monitored for. The type checker on the other hand, would print a lot of errors here, first complaining about the wrong generics types in test1() and then complain about the wrong data type in test2().

class MyClass {
    public function test(): bool {
        return 1;
    }
}

The same applies for the return type. The above example will not conflict with HHVM. The only way to catch this problem, is by the type checker.

So the way that Hack is able to work along side PHP, is that the VM does not enforce any Hack rules. If you want to check your code for type safety, you will have to check it using the type checker. For the most part this will suffice. But the type checker is still a work in progress, and it does contain a few bugs.

class MyClass {
    public function test1(): void {
        $this->internal(Map{"key"=>new Map(array(
            "key"=>1
        ))});
    }

    public function test2(): void {
        $this->internal(Map{"key"=>Map{
            "key"=>1
        }});
    }

    private function internal(Map<string, Map<string, string>> $param): void {
        // Code ...
    }
}

Both test1() and test2() will parse the exact same value to internal(). However the type checker will only report an error on test2(). The wrong generics type in test1() will not be caught.

Thursday, October 30, 2014

PHP Traits extends OOP posibilities

OOP if a wonderful concept in programming. People have different opinions about it, but I for one love it. First of all you have all of your work divided into groups (Classes), and adding other concepts like namespaces or packages, your classes becomes sub-groups in even larger groups. It makes it easy to keep track of your work in large code bases, and it reduces the chance of things colliding, especially in environments where 3'rd party code can be added dynamically (E.g. CMS modules for an example). It also allows classes to share code with one another. If you want to create a class that adds functionally to an existing class, you can extend from that class, and adopt the already existing code into your new class. Then all you have to do, is change and/or add whatever you had in mind, without having to copy/paste the content of one class into another. At the same time, adding to and/or fixing something the first class, will automatically be appended to the second one.

But OOP does have it's limitations. For one, you can only extend from one class. So if you want to adopt code from two classes, you are out of luck. You can of course implement as many interfaces as you'd like, but interfaces only defines the structure of a class, and does not provide any pre-done work. This has now changed in PHP with the introduction of Traits since version 5.4. A Trait is something like an abstract class, the difference being that you do not extend from it, instead you sort of includes it's content within your class. It can somewhat be compared to extending objects in JavaScript via the prototype property, and you can include as many Traits as you'd like.

trait Snipped1 {
    public static function printMessage() {
        echo "Prints a text!";
    }
}

trait Snipped2 {}

class Example {
    use Snipped1, Snipped2;
}

Example::printMessage();

The class above will contain all the content from both Traits. Also unlike when extending two classes, all static content in Traits, like static properties, will have their own instance pr. class that uses them. So changing the value of an static Trait property from one class, will not change the value in other class, using the same Trait.

One thing that Traits does not do, is parse their type to classes using them. Content that you include from a Trait, will be treated as if it belongs to the class itself. This means that you can't use something like instanceof to check whether or not a class uses a Trait. There are ways to check, but these ways are slow and not very handy. And there is nothing wrong with this, it is meant to work this way, because classes does not implement or inherit from Traits, they simply copy/paste their content.

Personally I did not find Traits very useful at the beginning, mostly because if they are used wrong, they can create a lot of chaos in your code. Much more than chaotic inheritance. But after playing around with them, I found that they can be handy if you include interfaces. By using an interface to define a class structure and then add a Trait with some partial code, you will have what can be considered an abstract class divided into two parts. One containing the partial code and one containing the details about how a class should look.

interface ISnipped {
    public function printMessage();
    public function secondMethod();
}

trait Snipped {
    public function printMessage() {
        echo "Prints a text!";
    }
}

class Example implements ISnipped {
    use Snipped;

    public function secondMethod() {
        // Do something
    }
}

$example = new Example();

if ($example instanceof ISnipped) {
    $example->printMessage();
}

The above example can be compared to the example below
public abstract class Snipped {
    public function printMessage() {
        echo "Prints a text!";
    }

    public abstract function secondMethod();
}

class Example extends Snipped {
    public function secondMethod() {
        // Do something
    }
}

$example = new Example();

if ($example instanceof Snipped) {
    $example->printMessage();
}

Both examples provide much the same structure, but using Traits we can adopt from more than one. All we have to do, is implement more interfaces and add more traits.

Wednesday, February 12, 2014

Android Resources

This is not a guide or an article. It is mainly an observation that I can no longer ignorer. The issue is that most Android developers have a habit of working out custom solutions using the few tools that they know, rather than looking to see if Android has a pee-built tool for that specific task.

In this case, the issue is regarding Android's Resources class. Let's say that we want to create a dynamic string using placeholders. If you try to google this, you will mostly find the same solution on each page that you visit. I have written this solution below.

<resources>
    <string name="dynamic_string">Let\'s insert the number %1$d</string>
</resources>

Integer numberToInsert = 1;
String dynamicString = String.format( getResources().getString(R.string.welcome_messages), numberToInsert );

The problem here is that there is no point in including String.format into this, because Resources.getString is already able to do this for you.

Integer numberToInsert = 1;
String dynamicString = getResources().getString(R.string.welcome_messages, numberToInsert );

If you took a look at the documentation for this method, you would see that it does not only take [String] as an argument. It actually takes [String, Object...], where each Object parsed will be used to replace the placeholders of the string.

Please have a look at the Resources Documentation. This class contains a lot of useful tools for when working with the resources in Android. Many of which is not seen being used very much, if even at all.