Tuesday, December 15, 2015

Apps on the big screen part III: Debugging on an Android TV

How cool would it be if you can debug your TV app on a real device! For tvOS all it takes is a provision profile and an USB-C to USB-A cable to connect the Apple TV 4 device with your MacBook. How to enable the debugging option on a real Android TV is less obvious. It starts with selecting the right Android TV device.

Android 5.0 set-top boxes are hardly available in my part of the world and getting one from Ali Express is not an option, because the delivery times are too long and I do not have that much patience. So I decided to get myself a TV running on Android.


1. Pick the right Android TV

First of all, if you have plans to develop apps for Android TV and want to be able to debug them then it is important to decide which brand and model you pick. Previously I have made the mistake to chose a Philips TV, the 32PFK6500 to be exactly. It was the only 32 inch model that was available, which made it the perfect development TV, or so I thought.

It turned out to be not such a good idea. There is no way to debug and test your apps on this or other recent Philips Android TVs, basically because of Philips security policy. Yes, you can unlock the developers menu, but you will never be allowed to connect the ADB. This makes debugging impossible.

Too bad! It is a nice TV and I really enjoyed the Ambilight experience. This TV is probably great if you just want to watch TV and use some apps, but it is not really suitable for app development, although there seems to be a workaround to get your app at least tested through the Google Play alpha- and beta distribution mechanism.

Tip of the day: If you want to return your smart TV to the shop then do not forget to restore it to the factory settings. You may have entered your google account and others details that you do want to erase first. Unlike me, do this before you put everything back into the box ;)

So I went back to the shop and exchanged the Philips TV for a Sony Bravia TV, the 43W80xC one. With this television I have made a new attempt; this time with success!



2. Unlock the developers menu

Just as is the case with Android running on a smart phone, you have to unlock the developers menu first. To do so click the home button on the remote control, go to Settings, choose About and scroll down until you see the Build option. Click seven times on it to unlock the developers menu.


Before you continue: Yes. Here comes the disclaimer. I guess there is a good reason for Philips to prevent app debugging and to disallow apps from unknown sources. Use this tutorial at your own risk. My TV did not explode or anything like that, but I am not too sure about yours ;)



3. Enable ADB debugging

The Developers menu will appear under System Preferences. Choose this option and next choose Debugging. Here you can change the setting for ADB debugging to On.



4. Debugging over LAN

I have not found a way for USB debugging yet. It just does not seem to work, although there are multiple USB (2.0) ports available on the device. So lets do this slightly different. It seems that out of the box the Sony Android TV allows debugging by LAN connection directly. Get its IP address and get connected!

Note : Your MacBook (or PC) and the TV have to be on the same network to make the magic happen.

Click on the Home button on the remote control and under the Settings section choose Network settings. Next click on Wi-Fi or Wired LAN, depending on how your TV is connected. Under IP address you will see the TV's IP address.

Open a new terminal window and connect ADB with the IP address (using the default port 5555) you have just found.

adb connect 192.168.2.18:5555

If everything went well the result will be something like: connected to 192.168.2.18:5555. At this point the Philips TV earlier returned the message Connection refused.


5. Create an Android TV project in Android Studio

In Android Studio create a new project and choose TV as a platform. This will create a ready made media centre app for you, which you can modify if you want to.

6. Launch your app

If the ADB connect command did succeed in the previous step and you run your app in Android Studio the TV will be shown under Connected devices. Select it and click on the OK button.



The first time the Allow USB debugging dialog will popup. Choose Always allow and click on the OK button to continue.

Another dialog that may appear is the one that says Allow Google to regularly check device activity for security problems.... So far I have chosen to decline this but I guess it will not do too much harm if you choose Accept




Conclusion

As you can see it is not that difficult to debug your Android TV app once you have the right equipment and know how to configure things. Having everything up and running the next challenge is to create a real cool TV app.


Further reading

Monday, December 7, 2015

App of the rings: Neyya, Android SDK and BLE

My great friend Wim Wepster gave me this interesting Neyya ring. Fortunately it did not come with a proposal. Instead it was a great opportunity to explore Bluetooth and alternative wearables, such as this ring.

Neyya is a ring that can send gestures such as taps and swipes to a mobile or another device that is supporting BLE. You can use it for presentations or games, although you can just use your mouse, watch or phone for that as well. So I wondered how it works and what could be an interesting use case for it.

Neyya comes with an iOS and Android app but also with an Android SDK. I was having some troubles with it as it was not able to detect my Neyya ring at all. For the time being (as there must be a more elegant solution for it) I have fixed this by modifying the NeyyaBaseService class within the NeyyaAndroidSDK project.



I removed the check to determine whether the Bluetooth device is a Neyya ring or not from the onLeScan method.

 private BluetoothAdapter.LeScanCallback mLeScanCallback =
   new BluetoothAdapter.LeScanCallback() {
     @Override
     public void onLeScan(final BluetoothDevice device, int rssi,
       byte[] scanRecord) {
         String deviceAddress = 
           device.getAddress().substring(0, 13);

         // if (neyyaMacSeries.equals(deviceAddress)) {
              NeyyaDevice neyyaDevice = new NeyyaDevice(
               device.getName(), device.getAddress());
              if (!mNeyyaDevices.contains(neyyaDevice)) {
                   logd("Device found - " + device.getAddress()+ 
                    " Name - " + device.getName());
                   mNeyyaDevices.add(neyyaDevice);
                   broadcastDevices();
              }
         //}
     }
  };
I did the same thing for the isNeyyaDevice method, like this.
public boolean isNeyyaDevice(NeyyaDevice device) {
  String deviceAddress = 
    device.getAddress().substring(0, 13);

  /* if (!neyyaMacSeries.equals(deviceAddress)) {
       logd("Not a neyya device");
       broadcastError(ERROR_NOT_NEYYA);
       mCurrentStatus = STATE_DISCONNECTED;
       broadcastState();
       return false;
     }
   */
    return true;
  }

Okay, I have to be more careful which Bluetooth device I pick from the list of available devices but at least I am able to continue my journey. Let's connect to the device.


Great! but what is it that we are trying to solve here?

The supported gestures are taps, double and triple taps, swipe left, right, up and down. Now, what problem could this ring solve other than the things that come with the Neyya app already, such as capturing a picture, turning the volume of a device up and down and moving to the next or previous song?

One of the problems that the Neyya ring could help me with is something that most people will recognize. Your best ideas come up when you are not able to write them down immediately, for example while taking a shower or driving a car. In such cases it would be great to just rub your ring to create an audio note. That is easy to implement.

To create a prototype I have modified the ConnectActivity class a little. First in the onReceive method of the BroadCastReceiver implementation I do call a new method actOnGesture

 ...
 else if (MyService.BROADCAST_GESTURE.equals(action)) {
   int gesture = intent.getIntExtra(MyService.DATA_GESTURE, 0);
   showData(Gesture.parseGesture(gesture));

   actOnGesture(gesture);
 ...

That method goes like this

    private String actOnGesture(int gesture){
        Gesture.parseGesture(gesture);
        switch (gesture) {
            case Gesture.SWIPE_UP:
                stopRecorder();
                return "SWIPE_UP";
            case Gesture.DOUBLE_TAP:
                startRecorder();
                return "DOUBLE_TAP";
        }
        return "";
    }

To start recording we will create a MediaRecorder instance and create an output file for it in the m4a format. in the stopRecorder method we will stop the recording.

   private static String mFileName = null;
   private MediaRecorder mRecorder = null;

   private void startRecorder() {
        if (mRecorder!=null){
            return;
        } 
        String timeStamp = "/" + System.currentTimeMillis() +
          ".m4a";
        mFileName = Environment.getExternalStorageDirectory().
          getAbsolutePath();
        mFileName += timeStamp;
        mRecorder = new MediaRecorder();
        mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        mRecorder.setOutputFormat(
         MediaRecorder.OutputFormat.MPEG_4);
        mRecorder.setOutputFile(mFileName);
        mRecorder.setAudioEncoder(.
         MediaRecorder.AudioEncoder.AAC);
        mRecorder.setAudioSamplingRate(16000);
        mRecorder.setAudioChannels(1);
        mRecorder.setAudioEncodingBitRate(16);

        try {
          mRecorder.prepare();
        } 
        catch (IOException e) {           
        }
        mRecorder.start();
    }

    private void stopRecorder() {
        if (mRecorder==null){
            return;
        }  
        mRecorder.stop();
        mRecorder.release();
        mRecorder = null;
    }

Do not forget to add the right permissions to the AndroidManifest.xml file before you test the app.

  <uses-permission 
    android:name="android.permission.BLUETOOTH" />
  <uses-permission 
    android:name="android.permission.BLUETOOTH_ADMIN" />
  <uses-permission 
    android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
  <uses-permission 
    android:name="android.permission.RECORD_AUDIO"/>

As soon as the app is running and the ring is connected, double tap on it to start recording and swipe up to stop the recording. You can use an app, such as the Astro app, to locate and play the audio file that you have recorded.


Conclusion

Later I will release the code of this POC on GitHub. I need to work out the concept a little bit more. Anyway, I am not fully convinced yet whether the Neyya ring is a useful wearable device or not, but by examing the code I have learned something about Android and Bluetooth and I do have a memo recorder that I can use just anywhere now.

Do not forget to take your phone with you as well, wherever you go. Wait for my first shower-voice-memos to arrive ;) Of course you can use the ring plus app as a spy tool if you want or find other purposes for it. My precious...

Further reading