2017-01-29 10 views
2

В настоящее время я использую эту ссылку http://blog.lemberg.co.uk/how-guide-obdii-reader-app-development, но я все еще смущен тем, что следующие шаги для моего приложения Android, чтобы иметь возможность подключиться к OBDII. Я нашел код онлайн для простого приложения Bluetooth. Приложение способно создавать соединения Bluetooth с другими телефонами Android, но не с OBDII.Как подключиться к OBDII через Android Bluetooth

public class MainActivity extends Activity { 

Button b1,b2,b3,b4; 
private BluetoothAdapter BA; 
private Set<BluetoothDevice>pairedDevices; 
ListView lv; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    b1 = (Button) findViewById(R.id.button); 
    b2=(Button)findViewById(R.id.button2); 
    b3=(Button)findViewById(R.id.button3); 
    b4=(Button)findViewById(R.id.button4); 

    BA = BluetoothAdapter.getDefaultAdapter(); 
    lv = (ListView)findViewById(R.id.listView); 
} 

public void on(View v) { 
    if (!BA.isEnabled()) { 
     Intent turnOn = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); 
     startActivityForResult(turnOn, 0); 
     Toast.makeText(getApplicationContext(), "Turned on", Toast.LENGTH_LONG).show(); 
    } else { 
     Toast.makeText(getApplicationContext(), "Already on", Toast.LENGTH_LONG).show(); 
    } 
} 

public void off(View v) { 
    BA.disable(); 
    Toast.makeText(getApplicationContext(), "Turned off", Toast.LENGTH_LONG).show(); 
} 

public void visible(View v) { 
    Intent getVisible = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE); 
    startActivityForResult(getVisible, 0); 
} 

public void list(View v) { 
    pairedDevices = BA.getBondedDevices(); 

    ArrayList list = new ArrayList(); 

    for (BluetoothDevice bt : pairedDevices) list.add(bt.getName()); 
    Toast.makeText(getApplicationContext(), "Showing Paired Devices", Toast.LENGTH_SHORT).show(); 

    final ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, list); 

    lv.setAdapter(adapter); 
} 

Двигаясь вперед, что должно быть сделано для того, чтобы приложение, чтобы иметь возможность успешно устанавливать и поддерживать соединения Bluetooth с OBDII.

ответ

0

Проверьте пример android-obd-reader OBDII, который поможет вам подключить OBDII к вашему устройству.

Для подключения и чтения данных из obd используется OBD-II Java API.

Используя классы ниже, вы можете управлять подключением и считывать данные из obd.

BluetoothManager.java: Это позволяет подключать устройству

public class BluetoothManager { 

private static final String TAG = BluetoothManager.class.getName(); 
/* 
* http://developer.android.com/reference/android/bluetooth/BluetoothDevice.html 
* #createRfcommSocketToServiceRecord(java.util.UUID) 
* 
* "Hint: If you are connecting to a Bluetooth serial board then try using the 
* well-known SPP UUID 00001101-0000-1000-8000-00805F9B34FB. However if you 
* are connecting to an Android peer then please generate your own unique 
* UUID." 
*/ 
private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); 

/** 
* Instantiates a BluetoothSocket for the remote device and connects it. 
* <p/> 
* See http://stackoverflow.com/questions/18657427/ioexception-read-failed-socket-might-closed-bluetooth-on-android-4-3/18786701#18786701 
* 
* @param dev The remote device to connect to 
* @return The BluetoothSocket 
* @throws IOException 
*/ 
public static BluetoothSocket connect(BluetoothDevice dev) throws IOException { 
    BluetoothSocket sock = null; 
    BluetoothSocket sockFallback = null; 

    Log.d(TAG, "Starting Bluetooth connection.."); 
    try { 
     sock = dev.createRfcommSocketToServiceRecord(MY_UUID); 
     sock.connect(); 
    } catch (Exception e1) { 
     Log.e(TAG, "There was an error while establishing Bluetooth connection. Falling back..", e1); 
     Class<?> clazz = sock.getRemoteDevice().getClass(); 
     Class<?>[] paramTypes = new Class<?>[]{Integer.TYPE}; 
     try { 
      Method m = clazz.getMethod("createRfcommSocket", paramTypes); 
      Object[] params = new Object[]{Integer.valueOf(1)}; 
      sockFallback = (BluetoothSocket) m.invoke(sock.getRemoteDevice(), params); 
      sockFallback.connect(); 
      sock = sockFallback; 
     } catch (Exception e2) { 
      Log.e(TAG, "Couldn't fallback while establishing Bluetooth connection.", e2); 
      throw new IOException(e2.getMessage()); 
     } 
    } 
    return sock; 
} 
} 

ObdGatewayService.java: Он имеет код подключения и чтения данных из БД.

import android.bluetooth.BluetoothAdapter; 
import android.bluetooth.BluetoothDevice; 
import android.bluetooth.BluetoothSocket; 
import android.content.Context; 
import android.content.Intent; 
import android.content.SharedPreferences; 
import android.net.Uri; 
import android.os.Build; 
import android.os.Environment; 
import android.util.Log; 
import android.widget.Toast; 

import com.github.pires.obd.commands.protocol.EchoOffCommand; 
import com.github.pires.obd.commands.protocol.LineFeedOffCommand; 
import com.github.pires.obd.commands.protocol.ObdResetCommand; 
import com.github.pires.obd.commands.protocol.SelectProtocolCommand; 
import com.github.pires.obd.commands.protocol.TimeoutCommand; 
import com.github.pires.obd.commands.temperature.AmbientAirTemperatureCommand; 
import com.github.pires.obd.enums.ObdProtocols; 
import com.github.pires.obd.exceptions.UnsupportedCommandException; 
import com.github.pires.obd.reader.R; 
import com.github.pires.obd.reader.activity.ConfigActivity; 
import com.github.pires.obd.reader.activity.MainActivity; 
import com.github.pires.obd.reader.io.ObdCommandJob.ObdCommandJobState; 
import com.google.inject.Inject; 

import java.io.File; 
import java.io.IOException; 

/** 
* This service is primarily responsible for establishing and maintaining a 
* permanent connection between the device where the application runs and a more 
* OBD Bluetooth interface. 
* <p/> 
* Secondarily, it will serve as a repository of ObdCommandJobs and at the same 
* time the application state-machine. 
*/ 
public class ObdGatewayService extends AbstractGatewayService { 

    private static final String TAG = ObdGatewayService.class.getName(); 
    @Inject 
    SharedPreferences prefs; 

    private BluetoothDevice dev = null; 
    private BluetoothSocket sock = null; 

    public void startService() throws IOException { 
     Log.d(TAG, "Starting service.."); 

     // get the remote Bluetooth device 
     final String remoteDevice = prefs.getString(ConfigActivity.BLUETOOTH_LIST_KEY, null); 
     if (remoteDevice == null || "".equals(remoteDevice)) { 
      Toast.makeText(ctx, getString(R.string.text_bluetooth_nodevice), Toast.LENGTH_LONG).show(); 

      // log error 
      Log.e(TAG, "No Bluetooth device has been selected."); 

      // TODO kill this service gracefully 
      stopService(); 
      throw new IOException(); 
     } else { 

      final BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter(); 
      dev = btAdapter.getRemoteDevice(remoteDevice); 


    /* 
    * Establish Bluetooth connection 
    * 
    * Because discovery is a heavyweight procedure for the Bluetooth adapter, 
    * this method should always be called before attempting to connect to a 
    * remote device with connect(). Discovery is not managed by the Activity, 
    * but is run as a system service, so an application should always call 
    * cancel discovery even if it did not directly request a discovery, just to 
    * be sure. If Bluetooth state is not STATE_ON, this API will return false. 
    * 
    * see 
    * http://developer.android.com/reference/android/bluetooth/BluetoothAdapter 
    * .html#cancelDiscovery() 
    */ 
      Log.d(TAG, "Stopping Bluetooth discovery."); 
      btAdapter.cancelDiscovery(); 

      showNotification(getString(R.string.notification_action), getString(R.string.service_starting), R.drawable.ic_btcar, true, true, false); 

      try { 
       startObdConnection(); 
      } catch (Exception e) { 
       Log.e(
         TAG, 
         "There was an error while establishing connection. -> " 
           + e.getMessage() 
       ); 

       // in case of failure, stop this service. 
       stopService(); 
       throw new IOException(); 
      } 
      showNotification(getString(R.string.notification_action), getString(R.string.service_started), R.drawable.ic_btcar, true, true, false); 
     } 
    } 

    /** 
    * Start and configure the connection to the OBD interface. 
    * <p/> 
    * See http://stackoverflow.com/questions/18657427/ioexception-read-failed-socket-might-closed-bluetooth-on-android-4-3/18786701#18786701 
    * 
    * @throws IOException 
    */ 
    private void startObdConnection() throws IOException { 
     Log.d(TAG, "Starting OBD connection.."); 
     isRunning = true; 
     try { 
      sock = BluetoothManager.connect(dev); 
     } catch (Exception e2) { 
      Log.e(TAG, "There was an error while establishing Bluetooth connection. Stopping app..", e2); 
      stopService(); 
      throw new IOException(); 
     } 

     // Let's configure the connection. 
     Log.d(TAG, "Queueing jobs for connection configuration.."); 
     queueJob(new ObdCommandJob(new ObdResetCommand())); 

     //Below is to give the adapter enough time to reset before sending the commands, otherwise the first startup commands could be ignored. 
     try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } 

     queueJob(new ObdCommandJob(new EchoOffCommand())); 

    /* 
    * Will send second-time based on tests. 
    * 
    * TODO this can be done w/o having to queue jobs by just issuing 
    * command.run(), command.getResult() and validate the result. 
    */ 
     queueJob(new ObdCommandJob(new EchoOffCommand())); 
     queueJob(new ObdCommandJob(new LineFeedOffCommand())); 
     queueJob(new ObdCommandJob(new TimeoutCommand(62))); 

     // Get protocol from preferences 
     final String protocol = prefs.getString(ConfigActivity.PROTOCOLS_LIST_KEY, "AUTO"); 
     queueJob(new ObdCommandJob(new SelectProtocolCommand(ObdProtocols.valueOf(protocol)))); 

     // Job for returning dummy data 
     queueJob(new ObdCommandJob(new AmbientAirTemperatureCommand())); 

     queueCounter = 0L; 
     Log.d(TAG, "Initialization jobs queued."); 


    } 

    /** 
    * This method will add a job to the queue while setting its ID to the 
    * internal queue counter. 
    * 
    * @param job the job to queue. 
    */ 
    @Override 
    public void queueJob(ObdCommandJob job) { 
     // This is a good place to enforce the imperial units option 
     job.getCommand().useImperialUnits(prefs.getBoolean(ConfigActivity.IMPERIAL_UNITS_KEY, false)); 

     // Now we can pass it along 
     super.queueJob(job); 
    } 

    /** 
    * Runs the queue until the service is stopped 
    */ 
    protected void executeQueue() throws InterruptedException { 
     Log.d(TAG, "Executing queue.."); 
     while (!Thread.currentThread().isInterrupted()) { 
      ObdCommandJob job = null; 
      try { 
       job = jobsQueue.take(); 

       // log job 
       Log.d(TAG, "Taking job[" + job.getId() + "] from queue.."); 

       if (job.getState().equals(ObdCommandJobState.NEW)) { 
        Log.d(TAG, "Job state is NEW. Run it.."); 
        job.setState(ObdCommandJobState.RUNNING); 
        if (sock.isConnected()) { 
         job.getCommand().run(sock.getInputStream(), sock.getOutputStream()); 
        } else { 
         job.setState(ObdCommandJobState.EXECUTION_ERROR); 
         Log.e(TAG, "Can't run command on a closed socket."); 
        } 
       } else 
        // log not new job 
        Log.e(TAG, 
          "Job state was not new, so it shouldn't be in queue. BUG ALERT!"); 
      } catch (InterruptedException i) { 
       Thread.currentThread().interrupt(); 
      } catch (UnsupportedCommandException u) { 
       if (job != null) { 
        job.setState(ObdCommandJobState.NOT_SUPPORTED); 
       } 
       Log.d(TAG, "Command not supported. -> " + u.getMessage()); 
      } catch (IOException io) { 
       if (job != null) { 
        if(io.getMessage().contains("Broken pipe")) 
         job.setState(ObdCommandJobState.BROKEN_PIPE); 
        else 
         job.setState(ObdCommandJobState.EXECUTION_ERROR); 
       } 
       Log.e(TAG, "IO error. -> " + io.getMessage()); 
      } catch (Exception e) { 
       if (job != null) { 
        job.setState(ObdCommandJobState.EXECUTION_ERROR); 
       } 
       Log.e(TAG, "Failed to run command. -> " + e.getMessage()); 
      } 

      if (job != null) { 
       final ObdCommandJob job2 = job; 
       ((MainActivity) ctx).runOnUiThread(new Runnable() { 
        @Override 
        public void run() { 
         ((MainActivity) ctx).stateUpdate(job2); 
        } 
       }); 
      } 
     } 
    } 

    /** 
    * Stop OBD connection and queue processing. 
    */ 
    public void stopService() { 
     Log.d(TAG, "Stopping service.."); 

     notificationManager.cancel(NOTIFICATION_ID); 
     jobsQueue.clear(); 
     isRunning = false; 

     if (sock != null) 
      // close socket 
      try { 
       sock.close(); 
      } catch (IOException e) { 
       Log.e(TAG, e.getMessage()); 
      } 

     // kill service 
     stopSelf(); 
    } 

    public boolean isRunning() { 
     return isRunning; 
    } 

    public static void saveLogcatToFile(Context context, String devemail) { 
     Intent emailIntent = new Intent(Intent.ACTION_SEND); 
     emailIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
     emailIntent.setType("text/plain"); 
     emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[]{devemail}); 
     emailIntent.putExtra(Intent.EXTRA_SUBJECT, "OBD2 Reader Debug Logs"); 

     StringBuilder sb = new StringBuilder(); 
     sb.append("\nManufacturer: ").append(Build.MANUFACTURER); 
     sb.append("\nModel: ").append(Build.MODEL); 
     sb.append("\nRelease: ").append(Build.VERSION.RELEASE); 

     emailIntent.putExtra(Intent.EXTRA_TEXT, sb.toString()); 

     String fileName = "OBDReader_logcat_" + System.currentTimeMillis() + ".txt"; 
     File sdCard = Environment.getExternalStorageDirectory(); 
     File dir = new File(sdCard.getAbsolutePath() + File.separator + "OBD2Logs"); 
     if (dir.mkdirs()) { 
      File outputFile = new File(dir, fileName); 
      Uri uri = Uri.fromFile(outputFile); 
      emailIntent.putExtra(Intent.EXTRA_STREAM, uri); 

      Log.d("savingFile", "Going to save logcat to " + outputFile); 
      //emailIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
      context.startActivity(Intent.createChooser(emailIntent, "Pick an Email provider").addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); 

      try { 
       @SuppressWarnings("unused") 
       Process process = Runtime.getRuntime().exec("logcat -f " + outputFile.getAbsolutePath()); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 

} 

Надеюсь, это вам поможет. Пожалуйста, оставьте комментарий или отредактируйте свой вопрос, если потребуется дополнительная помощь.