io.github.msc42.masterthemaze.SearchDeviceActivity.java Source code

Java tutorial

Introduction

Here is the source code for io.github.msc42.masterthemaze.SearchDeviceActivity.java

Source

// Copyright (C) 2016 Stefan Constantin
//
// This file is part of Master the maze.
//
// Master the maze 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.
//
// Master the maze 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 Master the maze. If not, see <http://www.gnu.org/licenses/>.

package io.github.msc42.masterthemaze;

import android.Manifest;
import android.app.AlertDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.view.Surface;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.Set;

/**
 * Represents the search device activity. It searches for paired (need not turned on and visible)
 * and visible devices.
 *
 * @author Stefan Constantin
 */
public final class SearchDeviceActivity extends AppCompatActivity {

    private BluetoothAdapter mBluetoothAdapter;

    private ArrayList<BluetoothDevice> mDevices = new ArrayList<BluetoothDevice>();
    private ArrayList<String> mDevicesList = new ArrayList<String>();

    private Handler mDiscoveryRepeatHandler;
    private RepeatedDiscovery mRepeatedDiscoveryRunnable;
    private boolean canOnResumeStartRepeatedDiscovery = false;

    private boolean mShowDoNotDisableBluetoothMessage = true;

    private TextView mSearchNoteTextView;
    private ListView mBluetoothDevicesListView;

    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (BluetoothDevice.ACTION_FOUND.equals(action)) {
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

                if (!mDevices.contains(device)) {
                    mDevices.add(device);
                    mDevicesList.add(device.getName() + "\n" + device.getAddress());
                    mBluetoothDevicesListView.setAdapter(
                            new ArrayAdapter<String>(context, android.R.layout.simple_list_item_1, mDevicesList));
                }
            }
        }
    };

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

        lockScreenOrientation();

        setContentView(R.layout.activity_search_device);

        mSearchNoteTextView = (TextView) findViewById(R.id.searchNoteTextView);

        mBluetoothDevicesListView = (ListView) findViewById(R.id.bluetoothDevicesListView);

        mBluetoothDevicesListView
                .setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mDevicesList));

        mBluetoothDevicesListView.setOnItemClickListener(new android.widget.AdapterView.OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
                if (mBluetoothAdapter != null) {
                    mBluetoothAdapter.cancelDiscovery();
                }
                BluetoothDevice device = mDevices.get(position);
                startMainActivity(device.getName(), device.getAddress());
            }
        });

        if (startBluetooth()) {
            searchDevices();
        }
    }

    private void lockScreenOrientation() {
        int orientation = getResources().getConfiguration().orientation;
        int rotation = getWindowManager().getDefaultDisplay().getRotation();

        if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
            if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_90) {
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
            } else {
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
            }
        } else if (orientation == Configuration.ORIENTATION_PORTRAIT) {
            if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_90) {
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
            } else {
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
            }
        } else {
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        }
    }

    private boolean startBluetooth() {
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

        if (mBluetoothAdapter == null) {
            AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.setTitle(R.string.error).setMessage(R.string.noBluetoothExisting).setCancelable(false)
                    .setPositiveButton(R.string.okay, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                            finish();
                        }
                    });

            builder.create().show();
            return false;
        }

        if (!mBluetoothAdapter.isEnabled()) {
            Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableBtIntent, Constants.REQUEST_ENABLE_BT);
            // if request is satisfied, in onActivityResult startRepeatedDiscovery is called,
            // otherwise there is an alert dialog, which finishes the app when it is confirmed
            return false;
        }

        return true;
    }

    private void searchDevices() {
        if (ContextCompat.checkSelfPermission(this,
                Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
            mSearchNoteTextView.setText(R.string.searchNote);
            startRepeatedDiscovery();
        } else {
            ActivityCompat.requestPermissions(SearchDeviceActivity.this,
                    new String[] { Manifest.permission.ACCESS_COARSE_LOCATION },
                    Constants.REQUEST_COARSE_LOCATION_PERMISSIONS);
            // if request is satisfied, in onRequestPermissionsResult startRepeatedDiscovery is
            // called, otherwise there is an alert dialog, which finishes the app when it is confirmed
        }
    }

    private void startRepeatedDiscovery() {
        mDiscoveryRepeatHandler = new Handler();
        mRepeatedDiscoveryRunnable = new RepeatedDiscovery();

        mDiscoveryRepeatHandler.postDelayed(mRepeatedDiscoveryRunnable, 0);
        canOnResumeStartRepeatedDiscovery = true;
    }

    private void startDiscovery() {
        if (!mBluetoothAdapter.isEnabled()) {
            showDoNotDisableBluetoothMessage();
        }

        if (mBluetoothAdapter.isDiscovering()) {
            mBluetoothAdapter.cancelDiscovery();
        }

        showBoundedDevices();

        mBluetoothAdapter.startDiscovery();
    }

    private void showBoundedDevices() {
        Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
        for (BluetoothDevice device : pairedDevices) {
            if (!mDevices.contains(device)) {
                mDevices.add(device);
                mDevicesList.add(device.getName() + "\n" + device.getAddress());
                mBluetoothDevicesListView.setAdapter(
                        new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mDevicesList));
            }
        }
    }

    private void showDoNotDisableBluetoothMessage() {
        if (mShowDoNotDisableBluetoothMessage) {
            mShowDoNotDisableBluetoothMessage = false;
            AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.setTitle(R.string.error).setMessage(R.string.bluetoothTurnedOffWhileUsing).setCancelable(false)
                    .setPositiveButton(R.string.okay, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                            finish();
                        }
                    });

            builder.create().show();
        }
    }

    private void startMainActivity(String deviceName, String macAddress) {
        Intent intent = new Intent(this, MainActivity.class);
        intent.putExtra(Constants.EXTRA_MESSAGE_DEVICE_NAME, deviceName);
        intent.putExtra(Constants.EXTRA_MESSAGE_MAC, macAddress);
        startActivity(intent);
    }

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

        IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
        registerReceiver(mReceiver, filter);

        if (canOnResumeStartRepeatedDiscovery) {
            mDiscoveryRepeatHandler.removeCallbacks(mRepeatedDiscoveryRunnable);
            mDiscoveryRepeatHandler.postDelayed(mRepeatedDiscoveryRunnable, 0);
        }
    }

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

        unregisterReceiver(mReceiver);

        if (mDiscoveryRepeatHandler != null && mRepeatedDiscoveryRunnable != null) {
            mDiscoveryRepeatHandler.removeCallbacks(mRepeatedDiscoveryRunnable);
        }

        if (mBluetoothAdapter != null) {
            mBluetoothAdapter.cancelDiscovery();
        }
    }

    @Override
    protected void onDestroy() {
        mShowDoNotDisableBluetoothMessage = false;

        super.onDestroy();
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
        switch (requestCode) {
        case Constants.REQUEST_ENABLE_BT:
            if (resultCode == RESULT_OK || mBluetoothAdapter.isEnabled()) {
                searchDevices();
            } else {
                AlertDialog.Builder builder = new AlertDialog.Builder(this);
                builder.setTitle(R.string.error).setMessage(R.string.bluetoothOffSearch).setCancelable(false)
                        .setPositiveButton(R.string.okay, new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int id) {
                                finish();
                            }
                        });

                builder.create().show();
            }
            break;
        default:
            // other request codes are ignored
            break;
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        switch (requestCode) {
        case Constants.REQUEST_COARSE_LOCATION_PERMISSIONS:
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                mSearchNoteTextView.setText(R.string.searchNote);
                startRepeatedDiscovery();
            } else {
                AlertDialog.Builder builder = new AlertDialog.Builder(this);
                builder.setTitle(R.string.info).setMessage(R.string.noPermissionLocation).setCancelable(false)
                        .setPositiveButton(R.string.okay, null);

                builder.create().show();

                mSearchNoteTextView.setText(R.string.searchNoteWithoutPermission);
                showBoundedDevices();
            }
            break;
        default:
            // other request codes are ignored
            break;
        }
    }

    private class RepeatedDiscovery implements Runnable {
        @Override
        public void run() {
            startDiscovery();
            mDiscoveryRepeatHandler.postDelayed(this, Constants.MILLISECONDS_TO_REPEAT_DISCOVERY);
        }
    }
}