{"_id":"551923b0337285170047f861","category":{"_id":"55093ef52ee8bf2b00491916","project":"55093b151c38c50d00611894","version":"55093b161c38c50d00611897","__v":9,"pages":["55094202961f17170070abbe","5509437a368a5617004146da","550963c0dd77250d007369c1","55096a172dd6a11900e6e774","5509811add77250d00736a1f","5509815f4ba6432d00bb7875","5509913ca2b4750d00a2341e","5509916add77250d00736a55","551923b0337285170047f861"],"sync":{"url":"","isSync":false},"reference":false,"createdAt":"2015-03-18T09:01:41.604Z","from_sync":false,"order":3,"slug":"code-examples","title":"Code Examples"},"__v":33,"version":{"_id":"55093b161c38c50d00611897","project":"55093b151c38c50d00611894","__v":4,"createdAt":"2015-03-18T08:45:10.369Z","releaseDate":"2015-03-18T08:45:10.368Z","categories":["55093b161c38c50d00611898","55093ee2961f17170070abb9","55093ee9961f17170070abba","55093ef52ee8bf2b00491916"],"is_deprecated":false,"is_hidden":false,"is_beta":false,"is_stable":true,"codename":"","version_clean":"1.0.0","version":"1.0"},"project":"55093b151c38c50d00611894","user":"55093bd84510200d00adf3c7","updates":[],"next":{"pages":[],"description":""},"createdAt":"2015-03-30T10:21:36.685Z","link_external":false,"link_url":"","githubsync":"","sync_unique":"","hidden":false,"api":{"settings":"","results":{"codes":[]},"auth":"required","params":[],"url":""},"isReference":false,"order":999,"body":"# MagicBeep #\n\nWelcome to _the first tutorial_ example !\n\nThis example presents the fundamental steps to master the ISKN API on Android studio. \nYou will learn how to connect to the slate, how to receive the slate events, \nand how to handle those events and get their parameters.\n\n\nThis is a simple sound player application using the ISKN Slate. \nThe application detects the presence of a pen  \nand plays a beep sound when the pen enters in the slate field of view.\nThe beep sounds depends on the pen colour.  \n\nNote that you can find __the full source code__ for this example in the ISKN_API examples folder.\n\nBefore you start, be sure you have your development environment set up (android studio (or eclipse with ADT) + SDK and JDK).\n \n## 1.Create Android Project\nIn this example you need to create an Android application.\nYou can specify __MagicBeep__ as an __Application name__.\n\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/t7icmWnBSNeT1gq6OKTk_Android_CreateApp.PNG\",\n        \"Android_CreateApp.PNG\",\n        \"1080\",\n        \"650\",\n        \"#6a9942\",\n        \"\"\n      ]\n    }\n  ]\n}\n[/block]\n\nTo use the ISKN_API module, you need to select API 18: Android 4.3 (Jelly Bean) as minimum SDK version. \nYou can select a higher version if you wish, but the minimum allowed by the ISKN_API is 18.\nPress  Next.\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/PXC1zG6T6yT0rum29lqA_Android_CreateApp_2.PNG\",\n        \"Android_CreateApp_2.PNG\",\n        \"1080\",\n        \"650\",\n        \"#6a9a43\",\n        \"\"\n      ]\n    }\n  ]\n}\n[/block]\n\nSelect __Blank Activity__ then press __Next__.\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/eglD54CiQAOdJWppuDWC_Android_CreateApp_3.PNG\",\n        \"Android_CreateApp_3.PNG\",\n        \"1080\",\n        \"650\",\n        \"#6d9b3b\",\n        \"\"\n      ]\n    }\n  ]\n}\n[/block]\n\n\nName the activity __MagicBeep__. Then press __Finish__.\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/hWinhdeuTma3CQAU1pR0_Android_CreateApp_4.PNG\",\n        \"Android_CreateApp_4.PNG\",\n        \"1080\",\n        \"650\",\n        \"#6a9941\",\n        \"\"\n      ]\n    }\n  ]\n}\n[/block]\n\n## 1.Add ISKN_API Module \n\nClick __File__>__New Module__.\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/VLZCAlDmQxKn3coYVN5t_Android_NewModule.PNG\",\n        \"Android_NewModule.PNG\",\n        \"252\",\n        \"153\",\n        \"#3a64b9\",\n        \"\"\n      ]\n    }\n  ]\n}\n[/block]\n\n\nSelect __Import .JAR or .AAR package__\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/udhuzpAjRDSWkba1gbfg_Android_NewModule_2.PNG\",\n        \"Android_NewModule_2.PNG\",\n        \"1080\",\n        \"650\",\n        \"#9aaf4b\",\n        \"\"\n      ]\n    }\n  ]\n}\n[/block]\n\n\nSelect the __ISKN_API.aar__ (release version) or ISKN_APId.aar (debug version) from the API folder then press __OK__.\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/tz7yURl2kjY6UHIEzARg_Android_NewModule_3.PNG\",\n        \"Android_NewModule_3.PNG\",\n        \"1078\",\n        \"649\",\n        \"#435c9b\",\n        \"\"\n      ]\n    }\n  ]\n}\n[/block]\n\n\nPress __Finish__.\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/HuDaLBxFTKWvD8XhdOks_Android_NewModule_4.PNG\",\n        \"Android_NewModule_4.PNG\",\n        \"301\",\n        \"247\",\n        \"#3560b1\",\n        \"\"\n      ]\n    }\n  ]\n}\n[/block]\n\n\nThe project is ready to use the ISKN API.\n\n## 2.Importing classes to the activity\n\nIn the import section of your activity, add the following imports :\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"import com.iskn.isknApi.*;\\nimport com.iskn.isknApi.events.*; \",\n      \"language\": \"java\"\n    }\n  ]\n}\n[/block]\n\n \n## 3.Preparing the event listener class\n\nTo receive the Slate events, you need to register a listener. \n\nIn this example, the MagicBeep class implements the Listener class.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"public class MagicBeep extends Activity implements Listener {\\n...\\n}\",\n      \"language\": \"java\"\n    }\n  ]\n}\n[/block]\n\n\nThe listener is an interface providing the following methods :\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \" :::at:::Override\\n    public void processEvent(Event event, int timecode) {\\n\\t\\t\\t...\\n    }\\n\\n    @Override\\n    public void connectionStatusChanged(boolean connected) {\\n\\t\\t\\t...\\n    }\",\n      \"language\": \"java\"\n    }\n  ]\n}\n[/block]\n\nThose methods __should be implemented__ by the subclass in order to receive the slate events.\n\nAt this point, the MagicBeep listener class is ready to be registered.\n \n \n## 4.Preparing the communication tools\n\nBefore registering the listener, we need to create the Slate manager object.\n\nTo do so, add this to your MagicBeep class :\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"private SlateManager iskn_SlateManager;\",\n      \"language\": \"java\"\n    }\n  ]\n}\n[/block]\nIn onCreate method of the MagicBeep activity, create the slate manager object. This object needs a context. Use the MagicBeep class instance as a context :\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"// Create slate manager\\n    iskn_SlateManager  = new SlateManager(this);\",\n      \"language\": \"java\"\n    }\n  ]\n}\n[/block]\n## 5. Registering the events listener\n\nOnce the slate manager is created, it is possible to register the MagicBeep class as a listener. \n\nTo do so, use the registerListener method of the slate manager in MagicBeep onCreate method :\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"//Register the MagicBeep class as a Listener\\n  \\tiskn_SlateManager.registerListener(this) ;\",\n      \"language\": \"java\"\n    }\n  ]\n}\n[/block]\n## 6. Connect to the slate \n\nBefore being able to receive events from the Slate, the application should connect to it.\nFirst you need to select the BLE device to connect to your Slate. \nYou can either select one device among paired devices, or scan for new devices.\n\n### 1. Select paired device by name \n\nThe first method is to select a previously paired device by using it's name.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"//======================================================================\\n        // 1-Connect to a previously paired device using the device name\\n //======================================================================\\n\\t\\t//Set the deviceName of your (already paired) Slate\\n        String deviceName=\\\"ISKNSlate\\\";\\n        BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();\\n\\t\\t\\n        // Get a set of currently paired devices\\n        Set<BluetoothDevice> pairedDevices = btAdapter.getBondedDevices();\\n\\t\\t\\n\\t\\t//iterate through all paired devices and connect to your Slate which has the deviceName\\n        for(BluetoothDevice btd:pairedDevices) {\\n            if(btd.getName().equals(deviceName))\\n            {\\n                iskn_SlateManager.connect(btd);\\n            }\\n        }\\n\",\n      \"language\": \"java\"\n    }\n  ]\n}\n[/block]\n\n\n### 2. Ask the user to select a previously paired device \n\nThis second method displays the list of paired devices. The user select one of these devices.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"//==============================================================================\\n        //2-Ask user to select one of the paired devices\\n        //==============================================================================\\n\\t\\t\\n        ArrayList<String> items = new ArrayList<String>();\\n        final ArrayList<BluetoothDevice>btDevices =new ArrayList<BluetoothDevice>();\\n        BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();\\n        // Get a set of currently paired devices\\n        Set<BluetoothDevice> pairedDevices = btAdapter.getBondedDevices();\\n        for(BluetoothDevice btd:pairedDevices) {\\n            items.add(btd.getName());\\n            btDevices.add(btd);\\n        }\\n        final ListView lstDevices=(ListView)findViewById(R.id.lstDevices);\\n        final LinearLayout ll =(LinearLayout)findViewById(R.id.ll);\\n        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,\\n        android.R.layout.simple_list_item_1, items);\\n        lstDevices.setAdapter(adapter);\\n        lstDevices.setOnItemClickListener(new AdapterView.OnItemClickListener() {\\n            @Override\\n            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {\\n                iskn_SlateManager.connect(btDevices.get(position));\\n                ll.setVisibility(View.GONE);\\n            }\\n        });\",\n      \"language\": \"java\"\n    }\n  ]\n}\n[/block]\n\n\n### 3. Scan for devices then ask the user to select one of these devices\n\nFirst, you need to enable bluetooth permissions in your application manifest file under the manifest tag.\nThis gives your application the permission to scan for bluetooth devices:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"<uses-permission android:name=\\\"android.permission.BLUETOOTH\\\"/>\\n<uses-permission android:name=\\\"android.permission.BLUETOOTH_ADMIN\\\"/>\\n<uses-feature android:name=\\\"android.hardware.bluetooth_le\\\" android:required=\\\"true\\\"/>\",\n      \"language\": \"xml\"\n    }\n  ]\n}\n[/block]\n\nThis third method displays the list of scanned devices. The user select one of these devices.\n\nImport the BleScanner class provided in the ISKN_API :\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"import com.iskn.isknApi.bleScanner.*;\",\n      \"language\": \"java\"\n    }\n  ]\n}\n[/block]\n\n\nAdd a ListView to the application. You can call it lstDevices. Put the listview inside a linearLayout. \nYou can call the layout ll. Create an instance of LinearLayout pointing on ll.\n\nAdd the following to the onCreate section :\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"//==============================================================================\\n        //3-Ask user to select one of the scanned devices\\n        //==============================================================================\\n\\n        final ArrayList<String> items = new ArrayList<String>();\\n        final ArrayList<BluetoothDevice>btDevices =new ArrayList<BluetoothDevice>();\\n        final ListView lstDevices=(ListView)findViewById(R.id.lstDevices);\\n        final LinearLayout ll =(LinearLayout)findViewById(R.id.ll);\\n        final ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, items);\\n        lstDevices.setAdapter(adapter);\\n        final BleScanner bleScanner=new BleScanner(this,new BLE_Scan_Listener() {\\n            @Override\\n            public void newDeviceFound(BluetoothDevice p_device) {\\n                if(p_device.getName()==null)\\n                items.add(\\\"No name : \\\"+\\\" \\\"+p_device.getAddress());\\n                else\\n                 items.add(p_device.getName());\\n\\n                adapter.notifyDataSetChanged();\\n                btDevices.add(p_device);\\n                Log.i(\\\"MagicBeep\\\",\\\"Device found\\\");\\n            }\\n\\n            @Override\\n            public void notify(final BleScanner_Event evt, String info)\\n            {\\n                runOnUiThread(new Runnable() {\\n                    @Override\\n                    public void run() {\\n                        switch (evt) {\\n                            case BLESCANNER_EVENT_BLE_NOT_SUPPORTED:\\n                                Log.i(\\\"MagicBeep\\\", \\\"BLE not supported on this device\\\");\\n                                break;\\n                            case BLESCANNER_EVENT_ACTIVATION_REQUIRED:\\n                                Log.i(\\\"MagicBeep\\\", \\\"Please activate BLE on the device\\\");\\n                                Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);\\n                                startActivityForResult(enableBtIntent, BleScanner.REQUEST_ENABLE_BT);\\n                                break;\\n                            case BLESCANNER_EVENT_BLE_SCAN_STARTED:\\n                                Log.i(\\\"MagicBeep\\\", \\\"Scan started\\\");\\n                                break;\\n                        }\\n                    }\\n                });\\n            }\\n\\n            @Override\\n            public void scanFinished() {\\n                Log.i(\\\"MagicBeep\\\",\\\"Scan finished\\\");\\n            }\\n        });\\n        try {\\n            bleScanner.startScan();\\n        } catch (Exception e) {\\n            e.printStackTrace();\\n        }\\n\\n        lstDevices.setOnItemClickListener(new AdapterView.OnItemClickListener() {\\n            @Override\\n            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {\\n                try {\\n                    bleScanner.stopScan();\\n                } catch (Exception e) {\\n                    e.printStackTrace();\\n                }\\n                txtConsole.setText(txtConsole.getText()+\\\"Connecting...\\\\n\\\");\\n                iskn_SlateManager.connect(btDevices.get(position));\\n                ll.setVisibility(View.GONE);\\n            }\\n        });\",\n      \"language\": \"java\"\n    }\n  ]\n}\n[/block]\n\n\nThis code uses the BleScanner class provided by the ISKN_API. The class scans for bluetooth devices.\nWhen the startScan method is called, the scanner tries to start a bluetooth low energy scan. \nIf the device do not support bluetooth low energy, the scanner calls the notify method with the event BLE_EVENT_NOT_SUPPORTED.\nIf the bluetooth is off, the scanner calls the notify method with the event BLE_EVENT_ACTIVATION_REQUIRED.\nEach time a new device is found, the bleScanner calls the newDeviceFound method with a BluetoothDevice object reference.\nWhen the scan is finished, the scanFinished method is called.\n\nIt is possible to stop the scan at any time by calling stopScan method.\n\n\n## 7. Subscribe to the services\n\nCheck if the connection succeeded by implementing the `void connectionStatusChanged(boolean connected)` method.\nNotice that this method is called in an independent thread. \nSo to interact with the UI, you must put the corresponding code in a runOnUiThread runnable. \nThe SlateManager object should also be manipulated only in UI thread.\nOnce connected, request the slate description in order to update the Device object information.\n\nThis gathers specific slate information such as slate name, the size of the slate, the writing zone of the slate.\nThis is performed by the request method of the Slate manager object.\n\nFinally, you need to subscribe to automatic events services. This tells the Slate which events your listener should receive.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"@Override\\npublic void connectionStatusChanged(boolean connected) {\\n\\tLog.i(\\\"MagicBeep\\\",\\\"Connection status changed\\\");\\n\\tif(connected) {\\n\\t\\trunOnUiThread(new Runnable() {\\n\\t\\t\\t@Override\\n\\t\\t\\tpublic void run() {\\n\\t\\t\\t\\tiskn_SlateManager.request(SlateManager.SingleRequestBlockType.REQ_DESCRIPTION);\\n\\t\\t\\t\\tiskn_SlateManager.subscribe(SlateManager.AutoBlockType.AUTO_STATUS.type() |\\n\\t\\t\\t\\t\\t\\tSlateManager.AutoBlockType.AUTO_PEN_3D.type() |\\n\\t\\t\\t\\t\\t\\tSlateManager.AutoBlockType.AUTO_HARDWARE_EVENTS.type() |\\n\\t\\t\\t\\t\\t\\tSlateManager.AutoBlockType.AUTO_SOFTWARE_EVENTS.type());\\t\\t\\t\\n\\t\\t\\t\\tToast.makeText(MagicBeep.this,\\\"Connected\\\\n\\\",Toast.LENGTH_LONG).show();\\n\\t\\t\\t}\\n\\t\\t});\\n\\t}\\n}\",\n      \"language\": \"java\"\n    }\n  ]\n}\n[/block]\n\nIn this application, we request four types of events :\n\n \n + AUTO_STATUS        \t\t: Asks to receive slate status changes (Battery charge change, (SD card insertion/ removal)).\n \n + AUTO_PEN_3D        \t\t: Asks to receive the Pen tip 3D position and contact status at a 140Hz frequency when the pen is in the field of view of the slate.  \n \n + AUTO_SOFTWARE_EVENTS    \t: Asks to receive Software events like object status change.\n (Object recognised (SE_OBJECT_IN), object lost(SE_OBJECT_OUT), handshake event (a periodic event used to detect that the Slate is still on)).\n \n + AUTO_HARDWARE_EVENTS \t: Asks to receive Hardware events (When a button is pressed (new page button, new layer button, reset event (long press on new page button)), SD card inserted or removed )\n\n \n## 7. Receive and extract events\n\nThe processEvent method is called whenever a new event is received from the Slate.\n\nUse the type attribute of the Event object in order to figure out the event type.\nYou can cast the event object to its corresponding event after testing its type.\nYou can use a switch case statement as follows :\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"\\n    @Override\\n    public void processEvent(final Event event, int timecode) {\\n       runOnUiThread(new Runnable() {\\n            @Override\\n            public void run() {\\n                switch(event.getType()){\\n                    case EVT_STATUS: {\\n                        EventStatus evt = (EventStatus) event;\\n                        txtConsole.setText(txtConsole.getText()+\\\"Battery :\\\"+ evt.getBattery() +\\\"\\\\n\\\");\\n                        break;\\n                    }\\n                    case EVT_DESCRIPTION: {\\n                        EventDescription evt = (EventDescription) event;\\n                        txtConsole.setText(txtConsole.getText()+ \\\"Connected to \\\" + evt.getDeviceName()+\\\"\\\\n\\\");\\n                        txtConsole.setText(txtConsole.getText()+ \\\"Firmware version :\\\" + evt.getFirmwareVersion()+\\\"\\\\n\\\");\\n\\n                        break;\\n                    }\\n                    case EVT_PEN_3D: {\\n                        EventPen3D evt = (EventPen3D) event;\\n                        Vector3D vec=evt.getPosition();\\n                        break;\\n                    }\\n                    case EVT_SOFTWARE:{\\n                        EventSoftware evt = (EventSoftware) event;\\n                        switch(evt.getSoftwareEventType()){\\n                            case SE_OBJECT_IN:\\n                                switch(evt.getObjectID())\\n                                {\\n                                    case 1:\\n                                        playShortResource(R.raw.beep);\\n                                        break;\\n                                    case 2:\\n                                        playShortResource(R.raw.beep_2);\\n                                        break;\\n                                    case 3:\\n                                        playShortResource(R.raw.beep_3);\\n                                        break;\\n                                    case 4:\\n                                        playShortResource(R.raw.beep_3);\\n                                        break;\\n                                }\\n                                txtConsole.setText(txtConsole.getText()+ \\\"Pen \\\"+ evt.getObjectID() +\\\" in\\\\n\\\");\\n                                break;\\n                            case SE_OBJECT_OUT:\\n                                txtConsole.setText(txtConsole.getText()+ \\\"Pen \\\"+ evt.getObjectID() +\\\" out\\\\n\\\");\\n                                break;\\n                        }\\n                        break;\\n                    }\\n                    case EVT_HARDWARE: {\\n                        EventHardware evt = (EventHardware) event;\\n                        switch (evt.getHardwareEventType()){\\n                            case HE_BUTTON1_PRESSED:\\n                                txtConsole.setText(txtConsole.getText()+ \\\"Button 1 pressed\\\\n\\\");\\n                                break;\\n                            case HE_BUTTON2_PRESSED:\\n                                txtConsole.setText(txtConsole.getText()+ \\\"Button 2 pressed\\\\n\\\");\\n                                break;\\n                        }\\n                        break;\\n                    }\\n                }\\n            }\\n        });\\n\\t}\",\n      \"language\": \"java\"\n    }\n  ]\n}\n[/block]\n\n\nDon't forget to add a reference to a textView that you put in your layout to show events. Call the TextView txtConsole.\nAdd the object definition to your activity class (MagicBeep).\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"private TextView txtConsole;\",\n      \"language\": \"java\"\n    }\n  ]\n}\n[/block]\n\n\nNow link it to the layout TextView in the onCreate method:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"txtConsole=(TextView)findViewById(R.id.txtConsole);\",\n      \"language\": \"java\"\n    }\n  ]\n}\n[/block]\n\n\nIt is important to use the runOnUiThread method in order to be able to interact with the UI, since the  `processEvent` method is executed in a separate thread.\nIn this application, when a pen is viewed, a sound is played. The sound depends on the id of the pen.\nWhen the pen is detected a EVT_SOFTWARE is sent to the `processEvent` method. The software event type is SE_OBJECT_IN. If this event is detected, you can use `getObjectID` method to determine the pen ID.\nWhen the pen disapeares a EVT_SOFTWARE is sent to the `processEvent` method. The software event type is SE_OBJECT_OUT.\n\n## 8. Play the sounds\n\nAdd the beep sounds (wave files named beep.wav, beep_2.wav and beep_3.wav) to the res/raw directory.\nAdd the following definitions to the activity :\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \" private SoundPool mShortPlayer= null;\\n    private HashMap mSounds = new HashMap();\",\n      \"language\": \"java\"\n    }\n  ]\n}\n[/block]\n\nIn the onCreate method add the following :\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"     // MAGIC_BEEP music engine\\n        this.mShortPlayer = new SoundPool(4, AudioManager.STREAM_MUSIC, 0);\\n\\n\\n        mSounds.put(R.raw.beep, this.mShortPlayer.load(this, R.raw.beep, 1));\\n        mSounds.put(R.raw.beep_2, this.mShortPlayer.load(this, R.raw.beep_2, 1));\\n        mSounds.put(R.raw.beep_3, this.mShortPlayer.load(this, R.raw.beep_3, 1));\",\n      \"language\": \"java\"\n    }\n  ]\n}\n[/block]\n\nyou can put other wave files\nFinally add the playShortResource method that plays the needed sound :\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \" public void playShortResource(int piResource) {\\n        int iSoundId = (Integer) mSounds.get(piResource);\\n        this.mShortPlayer.play(iSoundId, 0.99f, 0.99f, 0, 0, 1);\\n    }\",\n      \"language\": \"java\"\n    }\n  ]\n}\n[/block]\n\n\n## 9. Run your project\n\nYour project is now ready to run.\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/Xmxy45wR9CQenewV3Qgh_Android_Run_you_project2.png\",\n        \"Android_Run_you_project2.png\",\n        \"1920\",\n        \"1080\",\n        \"#424242\",\n        \"\"\n      ]\n    }\n  ]\n}\n[/block]","excerpt":"","slug":"getting-started-with-iskn-api-on-android","type":"basic","title":"Getting started with ISKN API on Android"}

Getting started with ISKN API on Android


# MagicBeep # Welcome to _the first tutorial_ example ! This example presents the fundamental steps to master the ISKN API on Android studio. You will learn how to connect to the slate, how to receive the slate events, and how to handle those events and get their parameters. This is a simple sound player application using the ISKN Slate. The application detects the presence of a pen and plays a beep sound when the pen enters in the slate field of view. The beep sounds depends on the pen colour. Note that you can find __the full source code__ for this example in the ISKN_API examples folder. Before you start, be sure you have your development environment set up (android studio (or eclipse with ADT) + SDK and JDK). ## 1.Create Android Project In this example you need to create an Android application. You can specify __MagicBeep__ as an __Application name__. [block:image] { "images": [ { "image": [ "https://files.readme.io/t7icmWnBSNeT1gq6OKTk_Android_CreateApp.PNG", "Android_CreateApp.PNG", "1080", "650", "#6a9942", "" ] } ] } [/block] To use the ISKN_API module, you need to select API 18: Android 4.3 (Jelly Bean) as minimum SDK version. You can select a higher version if you wish, but the minimum allowed by the ISKN_API is 18. Press Next. [block:image] { "images": [ { "image": [ "https://files.readme.io/PXC1zG6T6yT0rum29lqA_Android_CreateApp_2.PNG", "Android_CreateApp_2.PNG", "1080", "650", "#6a9a43", "" ] } ] } [/block] Select __Blank Activity__ then press __Next__. [block:image] { "images": [ { "image": [ "https://files.readme.io/eglD54CiQAOdJWppuDWC_Android_CreateApp_3.PNG", "Android_CreateApp_3.PNG", "1080", "650", "#6d9b3b", "" ] } ] } [/block] Name the activity __MagicBeep__. Then press __Finish__. [block:image] { "images": [ { "image": [ "https://files.readme.io/hWinhdeuTma3CQAU1pR0_Android_CreateApp_4.PNG", "Android_CreateApp_4.PNG", "1080", "650", "#6a9941", "" ] } ] } [/block] ## 1.Add ISKN_API Module Click __File__>__New Module__. [block:image] { "images": [ { "image": [ "https://files.readme.io/VLZCAlDmQxKn3coYVN5t_Android_NewModule.PNG", "Android_NewModule.PNG", "252", "153", "#3a64b9", "" ] } ] } [/block] Select __Import .JAR or .AAR package__ [block:image] { "images": [ { "image": [ "https://files.readme.io/udhuzpAjRDSWkba1gbfg_Android_NewModule_2.PNG", "Android_NewModule_2.PNG", "1080", "650", "#9aaf4b", "" ] } ] } [/block] Select the __ISKN_API.aar__ (release version) or ISKN_APId.aar (debug version) from the API folder then press __OK__. [block:image] { "images": [ { "image": [ "https://files.readme.io/tz7yURl2kjY6UHIEzARg_Android_NewModule_3.PNG", "Android_NewModule_3.PNG", "1078", "649", "#435c9b", "" ] } ] } [/block] Press __Finish__. [block:image] { "images": [ { "image": [ "https://files.readme.io/HuDaLBxFTKWvD8XhdOks_Android_NewModule_4.PNG", "Android_NewModule_4.PNG", "301", "247", "#3560b1", "" ] } ] } [/block] The project is ready to use the ISKN API. ## 2.Importing classes to the activity In the import section of your activity, add the following imports : [block:code] { "codes": [ { "code": "import com.iskn.isknApi.*;\nimport com.iskn.isknApi.events.*; ", "language": "java" } ] } [/block] ## 3.Preparing the event listener class To receive the Slate events, you need to register a listener. In this example, the MagicBeep class implements the Listener class. [block:code] { "codes": [ { "code": "public class MagicBeep extends Activity implements Listener {\n...\n}", "language": "java" } ] } [/block] The listener is an interface providing the following methods : [block:code] { "codes": [ { "code": " @Override\n public void processEvent(Event event, int timecode) {\n\t\t\t...\n }\n\n @Override\n public void connectionStatusChanged(boolean connected) {\n\t\t\t...\n }", "language": "java" } ] } [/block] Those methods __should be implemented__ by the subclass in order to receive the slate events. At this point, the MagicBeep listener class is ready to be registered. ## 4.Preparing the communication tools Before registering the listener, we need to create the Slate manager object. To do so, add this to your MagicBeep class : [block:code] { "codes": [ { "code": "private SlateManager iskn_SlateManager;", "language": "java" } ] } [/block] In onCreate method of the MagicBeep activity, create the slate manager object. This object needs a context. Use the MagicBeep class instance as a context : [block:code] { "codes": [ { "code": "// Create slate manager\n iskn_SlateManager = new SlateManager(this);", "language": "java" } ] } [/block] ## 5. Registering the events listener Once the slate manager is created, it is possible to register the MagicBeep class as a listener. To do so, use the registerListener method of the slate manager in MagicBeep onCreate method : [block:code] { "codes": [ { "code": "//Register the MagicBeep class as a Listener\n \tiskn_SlateManager.registerListener(this) ;", "language": "java" } ] } [/block] ## 6. Connect to the slate Before being able to receive events from the Slate, the application should connect to it. First you need to select the BLE device to connect to your Slate. You can either select one device among paired devices, or scan for new devices. ### 1. Select paired device by name The first method is to select a previously paired device by using it's name. [block:code] { "codes": [ { "code": "//======================================================================\n // 1-Connect to a previously paired device using the device name\n //======================================================================\n\t\t//Set the deviceName of your (already paired) Slate\n String deviceName=\"ISKNSlate\";\n BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();\n\t\t\n // Get a set of currently paired devices\n Set<BluetoothDevice> pairedDevices = btAdapter.getBondedDevices();\n\t\t\n\t\t//iterate through all paired devices and connect to your Slate which has the deviceName\n for(BluetoothDevice btd:pairedDevices) {\n if(btd.getName().equals(deviceName))\n {\n iskn_SlateManager.connect(btd);\n }\n }\n", "language": "java" } ] } [/block] ### 2. Ask the user to select a previously paired device This second method displays the list of paired devices. The user select one of these devices. [block:code] { "codes": [ { "code": "//==============================================================================\n //2-Ask user to select one of the paired devices\n //==============================================================================\n\t\t\n ArrayList<String> items = new ArrayList<String>();\n final ArrayList<BluetoothDevice>btDevices =new ArrayList<BluetoothDevice>();\n BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();\n // Get a set of currently paired devices\n Set<BluetoothDevice> pairedDevices = btAdapter.getBondedDevices();\n for(BluetoothDevice btd:pairedDevices) {\n items.add(btd.getName());\n btDevices.add(btd);\n }\n final ListView lstDevices=(ListView)findViewById(R.id.lstDevices);\n final LinearLayout ll =(LinearLayout)findViewById(R.id.ll);\n ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,\n android.R.layout.simple_list_item_1, items);\n lstDevices.setAdapter(adapter);\n lstDevices.setOnItemClickListener(new AdapterView.OnItemClickListener() {\n @Override\n public void onItemClick(AdapterView<?> parent, View view, int position, long id) {\n iskn_SlateManager.connect(btDevices.get(position));\n ll.setVisibility(View.GONE);\n }\n });", "language": "java" } ] } [/block] ### 3. Scan for devices then ask the user to select one of these devices First, you need to enable bluetooth permissions in your application manifest file under the manifest tag. This gives your application the permission to scan for bluetooth devices: [block:code] { "codes": [ { "code": "<uses-permission android:name=\"android.permission.BLUETOOTH\"/>\n<uses-permission android:name=\"android.permission.BLUETOOTH_ADMIN\"/>\n<uses-feature android:name=\"android.hardware.bluetooth_le\" android:required=\"true\"/>", "language": "xml" } ] } [/block] This third method displays the list of scanned devices. The user select one of these devices. Import the BleScanner class provided in the ISKN_API : [block:code] { "codes": [ { "code": "import com.iskn.isknApi.bleScanner.*;", "language": "java" } ] } [/block] Add a ListView to the application. You can call it lstDevices. Put the listview inside a linearLayout. You can call the layout ll. Create an instance of LinearLayout pointing on ll. Add the following to the onCreate section : [block:code] { "codes": [ { "code": "//==============================================================================\n //3-Ask user to select one of the scanned devices\n //==============================================================================\n\n final ArrayList<String> items = new ArrayList<String>();\n final ArrayList<BluetoothDevice>btDevices =new ArrayList<BluetoothDevice>();\n final ListView lstDevices=(ListView)findViewById(R.id.lstDevices);\n final LinearLayout ll =(LinearLayout)findViewById(R.id.ll);\n final ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, items);\n lstDevices.setAdapter(adapter);\n final BleScanner bleScanner=new BleScanner(this,new BLE_Scan_Listener() {\n @Override\n public void newDeviceFound(BluetoothDevice p_device) {\n if(p_device.getName()==null)\n items.add(\"No name : \"+\" \"+p_device.getAddress());\n else\n items.add(p_device.getName());\n\n adapter.notifyDataSetChanged();\n btDevices.add(p_device);\n Log.i(\"MagicBeep\",\"Device found\");\n }\n\n @Override\n public void notify(final BleScanner_Event evt, String info)\n {\n runOnUiThread(new Runnable() {\n @Override\n public void run() {\n switch (evt) {\n case BLESCANNER_EVENT_BLE_NOT_SUPPORTED:\n Log.i(\"MagicBeep\", \"BLE not supported on this device\");\n break;\n case BLESCANNER_EVENT_ACTIVATION_REQUIRED:\n Log.i(\"MagicBeep\", \"Please activate BLE on the device\");\n Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);\n startActivityForResult(enableBtIntent, BleScanner.REQUEST_ENABLE_BT);\n break;\n case BLESCANNER_EVENT_BLE_SCAN_STARTED:\n Log.i(\"MagicBeep\", \"Scan started\");\n break;\n }\n }\n });\n }\n\n @Override\n public void scanFinished() {\n Log.i(\"MagicBeep\",\"Scan finished\");\n }\n });\n try {\n bleScanner.startScan();\n } catch (Exception e) {\n e.printStackTrace();\n }\n\n lstDevices.setOnItemClickListener(new AdapterView.OnItemClickListener() {\n @Override\n public void onItemClick(AdapterView<?> parent, View view, int position, long id) {\n try {\n bleScanner.stopScan();\n } catch (Exception e) {\n e.printStackTrace();\n }\n txtConsole.setText(txtConsole.getText()+\"Connecting...\\n\");\n iskn_SlateManager.connect(btDevices.get(position));\n ll.setVisibility(View.GONE);\n }\n });", "language": "java" } ] } [/block] This code uses the BleScanner class provided by the ISKN_API. The class scans for bluetooth devices. When the startScan method is called, the scanner tries to start a bluetooth low energy scan. If the device do not support bluetooth low energy, the scanner calls the notify method with the event BLE_EVENT_NOT_SUPPORTED. If the bluetooth is off, the scanner calls the notify method with the event BLE_EVENT_ACTIVATION_REQUIRED. Each time a new device is found, the bleScanner calls the newDeviceFound method with a BluetoothDevice object reference. When the scan is finished, the scanFinished method is called. It is possible to stop the scan at any time by calling stopScan method. ## 7. Subscribe to the services Check if the connection succeeded by implementing the `void connectionStatusChanged(boolean connected)` method. Notice that this method is called in an independent thread. So to interact with the UI, you must put the corresponding code in a runOnUiThread runnable. The SlateManager object should also be manipulated only in UI thread. Once connected, request the slate description in order to update the Device object information. This gathers specific slate information such as slate name, the size of the slate, the writing zone of the slate. This is performed by the request method of the Slate manager object. Finally, you need to subscribe to automatic events services. This tells the Slate which events your listener should receive. [block:code] { "codes": [ { "code": "@Override\npublic void connectionStatusChanged(boolean connected) {\n\tLog.i(\"MagicBeep\",\"Connection status changed\");\n\tif(connected) {\n\t\trunOnUiThread(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\tiskn_SlateManager.request(SlateManager.SingleRequestBlockType.REQ_DESCRIPTION);\n\t\t\t\tiskn_SlateManager.subscribe(SlateManager.AutoBlockType.AUTO_STATUS.type() |\n\t\t\t\t\t\tSlateManager.AutoBlockType.AUTO_PEN_3D.type() |\n\t\t\t\t\t\tSlateManager.AutoBlockType.AUTO_HARDWARE_EVENTS.type() |\n\t\t\t\t\t\tSlateManager.AutoBlockType.AUTO_SOFTWARE_EVENTS.type());\t\t\t\n\t\t\t\tToast.makeText(MagicBeep.this,\"Connected\\n\",Toast.LENGTH_LONG).show();\n\t\t\t}\n\t\t});\n\t}\n}", "language": "java" } ] } [/block] In this application, we request four types of events : + AUTO_STATUS : Asks to receive slate status changes (Battery charge change, (SD card insertion/ removal)). + AUTO_PEN_3D : Asks to receive the Pen tip 3D position and contact status at a 140Hz frequency when the pen is in the field of view of the slate. + AUTO_SOFTWARE_EVENTS : Asks to receive Software events like object status change. (Object recognised (SE_OBJECT_IN), object lost(SE_OBJECT_OUT), handshake event (a periodic event used to detect that the Slate is still on)). + AUTO_HARDWARE_EVENTS : Asks to receive Hardware events (When a button is pressed (new page button, new layer button, reset event (long press on new page button)), SD card inserted or removed ) ## 7. Receive and extract events The processEvent method is called whenever a new event is received from the Slate. Use the type attribute of the Event object in order to figure out the event type. You can cast the event object to its corresponding event after testing its type. You can use a switch case statement as follows : [block:code] { "codes": [ { "code": "\n @Override\n public void processEvent(final Event event, int timecode) {\n runOnUiThread(new Runnable() {\n @Override\n public void run() {\n switch(event.getType()){\n case EVT_STATUS: {\n EventStatus evt = (EventStatus) event;\n txtConsole.setText(txtConsole.getText()+\"Battery :\"+ evt.getBattery() +\"\\n\");\n break;\n }\n case EVT_DESCRIPTION: {\n EventDescription evt = (EventDescription) event;\n txtConsole.setText(txtConsole.getText()+ \"Connected to \" + evt.getDeviceName()+\"\\n\");\n txtConsole.setText(txtConsole.getText()+ \"Firmware version :\" + evt.getFirmwareVersion()+\"\\n\");\n\n break;\n }\n case EVT_PEN_3D: {\n EventPen3D evt = (EventPen3D) event;\n Vector3D vec=evt.getPosition();\n break;\n }\n case EVT_SOFTWARE:{\n EventSoftware evt = (EventSoftware) event;\n switch(evt.getSoftwareEventType()){\n case SE_OBJECT_IN:\n switch(evt.getObjectID())\n {\n case 1:\n playShortResource(R.raw.beep);\n break;\n case 2:\n playShortResource(R.raw.beep_2);\n break;\n case 3:\n playShortResource(R.raw.beep_3);\n break;\n case 4:\n playShortResource(R.raw.beep_3);\n break;\n }\n txtConsole.setText(txtConsole.getText()+ \"Pen \"+ evt.getObjectID() +\" in\\n\");\n break;\n case SE_OBJECT_OUT:\n txtConsole.setText(txtConsole.getText()+ \"Pen \"+ evt.getObjectID() +\" out\\n\");\n break;\n }\n break;\n }\n case EVT_HARDWARE: {\n EventHardware evt = (EventHardware) event;\n switch (evt.getHardwareEventType()){\n case HE_BUTTON1_PRESSED:\n txtConsole.setText(txtConsole.getText()+ \"Button 1 pressed\\n\");\n break;\n case HE_BUTTON2_PRESSED:\n txtConsole.setText(txtConsole.getText()+ \"Button 2 pressed\\n\");\n break;\n }\n break;\n }\n }\n }\n });\n\t}", "language": "java" } ] } [/block] Don't forget to add a reference to a textView that you put in your layout to show events. Call the TextView txtConsole. Add the object definition to your activity class (MagicBeep). [block:code] { "codes": [ { "code": "private TextView txtConsole;", "language": "java" } ] } [/block] Now link it to the layout TextView in the onCreate method: [block:code] { "codes": [ { "code": "txtConsole=(TextView)findViewById(R.id.txtConsole);", "language": "java" } ] } [/block] It is important to use the runOnUiThread method in order to be able to interact with the UI, since the `processEvent` method is executed in a separate thread. In this application, when a pen is viewed, a sound is played. The sound depends on the id of the pen. When the pen is detected a EVT_SOFTWARE is sent to the `processEvent` method. The software event type is SE_OBJECT_IN. If this event is detected, you can use `getObjectID` method to determine the pen ID. When the pen disapeares a EVT_SOFTWARE is sent to the `processEvent` method. The software event type is SE_OBJECT_OUT. ## 8. Play the sounds Add the beep sounds (wave files named beep.wav, beep_2.wav and beep_3.wav) to the res/raw directory. Add the following definitions to the activity : [block:code] { "codes": [ { "code": " private SoundPool mShortPlayer= null;\n private HashMap mSounds = new HashMap();", "language": "java" } ] } [/block] In the onCreate method add the following : [block:code] { "codes": [ { "code": " // MAGIC_BEEP music engine\n this.mShortPlayer = new SoundPool(4, AudioManager.STREAM_MUSIC, 0);\n\n\n mSounds.put(R.raw.beep, this.mShortPlayer.load(this, R.raw.beep, 1));\n mSounds.put(R.raw.beep_2, this.mShortPlayer.load(this, R.raw.beep_2, 1));\n mSounds.put(R.raw.beep_3, this.mShortPlayer.load(this, R.raw.beep_3, 1));", "language": "java" } ] } [/block] you can put other wave files Finally add the playShortResource method that plays the needed sound : [block:code] { "codes": [ { "code": " public void playShortResource(int piResource) {\n int iSoundId = (Integer) mSounds.get(piResource);\n this.mShortPlayer.play(iSoundId, 0.99f, 0.99f, 0, 0, 1);\n }", "language": "java" } ] } [/block] ## 9. Run your project Your project is now ready to run. [block:image] { "images": [ { "image": [ "https://files.readme.io/Xmxy45wR9CQenewV3Qgh_Android_Run_you_project2.png", "Android_Run_you_project2.png", "1920", "1080", "#424242", "" ] } ] } [/block]