Home | History | Annotate | Download | only in com.example.android.bluetoothadvertisements
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.example.android.bluetoothadvertisements;
     18 
     19 import android.bluetooth.le.AdvertiseCallback;
     20 import android.content.BroadcastReceiver;
     21 import android.content.Context;
     22 import android.content.Intent;
     23 import android.content.IntentFilter;
     24 import android.os.Bundle;
     25 import android.support.v4.app.Fragment;
     26 import android.view.LayoutInflater;
     27 import android.view.View;
     28 import android.view.ViewGroup;
     29 import android.widget.Switch;
     30 import android.widget.Toast;
     31 
     32 /**
     33  * Allows user to start & stop Bluetooth LE Advertising of their device.
     34  */
     35 public class AdvertiserFragment extends Fragment implements View.OnClickListener {
     36 
     37     /**
     38      * Lets user toggle BLE Advertising.
     39      */
     40     private Switch mSwitch;
     41 
     42     /**
     43      * Listens for notifications that the {@code AdvertiserService} has failed to start advertising.
     44      * This Receiver deals with Fragment UI elements and only needs to be active when the Fragment
     45      * is on-screen, so it's defined and registered in code instead of the Manifest.
     46      */
     47     private BroadcastReceiver advertisingFailureReceiver;
     48 
     49     @Override
     50     public void onCreate(Bundle savedInstanceState) {
     51         super.onCreate(savedInstanceState);
     52 
     53         advertisingFailureReceiver = new BroadcastReceiver() {
     54 
     55             /**
     56              * Receives Advertising error codes from {@code AdvertiserService} and displays error messages
     57              * to the user. Sets the advertising toggle to 'false.'
     58              */
     59             @Override
     60             public void onReceive(Context context, Intent intent) {
     61 
     62                 int errorCode = intent.getIntExtra(AdvertiserService.ADVERTISING_FAILED_EXTRA_CODE, -1);
     63 
     64                 mSwitch.setChecked(false);
     65 
     66                 String errorMessage = getString(R.string.start_error_prefix);
     67                 switch (errorCode) {
     68                     case AdvertiseCallback.ADVERTISE_FAILED_ALREADY_STARTED:
     69                         errorMessage += " " + getString(R.string.start_error_already_started);
     70                         break;
     71                     case AdvertiseCallback.ADVERTISE_FAILED_DATA_TOO_LARGE:
     72                         errorMessage += " " + getString(R.string.start_error_too_large);
     73                         break;
     74                     case AdvertiseCallback.ADVERTISE_FAILED_FEATURE_UNSUPPORTED:
     75                         errorMessage += " " + getString(R.string.start_error_unsupported);
     76                         break;
     77                     case AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR:
     78                         errorMessage += " " + getString(R.string.start_error_internal);
     79                         break;
     80                     case AdvertiseCallback.ADVERTISE_FAILED_TOO_MANY_ADVERTISERS:
     81                         errorMessage += " " + getString(R.string.start_error_too_many);
     82                         break;
     83                     case AdvertiserService.ADVERTISING_TIMED_OUT:
     84                         errorMessage = " " + getString(R.string.advertising_timedout);
     85                         break;
     86                     default:
     87                         errorMessage += " " + getString(R.string.start_error_unknown);
     88                 }
     89 
     90                 Toast.makeText(getActivity(), errorMessage, Toast.LENGTH_LONG).show();
     91             }
     92         };
     93     }
     94 
     95     @Override
     96     public View onCreateView(LayoutInflater inflater, ViewGroup container,
     97                              Bundle savedInstanceState) {
     98 
     99         View view = inflater.inflate(R.layout.fragment_advertiser, container, false);
    100 
    101         mSwitch = (Switch) view.findViewById(R.id.advertise_switch);
    102         mSwitch.setOnClickListener(this);
    103 
    104         return view;
    105     }
    106 
    107     /**
    108      * When app comes on screen, check if BLE Advertisements are running, set switch accordingly,
    109      * and register the Receiver to be notified if Advertising fails.
    110      */
    111     @Override
    112     public void onResume() {
    113         super.onResume();
    114 
    115         if (AdvertiserService.running) {
    116             mSwitch.setChecked(true);
    117         } else {
    118             mSwitch.setChecked(false);
    119         }
    120 
    121         IntentFilter failureFilter = new IntentFilter(AdvertiserService.ADVERTISING_FAILED);
    122         getActivity().registerReceiver(advertisingFailureReceiver, failureFilter);
    123 
    124     }
    125 
    126     /**
    127      * When app goes off screen, unregister the Advertising failure Receiver to stop memory leaks.
    128      * (and because the app doesn't care if Advertising fails while the UI isn't active)
    129      */
    130     @Override
    131     public void onPause() {
    132         super.onPause();
    133         getActivity().unregisterReceiver(advertisingFailureReceiver);
    134     }
    135 
    136     /**
    137      * Returns Intent addressed to the {@code AdvertiserService} class.
    138      */
    139     private static Intent getServiceIntent(Context c) {
    140         return new Intent(c, AdvertiserService.class);
    141     }
    142 
    143     /**
    144      * Called when switch is toggled - starts or stops advertising.
    145      */
    146     @Override
    147     public void onClick(View v) {
    148         // Is the toggle on?
    149         boolean on = ((Switch) v).isChecked();
    150 
    151         if (on) {
    152             startAdvertising();
    153         } else {
    154             stopAdvertising();
    155         }
    156     }
    157 
    158     /**
    159      * Starts BLE Advertising by starting {@code AdvertiserService}.
    160      */
    161     private void startAdvertising() {
    162         Context c = getActivity();
    163         c.startService(getServiceIntent(c));
    164     }
    165 
    166     /**
    167      * Stops BLE Advertising by stopping {@code AdvertiserService}.
    168      */
    169     private void stopAdvertising() {
    170         Context c = getActivity();
    171         c.stopService(getServiceIntent(c));
    172         mSwitch.setChecked(false);
    173     }
    174 
    175 }