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