Monday, July 13, 2015

Touchscreen Laptops: Handy tool for mobile developers.

You know all those touchscreen laptops that have been showing up in the past few years? I was one of the many people that thought "that is absolutely pointless, how would that make anything easier on a laptop?". Well if you're a mobile developer and frequently use the emulation tools such as the AVD for Android, it really is a godsend.

I purchased my Dell Inspiron 5000 laptop with a touch screen laptop thinking I'd never use that touch screen. I was wrong. So wrong. After about two weeks of using it, I found myself constantly touching my Acer Chromebook's screen while I'm browsing webpages. But it really hit me when I started using AVD/emulators to test apps out that I was finally able to develop apps and use them on my laptop like they're physical touch devices. Nothing is more annoying then using a mouse to try to operate something that is controlled by touch.

Those touchscreen laptops are pieces of gems for mobile devs.

Wednesday, May 06, 2015

Android UI: Supporting multiple screen dimensions

My PART store app has evolved from a crappy jam-every-bits-of-code-into-one-java-file-and-ignore-OOP-project to a full-fledged Material-themed app taking into consideration some Android Design Patterns and all the Object Oriented goodness. However, working with fragments and separating all the bits into paginated layouts such as the Drawer Navigation as I've done, I quickly come to realize that while it works great for small phones, the UI looks like a waste of space on larger tablets. This is what iOS users have been complaining about about two years ago when they said that Android tablet apps are just phone apps blown up. Well, Android Studio makes the adjustment for this SUPER easy.

Now you can do this manually or you can just let AndroidStudio dialog interface work out the kins for you.

If you were to right click res > New > Android Resource Directory.. you'd get the following dialog:

So I can either just name the layout resource directory as layout-w600dp or.. if I just select "Screen Width" and enter 600 as a value, it will automatically create the new layout directory as layout-w600dp. But I'm not done yet. What I'll have to do is create anther layout that gets used when a width of 600 dp has been exceeded. That's easy, just copy and paste the original activity's layout. However, instead of using a DrawerLayout, I want to fix the Navigation ListView to the left of the screen. So I'd change the DrawerLayout view to a LinearLayout view, set the orientation to horizontal and put the drawerlist before the mainContent view. For example, here is mine for a layout with a slide-out DrawerLayout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <!-- Toolbar -->
    <android.support.v7.widget.Toolbar
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/tool_bar"
        android:background="@color/ColorPrimary"
        app:theme="@style/ThemeOverlay.AppCompat.Dark"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />

    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">

        <!-- DropShadow-->
        <View
            android:layout_width="fill_parent"
            android:layout_height="3dip"
            android:background="@drawable/drop_shadow" >
        </View>


        <android.support.v4.widget.DrawerLayout
            android:id="@+id/drawer_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <!-- Main Content -->
            <RelativeLayout
                android:id="@+id/mainContent"
                android:layout_width="match_parent"
                android:layout_height="match_parent">

            </RelativeLayout>


            <!-- Side navigation drawer UI -->
            <LinearLayout
                android:id="@+id/drawer_pane"
                android:layout_width="@dimen/drawer_width"
                android:layout_height="match_parent"
                android:layout_gravity="left|start">

                <ListView
                    android:id="@+id/navList"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:background="#ffeeeeee" />
            </LinearLayout>

        </android.support.v4.widget.DrawerLayout>

    </RelativeLayout>
</LinearLayout>

And here it is after I've changed the DrawerLayout to a LinearLayout (keeping the same id "@+id/drawer_layout") and readjusted the position

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <!-- Toolbar -->
    <android.support.v7.widget.Toolbar
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/tool_bar"
        android:background="@color/ColorPrimary"
        app:theme="@style/ThemeOverlay.AppCompat.Dark"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />

    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
        
        <LinearLayout
            android:orientation="horizontal"
            android:id="@+id/drawer_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <!-- Side navigation drawer UI -->
            <RelativeLayout
                android:id="@+id/drawer_pane"
                android:layout_width="@dimen/drawer_width"
                android:layout_height="match_parent"
                android:layout_gravity="left|start">

                <ListView
                    android:id="@+id/navList"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:background="#ffeeeeee" />

                <View
                    android:layout_width="fill_parent"
                    android:layout_height="3dip"
                    android:background="@drawable/drop_shadow" >
                </View>
            </RelativeLayout>

            <!-- Main Content -->
            <RelativeLayout
                android:id="@+id/mainContent"
                android:layout_width="match_parent"
                android:layout_height="match_parent">

            </RelativeLayout>
        </LinearLayout>
    </RelativeLayout>
</LinearLayout>

Lastly, how does the main activity handle this? Well, it can't. So the way to do this is to just simply check to see what kind of View the resource with id R.id.drawer_layout is. And if it's a drawerlayout, then you would proceed to create a hamburger menu icon, handle sliding in and out, etc. Otherwise if it's not a drawer_layout, then set it as a linear layout, in which case is probably not required.

private boolean slideOutDrawerMode = false;

//...

@Override
protected void onCreate(Bundle savedInstanceState) {

   //...
   View layout = findViewById(R.id.drawer_layout);

   slideOutDrawerMode = layout instanceof DrawerLayout;


   //..
   if (slideOutDrawerMode) {
      // Show hamburger menu icon
      getSupportActionBar().setDisplayHomeAsUpEnabled(true);

      // Do other things
   }
}

Wednesday, April 22, 2015

Android UI: CardView

I may be late to the game, but as I'm delving into the depths of Android UI design, the card views are a fantastic compatibility library to make apps look more professional. And it's simple, too.

To use the Card UI, simply add the following into the dependencies of the build.gradle file of the app.

    compile 'com.android.support:cardview-v7:21.0.+'
    compile 'com.android.support:recyclerview-v7:21.0.+'

Then to use this in the layout xml:

<android.support.v7.widget.CardView
      xmlns:card_view="http://schemas.android.com/apk/res-auto"
      xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      card_view:cardCornerRadius="2dp"
      android:layout_margin="5dp">
...
</android.support.v7.widget.CardView>

Monday, April 20, 2015

My first Github Repository - USBSerialDevice

I've finally created my own github repo that hosts a Android Java class called USBSerialDevice for Android. It wraps around mik3y's usb-serial-for-android library but has the added bonus of including the USB permission and enumeration code. Having to constantly make Android apps that collect data from serial devices, it'd make much more sense to create this so that I don't have to copy-paste my code that does the USB enumeration and permission request (it's a lot of lines of code to copy every single time). In this repository, I've included an example subclass called ArduinoSensor as I play with Android-to-Arduino connections a lot.

Notes on usage: As stated on the README.md, protected method processData(byte buffer[], int numBytesRead) needs to be overridden if you want to actually do anything with the data, otherwise it just writes the output to a file.

Example usage:

USBSerialDevice mySerialDev = new USBSerialDevice(this, 1027, 19200, 10){
            @Override
            protected void processData(byte[] buffer, int numBytesRead) {
                // Print out the buffer to log or something
            }
        };
mySerialDev.setDirectory("/sdcard/mydirectory/");
mySerialDev.setFileNameUsingTimestamp("ARDUINO");
mySerialDev.setRecord(true);
mySerialDev.start();

No fuss, no muss. Much easier than having to copy the 100+ lines of code for USB broadcast receiver, intent filters, usb device listing, etc

Wednesday, April 15, 2015

Algorithms/Java : Removing Multiple Spaces

As I'm looking at different job potings, I've come to realize that most software companies do not want people with skills in C but always Java or C#. So it's time I get into the deep levels of Java and not just the Java touched on the Android programming side. This would also be great practice for any potential upcoming interviews.

So starting off, here's a simple one I need at the moment. I have a string coming in from a USB serial port in the format:

DATE TIME   MEASUREMENT1    MEASUREMENT2      MEASUREMENT3   SO

I need to split the string and parse the measurements, but the multiple and variable number of spaces is really throwing things off. So my goal is to output only one space for each segment of multiple spaces. Here is my code in O(n) linear time:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public static String removeMultipleSpaces(String str){
 StringBuffer sb = new StringBuffer();
 
 int i = 0;
 boolean firstSpace = false;
 while (i < str.length()) {
  if (str.charAt(i) != ' ') {
   // if not a space, then copy the character and mark flag as true
   sb.append(str.charAt(i));
   firstSpace = true;
  } else {
   // if this is a space and this is the first instance of the space
   // since the last group, then copy the character as well, but mark
   // the flag to false
   if (firstSpace) {
    sb.append(str.charAt(i));
    firstSpace = false;
   }
  }
  i++;
 }
 
 return sb.toString();
}

Basically as the string is being traversed, a boolean flag determines whether the space I examine is the first space or subsequent spaces. Whenever I detect a character, the flag is set to true again, meaning the first space we see from that point will be kept. And the output I get from this is then:

DATE TIME MEASUREMENT1 MEASUREMENT2 MEASUREMENT3 SO