Part 1: Basic Bluetooth communications using App Inventor

You may also like...

89 Responses

  1. TechWorm says:

    Hey! Really helpful tutorial… I’m creating this new app that requires PvP feature.. I hope that I can use this as reference for my app ! Your contributions will be very much acknowledged!

    • Edward M says:

      Your are most welcome – I appreciate hearing that these tutorials are helpful! Thanks for the feedback!

      Ed

      • Kevin says:

        I am getting an error anytime I try to send data as a list “could not decode element 1 as integer” I try to send bytes as list text and number from database what am I doing wrong.

        • Edward M says:

          We’d need to see the blocks code – sounds like a programming error that is fixable.

          Am guessing that the item you are trying to convert to an integer is an actual list element. There are several ways to force the conversion. You might try a define global or local variable that is first assigned an integer value like 0. Then let that variable get the value of the list element. It should convert it to an integer there.

          Ed

  2. TechWorm says:

    May I use the .aia from this website?

    • Edward M says:

      I realize this question is old – but YES! The source code here is intended to illustrate how to do things – no guarantees as it is not done as rigorously as done for a commercial product! But I post the code here for anyone to use in their projects!

      Ed

  3. TechWorm says:

    One thing! I get this error
    “Error:com.google.appinventor.components.runtime.BluetoothClient@21b34368,507,Connect,Unable to connect . Is the device turned on”

    obviously turned it on.. no luck on it yet 🙂
    thanks

  4. Rogerio says:

    Hi,

    I would like to know how to receive and compare numbers using app inventor 2 programing. I am using an arduino with a bluetooth shield.
    Can you help me?

    Thank you

    • Edward M says:

      It is possible – but I have not yet implemented Arduino–>Bluetooth–>Android App Inventor – so I cannot help you right now but perhaps someone else can.

      It may also depend on which Bluetooth shield you have for the Arduino. I know that this one
      http://hobbycomponents.com/wireless/64-jy-mcu-bluetooth-wireless-serial-port-module-slave
      will work to talk to an Android App Inventor app.

      However, some of the Bluetooth shields are Bluetooth LE (low energy) which is a newer standard that is part of Bluetooth. It provides for low power/long battery life for applications in health care, sensor networks (like security or environmental sensing). Bluetooth LE also requires support in your device (my Nexus 5 has both traditional Bluetooth and Bluetooth LE). But App Inventor does not support the Bluetooth LE mode so we cannot yet write apps directly in App Inventor that communicate with a Bluetooth LE device.

      (I could be wrong here – I looked into this a while ago. I have the parts sitting on my desk and just need to get to work on getting Arduino–BT–App Inventor working!)

      Ed

  5. Vorms says:

    Hello,
    Thanks for the tutorial.
    I have BLE cards from redbearlab (http://redbearlab.com/bleshield/).
    Is this card usable to this app inventor technique ?

    Many thanks for your help,

    Thierry Vorms
    vormsty@gmail.com

    • Edward M says:

      Hi Thierry,

      I have a different Bluetooth LE card – and I have it talking between the Arduino and an Android app supplied by the vendor, running on my Nexus 5 smart phone. But that is not an App Inventor app. My recollection from going through the App Inventor source code itself is that App Inventor does not work with the low energy version of Bluetooth. That said, many Bluetooth devices support both the newer LE standard and also the original Bluetooth standard (e.g. Bluetooth 2.1 and upwards). Without knowing the specifics of that board, you might give it a try and see first if your Android phone device can see the BLE card (probably can), and then write some App Inventor code to see if it can just make a connection.

      Ed

  6. Manuela says:

    Hi Edward,
    I need to create a Multiple bluetooth connections to multiple devices to implement a “chat room”. I don’t know what i do. I read and undestand your article about Bluetooth communications between 2 devices, but i don’t know how to make it between three or four or five, ect device. Could you help me?

    • Edward M says:

      Bluetooth only pairs 2 devices.

      I’m waiting for an airplane flight and can’t lookup anymore right at the moment.

      Ed

  7. Haroon Al Isa says:

    This tutorial saved my project.
    Thanks Edward M,

  8. Bilal says:

    i almost had same project but my app freez when receive byte

  9. Krishna says:

    Hey there, im trying to build an attendance system using bluetooth, i would like to know, how to restrict the server to accept connections ,only from specified mac addresses and also how to link server to a database to store the attendance .

  10. luis Rojas says:

    Muchas gracias hermano, me fue de suma utilidad para una aplicación que estoy realizando, aun me faltan las pruebas finales claro.

  11. Justin Johnson says:

    Hey i tried to access the bluetooth project and test on it but i have a problem everytime i hit accept connection or connect device it freezes. anyway i can select the bluetooth to pair with the bluetooth module from the program?

    • Edward M says:

      A lot of people have this working okay. What type of phone(s) are you using?

      For example, I can get my Android 5 Nexus 5 to talk to an old LG Android 2.2 phone, but I have to jump through hurdles to make it work because of changes in Bluetooth support between those versions.

      Ed

  12. Nadim h khasdar says:

    i made blutooth chat app. when i click listpicker it opens and always shows blank screen. it can’t display BT device name. please tell me what is the mistake is going on?

    • Edward M says:

      It should show the list of known bluetooth devices. Have you “paired” the bluetooth device before running the program?

      For some unknown reason, it seems the App Inventor’s call to get the list of BT devices is returning no devices.

    • Edward M says:

      Did you ever resolve this? Another basic item to check is that Bluetooth is turned on in Android Settings.

      Ed

  13. Gerard says:

    Very helpful, thank you.

  14. Paul Kidman says:

    OK Ed question 2?

    do you know if there is away to link to a bluetooth headset.
    I want to use the button on the headset to work as a click event in my program?

    also your site is good and helpful. I am tempted to make a site with some guides my self.

    • Edward M says:

      Paul,
      This might be possible but would be very complex. App Inventor supports some Bluetooth communications (but not the newer “LE” low energy type) and can likely link to a BT headset. Once the link is established, compatible devices communicate with a “protocol” over the link. For those not familiar with protocols, think of this as defining who talks first on the link and what are appropriate replies and had the data back and forth is formulated. Is it possible for an App Inventor program to implement the protocol to a BT headset? Possibly.

      There are a lot of protocols, for different applications, defined for Bluetooth. You can see a nice summary at Wikipedia https://en.wikipedia.org/wiki/List_of_Bluetooth_protocols.

      I am guessing that the synchronous communications-oriented link is the one that headsets use. The next step would be to search online to see how that protocol is defined and to see if the BT headset and AI code can actually see bits going back and forth.

      Ed

  15. Param Dave says:

    What if we implement in the same screen?

    • Edward M says:

      I think you are asking – could the server and client apps, which I created as 2 separate apps, be combined into one app? Yes, they could. They do not have to be in separate apps. I kept them separate so that the concept of the client and server could be explained in a simple example – combining them into a single app would make the example a little more complicated.

      Ed

  16. James says:

    Is it possible to have the server accept connections from more than one device at a time? Trying to design an attendance app where a lecturer can send out a bluetooth signal and present students can connect and send back their student numbers to be marked as having attended.

    • Edward M says:

      Originally, I thought multiple device support would not be possible. However, Bluetooth does support the concept of up to 7 devices connected to a “master” device (for example, on my Nexus 7, I can use a Bluetooth keyboard and a Bluetooth mouse, simultaneously). The question is, then, does App Inventor support this capability? I do not know the answer to that. But what I would perhaps first try to do is something like the following:

      1. Drag a Bluetooth component (such as the BTServer) into the Designer window.
      2. Drag a second Bluetooth Bluetooth component (another BTServer) into the Designer window.
      3. Implement the connection and receive code for both BTServer components – one will be named BluetoothServer1 and the other will be BluetoothServer2.
      4. Now, get two more Android phones and implement the Client code and see if you can set up two connections – one going to Server1 and the other going to Server2.

      For now, duplicating the code for each Bluetooth channel is going to be the simplest to explain. However, there is a way to write one set of code that can maybe handle both servers – but that would need a whole tutorial on another programming concept before we even get to the Bluetooth part.

      If you try this, let us know how this work? This could be a great tutorial opportunity for the blog!

      Ed

      • Monika Kumar says:

        Hi Ed.This really worked and done a trick..Awsome man!!! I have been working on it as a part of my project and done it..

        • Monika Kumar says:

          I am sorry to disturb..but I have a doubt..is it possible to have many bluetoothclient to be used in client application??I think it works but still i didnot try it out..

          • Edward M says:

            You set up the multiple Bluetooth components? If that works, let us know! And if you wish to share sample code, I could post it here to help others – if this all works!

          • Monika Kumar says:

            Yeah sure Ed..but how to share and can I have multiple client??I tried it but didnot work..

          • Monika Kumar says:

            Ed..can you please help me to display the history of received tetxs in that app??I am using currently file component and im trying it..not sure if it will give me proper result..

          • Edward M says:

            The Bluetooth app that I have does not keep a history of text received. That could be added by putting code in the Timer event handler – where the message is read. There, add the incoming message to a list.

            This tutorial gives some info on reading and writing text files http://appinventor.pevest.com/?p=490

    • Edward M says:

      Also, another thought – it just so happens that I am a volunteer engineering mentor for a FIRST Robotics team (#4488). One of the students is implementing an attendance app in App Inventor.

      Each student has a Team #4488 ID card they are supposed to have with them during each robotics meeting and event. On the card we are printing a QR Code with the student’s ID#. The attendance app does a QR code scan of the student IDs. This does, of course, require the students to sequentially walk by the Nexus 7 tablet we have out at the beginning of meetings.

      I imagine we will be making this code public, once its ready, as our team tries to help out other robotics teams as much as possible. Even if you are not doing robots, you’d be welcome to the code!

      If you want to write your own, I have sample code to scan QR codes available in this tutorial
      http://appinventor.pevest.com/?p=1086

      Ed

      • James says:

        Perfect thanks for the info.
        Yes I’ll try adding the coding for QR Code scanning as another option. So my app will have both Bluetooth Option for recording attendance and a QR Code scanning option.
        Thanks for the help, looking forward to seeing the code for what ye finish with and seeing if I can return any help to ye.

      • JamesF391 says:

        Hi Ed,
        Sorry to be bothering you again.
        Just a thought, do you think its possible to have the app export all the text received to the BluetoothServer as a list, and then using the share function, email it to a specified email address.
        Currently testing your idea of dragging in multiple bluetooth servers to allow multiple connections.
        Thanks for the idea.

        • Edward M says:

          James,

          Yes, you can certainly save the output to a text file stored on the device, and then transfer that file to email or another device using various methods.

          You can find my tutorials on basic text files using this web site search
          http://appinventor.pevest.com/?s=text+files

          I used a free app from the Google Play store called File Manager. I navigated to the text file I created, selected the file (by placing a checkmark to the right of the file) and then sent via email.

          Thus, your ideas should work out fine.

          A more complex approach could even store values into a TinyDB database, or remotely into a cloud-based database using TinyWebDB or Google Fusion Tables. The advantage of the latter approach is that it moves the data into a cloud-based database accessible from a browser or (with Fusion) downloadable to a Google Docs spreadsheet or Microsoft Excel spreadsheet. I describe how to do that in Volume 3 of my e-book series, available from Amazon http://amzn.to/1UxQGSO

          Ed

      • Monika Kumar says:

        Yeah Ed.,I got it …and regarding multiple bluetooth connection you have to add to the accept connection method 7or less servers and that works…Thank you again man!!!!

  17. Lee says:

    Why I sent it possible to have an app that allows me to connect my iPod too 6 Bluetooth speakers at the same time I am trying as we speak to creat this app. Connect 8 Bluetooth headsets to one cell phone to run the office would be nice also

    • Edward M says:

      Lee,

      Classic Bluetooth can support one “master” device paired with up to 7 additional devices. Bluetooth LE (low energy) is a newer kind of Bluetooth (but not backwards compatible with older devices). Bluetooth LE does not have a specific limit on the # of devices that can be connected.

      Based on my past experiments and looking at the MIT App Inventor source code directly, App Inventor works with the “classic” form of Bluetooth and not LE.

      There may be additional useful information here – including in the comments there
      http://appinventor.pevest.com/?p=569

      I have some comments also on how you might connect multiple Bluetooth devices in App Inventor – I have not tried those ideas myself, yet – but worth a try – see here: http://appinventor.pevest.com/?p=520&cpage=1#comment-35746

      Ed

      • Lee says:

        Scenario is I have 6 Budweiser speakers and the iPod will only connect to one at a time also tried iphone 3 same thing

        • Edward M says:

          That is probably a limitation of the iPod / iPhone / iOS software, or the app running on iOS. They may not have envisioned that someone would want to connect one device to multiple speakers – and chose not to implement that feature.

          From the comments on this page, it seems there would be a lot of interest in getting multiple bluetooth links working from one Android device.

          • Monika Kumar says:

            Hi Ed.I have published my bluetooth free chat app on app inventor gallery so you can find the codes there.Thank you Ed.,I think may be it helps you..

  18. James says:

    Hey Guys,
    I tried putting in more servers and replicating the coding for up to 7 servers,unfortunately I only had 3 devices I could test on and was able to receive data to the server device from the 2 client devices at the same time, however I now have an error code appearing in the status area coming up as the following;
    ” Error:com.google.appinventor.components.runtime.BluetoothServer@43821af8,ReceiveText,515,Not connected to a Bluetooth device.”
    I was wondering if any of ye might be able to help me out. Seeing as I know when I replicated the code for just 2 client devices and there was no error that data transmission was possible and genereal bluetooth capabilities allow up to 7 clients, I was wondering could ye help me or give me an an opinion with the error. Is this coming up because not all 7 bluetooth servers have a client connected? I can still receive data as I have another label to show the text received via bluetooth but the error stays in the status label. So to say if I connected 7 clients to the 7 servers the error may go away? Or is there a different reason for this? Any help would be great.

  19. Garvin says:

    Hello, is there an app where two wireless ear pieces can talk together using Bluetooth and no cell service? Thanks

    • Edward M says:

      Check the Google Play store. I suspect there are free apps that will do this where you can connect your bluetooth earpiece to your phone, and then use your phone to talk to another Android phone over Wi-Fi. There are plenty of Android to Android over WiFi apps in the Google Play store.

      Ed

  20. mauros says:

    It was realy helpful!!!!..thank you!

  21. ash says:

    package com.raw.arview;

    import java.io.IOException;
    import java.util.Collections;
    import java.util.Iterator;
    import java.util.List;
    import java.lang.Integer;
    import java.lang.Float;
    import java.lang.Math;
    import java.util.UUID;

    import android.app.Activity;
    import android.bluetooth.BluetoothAdapter;
    import android.content.Context;
    import android.content.Intent;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Path;
    import android.graphics.RectF;
    import android.hardware.Camera;
    import android.hardware.Sensor;
    import android.hardware.SensorEvent;
    import android.hardware.SensorEventListener;
    import android.hardware.SensorManager;
    import android.os.Bundle;
    import android.os.PowerManager;
    import android.os.PowerManager.WakeLock;
    import android.util.DisplayMetrics;
    import android.util.Log;
    import android.util.TypedValue;
    import android.view.Gravity;
    import android.view.MotionEvent;
    import android.view.SurfaceHolder;
    import android.view.SurfaceView;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.view.View.OnTouchListener;
    import android.view.ViewGroup.LayoutParams;
    import android.view.Window;
    import android.view.WindowManager;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.FrameLayout;
    import android.widget.RelativeLayout;
    import android.widget.TextView;
    import android.widget.Toast;
    import com.raw.utils.Compatibility;
    import com.raw.utils.PaintUtils;
    import android.graphics.Paint;

    import android.app.Activity;
    import android.bluetooth.BluetoothAdapter;
    import android.bluetooth.BluetoothServerSocket;
    import android.bluetooth.BluetoothSocket;
    import android.content.Intent;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Message;
    import android.util.Log;
    import android.view.Gravity;
    import android.widget.EditText;
    import android.view.Gravity;

    public class ARView extends Activity implements SensorEventListener{

    private static Context _context;
    WakeLock mWakeLock;
    CameraView cameraView;
    RadarMarkerView radarMarkerView;
    public RelativeLayout upperLayerLayout;
    static PaintUtils paintScreen;
    static DataView dataView;
    boolean isInited = false;
    public static float azimuth;
    public static float pitch;
    public static float roll;
    public double latitudeprevious;
    public double longitude;
    String locationContext;
    String provider;
    DisplayMetrics displayMetrics;
    Camera camera;
    public int screenWidth;
    public int screenHeight;

    private float RTmp[] = new float[9];
    private float Rot[] = new float[9];
    private float I[] = new float[9];
    private float grav[] = new float[3];
    private float mag[] = new float[3];
    private float results[] = new float[3];
    private SensorManager sensorMgr;
    private List sensors;
    private Sensor sensorGrav, sensorMag;

    static final float ALPHA = 0.25f;
    protected float[] gravSensorVals;
    protected float[] magSensorVals;

    //……..bluetooth

    public static final int MESSAGE_READ = 1;

    private static final String TAG = “BluetoothServer”;
    private static final boolean DEBUG = true;

    private static final UUID MY_UUID = UUID.fromString(“000011008-0000-1000-8000-00805F9B34FB”);
    private static final int REQUEST_ENABLE_BT = 3;

    private BluetoothAdapter mBTAdapter;
    private AcceptThread mAcceptThread;
    private EditText view;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    final PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
    this.mWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, “”);
    //getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);

    displayMetrics = new DisplayMetrics();
    getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);

    screenHeight = displayMetrics.heightPixels;
    screenWidth = displayMetrics.widthPixels;

    screenHeight = 480;
    screenWidth = 640;

    upperLayerLayout = new RelativeLayout(this);
    RelativeLayout.LayoutParams upperLayerLayoutParams = new RelativeLayout.LayoutParams(android.widget.RelativeLayout.LayoutParams.FILL_PARENT, android.widget.RelativeLayout.LayoutParams.FILL_PARENT);
    upperLayerLayout.setLayoutParams(upperLayerLayoutParams);
    upperLayerLayout.setBackgroundColor(Color.TRANSPARENT);

    _context = this;
    cameraView = new CameraView(this);
    radarMarkerView = new RadarMarkerView(this, displayMetrics, upperLayerLayout);

    displayMetrics = new DisplayMetrics();
    getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);

    requestWindowFeature(Window.FEATURE_NO_TITLE);

    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    view = (EditText)findViewById(R.id.editText1);
    view.setGravity(Gravity.TOP | Gravity.LEFT);

    mBTAdapter = BluetoothAdapter.getDefaultAdapter();
    if (mBTAdapter == null) {
    Log.i(TAG, “device does not support Bluetooth”);
    }

    FrameLayout headerFrameLayout = new FrameLayout(this);
    /*RelativeLayout headerRelativeLayout = new RelativeLayout(this);
    RelativeLayout.LayoutParams relaLayoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.FILL_PARENT, RelativeLayout.LayoutParams.FILL_PARENT);
    headerRelativeLayout.setBackgroundColor(Color.BLACK);
    headerRelativeLayout.setLayoutParams(relaLayoutParams);
    Button button = new Button(this);
    RelativeLayout.LayoutParams buttonparams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
    buttonparams.addRule(RelativeLayout.ALIGN_PARENT_LEFT, RelativeLayout.TRUE);
    button.setLayoutParams(buttonparams);
    button.setText(“Cancel”);
    button.setPadding(15, 0, 15, 0);

    TextView titleTextView = new TextView(this);
    RelativeLayout.LayoutParams textparams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
    textparams.addRule(RelativeLayout.CENTER_HORIZONTAL, RelativeLayout.TRUE);
    textparams.addRule(RelativeLayout.CENTER_VERTICAL, RelativeLayout.TRUE);
    titleTextView.setLayoutParams(textparams);
    titleTextView.setText(“Augmented Reality View”); */

    //headerRelativeLayout.addView(button);
    //headerRelativeLayout.addView(titleTextView);
    //headerFrameLayout.addView(headerRelativeLayout);
    setContentView(cameraView);
    addContentView(radarMarkerView, new LayoutParams(
    LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
    //addContentView(headerFrameLayout, new FrameLayout.LayoutParams(
    // LayoutParams.FILL_PARENT, 44,
    // Gravity.TOP));
    addContentView(upperLayerLayout, upperLayerLayoutParams);

    if(!isInited){
    dataView = new DataView(ARView.this);
    paintScreen = new PaintUtils();
    isInited = true;
    }

    upperLayerLayout.setOnClickListener(new OnClickListener() {

    @Override
    public void onClick(View v) {
    Toast.makeText(_context, “RELATIVE LAYOUT CLICKED”, Toast.LENGTH_SHORT).show();
    }
    });

    cameraView.setOnTouchListener(new OnTouchListener() {

    @Override
    public boolean onTouch(View arg0, MotionEvent event) {

    for (int i = 0 ; i < dataView.coordinateArray.length; i++) {
    if((int)event.getX() dataView.coordinateArray[i][0]){
    if((int)event.getY() dataView.coordinateArray[i][1]){
    Toast.makeText(_context, “match Found its “+dataView.places[i], Toast.LENGTH_SHORT).show();
    return false;
    }
    }
    }
    return true;
    }
    });
    }

    public static Context getContext() {
    return _context;
    }

    public int convertToPix(int val){
    float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10, _context.getResources().getDisplayMetrics());
    return (int)px;

    }
    @Override
    protected void onDestroy() {
    super.onDestroy();

    }

    @Override
    protected void onStart() {
    super.onStart();

    if (!mBTAdapter.isEnabled()) {
    Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
    startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
    }
    else {
    setDiscoveralbe();
    }
    }

    @Override
    protected void onPause() {
    super.onPause();
    this.mWakeLock.release();
    mAcceptThread.cancel();
    super.onPause();
    sensorMgr.unregisterListener(this, sensorGrav);
    sensorMgr.unregisterListener(this, sensorMag);
    sensorMgr = null;
    }

    @Override
    protected void onResume() {

    super.onResume();
    this.mWakeLock.acquire();

    mAcceptThread = new AcceptThread();
    mAcceptThread.start();
    sensorMgr = (SensorManager) getSystemService(SENSOR_SERVICE);

    sensors = sensorMgr.getSensorList(Sensor.TYPE_ACCELEROMETER);
    if (sensors.size() > 0) {
    sensorGrav = sensors.get(0);
    }

    sensors = sensorMgr.getSensorList(Sensor.TYPE_MAGNETIC_FIELD);
    if (sensors.size() > 0) {
    sensorMag = sensors.get(0);
    }

    sensorMgr.registerListener(this, sensorGrav, SensorManager.SENSOR_DELAY_NORMAL);
    sensorMgr.registerListener(this, sensorMag, SensorManager.SENSOR_DELAY_NORMAL);
    }

    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == REQUEST_ENABLE_BT) {
    if (resultCode == Activity.RESULT_OK) {
    view.append(“Enabled BT\n”);

    setDiscoveralbe();
    }
    }
    super.onActivityResult(requestCode, resultCode, data);
    }

    private class AcceptThread extends Thread {
    private final BluetoothServerSocket mmServerSocket;

    public AcceptThread() {
    BluetoothServerSocket tmp = null;
    try {
    tmp = mBTAdapter.listenUsingRfcommWithServiceRecord(“BluetoothServer”, MY_UUID);
    }
    catch (IOException e) { }
    mmServerSocket = tmp;
    }

    @Override
    public void run() {
    BluetoothSocket socket = null;
    while (true) {
    try {
    socket = mmServerSocket.accept();
    }
    catch (IOException e) {
    break;
    }

    if (socket != null) {
    manageConnectedSocket(socket);
    try {
    mmServerSocket.close();
    } catch (IOException e) {
    }
    break;
    }
    }
    }

    public void cancel() {
    try {
    mmServerSocket.close();
    }
    catch (IOException e) { }
    }
    }

    public void manageConnectedSocket(BluetoothSocket socket) {
    if (DEBUG) Log.d(TAG, “Connected”);
    com.raw.arview.ConnectedThread server = new com.raw.arview.ConnectedThread(mHandler, socket);
    server.start();
    }

    private final Handler mHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
    switch (msg.what) {
    case MESSAGE_READ:
    byte[] readBuf = (byte[])msg.obj;
    String readMessage = new String(readBuf, 0, msg.arg1);
    view.append(readMessage);
    }
    }
    };

    private void setDiscoveralbe() {
    view.append(“set BT as being discoverable during 2 minutes\n”);
    Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
    discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 120); // 2 minutes
    startActivity(discoverableIntent);
    }

    @Override
    public void onAccuracyChanged(Sensor arg0, int arg1) {

    }

    @Override
    public void onSensorChanged(SensorEvent evt) {

    if (evt.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
    gravSensorVals = lowPass(evt.values.clone(), gravSensorVals);
    grav[0] = evt.values[0];
    grav[1] = evt.values[1];
    grav[2] = evt.values[2];

    } else if (evt.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
    magSensorVals = lowPass(evt.values.clone(), magSensorVals);
    mag[0] = evt.values[0];
    mag[1] = evt.values[1];
    mag[2] = evt.values[2];

    }

    if (gravSensorVals != null && magSensorVals != null) {
    boolean success = SensorManager.getRotationMatrix(RTmp, I, gravSensorVals, magSensorVals);

    int rotation = Compatibility.getRotation(this);

    /*if (rotation == 1) {
    SensorManager.remapCoordinateSystem(RTmp, SensorManager.AXIS_X, SensorManager.AXIS_MINUS_Z, Rot);
    } else {
    SensorManager.remapCoordinateSystem(RTmp, SensorManager.AXIS_Y, SensorManager.AXIS_MINUS_Z, Rot);
    }

    if(success) {
    SensorManager.getOrientation(Rot, results);

    ARView.azimuth = (float) (((results[0] * 180) / Math.PI) + 180);
    ARView.pitch = (float) (((results[1] * 180 / Math.PI)) + 90);
    ARView.roll = (float) (((results[2] * 180 / Math.PI)));

    }*/

    if (success) {
    SensorManager.getOrientation(RTmp, results);
    ARView.azimuth = results[0];
    ARView.pitch = results[1];
    ARView.roll = results[2];
    }

    radarMarkerView.postInvalidate();
    }

    }

    protected float[] lowPass( float[] input, float[] output ) {
    if ( output == null ) return input;

    for ( int i=0; i<input.length; i++ ) {
    output[i] = output[i] + ALPHA * (input[i] – output[i]);
    }
    return output;
    }
    }
    class CameraView extends SurfaceView implements SurfaceHolder.Callback {

    ARView arView;
    SurfaceHolder holder;
    Camera camera;

    public CameraView(Context context) {
    super(context);
    arView = (ARView) context;

    holder = getHolder();
    holder.addCallback(this);
    holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
    try {
    Camera.Parameters parameters = camera.getParameters();
    try {
    List supportedSizes = null;
    supportedSizes = com.raw.utils.Compatibility.getSupportedPreviewSizes(parameters);

    Iterator itr = supportedSizes.iterator();
    while(itr.hasNext()) {
    Camera.Size element = itr.next();
    element.width -= w;
    element.height -= h;
    }
    Collections.sort(supportedSizes, new ResolutionsOrder());
    //parameters.setPreviewSize(w + supportedSizes.get(supportedSizes.size()-1).width, h + supportedSizes.get(supportedSizes.size()-1).height);
    parameters.setPreviewSize(arView.screenWidth , arView.screenHeight);
    } catch (Exception ex) {
    parameters.setPreviewSize(arView.screenWidth , arView.screenHeight);
    }

    camera.setParameters(parameters);
    camera.startPreview();
    } catch (Exception ex) {
    ex.printStackTrace();
    }
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
    try {
    if (camera != null) {
    try {
    camera.stopPreview();
    } catch (Exception ignore) {
    }
    try {
    camera.release();
    } catch (Exception ignore) {
    }
    camera = null;
    }

    camera = Camera.open();
    arView.camera = camera;
    camera.setPreviewDisplay(holder);
    } catch (Exception ex) {
    try {
    if (camera != null) {
    try {
    camera.stopPreview();
    } catch (Exception ignore) {
    }
    try {
    camera.release();
    } catch (Exception ignore) {
    }
    camera = null;
    }
    } catch (Exception ignore) {

    }
    }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
    try {
    if (camera != null) {
    try {
    camera.stopPreview();
    } catch (Exception ignore) {
    }
    try {
    camera.release();
    } catch (Exception ignore) {
    }
    camera = null;
    }
    } catch (Exception ex) {
    ex.printStackTrace();
    }
    }

    }
    class RadarMarkerView extends View{

    String dataa = “Azimuth”;
    String datab = “Pitch”;
    String datac = “Roll”;
    String deg = “°”;
    String senvalve = “”;
    String pitvalve = “”;
    public int pitch = 0;
    public int roll = 0;
    public int azimuth = 0;

    public int pitchscale = 0;

    public double azimuthdeg = 0.0d;
    public double pitchdeg = 0.0d;
    public double rolldeg = 0.0d;
    public float azi =0.0f;

    Paint mPaint = new Paint();
    ARView arView;
    DisplayMetrics displayMetrics;
    RelativeLayout upperLayoutView = null;
    public RadarMarkerView(Context context, DisplayMetrics displayMetrics, RelativeLayout rel) {
    super(context);
    mPaint.setColor(Color.GREEN);
    mPaint.setTextSize(35);
    //mPaint.setStrokeWidth(1 / getResources().getDisplayMetrics().density);
    mPaint.setStrokeWidth(6);
    mPaint.setAntiAlias(true);

    arView = (ARView) context;
    this.displayMetrics = displayMetrics;
    upperLayoutView = rel;
    }

    @Override
    protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    ARView.paintScreen.setWidth(canvas.getWidth());
    ARView.paintScreen.setHeight(canvas.getHeight());
    ARView.paintScreen.setCanvas(canvas);

    if (!ARView.dataView.isInited()) {
    ARView.dataView.init(ARView.paintScreen.getWidth(), ARView.paintScreen.getHeight(),arView.camera, displayMetrics,upperLayoutView);
    }

    //ARView.dataView.draw(ARView.paintScreen, ARView.azimuth, ARView.pitch, ARView.roll);

    ARView.dataView.draw(ARView.paintScreen, azi, ARView.pitch, ARView.roll);

    ////////////////////////// arc begin

    float width = (float)getWidth();
    float height = (float)getHeight();
    float radius;

    if (width > height){

    radius = height/3;

    }else{

    radius = width/2;
    }

    Path path = new Path();

    path.addCircle(width/2,

    height/2,radius,

    Path.Direction.CW);

    Paint paint = new Paint();

    paint.setColor(Color.GREEN);

    paint.setStrokeWidth(5);

    paint.setStyle(Paint.Style.FILL);

    float center_x, center_y;
    final RectF oval = new RectF();

    paint.setStyle(Paint.Style.STROKE);
    center_x = width/2;

    center_y = height / 2;

    oval.set(center_x – radius,

    center_y – radius,

    center_x + radius,

    center_y + radius);

    canvas.drawArc(oval, 210, 120, false, paint);
    ///arc ends

    mPaint.setTextSize(25f);

    //azimuth center horizontal lines
    //canvas.drawLine(442, 70, 517, 70, mPaint);
    //canvas.drawText(“15”, 432, 78, mPaint);
    //canvas.drawText(“15”, 527, 78, mPaint);

    canvas.drawLine(392,130,567,130,mPaint);
    canvas.drawText(“10”, 352, 138, mPaint);
    canvas.drawText(“10”, 577, 138, mPaint);

    canvas.drawLine(442,190,517,190,mPaint);
    canvas.drawText(“5”, 412, 198, mPaint);
    canvas.drawText(“5”, 527, 198, mPaint);

    canvas.drawLine(392,220,567,220,mPaint);
    canvas.drawText(“0”, 372, 228, mPaint);
    canvas.drawText(“0”, 577, 228, mPaint);

    canvas.drawLine(442,280,517,280,mPaint);
    canvas.drawText(“-5”, 408, 288, mPaint);
    canvas.drawText(“-5”, 527, 288, mPaint);

    canvas.drawLine(392,340,567,340,mPaint);
    canvas.drawText(“-10”, 348, 348, mPaint);
    canvas.drawText(“-10”, 577, 348, mPaint);
    //displaying plus on screen

    // canvas.drawLine(480,220,480,320, mPaint); //plus vertical
    // canvas.drawLine(430, 270, 530, 270, mPaint); //plus horizontal

    // targent square sign

    // canvas.drawLine(430,170,380,170,mPaint); //top corner left h line
    // canvas.drawLine(380,170,380,220,mPaint); //top corner left v line
    // canvas.drawLine(380,320,380,370,mPaint); //bottom corner left v line
    // canvas.drawLine(380,370,430,370,mPaint); //bottom corner left h line
    // canvas.drawLine(530,370,580,370,mPaint); //bottom corner right h line
    // canvas.drawLine(580,370,580,320,mPaint); //bottom corner right v line
    // canvas.drawLine(580,220,580,170,mPaint); //top corner right v line
    // canvas.drawLine(580, 170, 530, 170, mPaint); //top corner right h line

    //top header line
    canvas.drawLine(330,50,630,50,mPaint);
    //reading lines for top header
    canvas.drawLine(330,5,330,50,mPaint);
    canvas.drawLine(355,20,355,50,mPaint);
    canvas.drawLine(380,5,380,50,mPaint);
    canvas.drawLine(405,20,405,50,mPaint);
    canvas.drawLine(430,5,430,50,mPaint);
    canvas.drawLine(455,20,455,50,mPaint);
    canvas.drawLine(480,5,480,50,mPaint);
    canvas.drawLine(505,20,505,50,mPaint);
    canvas.drawLine(530,5,530,50,mPaint);
    canvas.drawLine(555,20,555,50, mPaint);
    canvas.drawLine(580,5,580,50,mPaint);
    canvas.drawLine(605,20,605,50, mPaint);
    canvas.drawLine(630,5,630,50,mPaint);

    // vertical left speed line
    canvas.drawLine(80, 170, 80, 470, mPaint);
    // reading scale for speed

    canvas.drawLine(60, 170, 80, 170, mPaint);
    pitvalve = Integer.toString(pitchscale+30);
    canvas.drawText(pitvalve, 20, 178, mPaint);
    canvas.drawLine(60, 220, 80, 220, mPaint);
    pitvalve = Integer.toString(pitchscale+20);
    canvas.drawText(pitvalve, 20, 228, mPaint);
    canvas.drawLine(60, 270, 80, 270, mPaint);
    pitvalve = Integer.toString(pitchscale+10);
    canvas.drawText(pitvalve, 20, 278, mPaint);
    canvas.drawLine(60, 320, 80, 320, mPaint);
    pitvalve = Integer.toString(pitchscale);
    canvas.drawText(pitvalve, 20, 328, mPaint);
    canvas.drawLine(60, 370, 80, 370, mPaint);
    pitvalve = Integer.toString(pitchscale-10);
    canvas.drawText(pitvalve, 10, 378, mPaint);
    canvas.drawLine(60, 420, 80, 420, mPaint);
    pitvalve = Integer.toString(pitchscale-20);
    canvas.drawText(pitvalve, 10, 428, mPaint);
    canvas.drawLine(60, 470, 80, 470, mPaint);
    pitvalve = Integer.toString(pitchscale-30);
    canvas.drawText(pitvalve, 10, 478, mPaint);

    // vertical right ALT line
    canvas.drawLine(880, 170, 880, 470, mPaint);
    // reading lines for ALT line
    canvas.drawLine(880, 170, 900, 170, mPaint);
    canvas.drawText(“30”, 920, 178, mPaint);
    canvas.drawLine(880, 220, 900, 220, mPaint);
    canvas.drawText(“20”, 920, 228, mPaint);
    canvas.drawLine(880, 270, 900, 270, mPaint);
    canvas.drawText(“10”, 920, 278, mPaint);
    canvas.drawLine(880, 320, 900, 320, mPaint);
    canvas.drawText(“0”, 920, 328, mPaint);
    canvas.drawLine(880, 370, 900, 370, mPaint);
    canvas.drawText(“-10”, 910, 378, mPaint);
    canvas.drawLine(880, 420, 900, 420, mPaint);
    canvas.drawText(“-20”, 910, 428, mPaint);
    canvas.drawLine(880, 470, 900, 470, mPaint);
    canvas.drawText(“-30”, 910, 478, mPaint);

    // pointer for speed reading
    canvas.drawLine(80, 320, 110, 300, mPaint);
    canvas.drawLine(110, 300, 140, 300, mPaint);
    canvas.drawLine(140, 300, 140, 340, mPaint);
    canvas.drawLine(140, 340, 110, 340, mPaint);
    canvas.drawLine(110, 340, 80, 320, mPaint);
    pitvalve = Integer.toString(pitchscale);
    canvas.drawText(pitvalve, 120, 328, mPaint);

    // pointer for ALT reading
    canvas.drawLine(880, 320, 850, 300, mPaint);
    canvas.drawLine(850, 300, 820, 300, mPaint);
    canvas.drawLine(820, 300, 820, 340, mPaint);
    canvas.drawLine(820, 340, 850, 340, mPaint);
    canvas.drawLine(850, 340, 880, 320, mPaint);
    canvas.drawText(“0”, 835, 328, mPaint);

    canvas.drawText(datab, 160.0f, 478.0f, mPaint);
    pitchdeg = Math.toDegrees(ARView.pitch);
    pitch = (int)pitchdeg;

    if(pitch < 0) {
    pitch = pitch + 90;
    }
    else
    {
    pitch = pitch – 90;
    }
    pitchscale = pitch;
    senvalve = Integer.toString(pitch);
    canvas.drawText(senvalve, 225.0f, 478.0f, mPaint);
    canvas.drawText(deg, 265.0f, 478.0f, mPaint);

    canvas.drawText(datac, 280.0f, 478.0f, mPaint);
    rolldeg = Math.toDegrees(ARView.roll);
    /*intervalve = (float)rolldeg;
    senvalve = Float.toString(intervalve);*/
    roll = (int)rolldeg;
    senvalve = Integer.toString(roll);
    canvas.drawText(senvalve, 330.0f, 478.0f, mPaint);
    canvas.drawText(deg, 370.0f, 478.0f, mPaint);

    canvas.drawText(dataa, 400.0f, 478.0f, mPaint);
    azimuthdeg = Math.toDegrees(ARView.azimuth);
    if (azimuthdeg < 0.0){
    azimuthdeg = azimuthdeg + 360.0f;
    }
    azi = (float) azimuthdeg;
    azimuth = (int)azimuthdeg;
    senvalve = Integer.toString(azimuth);
    canvas.drawText(senvalve, 505.0f, 478.0f, mPaint);
    canvas.drawText(deg, 560.0f, 478.0f, mPaint);

    }
    }
    class ResolutionsOrder implements java.util.Comparator {
    public int compare(Camera.Size left, Camera.Size right) {

    return Float.compare(left.width + left.height, right.width + right.height);
    }
    }

  22. ash says:

    Please explain the following code and how Bluetooth works so that i can redraw on ondraw method. Further can be displayed on the screen.
    package com.raw.arview;

    import java.io.IOException;
    import java.util.Collections;
    import java.util.Iterator;
    import java.util.List;
    import java.lang.Integer;
    import java.lang.Float;
    import java.lang.Math;
    import java.util.UUID;

    import android.app.Activity;
    import android.bluetooth.BluetoothAdapter;
    import android.content.Context;
    import android.content.Intent;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Path;
    import android.graphics.RectF;
    import android.hardware.Camera;
    import android.hardware.Sensor;
    import android.hardware.SensorEvent;
    import android.hardware.SensorEventListener;
    import android.hardware.SensorManager;
    import android.os.Bundle;
    import android.os.PowerManager;
    import android.os.PowerManager.WakeLock;
    import android.util.DisplayMetrics;
    import android.util.Log;
    import android.util.TypedValue;
    import android.view.Gravity;
    import android.view.MotionEvent;
    import android.view.SurfaceHolder;
    import android.view.SurfaceView;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.view.View.OnTouchListener;
    import android.view.ViewGroup.LayoutParams;
    import android.view.Window;
    import android.view.WindowManager;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.FrameLayout;
    import android.widget.RelativeLayout;
    import android.widget.TextView;
    import android.widget.Toast;
    import com.raw.utils.Compatibility;
    import com.raw.utils.PaintUtils;
    import android.graphics.Paint;

    import android.app.Activity;
    import android.bluetooth.BluetoothAdapter;
    import android.bluetooth.BluetoothServerSocket;
    import android.bluetooth.BluetoothSocket;
    import android.content.Intent;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Message;
    import android.util.Log;
    import android.view.Gravity;
    import android.widget.EditText;
    import android.view.Gravity;

    public class ARView extends Activity implements SensorEventListener{

    private static Context _context;
    WakeLock mWakeLock;
    CameraView cameraView;
    RadarMarkerView radarMarkerView;
    public RelativeLayout upperLayerLayout;
    static PaintUtils paintScreen;
    static DataView dataView;
    boolean isInited = false;
    public static float azimuth;
    public static float pitch;
    public static float roll;
    public double latitudeprevious;
    public double longitude;
    String locationContext;
    String provider;
    DisplayMetrics displayMetrics;
    Camera camera;
    public int screenWidth;
    public int screenHeight;

    private float RTmp[] = new float[9];
    private float Rot[] = new float[9];
    private float I[] = new float[9];
    private float grav[] = new float[3];
    private float mag[] = new float[3];
    private float results[] = new float[3];
    private SensorManager sensorMgr;
    private List sensors;
    private Sensor sensorGrav, sensorMag;

    static final float ALPHA = 0.25f;
    protected float[] gravSensorVals;
    protected float[] magSensorVals;

    //……..bluetooth

    public static final int MESSAGE_READ = 1;

    private static final String TAG = “BluetoothServer”;
    private static final boolean DEBUG = true;

    private static final UUID MY_UUID = UUID.fromString(“000011008-0000-1000-8000-00805F9B34FB”);
    private static final int REQUEST_ENABLE_BT = 3;

    private BluetoothAdapter mBTAdapter;
    private AcceptThread mAcceptThread;
    private EditText view;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    final PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
    this.mWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, “”);
    //getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);

    displayMetrics = new DisplayMetrics();
    getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);

    screenHeight = displayMetrics.heightPixels;
    screenWidth = displayMetrics.widthPixels;

    screenHeight = 480;
    screenWidth = 640;

    upperLayerLayout = new RelativeLayout(this);
    RelativeLayout.LayoutParams upperLayerLayoutParams = new RelativeLayout.LayoutParams(android.widget.RelativeLayout.LayoutParams.FILL_PARENT, android.widget.RelativeLayout.LayoutParams.FILL_PARENT);
    upperLayerLayout.setLayoutParams(upperLayerLayoutParams);
    upperLayerLayout.setBackgroundColor(Color.TRANSPARENT);

    _context = this;
    cameraView = new CameraView(this);
    radarMarkerView = new RadarMarkerView(this, displayMetrics, upperLayerLayout);

    displayMetrics = new DisplayMetrics();
    getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);

    requestWindowFeature(Window.FEATURE_NO_TITLE);

    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    view = (EditText)findViewById(R.id.editText1);
    view.setGravity(Gravity.TOP | Gravity.LEFT);

    mBTAdapter = BluetoothAdapter.getDefaultAdapter();
    if (mBTAdapter == null) {
    Log.i(TAG, “device does not support Bluetooth”);
    }

    FrameLayout headerFrameLayout = new FrameLayout(this);
    /*RelativeLayout headerRelativeLayout = new RelativeLayout(this);
    RelativeLayout.LayoutParams relaLayoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.FILL_PARENT, RelativeLayout.LayoutParams.FILL_PARENT);
    headerRelativeLayout.setBackgroundColor(Color.BLACK);
    headerRelativeLayout.setLayoutParams(relaLayoutParams);
    Button button = new Button(this);
    RelativeLayout.LayoutParams buttonparams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
    buttonparams.addRule(RelativeLayout.ALIGN_PARENT_LEFT, RelativeLayout.TRUE);
    button.setLayoutParams(buttonparams);
    button.setText(“Cancel”);
    button.setPadding(15, 0, 15, 0);

    TextView titleTextView = new TextView(this);
    RelativeLayout.LayoutParams textparams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
    textparams.addRule(RelativeLayout.CENTER_HORIZONTAL, RelativeLayout.TRUE);
    textparams.addRule(RelativeLayout.CENTER_VERTICAL, RelativeLayout.TRUE);
    titleTextView.setLayoutParams(textparams);
    titleTextView.setText(“Augmented Reality View”); */

    //headerRelativeLayout.addView(button);
    //headerRelativeLayout.addView(titleTextView);
    //headerFrameLayout.addView(headerRelativeLayout);
    setContentView(cameraView);
    addContentView(radarMarkerView, new LayoutParams(
    LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
    //addContentView(headerFrameLayout, new FrameLayout.LayoutParams(
    // LayoutParams.FILL_PARENT, 44,
    // Gravity.TOP));
    addContentView(upperLayerLayout, upperLayerLayoutParams);

    if(!isInited){
    dataView = new DataView(ARView.this);
    paintScreen = new PaintUtils();
    isInited = true;
    }

    upperLayerLayout.setOnClickListener(new OnClickListener() {

    @Override
    public void onClick(View v) {
    Toast.makeText(_context, “RELATIVE LAYOUT CLICKED”, Toast.LENGTH_SHORT).show();
    }
    });

    cameraView.setOnTouchListener(new OnTouchListener() {

    @Override
    public boolean onTouch(View arg0, MotionEvent event) {

    for (int i = 0 ; i < dataView.coordinateArray.length; i++) {
    if((int)event.getX() dataView.coordinateArray[i][0]){
    if((int)event.getY() dataView.coordinateArray[i][1]){
    Toast.makeText(_context, “match Found its “+dataView.places[i], Toast.LENGTH_SHORT).show();
    return false;
    }
    }
    }
    return true;
    }
    });
    }

    public static Context getContext() {
    return _context;
    }

    public int convertToPix(int val){
    float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10, _context.getResources().getDisplayMetrics());
    return (int)px;

    }
    @Override
    protected void onDestroy() {
    super.onDestroy();

    }

    @Override
    protected void onStart() {
    super.onStart();

    if (!mBTAdapter.isEnabled()) {
    Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
    startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
    }
    else {
    setDiscoveralbe();
    }
    }

    @Override
    protected void onPause() {
    super.onPause();
    this.mWakeLock.release();
    mAcceptThread.cancel();
    super.onPause();
    sensorMgr.unregisterListener(this, sensorGrav);
    sensorMgr.unregisterListener(this, sensorMag);
    sensorMgr = null;
    }

    @Override
    protected void onResume() {

    super.onResume();
    this.mWakeLock.acquire();

    mAcceptThread = new AcceptThread();
    mAcceptThread.start();
    sensorMgr = (SensorManager) getSystemService(SENSOR_SERVICE);

    sensors = sensorMgr.getSensorList(Sensor.TYPE_ACCELEROMETER);
    if (sensors.size() > 0) {
    sensorGrav = sensors.get(0);
    }

    sensors = sensorMgr.getSensorList(Sensor.TYPE_MAGNETIC_FIELD);
    if (sensors.size() > 0) {
    sensorMag = sensors.get(0);
    }

    sensorMgr.registerListener(this, sensorGrav, SensorManager.SENSOR_DELAY_NORMAL);
    sensorMgr.registerListener(this, sensorMag, SensorManager.SENSOR_DELAY_NORMAL);
    }

    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == REQUEST_ENABLE_BT) {
    if (resultCode == Activity.RESULT_OK) {
    view.append(“Enabled BT\n”);

    setDiscoveralbe();
    }
    }
    super.onActivityResult(requestCode, resultCode, data);
    }

    private class AcceptThread extends Thread {
    private final BluetoothServerSocket mmServerSocket;

    public AcceptThread() {
    BluetoothServerSocket tmp = null;
    try {
    tmp = mBTAdapter.listenUsingRfcommWithServiceRecord(“BluetoothServer”, MY_UUID);
    }
    catch (IOException e) { }
    mmServerSocket = tmp;
    }

    @Override
    public void run() {
    BluetoothSocket socket = null;
    while (true) {
    try {
    socket = mmServerSocket.accept();
    }
    catch (IOException e) {
    break;
    }

    if (socket != null) {
    manageConnectedSocket(socket);
    try {
    mmServerSocket.close();
    } catch (IOException e) {
    }
    break;
    }
    }
    }

    public void cancel() {
    try {
    mmServerSocket.close();
    }
    catch (IOException e) { }
    }
    }

    public void manageConnectedSocket(BluetoothSocket socket) {
    if (DEBUG) Log.d(TAG, “Connected”);
    com.raw.arview.ConnectedThread server = new com.raw.arview.ConnectedThread(mHandler, socket);
    server.start();
    }

    private final Handler mHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
    switch (msg.what) {
    case MESSAGE_READ:
    byte[] readBuf = (byte[])msg.obj;
    String readMessage = new String(readBuf, 0, msg.arg1);
    view.append(readMessage);
    }
    }
    };

    private void setDiscoveralbe() {
    view.append(“set BT as being discoverable during 2 minutes\n”);
    Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
    discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 120); // 2 minutes
    startActivity(discoverableIntent);
    }

    @Override
    public void onAccuracyChanged(Sensor arg0, int arg1) {

    }

    @Override
    public void onSensorChanged(SensorEvent evt) {

    if (evt.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
    gravSensorVals = lowPass(evt.values.clone(), gravSensorVals);
    grav[0] = evt.values[0];
    grav[1] = evt.values[1];
    grav[2] = evt.values[2];

    } else if (evt.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
    magSensorVals = lowPass(evt.values.clone(), magSensorVals);
    mag[0] = evt.values[0];
    mag[1] = evt.values[1];
    mag[2] = evt.values[2];

    }

    if (gravSensorVals != null && magSensorVals != null) {
    boolean success = SensorManager.getRotationMatrix(RTmp, I, gravSensorVals, magSensorVals);

    int rotation = Compatibility.getRotation(this);

    /*if (rotation == 1) {
    SensorManager.remapCoordinateSystem(RTmp, SensorManager.AXIS_X, SensorManager.AXIS_MINUS_Z, Rot);
    } else {
    SensorManager.remapCoordinateSystem(RTmp, SensorManager.AXIS_Y, SensorManager.AXIS_MINUS_Z, Rot);
    }

    if(success) {
    SensorManager.getOrientation(Rot, results);

    ARView.azimuth = (float) (((results[0] * 180) / Math.PI) + 180);
    ARView.pitch = (float) (((results[1] * 180 / Math.PI)) + 90);
    ARView.roll = (float) (((results[2] * 180 / Math.PI)));

    }*/

    if (success) {
    SensorManager.getOrientation(RTmp, results);
    ARView.azimuth = results[0];
    ARView.pitch = results[1];
    ARView.roll = results[2];
    }

    radarMarkerView.postInvalidate();
    }

    }

    protected float[] lowPass( float[] input, float[] output ) {
    if ( output == null ) return input;

    for ( int i=0; i<input.length; i++ ) {
    output[i] = output[i] + ALPHA * (input[i] – output[i]);
    }
    return output;
    }
    }
    class CameraView extends SurfaceView implements SurfaceHolder.Callback {

    ARView arView;
    SurfaceHolder holder;
    Camera camera;

    public CameraView(Context context) {
    super(context);
    arView = (ARView) context;

    holder = getHolder();
    holder.addCallback(this);
    holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
    try {
    Camera.Parameters parameters = camera.getParameters();
    try {
    List supportedSizes = null;
    supportedSizes = com.raw.utils.Compatibility.getSupportedPreviewSizes(parameters);

    Iterator itr = supportedSizes.iterator();
    while(itr.hasNext()) {
    Camera.Size element = itr.next();
    element.width -= w;
    element.height -= h;
    }
    Collections.sort(supportedSizes, new ResolutionsOrder());
    //parameters.setPreviewSize(w + supportedSizes.get(supportedSizes.size()-1).width, h + supportedSizes.get(supportedSizes.size()-1).height);
    parameters.setPreviewSize(arView.screenWidth , arView.screenHeight);
    } catch (Exception ex) {
    parameters.setPreviewSize(arView.screenWidth , arView.screenHeight);
    }

    camera.setParameters(parameters);
    camera.startPreview();
    } catch (Exception ex) {
    ex.printStackTrace();
    }
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
    try {
    if (camera != null) {
    try {
    camera.stopPreview();
    } catch (Exception ignore) {
    }
    try {
    camera.release();
    } catch (Exception ignore) {
    }
    camera = null;
    }

    camera = Camera.open();
    arView.camera = camera;
    camera.setPreviewDisplay(holder);
    } catch (Exception ex) {
    try {
    if (camera != null) {
    try {
    camera.stopPreview();
    } catch (Exception ignore) {
    }
    try {
    camera.release();
    } catch (Exception ignore) {
    }
    camera = null;
    }
    } catch (Exception ignore) {

    }
    }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
    try {
    if (camera != null) {
    try {
    camera.stopPreview();
    } catch (Exception ignore) {
    }
    try {
    camera.release();
    } catch (Exception ignore) {
    }
    camera = null;
    }
    } catch (Exception ex) {
    ex.printStackTrace();
    }
    }

    }
    class RadarMarkerView extends View{

    String dataa = “Azimuth”;
    String datab = “Pitch”;
    String datac = “Roll”;
    String deg = “°”;
    String senvalve = “”;
    String pitvalve = “”;
    public int pitch = 0;
    public int roll = 0;
    public int azimuth = 0;

    public int pitchscale = 0;

    public double azimuthdeg = 0.0d;
    public double pitchdeg = 0.0d;
    public double rolldeg = 0.0d;
    public float azi =0.0f;

    Paint mPaint = new Paint();
    ARView arView;
    DisplayMetrics displayMetrics;
    RelativeLayout upperLayoutView = null;
    public RadarMarkerView(Context context, DisplayMetrics displayMetrics, RelativeLayout rel) {
    super(context);
    mPaint.setColor(Color.GREEN);
    mPaint.setTextSize(35);
    //mPaint.setStrokeWidth(1 / getResources().getDisplayMetrics().density);
    mPaint.setStrokeWidth(6);
    mPaint.setAntiAlias(true);

    arView = (ARView) context;
    this.displayMetrics = displayMetrics;
    upperLayoutView = rel;
    }

    @Override
    protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    ARView.paintScreen.setWidth(canvas.getWidth());
    ARView.paintScreen.setHeight(canvas.getHeight());
    ARView.paintScreen.setCanvas(canvas);

    if (!ARView.dataView.isInited()) {
    ARView.dataView.init(ARView.paintScreen.getWidth(), ARView.paintScreen.getHeight(),arView.camera, displayMetrics,upperLayoutView);
    }

    //ARView.dataView.draw(ARView.paintScreen, ARView.azimuth, ARView.pitch, ARView.roll);

    ARView.dataView.draw(ARView.paintScreen, azi, ARView.pitch, ARView.roll);

    ////////////////////////// arc begin

    float width = (float)getWidth();
    float height = (float)getHeight();
    float radius;

    if (width > height){

    radius = height/3;

    }else{

    radius = width/2;
    }

    Path path = new Path();

    path.addCircle(width/2,

    height/2,radius,

    Path.Direction.CW);

    Paint paint = new Paint();

    paint.setColor(Color.GREEN);

    paint.setStrokeWidth(5);

    paint.setStyle(Paint.Style.FILL);

    float center_x, center_y;
    final RectF oval = new RectF();

    paint.setStyle(Paint.Style.STROKE);
    center_x = width/2;

    center_y = height / 2;

    oval.set(center_x – radius,

    center_y – radius,

    center_x + radius,

    center_y + radius);

    canvas.drawArc(oval, 210, 120, false, paint);
    ///arc ends

    mPaint.setTextSize(25f);

    //azimuth center horizontal lines
    //canvas.drawLine(442, 70, 517, 70, mPaint);
    //canvas.drawText(“15”, 432, 78, mPaint);
    //canvas.drawText(“15”, 527, 78, mPaint);

    canvas.drawLine(392,130,567,130,mPaint);
    canvas.drawText(“10”, 352, 138, mPaint);
    canvas.drawText(“10”, 577, 138, mPaint);

    canvas.drawLine(442,190,517,190,mPaint);
    canvas.drawText(“5”, 412, 198, mPaint);
    canvas.drawText(“5”, 527, 198, mPaint);

    canvas.drawLine(392,220,567,220,mPaint);
    canvas.drawText(“0”, 372, 228, mPaint);
    canvas.drawText(“0”, 577, 228, mPaint);

    canvas.drawLine(442,280,517,280,mPaint);
    canvas.drawText(“-5”, 408, 288, mPaint);
    canvas.drawText(“-5”, 527, 288, mPaint);

    canvas.drawLine(392,340,567,340,mPaint);
    canvas.drawText(“-10”, 348, 348, mPaint);
    canvas.drawText(“-10”, 577, 348, mPaint);
    //displaying plus on screen

    // canvas.drawLine(480,220,480,320, mPaint); //plus vertical
    // canvas.drawLine(430, 270, 530, 270, mPaint); //plus horizontal

    // targent square sign

    // canvas.drawLine(430,170,380,170,mPaint); //top corner left h line
    // canvas.drawLine(380,170,380,220,mPaint); //top corner left v line
    // canvas.drawLine(380,320,380,370,mPaint); //bottom corner left v line
    // canvas.drawLine(380,370,430,370,mPaint); //bottom corner left h line
    // canvas.drawLine(530,370,580,370,mPaint); //bottom corner right h line
    // canvas.drawLine(580,370,580,320,mPaint); //bottom corner right v line
    // canvas.drawLine(580,220,580,170,mPaint); //top corner right v line
    // canvas.drawLine(580, 170, 530, 170, mPaint); //top corner right h line

    //top header line
    canvas.drawLine(330,50,630,50,mPaint);
    //reading lines for top header
    canvas.drawLine(330,5,330,50,mPaint);
    canvas.drawLine(355,20,355,50,mPaint);
    canvas.drawLine(380,5,380,50,mPaint);
    canvas.drawLine(405,20,405,50,mPaint);
    canvas.drawLine(430,5,430,50,mPaint);
    canvas.drawLine(455,20,455,50,mPaint);
    canvas.drawLine(480,5,480,50,mPaint);
    canvas.drawLine(505,20,505,50,mPaint);
    canvas.drawLine(530,5,530,50,mPaint);
    canvas.drawLine(555,20,555,50, mPaint);
    canvas.drawLine(580,5,580,50,mPaint);
    canvas.drawLine(605,20,605,50, mPaint);
    canvas.drawLine(630,5,630,50,mPaint);

    // vertical left speed line
    canvas.drawLine(80, 170, 80, 470, mPaint);
    // reading scale for speed

    canvas.drawLine(60, 170, 80, 170, mPaint);
    pitvalve = Integer.toString(pitchscale+30);
    canvas.drawText(pitvalve, 20, 178, mPaint);
    canvas.drawLine(60, 220, 80, 220, mPaint);
    pitvalve = Integer.toString(pitchscale+20);
    canvas.drawText(pitvalve, 20, 228, mPaint);
    canvas.drawLine(60, 270, 80, 270, mPaint);
    pitvalve = Integer.toString(pitchscale+10);
    canvas.drawText(pitvalve, 20, 278, mPaint);
    canvas.drawLine(60, 320, 80, 320, mPaint);
    pitvalve = Integer.toString(pitchscale);
    canvas.drawText(pitvalve, 20, 328, mPaint);
    canvas.drawLine(60, 370, 80, 370, mPaint);
    pitvalve = Integer.toString(pitchscale-10);
    canvas.drawText(pitvalve, 10, 378, mPaint);
    canvas.drawLine(60, 420, 80, 420, mPaint);
    pitvalve = Integer.toString(pitchscale-20);
    canvas.drawText(pitvalve, 10, 428, mPaint);
    canvas.drawLine(60, 470, 80, 470, mPaint);
    pitvalve = Integer.toString(pitchscale-30);
    canvas.drawText(pitvalve, 10, 478, mPaint);

    // vertical right ALT line
    canvas.drawLine(880, 170, 880, 470, mPaint);
    // reading lines for ALT line
    canvas.drawLine(880, 170, 900, 170, mPaint);
    canvas.drawText(“30”, 920, 178, mPaint);
    canvas.drawLine(880, 220, 900, 220, mPaint);
    canvas.drawText(“20”, 920, 228, mPaint);
    canvas.drawLine(880, 270, 900, 270, mPaint);
    canvas.drawText(“10”, 920, 278, mPaint);
    canvas.drawLine(880, 320, 900, 320, mPaint);
    canvas.drawText(“0”, 920, 328, mPaint);
    canvas.drawLine(880, 370, 900, 370, mPaint);
    canvas.drawText(“-10”, 910, 378, mPaint);
    canvas.drawLine(880, 420, 900, 420, mPaint);
    canvas.drawText(“-20”, 910, 428, mPaint);
    canvas.drawLine(880, 470, 900, 470, mPaint);
    canvas.drawText(“-30”, 910, 478, mPaint);

    // pointer for speed reading
    canvas.drawLine(80, 320, 110, 300, mPaint);
    canvas.drawLine(110, 300, 140, 300, mPaint);
    canvas.drawLine(140, 300, 140, 340, mPaint);
    canvas.drawLine(140, 340, 110, 340, mPaint);
    canvas.drawLine(110, 340, 80, 320, mPaint);
    pitvalve = Integer.toString(pitchscale);
    canvas.drawText(pitvalve, 120, 328, mPaint);

    // pointer for ALT reading
    canvas.drawLine(880, 320, 850, 300, mPaint);
    canvas.drawLine(850, 300, 820, 300, mPaint);
    canvas.drawLine(820, 300, 820, 340, mPaint);
    canvas.drawLine(820, 340, 850, 340, mPaint);
    canvas.drawLine(850, 340, 880, 320, mPaint);
    canvas.drawText(“0”, 835, 328, mPaint);

    canvas.drawText(datab, 160.0f, 478.0f, mPaint);
    pitchdeg = Math.toDegrees(ARView.pitch);
    pitch = (int)pitchdeg;

    if(pitch < 0) {
    pitch = pitch + 90;
    }
    else
    {
    pitch = pitch – 90;
    }
    pitchscale = pitch;
    senvalve = Integer.toString(pitch);
    canvas.drawText(senvalve, 225.0f, 478.0f, mPaint);
    canvas.drawText(deg, 265.0f, 478.0f, mPaint);

    canvas.drawText(datac, 280.0f, 478.0f, mPaint);
    rolldeg = Math.toDegrees(ARView.roll);
    /*intervalve = (float)rolldeg;
    senvalve = Float.toString(intervalve);*/
    roll = (int)rolldeg;
    senvalve = Integer.toString(roll);
    canvas.drawText(senvalve, 330.0f, 478.0f, mPaint);
    canvas.drawText(deg, 370.0f, 478.0f, mPaint);

    canvas.drawText(dataa, 400.0f, 478.0f, mPaint);
    azimuthdeg = Math.toDegrees(ARView.azimuth);
    if (azimuthdeg < 0.0){
    azimuthdeg = azimuthdeg + 360.0f;
    }
    azi = (float) azimuthdeg;
    azimuth = (int)azimuthdeg;
    senvalve = Integer.toString(azimuth);
    canvas.drawText(senvalve, 505.0f, 478.0f, mPaint);
    canvas.drawText(deg, 560.0f, 478.0f, mPaint);

    }
    }
    class ResolutionsOrder implements java.util.Comparator {
    public int compare(Camera.Size left, Camera.Size right) {

    return Float.compare(left.width + left.height, right.width + right.height);
    }
    }

  23. Bhanu says:

    can i make a game using this concept of BT

    • Edward M says:

      Yes! If you wanted to create a game that was played between two Android phones, you could do this using App Inventor and Bluetooth to communicate game actions between the phone. Sounds like a great idea!

      Ed

  24. ZsoCza says:

    Hi, Thanks for the tutorial, really helpful.
    Can you please help me in a question? I just couldn’t figure out if I use multiple screens and I connected to the bluetooth, how can I send data from the other screens? Is it possible to send the necessary thigs to the other screens?

    • Edward M says:

      You would need to add the Bluetooth control to each screen. I can see some problems with that, however. This is something I will try to experiment with eventually. Right now I am working on Bluetooth LE, which is a new feature in App Inventor.

  25. Cybi says:

    Thank you so much for this tutorial! I’m not very well-versed with development, but I’m working on it. I’m trying to create an app that very simply connects with a bluetooth device not to transmit data, but to then set off an alarm if that connection is broken (as in, the user’s phone moves too far away from the device to maintain the connection). It seems like everything here is focused on using the BTClient to connect for communication between two phones. Is it possible to use this to establish a link with a non-communication device? I tried testing it using a bluetooth speaker I have – my phone in general recognized that a bluetooth object was present, but nothing came up when I tested the app (both my own using your method and your aia). Help please? 🙂

    • Edward M says:

      That is an excellent question! But unfortunately, I do not know the answer as I do not have other Bluetooth devices in order to check on this. I also have a tutorial on the website that connects the Android phone with an Arduino board through a Bluetooth link (its the single most popular tutorial on this web site!) Therefore, I know it is possible to connect Android / App Inventor apps over Bluetooth to non-Android devices. However, in that particular example, I also wrote the code for the Arduino board so that the App Inventor app and the Arduino are compatible.

      Another issue is that there might be a dependency on the version of Bluetooth that is in use. We are presently on version 4.1 or 4.2 but many devices are still using older Bluetooth versions (even back to 2.1). In theory, newer versions of Bluetooth are supposed to be backwards compatible with the older versions. But in practice, I have an older phone with BT 2.1 and it did not fully function with my BT 4.0 device.

      Finally, it is possible that the speaker uses Bluetooth Low Energy (part of the version 4 spec). The example code I have here works only with Bluetooth Classic features and does not support Bluetooth LE. I have some hardware and code that I’ve created which does work with app inventor to link to a Bluetooth LE device and I am slowly working on some more things for this, to eventually post on the web site.

      Ed

  26. CH Ng says:

    Hi i would like to know how do i print to a Bluetooth printer from my Android phone? For start, i dont need anything fancy. I just want to write an application from app inventor to send some text (sales receipt) to a bluetooth printer. How to i use the code that you have and add in code to print to a BT printer? Thanks in advance for your help and advice.

    • Edward M says:

      I do not know if this can be done, but it probably would be somewhat difficult to do, if it is possible.

      When you send a file to a printer from your personal computer, your computer’s operating system contains a “print driver”. The print driver software translates requests for font sizes, colors, bold, italics and so on, into the specific commands needed to tell the printer how to display these items. To implement printing would require setting up a connection with the printer, and then properly preparing and formatting the data for the printer.

      Now, it might be possible to connect, and it might be possible to output characters in a standard code (such as ASCII) that display as ordinary text characters. It would be neat if this could be done but I do not have any specific information on how to communicate directly to printers.

      You could try using the basic Bluetooth communications code to see if you can discover a BT-equipped printer and then connect to it. If that works, you could try sending data bytes to the printer and see what happens!

      Ed

      • CH Ng says:

        thanks for the fast reply. Sorry, i should make it clearer. Actually, the printer i have is a bluetooth thermal receipt printer (http://www.zjiang.com/cn/cpzx/pjdyj/bianxieshilanyadayinji/255.html). Based on the manual, it supports ESC/POS/STAR command.

        So, i would like to learn how do i send these command to print simple text to the receipt printer. At a start, no need fancy. just plain text. later, once I know how it works, only then i start to add in bold font, italic etc. Hope you able to give me some pointers….if possible, some example codes.
        thanks v much.

  27. Raffaele says:

    Dalle indicazioni ho realizzato un App con bluetooth client per comandare arduino per apertura/chiusura tapparella tutto ok.
    Vorrei per attivare Bluetooth all’avvio dell’app e disattivarlo all’uscita, ho visto alcune app già realizzate che all’avvio chiedono di attivare Bluetooth, ma non riesco a trovare lo script con MIT App
    Potete darmi una dritta
    Saluti

  28. Natarizqi says:

    Thank for the tutorial. It’s very helpful to solve my project

  29. vivek says:

    Can we share files or list of tables directly using the Bluetooth in MIT app inventory2 ..??

  30. Evelyn P Licona says:

    Hello. I was trying this app but I receive an error some other people had and didnt get a response.
    (Error Unable to Connect. Is the device turned on?)
    I am not sure on how to fix it, I had it in another app as well that’s why I turned to this one. Obviously, I checked that the device is on, I have a samsung s5. Can you please help me out?

    • Edward M says:

      Hi,

      Usually that means that the Bluetooth device has been paired, but the other device is not reachable – either because it is off or because it is out of range.

      One of your devices is a Samsung S5 – what is the other device you are trying to connect to?

      I have been using Bluetooth between two Android devices, and between an Android device and six other Bluetooth connected Arduino boards, where I have separate Bluetooth components for each of the connections (in other words, 6 Bluetooth components added to the app). This is working okay for me.

      Let me know what the other device is in your set up? I’d like to understand this better.

      Ed

  1. February 2, 2015

    […] Part 1 of this tutorial introduced Bluetooth communications and implemented a simple method of sending text data back and forth between two Android devices over the Bluetooth wireless link. If you are not familiar with using App Inventor’s Bluetooth component, start with Part 1. […]

  2. April 30, 2015

    […] 3. Add a special “Error handler” to catch and display information when the program encounters a serious problem. The following section is adapted from my tutorial on basic Bluetooth communications. […]

  3. May 7, 2015

    […] functions that may be used to send data between smart phones and tablets (see previous tutorials: Part 1, Part […]

  4. June 13, 2015

    […] 情報源: Part 1: Basic Bluetooth communications using App Inventor | App Inventor 2 Tutorial – Learn to Cod… […]

  5. October 29, 2015

    […] App Inventor sample source code available here. […]

  6. February 17, 2016

    […] pas bluetooth app inventor : http://appinventor.pevest.com/?p=520 doc arduino en français : […]

  7. October 11, 2016

    […] Inventor Tutorial 11. Part 1: Basic Bluetooth communications using App Inventor | App Inventor 2 – Learn to Code! This tutorial covers basic App Inventor Bluetooth communications code. Subsequent tutorials will […]

  8. October 11, 2016

    […] original version is known as Bluetooth Classic. I wrote a popular tutorial on using Bluetooth Classic in MIT App Inventor apps for Android. Please refer to that tutorial to learn more about the history of Bluetooth and how to write MIT […]

  9. November 23, 2016

    […] Part 0 for a brief introduction to this series and Bluetooth LE plus our past tutorial series on classic Bluetooth for communicating between Android devices, and between an Android device and an Arduino board with […]

  10. January 6, 2017

    […] start with “Part 1: Basic Bluetooth communications using App Inventor” to learn how to configure, set up and program an App Inventor app that communicates over […]

  11. March 21, 2017

    […] that the tools for Serial Port Protocol (SPP) were included in the app inventor, and found this tutorial to be a really good starting point. Once two phones were connected, it was pretty straightforward […]

LinkedIn Auto Publish Powered By : XYZScripts.com