質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.92%

import してるはずなのに...

受付中

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 310

ThiHuynh

score 7

import android.app.Activity
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothManager
import android.bluetooth.le.ScanCallback
import android.content.Context
import android.os.Bundle
import android.os.Handler
import android.os.Parcel
import android.os.Parcelable
import android.widget.*
import androidx.appcompat.app.AppCompatActivity
import com.hiramine.blecommunicator.R
import android.widget.Toast
import android.content.Intent
import android.view.*
import android.widget.AdapterView
import android.bluetooth.le.ScanResult as ScanResult1

abstract class DeviceListActivity() : AppCompatActivity(), Parcelable,
    AdapterView.OnItemClickListener {

    internal class DeviceListAdapter(activity: Activity) : BaseAdapter() {
        private val mDeviceList: ArrayList<BluetoothDevice>
        private val mInflator: LayoutInflater

        init {
            mDeviceList = ArrayList()
            mInflator = activity.layoutInflater
        }

        // リストへの追加
        fun addDevice(device: BluetoothDevice) {
            if (!mDeviceList.contains(device)) {    // 加えられていなければ加える
                mDeviceList.add(device)
                notifyDataSetChanged()    // ListViewの更新
            }
        }

        // リストのクリア
        fun clear() {
            mDeviceList.clear()
            notifyDataSetChanged()    // ListViewの更新
        }

        override fun getCount(): Int {
            return mDeviceList.size
        }

        override fun getItem(position: Int): Any {
            return mDeviceList[position]
        }

        override fun getItemId(position: Int): Long {
            return position.toLong()
        }

        internal class ViewHolder {
            var deviceName: TextView? = null
            var deviceAddress: TextView? = null
        }

        override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
            var convertView = convertView
            val viewHolder: ViewHolder
            // General ListView optimization code.
            if (null == convertView) {
                convertView = mInflator.inflate(R.layout.listitem_device, parent, false)
                viewHolder = ViewHolder()
                viewHolder.deviceAddress = convertView!!.findViewById(R.id.textview_deviceaddress)
                viewHolder.deviceName = convertView.findViewById(R.id.textview_devicename)
                convertView.setTag(viewHolder)
            } else {
                viewHolder = convertView.getTag() as ViewHolder
            }

            val device = mDeviceList[position]
            val deviceName = device.name
            if (null != deviceName && 0 < deviceName.length) {
                viewHolder.deviceName!!.text = deviceName
            } else {
                viewHolder.deviceName!!.setText(R.string.unknown_device)
            }
            viewHolder.deviceAddress!!.text = device.address

            return convertView
        }
    }

    // 定数
    private val REQUEST_ENABLEBLUETOOTH = 1 // Bluetooth機能の有効化要求時の識別コード
    private val SCAN_PERIOD: Long = 10000    // スキャン時間。単位はミリ秒。
    val EXTRAS_DEVICE_NAME = "DEVICE_NAME"
    val EXTRAS_DEVICE_ADDRESS = "DEVICE_ADDRESS"

    // メンバー変数
    private var mBluetoothAdapter: BluetoothAdapter? =
        null        // BluetoothAdapter : Bluetooth処理で必要
    private var mDeviceListAdapter: DeviceListAdapter? = null    // リストビューの内容
    private var mHandler: Handler? =
        null                            // UIスレッド操作ハンドラ : 「一定時間後にスキャンをやめる処理」で必要
    private var mScanning = false                // スキャン中かどうかのフラグ

    // デバイススキャンコールバック
    private val mLeScanCallback = object : ScanCallback() {
        // スキャンに成功(アドバタイジングは一定間隔で常に発行されているため、本関数は一定間隔で呼ばれ続ける)
        override fun onScanResult(callbackType: Int, result: ScanResult1) {
            super.onScanResult(callbackType, result)
            runOnUiThread { mDeviceListAdapter!!.addDevice(result.getDevice()) }
        }

        // スキャンに失敗
        override fun onScanFailed(errorCode: Int) {
            super.onScanFailed(errorCode)
        }
    }

    constructor(parcel: Parcel) : this() {

    }


    override fun onCreate(savedInstanceState: Bundle?) {

        super.onCreate(savedInstanceState)
        setContentView(com.hiramine.blecommunicator.R.layout.activity_device_list)

        // 戻り値の初期化
        setResult(Activity.RESULT_CANCELED)

        // リストビューの設定
        mDeviceListAdapter = DeviceListAdapter(this) // ビューアダプターの初期化
        val listView = findViewById(R.id.devicelist) as ListView    // リストビューの取得
        listView.adapter = mDeviceListAdapter    // リストビューにビューアダプターをセット
        listView.setOnItemClickListener(this) // クリックリスナーオブジェクトのセット

        // UIスレッド操作ハンドラの作成(「一定時間後にスキャンをやめる処理」で使用する)
        mHandler = Handler()

        // Bluetoothアダプタの取得
        val bluetoothManager = getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
        mBluetoothAdapter = bluetoothManager.adapter
        if (null == mBluetoothAdapter) {    // デバイス(=スマホ)がBluetoothをサポートしていない
            Toast.makeText(this, R.string.bluetooth_is_not_supported, Toast.LENGTH_SHORT).show()
            finish()    // アプリ終了宣言
            return
        }
    }

    override fun onResume() {
        super.onResume()

        // デバイスのBluetooth機能の有効化要求
        requestBluetoothFeature()

        // スキャン開始
        startScan()
    }

    // 別のアクティビティ(か別のアプリ)に移行したことで、バックグラウンドに追いやられた時
    override fun onPause() {
        super.onPause()

        // スキャンの停止
        stopScan()
    }

    // デバイスのBluetooth機能の有効化要求
    private fun requestBluetoothFeature() {
        if (mBluetoothAdapter!!.isEnabled()) {
            return
        }
        // デバイスのBluetooth機能が有効になっていないときは、有効化要求(ダイアログ表示)
        val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
        startActivityForResult(enableBtIntent, REQUEST_ENABLEBLUETOOTH)
    }

    // 機能の有効化ダイアログの操作結果
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        when (requestCode) {
            REQUEST_ENABLEBLUETOOTH // Bluetooth有効化要求
            -> if (Activity.RESULT_CANCELED == resultCode) {    // 有効にされなかった
                Toast.makeText(this, R.string.bluetooth_is_not_working, Toast.LENGTH_SHORT).show()
                finish()    // アプリ終了宣言
                return
            }
        }
        super.onActivityResult(requestCode, resultCode, data)
    }

    // スキャンの開始
    private fun startScan() {
        // リストビューの内容を空にする。
        mDeviceListAdapter?.clear()

        // BluetoothLeScannerの取得
        // ※Runnableオブジェクト内でも使用できるようfinalオブジェクトとする。
        val scanner = mBluetoothAdapter!!.getBluetoothLeScanner() ?: return


        // スキャン開始(一定時間後にスキャン停止する)
        mHandler?.postDelayed(Runnable {
            mScanning = false
            scanner.stopScan(mLeScanCallback)

            // メニューの更新
            invalidateOptionsMenu()
        }, SCAN_PERIOD)

        mScanning = true
        scanner.startScan(mLeScanCallback)

        // メニューの更新
        invalidateOptionsMenu()
    }

    // スキャンの停止
    private fun stopScan() {
        // 一定期間後にスキャン停止するためのHandlerのRunnableの削除
        mHandler?.removeCallbacksAndMessages(null)

        // BluetoothLeScannerの取得
        val scanner = mBluetoothAdapter?.getBluetoothLeScanner() ?: return
        mScanning = false
        scanner.stopScan(mLeScanCallback)

        // メニューの更新
        invalidateOptionsMenu()
    }


    override fun onItemClick(parent: AdapterView<*>, view: View, position: Int, id: Long) {
        // クリックされたアイテムの取得
        val device = mDeviceListAdapter?.getItem(position) as BluetoothDevice
// 戻り値の設定
        val intent = Intent()
        intent.putExtra(EXTRAS_DEVICE_NAME, device.name)
        intent.putExtra(EXTRAS_DEVICE_ADDRESS, device.address)
        setResult(Activity.RESULT_OK, intent)
        finish()
    }

    // オプションメニュー作成時の処理
    override fun onCreateOptionsMenu(menu: Menu): Boolean {
        menuInflater.inflate(R.menu.activity_device_list, menu)
        if (mScanning) {
            menu.findItem(R.id.menuitem_stop).setVisible(false)
            menu.findItem(R.id.menuitem_scan).setVisible(true)
            menu.findItem(R.id.menuitem_progress).setActionView(null)
        } else {
            menu.findItem(R.id.menuitem_stop).setVisible(true)
            menu.findItem(R.id.menuitem_scan).setVisible(false)
            menu.findItem(R.id.menuitem_progress)
                .setActionView(R.layout.actionbar_indeterminate_progress)
        }
        return true
    }

    // オプションメニューのアイテム選択時の処理
    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        when (item.getItemId()) {
            R.id.menuitem_scan -> startScan()    // スキャンの開始
            R.id.menuitem_stop -> stopScan()    // スキャンの停止
        }
        return true
    }

}





コード

[イメージ説明](1aaa490cbf8722c93171b0eac7f9541d.png)
MainActivityの分です。deviceListActivity.で引っ張ってきているはずなのに、赤字の部分が直りません。わかるかたお願いします。 

ちなみにBLEのアプリを作っています

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • jimbe

    2019/12/28 14:14

    赤字の部分で何のエラーとなっているのでしょう.
    また, ご提示の情報だけでは, 本当に import しているのかや DeviceListActivity での定義が合っているのか等はこちらでは分かりません.

    キャンセル

  • ThiHuynh

    2019/12/28 14:26

    https://www.hiramine.com/programming/blecommunicator/02_scan_device.htmlこちらのサイトを参考にしています

    キャンセル

  • jimbe

    2019/12/28 15:08

    参考にされているほうで同様の現象が発生していないのでしたら, ThiHuynh さんの入力(転記)されたコードのほうで何か間違っているということになります. そして, どう間違っているかは "ThiHuynh さんの入力(転記)されたコード" を見なければ分からないということです.

    キャンセル

  • ThiHuynh

    2019/12/28 15:32

    なるほどです。質問を変更させてもらいました。まだ数回しかteratailを使ったことないので、コードの分け方をしらないので長くなってしまっています。乗せたコードはjava→kotlinに変更していて、DeviceListActivityのコードです

    キャンセル

回答 1

0

public static final  String EXTRAS_DEVICE_NAME      = "DEVICE_NAME";
public static final  String EXTRAS_DEVICE_ADDRESS   = "DEVICE_ADDRESS";

オリジナル java では public static final ですが, ご提示の kotlin では val になっています.

val EXTRAS_DEVICE_NAME = "DEVICE_NAME"
val EXTRAS_DEVICE_ADDRESS = "DEVICE_ADDRESS"

java での public static final を kotlin ではどう記述すれば良いのかをお調べになっては如何でしょうか.

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.92%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る