Wednesday, 21 August 2013

Samples and API: getting started

Several people have already received their samples. I've got more requests about samples, so I think about going for a short pick-and-place assembly run. Hand-soldering is OK for 1-2 prototypes, otherwise it just takes way too much time. Currently I'm waiting to get quotes.

Here's a simple "getting started" guide:

Device Manager (InputStickUtility):

To use InputStick you have to install DeviceManager app on your Android phone.

Installation:
  • Make sure that "allow installation of non-market applications" is checked in your devices settings.
  • Copy DeviceManager.apk to your device and install it.

Pairing with InputStick:
  • Plug InputStick into any USB port in order to power it up.
  • Run DeviceManager, if Bluetooth is disabled it will ask you to enable it. 
  • Manage devices -> Add device -> Discover device -> Select device form the list -> Add device.
  • By default it will be named "Dev-00" and set as "Home", however application will ask you if you want to edit this.
Settings:

Dialog settings:
  • Always ask: each time you will be asked to manually select InputStick device that you want to connect to. Use this if you want to be sure that no application will be able to connect to InputStick without you knowing.
  • Ask when more than 1 [Default]: you will be asked to select device only when more than one InputStick is paired with your phone. Otherwise it will connect automatically.
  • Never ask: you won't be bothered with dialog. If there is more than one device paired, it will attempt to connect to the one marked as "Default device".
Toast settings:
  • Show all - show all toasts, useful mainly in my case.
  • Show important - show only important toasts, useful for application developers.
  • Show none [Default] : DeviceManager won't be displaying any Toast messages.
Status Bar Notifications:
  • Enabled - notification will be displayed when InputStick device is in use.
  • Disabled - no notifications will be displayed.

Demo apps:

Use Connect/Disconnect button, exact behaviour depends on configuration of DeviceManager.  If it is the first time that you are using your InputStick device you will be asked to enter PIN code (1234), unless you have already paired it manually.

BUG: if attempt to establish Bluetooth connection fails (InputStick not plugged in, out of range etc), pressing "Connect" again will do nothing. You have to kill the app and try again. Next API release will solve this issue.

Depending on USB host, OS, and settings it may take some time to detect new hardware and install drivers.  During this period you won't be able to use application, even though it may appear to be ready. Next time, this should be much faster (OS will recognize the device using PID/VID pair).


API & Demos:

Import InputStickLibrary project into Eclipse:

  • File -> Import -> Existing projects into workspace -> browse -> select InputStickLibrary directory -> check "Copy into workspace" -> Finish

Depending on your ADT version you may get some error messages, in such case go to:
  • Project Properties -> Android -> Select build target -> OK
  • Android Tools -> Fix project properties
This should fix all error messages. Do the same for demo projects.

Starting new project:

  • Create new Android project. Choose minimum SDK > 2.3. 
  • Project Properties -> Android -> Add -> Select InputStickLibrary -> OK

Using API in your project:

Let's take "HelloInputStick" project as an example. This simple app uses USBKeyboard class to type:

Hello world!
XyZ

This version is a little bit different from the one posted some time ago. Comments should explain everything. (GitHub)



package com.example.helloinputstick;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import com.example.inputsticklibrary.usb.USBDevice;
import com.example.inputsticklibrary.usb.USBDeviceListener;
import com.example.inputsticklibrary.usb.devices.USBKeyboard;
//USBDeviceListener interface allows to receive callbacks
public class HelloInputStick extends Activity implements USBDeviceListener {
//create new instance of USBKeyboard
//if your app consists of more than one Activity
//it might be a good idea to use some sort of Singleton class to share USBKeyboard
private static final USBKeyboard keyb = new USBKeyboard();
private Button buttonConnect;
private Button buttonType;
//called when data is received form USB host
@Override
public void onUSBData(int endpoint, byte[] data) {
// TODO Auto-generated method stub
//USBKeyboard already takes care of handling NumLock/CapsLock/ScrollLock state
}
//Called when connection state has changed, update UI
public void onUSBEvent(int code) {
manageUI();
}
//Set appropriate caption for buttonConnect, depending on current connection state
//Enable buttonType only if InputStick has been successfully enumerated
private void manageUI() {
int state = keyb.getState();
switch (state) {
case USBDevice.STATE_NONE:
buttonConnect.setText(getString(R.string.string_connect));
buttonConnect.setEnabled(true);
enableUI(false);
break;
case USBDevice.STATE_CONNECTING:
buttonConnect.setText(getString(R.string.string_connecting));
buttonConnect.setEnabled(false);
enableUI(false);
break;
case USBDevice.STATE_CONNECTED:
buttonConnect.setText(getString(R.string.string_disconnect));
buttonConnect.setEnabled(true);
enableUI(false);
break;
case USBDevice.STATE_READY:
buttonConnect.setText(getString(R.string.string_disconnect));
buttonConnect.setEnabled(true);
enableUI(true);
break;
}
}
private void enableUI(boolean enabled) {
buttonType.setEnabled(enabled);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_hello_input_stick);
//Pass application context!
//It will allow to bind to InputStickService (part of DeviceManager app)
keyb.setContext(this.getApplicationContext());
buttonConnect = (Button) findViewById(R.id.buttonConnect);
buttonConnect.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
//Action depends on current connection state
switch (keyb.getState()) {
case USBDevice.STATE_NONE:
keyb.connect();
break;
case USBDevice.STATE_CONNECTED:
case USBDevice.STATE_READY:
keyb.disconnect();
break;
}
}
});
buttonType = (Button) findViewById(R.id.buttonType);
//choose one!
buttonType.setOnClickListener(new MyOnClickListener());
//buttonType.setOnClickListener(new MyOnClickListenerCaps());
//buttonType.setOnClickListener(new MyOnClickListenerLayout());
}
@Override
protected void onResume() {
super.onResume();
//register as a listener for callbacks
keyb.registerListener(this);
//Update UI depending on current connection state
manageUI();
}
@Override
protected void onPause() {
super.onPause();
//Activity is paused, unregister listener
keyb.unregisterListener();
}
//1) Simple case: ignore CapsLock and assume keyboard layout used in OS is set to EN-US or compatible
private class MyOnClickListener implements OnClickListener {
@Override
public void onClick(View arg0) {
//SHIFT key + H key = 'H'
keyb.pressAndRelease(USBKeyboard.SHIFT_LEFT, USBKeyboard.KEY_H);
//E key = 'e'
keyb.pressAndRelease(USBKeyboard.NONE, USBKeyboard.KEY_E);
//'llo world!', USBKeyboard class takes care of adding SHIFT key when necessary
keyb.type("llo world!");
//press ENTER key
keyb.pressAndRelease(USBKeyboard.NONE, USBKeyboard.KEY_ENTER);
//type 'XyZ'
keyb.type("XyZ");
}
}
//2) Take state of CapsLock into account
private class MyOnClickListenerCaps implements OnClickListener {
@Override
public void onClick(View arg0) {
if (keyb.isCapsLockOn()) {
//CapsLock is on! Change case of keys affected by CapsLock
keyb.type("hELLO WORLD!");
keyb.pressAndRelease(USBKeyboard.NONE, USBKeyboard.KEY_ENTER);
keyb.type("xYz");
} else {
keyb.pressAndRelease(USBKeyboard.SHIFT_LEFT, USBKeyboard.KEY_H);
keyb.pressAndRelease(USBKeyboard.NONE, USBKeyboard.KEY_E);
keyb.type("llo world!");
keyb.pressAndRelease(USBKeyboard.NONE, USBKeyboard.KEY_ENTER);
keyb.type("XyZ");
}
}
}
//3) Assume that USB host uses different keyboard layout: qwertz instead of qwerty
private class MyOnClickListenerLayout implements OnClickListener {
@Override
public void onClick(View arg0) {
if (keyb.isCapsLockOn()) {
//CapsLock is on! Change case of keys affected by CapsLock
keyb.type("hELLO WORLD!");
keyb.pressAndRelease(USBKeyboard.NONE, USBKeyboard.KEY_ENTER);
//replace 'z' and 'y' characters to produce expected result
keyb.type("xZy");
} else {
keyb.pressAndRelease(USBKeyboard.SHIFT_LEFT, USBKeyboard.KEY_H);
keyb.pressAndRelease(USBKeyboard.NONE, USBKeyboard.KEY_E);
keyb.type("llo world!");
keyb.pressAndRelease(USBKeyboard.NONE, USBKeyboard.KEY_ENTER);
//replace 'z' and 'y' characters to produce expected result
keyb.type("XzY");
}
}
}
}
view raw gistfile1.java hosted with ❤ by GitHub
For other device classes see: this post

6 comments:

  1. When can i buy inputstick?

    ReplyDelete
    Replies
    1. If you are an Android developer or don't mind being early adopter, I should have some more "pre production samples" available soon (more info at the beginning of next week).

      Delete
    2. That's good, I'm not very good but i am a developer, so a sample would be fine.
      But will have have to be able to releae apps on play? Because I'm not sure how to do that yet.

      Delete
    3. No, you don't have to release your app.

      Delete
  2. qubas - I'd be very interested in obtaining a pre production sample. What kind of contribution would you like for one unit?

    I can think of some very cool applications for this, specifically in device management.

    Thanks

    ReplyDelete
    Replies
    1. please send me an email, I'll reply with more details. Here you'll find the address:
      http://inputstick.com/index.php/contact

      Delete