Android Open Source - legacy_bluetrack Bluetooth Log Service






From Project

Back to project page legacy_bluetrack.

License

The source code is released under:

GNU General Public License

If you think the Android project legacy_bluetrack listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

//*****************************************************************************
// This file is part of bluetrack.
///*w ww.  j a v  a2  s .  c  o m*/
// bluetrack is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// bluetrack is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with bluetrack.  If not, see <http://www.gnu.org/licenses/>.
//*****************************************************************************

package org.jonblack.bluetrack.services;

import java.text.SimpleDateFormat;
import java.util.Date;

import org.jonblack.bluetrack.BluetrackIdentifiers;
import org.jonblack.bluetrack.R;
import org.jonblack.bluetrack.activities.MainActivity;
import org.jonblack.bluetrack.storage.DeviceDiscoveryTable;
import org.jonblack.bluetrack.storage.DeviceTable;

import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.support.v4.app.NotificationCompat;
import android.util.Log;


public class BluetoothLogService extends Service
{
  private static final String TAG = "BluetoothLogService";
  
  /**
   * Handler that periodically fires.
   */
  private Handler mPeriodicEventHandler;
  
  /**
   * The bluetooth adapter of this device.
   */
  private BluetoothAdapter mLocalBtAdapter;
  
  /**
   * Id of this tracking session.
   */
  private long mSessionId = -1;
  
  /**
   * Receiver used when bluetooth devices have been found during discovery.
   */
  private final BroadcastReceiver mBtDiscoveryReceiver = new BroadcastReceiver() {
    
    /**
     * The date and time a device was discovered.
     * 
     * Although scanning lasts for approx. 12 seconds, the date time of the
     * discovery is only set once to the date/time of the discovery of the
     * first device.
     */
    private Date discoveryDate = null;
    
    @Override
    public void onReceive(Context context, Intent intent)
    {
      // Get the action that prompted the broadcast
      String action = intent.getAction();
      
      // If the discovery process found devices, add the details to the
      // database.
      if (action.equals(BluetoothDevice.ACTION_FOUND))
      {
        // Set the discovery date if not yet set.
        if (discoveryDate == null)
        {
          discoveryDate = new Date();
        }
        
        // Get the device that was found
        BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
        BluetoothClass deviceClass = intent.getParcelableExtra(BluetoothDevice.EXTRA_CLASS);
        Log.d(TAG, String.format("Found device: %s (%s) class=%d, majorClass=%d",
                                 device.getName(),
                                 device.getAddress(),
                                 deviceClass.getDeviceClass(),
                                 deviceClass.getMajorDeviceClass()));
        
        // If the device is unknown, add it to the database.
        Log.i(TAG, "Checking if the device is new.");
        final Cursor c = getContentResolver().query(DeviceTable.CONTENT_URI,
                                                    new String[] {DeviceTable.COL_ID},
                                                    "mac_address = ?",
                                                    new String[] {device.getAddress()},
                                                    null);
        if (c == null)
        {
          Log.e(TAG, "Database query unexpectedly returned a null Cursor.");
          return;
        }
        
        long id = -1;
        if (c.getCount() < 1)
        {
          // No device found, add it to the database
          id = addDevice(device, deviceClass);
        }
        else
        {
          // Only one row should be returned from the query.
          assert(c.getCount() == 1);
          
          Log.i(TAG, "Device is known. Getting id.");
          c.moveToFirst();
          id = c.getLong(c.getColumnIndex(DeviceTable.COL_ID));
        }
        assert(id != -1);
        c.close();
        
        // Get the rssi value (signal strength)
        Short rssi = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI,
                                          Short.MIN_VALUE);
        if (rssi == Short.MIN_VALUE)
        {
          rssi = null;
        }
        Log.d(TAG, "RSSI: " + rssi);
        
        // Add discovery of device to database.
        addDeviceDiscovery(id, rssi);
        
        return;
      }
      
      // If the discovery process has finished, setup the handler to trigger
      // again after a delay.
      SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(BluetoothLogService.this);
      String scanDelayString = sharedPrefs.getString("pref_tracking_scan_delay", null);
      assert(scanDelayString != null);
      int scanDelay = Integer.parseInt(scanDelayString);
      
      if (action.equals(BluetoothAdapter.ACTION_DISCOVERY_FINISHED))
      {
        Log.d(TAG, "Discovery process finished.");
        
        // Reset the periodic handler
        Log.d(TAG, String.format("Set handler to discover again in %d ms.",
                                 scanDelay * 1000));
        mPeriodicEventHandler.postDelayed(doPeriodicTask, scanDelay * 1000);
        
        // Reset the discovery date
        discoveryDate = null;
        
        return;
      }
    }
    
    private long addDevice(BluetoothDevice device, BluetoothClass deviceClass)
    {
      Log.i(TAG, "Device is unknown. Adding device.");
      
      String name = device.getName();
      if (name == null)
      {
        name = "";
      }
      
      ContentValues values = new ContentValues();
      values.put("mac_address", device.getAddress());
      values.put("name", name);
      values.put("minor_class", deviceClass.getDeviceClass());
      values.put("major_class", deviceClass.getMajorDeviceClass());
      Uri uri = getContentResolver().insert(DeviceTable.CONTENT_URI, values);
      
      // Get the id of the new row
      return ContentUris.parseId(uri);
    }
    
    private void addDeviceDiscovery(long id, short rssi)
    {
      Log.i(TAG, "Adding discovery.");
      
      assert(mSessionId != -1);
      
      SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 
      
      ContentValues values = new ContentValues();
      values.put("date_time", dateFormat.format(discoveryDate));
      values.put("device_id", id);
      values.put("session_id", mSessionId);
      values.put("rssi", rssi);
      getContentResolver().insert(DeviceDiscoveryTable.CONTENT_URI, values);
    }
  };
  
  private final Runnable doPeriodicTask = new Runnable()
  {
    public void run()
    {
      Log.d(TAG, "doPeriodicTask");
      
      // Bluetooth should be available and enabled at this point.
      assert(mLocalBtAdapter != null);
      assert(mLocalBtAdapter.isEnabled());
      
      // If the bluetooth adapter isn't discovering, start discovering.
      if (!mLocalBtAdapter.isDiscovering())
      {
        Log.d(TAG, "Starting bluetooth discovery.");
        mLocalBtAdapter.startDiscovery();
      }
      else
      {
        Log.d(TAG, "Already discovering bluetooth devices.");
      }
    }
  };
  
  /**
   * Allows clients to get the session id from the service via the binder.
   * @return sessionId, -1 when no session is running.
   */
  public void setSessionId(long sessionId)
  {
    mSessionId = sessionId;
  }
  
  @Override
  public void onCreate()
  {
    Log.d(TAG, "Creating BluetoothLogService");
    
    super.onCreate();
    
    mLocalBtAdapter = BluetoothAdapter.getDefaultAdapter();
    
    // Bluetooth should be available and enabled at this point.
    assert(mLocalBtAdapter != null);
    assert(mLocalBtAdapter.isEnabled());
    
    // Register broadcast receiver for finding bluetooth devices.
    registerReceiver(mBtDiscoveryReceiver,
                     new IntentFilter(BluetoothDevice.ACTION_FOUND));
    
    // Register broadcast receiver for when discovery finished.
    registerReceiver(mBtDiscoveryReceiver,
                     new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED));
    
    // Setup the periodic handler which will do the discovery
    mPeriodicEventHandler = new Handler();
  }
  
  @Override
  public void onDestroy()
  {
    Log.d(TAG, "Destroying BluetoothLogService");
    
    // Unregister the broadcast receiver for finding bluetooth devices.
    unregisterReceiver(mBtDiscoveryReceiver);
    
    // If the bluetooth device is in discovery mode, cancel it.
    if (mLocalBtAdapter.isDiscovering())
    {
      Log.d(TAG, "Canceling discovery.");
      mLocalBtAdapter.cancelDiscovery();
    }
    
    super.onDestroy();
  }
  
  @Override
  public int onStartCommand(Intent intent, int flags, int startId)
  {
    // Bluetooth should be available and enabled at this point.
    assert(mLocalBtAdapter != null);
    assert(mLocalBtAdapter.isEnabled());
    
    Bundle extras = intent.getExtras(); 
    if (extras != null)
    {
      mSessionId = extras.getLong("sessionId");
      Log.d(TAG, "Started service with sessionId: " + mSessionId);
    }
    assert(mSessionId != -1);
    
    // Start in the foreground so there is less chance of being killed; include
    // permanent notification.
    Intent notiIntent = new Intent(this, MainActivity.class);
    notiIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |
                        Intent.FLAG_ACTIVITY_SINGLE_TOP);
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
                                                            notiIntent,
                                                            PendingIntent.FLAG_UPDATE_CURRENT);
    
    Notification noti = new NotificationCompat.Builder(this)
      .setSmallIcon(R.drawable.logo)
      .setContentTitle(getString(R.string.app_name))
      .setContentText(getString(R.string.notification_tracking))
      .setContentIntent(pendingIntent)
      .build();
    
    startForeground(BluetrackIdentifiers.NOTIFICATION_ID_TRACKING, noti);
    
    // Discover devices immediately
    mPeriodicEventHandler.post(doPeriodicTask);
    
    // We want this service to continue running until it is explicitly stopped,
    // so return sticky.
    return START_STICKY;
  }
  
  /**
   * Disables binding.
   * @see android.app.Service.onBind
   */
  @Override
  public IBinder onBind(Intent intent)
  {
    return null;
  }
}




Java Source Code List

org.jonblack.bluetrack.BluetoothClassLookup.java
org.jonblack.bluetrack.BluetrackIdentifiers.java
org.jonblack.bluetrack.DeviceDiscovery.java
org.jonblack.bluetrack.Device.java
org.jonblack.bluetrack.Session.java
org.jonblack.bluetrack.activities.DevicesFragment.java
org.jonblack.bluetrack.activities.LiveTrackingFragment.java
org.jonblack.bluetrack.activities.MainActivity.java
org.jonblack.bluetrack.activities.SessionFragment.java
org.jonblack.bluetrack.activities.SettingsActivity.java
org.jonblack.bluetrack.adapters.DeviceCursorAdapter.java
org.jonblack.bluetrack.adapters.LiveTrackingCursorAdapter.java
org.jonblack.bluetrack.adapters.SessionCursorAdapter.java
org.jonblack.bluetrack.services.BluetoothLogService.java
org.jonblack.bluetrack.storage.BluetrackContentProvider.java
org.jonblack.bluetrack.storage.BluetrackOpenHelper.java
org.jonblack.bluetrack.storage.DeviceDiscoveryTable.java
org.jonblack.bluetrack.storage.DeviceTable.java
org.jonblack.bluetrack.storage.SessionTable.java