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

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

ただいまの
回答率

88.80%

ビーコン受信開始をボタンのクリックで実行するには?

解決済

回答 1

投稿 編集

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

yuko0524

score 21

いつもお世話になっております。

以前、似たような質問を上げましたが、質問の仕方が適切ではなかったので閉じた経緯がありました。
今回は自分なりに調べたりトライした上で質問させていただきますのでよろしくお願いします。
(ソース全てを貼り付けたら、文字数オーバーとなってしまいましたので、部分的にソースを割愛しています。)

【目的】付近にあるビーコンをアンドロイド端末で受信して、情報をログに出力する(強度の強い順にMAX3つのビーコン)。

【方法】端末画面にて、ドロップダウンリスト(1~25の番号表示)から1つ選択し、[START]ボタンをクリックすると受信開始し、
[STOP]ボタンクリックで受信を終了する。

【現状】アプリを起動と同時に電波受信開始、アプリ終了で受信終了。
ドロップダウンリストは表示&選択できる状態。ボタンは画面に配置したが、まだ機能はつけていない。

※ソースの下に、実現したいことを記載しています。

package com.example.*****.myapplication
import android.Manifest
//***割愛します****//
・
・
・
import org.altbeacon.beacon.*

@Suppress("DEPRECATION")
class MainActivity : AppCompatActivity() ,BeaconConsumer {

    // BeaconManager型変数の宣言
    private var beaconManager: BeaconManager? = null

    // uuidの指定
    private val uuidString = "FDA50693-A4E2-4FB1-AFCF-C6EB07647825"
    private val uuid = Identifier.parse(uuidString)

    // ビーコンのフォーマット設定
    private val IBEACON_FORMAT: String = "m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24"

    // Handlerクラスの変数の宣言(追加)
    private val handler: Handler = Handler()

    // 選択肢
    private val spinnerItems = arrayOf("1", "2", "3", "4" , "5" ,"6" , "7" , "8", "9" , "10" ,
        "11" , "12" , "13" , "14", "15", "16", "17", "18", "19", "20", "21", "22","23","24","25")

    /**************************************************
     * AppCompatActivity内のメソッドをoverride
     **************************************************/
    // onCreate
    @SuppressLint("HardwareIds")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

    //-------------------------------------------------------------------------//
        // ArrayAdapter
        val adapter = ArrayAdapter(applicationContext,
            android.R.layout.simple_spinner_item, spinnerItems)

        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)

        // spinner に adapter をセット
        spinner.adapter = adapter

        // リスナーを登録
        spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener{
            // アイテムが選択された時
            override fun onItemSelected(parent: AdapterView<*>?,
                                        view: View?, position: Int, id: Long) {
                val spinnerParent = parent as Spinner
                val item = spinnerParent.selectedItem as String
                // Kotlin Android Extensions
                textView.text = item
                val fileName = "logfile"  + item + ".txt"
                Log.d("Rssi_===fileName===", "$fileName")

             }

            // アイテムが選択されなかった時
            override fun onNothingSelected(parent: AdapterView<*>?) {
                //
            }
        }
    //-----------------------------------------------------------------------------//
                 // デバイスのBLE対応チェック
                if (!packageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {

                    // 未対応の場合、Toast表示
                    showToast("このデバイスはBLE未対応です", Toast.LENGTH_LONG)
                }

                // API 23以上かのチェック
                if (Build.VERSION.SDK_INT >= 23) {
                    // パーミッションの要求
                    checkPermission()
                }
                // ビーコンマネージャのインスタンスを生成
                beaconManager = BeaconManager.getInstanceForApplication(applicationContext)

                // BeaconManagerの設定
                beaconManager!!.beaconParsers.add(BeaconParser().setBeaconLayout(IBEACON_FORMAT))

    }

    // onResume
    override fun onResume() {
        super.onResume()

        // ビーコンサービスの開始
        beaconManager!!.bind(this)
    }

    // onPause
    override fun onPause() {
        super.onPause()

        // ビーコンサービスの停止
        beaconManager!!.unbind(this)
    }

    override fun onBackPressed() {
        // バックキーの無効化
        moveTaskToBack (true)
    }


    /**************************************************
     * BeaconConsumer内のメソッドをoverride
     **************************************************/
    // onBeaconServiceConnect
    override fun onBeaconServiceConnect() {

        try {
            // ビーコン情報の監視を開始、第3,4引数はmajor・minor値を指定する時に使用
            beaconManager!!.startMonitoringBeaconsInRegion(Region("beacon-test", uuid, null, null ))
        } catch (e: RemoteException) {
            e.printStackTrace()
        }

        // モニタリングの通知受取り処理
        beaconManager!!.addMonitorNotifier(object : MonitorNotifier {

            // 領域内に侵入した時に呼ばれる
            override fun didEnterRegion(region: Region) {

                // レンジングの開始
                beaconManager!!.startRangingBeaconsInRegion(region)
            }

            // 領域外に退出した時に呼ばれる
            override fun didExitRegion(region: Region) {

                // レンジングの停止
                beaconManager!!.stopRangingBeaconsInRegion(region)
            }

            // 領域への侵入/退出のステータスが変化した時に呼ばれる
            override fun didDetermineStateForRegion(i: Int, region: Region) {
                //
            }
        })

        // レンジングの通知受け取り処理
        beaconManager!!.addRangeNotifier { beacons, _ ->

            // 範囲内のビーコン情報を受け取る

     //***ここからしばらく処理のコードがありますが長いので割愛します****//

                // 携帯端末固有ID
                val deviceId = Settings.Secure.getString(this.getContentResolver(), Settings.System.ANDROID_ID);
                Log.d("Rssi_0_Maj_Min_Dis_Rs", "$deviceId,$maxName0,$maxMajor0,$maxMinor0,$maxDistance0,$maxRssi0")
                Log.d("Rssi_1_Maj_Min_Dis_Rs", "$deviceId,$maxName1,$maxMajor1,$maxMinor1,$maxDistance1,$maxRssi1")
                Log.d("Rssi_2_Maj_Min_Dis_Rs", "$deviceId,$maxName2,$maxMajor2,$maxMinor2,$maxDistance2,$maxRssi2")


                // メインスレッドで実装(追加)
                handler.post {
                    // 空の引数を渡して、Viewの更新
  //***割愛します****//
                    )
                }

                // Viewの更新
                viewUpdate(
//***割愛します****//
                )
            }
        }
    }

    private fun viewUpdate(
//***割愛します****//

    )
    {

        // Viewの取得
//***割愛します****//
    }


    /**************************************************
     * メソッド
     **************************************************/
    // トースト表示のメソッド
//***割愛します****//

    // パーミッションの許可チェック
//***割愛します****//
}


【実現したいこと】
下記の順番で処理を実行させたい。
1.アプリ起動。
2.ドロップダウンリストにて選択。
3.[START]ボタンクリックで電波受信開始。
4.任意の時間、電波収集
5.[STOP]ボタンクリックで受信終了。

今は、アプリ起動と同時に電波受信が始まります。
実際そのようなコードになっているのだと思いますが、
上記2、3、5の処理をソース中のどこに入れたら良いのかがわかりません。
ボタンのリスナー(まだコードに書いていませんが)を、
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
の下に書いたりしましたが、異常終了してしまいました。
また、//----------------//で挟みましたが、
spinnerのリスナーの場所もそこが正しいのでしょうか。

以上になります。
長々とした質問となり申し訳ございません。
ご教示のほどよろしくお願いいたします。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

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

  • jimbe

    2019/02/13 01:56

    > 今は、アプリ起動と同時に電波受信が始まります。

    はい, 実際そのようなコードになっております.
    Activity のライフサイクルについてお調べになると良いかと思います.

    キャンセル

  • jimbe

    2019/02/13 02:36

    若干違和感のあるコードと思いまして検索致しました.
    ↓で提示されているコードを改造されようということでしょうか.

    https://qiita.com/seaka829/items/613d27035dab7b3a9121

    権利云々ということも無いかと思いますが, 元にされたのでしたら, リンクを付けておいて頂けると参考になると思います.

    キャンセル

回答 1

checkベストアンサー

+1

altbeacon の使い方を知らないので失礼しますが, ご質問の内容はビーコンと直接関係無さそうに思います.
まずビーコンに関する処理の実装を別クラスとしておいてダミーを用意し, 画面関係を作られては如何でしょうか.
それによってコード量が減少し動作する状態でのご提示を頂けるようになれば, 回答も得やすくなるものと考えます.


追記・修正依頼と回答が逆になってしまいました. 失礼しました.

一般的にはリスナーの登録などは onCreate 内で行われると思います.
この場合のスピナーやボタンのリスナーの登録も, 同様かと思います.
しかし, ボタンのリスナーを登録したことによる異常終了に関しましては, コードがなければ判断できません.

今は、アプリ起動と同時に電波受信が始まります。

実際そのようなコードになっております.
Activity のライフサイクルについてお調べになると良いかと思います.

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/02/14 18:31

    start ボタンを押して beaconManager!!.bind(this) で実行され, stop ボタンを押して beaconManager!!.unbind(this) しているのであれば, 2度目の start(bind) で動かないのは beaconManager 内で何か起きている(ガードしている?)と思われます.
    onBeaconServiceConnect メソッドで行っている中には startXxx というのが多くありますので, もしかすると unbind 時に stopXxx という対応するようなメソッドを呼ばなくてはならない等があるのかもしれません. そのような記述を探していますが, 見つかっておりません.
    beaconManager からの(1度目と異なる)ログメッセージは logcat に出ていないでしょうか. もしくは 1度目に出ていて2度目に出ていないメッセージはありませんでしょうか.

    キャンセル

  • 2019/02/21 16:06 編集

    ログも調べましたが、ご指摘の内容は残念ながら見つけられずじまいでした。
    結局、STARTボタンで受信開始し、STOPで終了し、アプリも終了、という流れで完結して
    続けて受信したいときは、再度アプリ起動→STARTボタンで受信開始し、
    受信内容のファイルは前回のものに追加して書き込む、という手段でいくことにしました。

    この度は誠にありがとうございました。
    初歩的なところのソースの書き方なども勉強になりました。
    もっと精進いたします。

    キャンセル

  • 2019/02/21 16:19

    左様でしたか, 私も残念です.
    もし今後私も beacon を使うようなことがありましたら, また調査してみたいと思います.

    キャンセル

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

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

関連した質問

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