Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

【Android】自分で設定した通知音で通知させたい

解決したいこと

AndroidStudioでAndroidアプリを開発しています。
自分で設定した通知音で通知させたいのですが設定した音が流れてくれません。
解決方法を教えてください。

使用環境
Android Studio Chipmunk | 2021.2.1 Patch 1
Kotlin 1.7.0
macOS monterey 12.4

発生している問題・エラー

Serviceを用いて定期的に通知してくれるアプリを開発しています。
しかしながら、自分で設定した通知音で通知させたいのですが設定した音が流れてくれません。

Serviceの中には通知音を鳴らしたい該当の通知チャンネル以外に
フォアグラウンド処理をしているという表示をする通知チャンネルが存在します。

該当するソースコード

とても長くなってしまいましたが、該当のコード部分は後半部分の通知チャンネルで
「APIレベルに応じた通知チャンネルの作成(該当部分)」とコメントアウトされています。

//アプリを落としても表示画面外で動き続けるための処理(フォアグラウンド処理)
class GetttingWeatherInformationService : Service() {

    private lateinit var realm: Realm

    companion object {
        const val CHANNEL_ID = "1111"
    }

    override fun onBind(p0: Intent?): IBinder? {
        return null
    }

    //    他のActivityがサービスの開始をリクエストした際の処理
    @SuppressLint("UnspecifiedImmutableFlag")
    @RequiresApi(Build.VERSION_CODES.O)
    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {

        //1.常時通知されている通知領域をタップした時に戻ってくる先のActivity
        val openIntent = Intent(this, MainActivity::class.java).let {
            PendingIntent.getActivity(this, 0, it, 0)
        }

        //2.フォアグラウンド処理をしている通知チャンネル登録
        val channelId = CHANNEL_ID
        val channelName = "TestService Channel"
        val channel = NotificationChannel(
            channelId, channelName,
            NotificationManager.IMPORTANCE_DEFAULT
        )
        val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        manager.createNotificationChannel(channel)

        //3.ブロードキャストレシーバーをPendingIntent化
        val sendIntent = Intent(this, GetttingWeatherInformationReceiver::class.java).apply {
            action = Intent.ACTION_SEND
        }
        val sendPendingIntent = PendingIntent.getBroadcast(this, 0, sendIntent, 0)

        //4.通知の作成(ここでPendingIntentを通知領域に渡す)
        val notification = NotificationCompat.Builder(this, CHANNEL_ID)
            .setSmallIcon(R.drawable.notification_icon)
            .setContentTitle("曇を観測中")
            .setContentText("現在の状況の確認はこの通知をタップ")
            .setPriority(NotificationCompat.PRIORITY_DEFAULT)
            .setContentIntent(openIntent)
            .addAction(R.drawable.notification_icon, "観測の終了はこちら", sendPendingIntent)
            .build()

        //5.フォアグラウンド開始。
        startForeground(2222, notification)

//    繰り返し通知するための時間設定(現在はServiceが開始してから30分ごと)
        val notificationInterval: TimerTask.() -> Unit = {
            realm = Realm.getDefaultInstance()
            val points = realm.where<Point>().findAll()
            //DBのpointそれぞれでAPIを叩く
            for(point in points) {
                //APIキーを含むURLを入力して天気の情報を受け取る関数
                val id: Long = point.id
                gettingWeatherInformation(id)
            }
//            APIキーを含むURLを入力して天気の情報を受け取る関数
            //gettingWeatherInformation()
        }
        Timer().schedule(0, 1800000, notificationInterval)

        return START_STICKY
    }

    //    サービスの終了(GetttingWeatherInformationReceiver.ktで呼び出してる)
    override fun stopService(name: Intent?): Boolean {
        return super.stopService(name)
    }



//    各ライフサイクル内で使う関数の定義

    //    APIキーを含むURLを入力して天気の情報を受け取る関数
    private fun gettingWeatherInformation(id: Long) {
        val point = realm.where<Point>().equalTo("id", id)?.findFirst()
        val city_name: String = point?.point_name.toString()
//    APIキーを含むURLの定義
        val apiKey = "〜"
        val lon: Double = point?.lon.toString().toDouble()
        val lat: Double = point?.lat.toString().toDouble()
        val mapDisplay = "lat=${lat}&lon=${lon}"
        val weatherUrl = "https://api.openweathermap.org/data/2.5/onecall?$mapDisplay&units=metric&lang=ja&appid=$apiKey"

//    weatherTask関数にURLを入力(さらに、ポイント名も渡す)
        weatherTask(weatherUrl, city_name)
    }

    //    URLの検索及び、検索した結果の処理の関数(コルーチンを始める)
    private fun weatherTask(weatherUrl:String, city_name: String) {
        GlobalScope.launch(Dispatchers.Main,CoroutineStart.DEFAULT){
//            入力されたURLの検索
            val result = weatherBackgroundTask(weatherUrl)
//            weatherJsonTask関数で、URLを検索した結果のJSON形式のデータを処理
            weatherJsonTask(result, city_name)
        }
    }

    //    入力されたURLの検索
    private suspend fun weatherBackgroundTask(weatherUrl:String):String{
//        入力されたURLの検索
        val response = withContext(Dispatchers.IO){
            var httpResult = ""
//            とりあえず入力されたURLを検索してみる
            try {
                val urlObj = URL(weatherUrl)
                val br = BufferedReader(InputStreamReader(urlObj.openStream()))
                httpResult = br.readText()
//            検索できなかった時の処理
            }catch (e: IOException){
                e.printStackTrace()
            }catch (e: JSONException){
                e.printStackTrace()
            }
//            "response"に"httpResult"を返す
            return@withContext httpResult
        }
//        "weatherBackgroundTask"の戻り値に"response"(="httpResult")を返す
        return response
    }

    //    天気の情報が入ったJSON形式のデータの処理及びその内容を通知する関数
    @SuppressLint("UnspecifiedImmutableFlag")
    private  fun weatherJsonTask(result:String, city_name: String) {

//    変数の定義
        val jsonObj = JSONObject(result)
        val weatherNowJSONObject = jsonObj.getJSONObject("current")
        val nowClouds = weatherNowJSONObject.getInt("clouds")
        val weatherFutureJSONArray = jsonObj.getJSONArray("hourly")
        val weatherFutureJSONObject = weatherFutureJSONArray.getJSONObject(1)
        val futureClouds = weatherFutureJSONObject.getInt("clouds")
        val nowTime = weatherNowJSONObject.getInt("dt")
        val futureTime = weatherFutureJSONObject.getInt("dt")
        val minute: Int = (futureTime - nowTime) / 60

//    通知をするための準備
        var notificationId = 0
        val CHANNEL_ID = "channel_id"

//    APIレベルに応じた通知チャンネルの作成(該当部分)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val audioAttributes = AudioAttributes.Builder()
                .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
                .setUsage(AudioAttributes.USAGE_NOTIFICATION_EVENT)
                .build()
            val uri = Uri.parse("android.resource://$packageName/${R.raw.notification_sound}")
            val importance = NotificationManager.IMPORTANCE_DEFAULT
            val channel = NotificationChannel(CHANNEL_ID, "雲量通知", importance).apply {
                description = "雲量の通知"
                setSound(uri,audioAttributes)
            }
            /// チャネルを登録
            val notificationManager: NotificationManager =
                getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
            notificationManager.createNotificationChannel(channel)
        }

//    天気の通知をタップした時に画面遷移するための準備
        val openIntent = Intent(this, MainActivity::class.java).let {
            PendingIntent.getActivity(this, 0, it, 0)
        }

//    通知の詳細
        val builder = NotificationCompat.Builder(this, CHANNEL_ID)
            .setSmallIcon(R.drawable.notification_icon)  /// 表示されるアイコン
            .setContentTitle("${city_name}の上空")                     /// 通知タイトル(仮に東京を代入)
            .setContentText("現在の雲量は${nowClouds},${minute}分後の雲量は${futureClouds},")  /// 通知コンテンツ
            .setPriority(NotificationCompat.PRIORITY_MAX)    /// 通知の優先度
            .setContentIntent(openIntent)                    /// 天気の通知をタップした時に画面遷移

//    通知のビルド
        with(NotificationManagerCompat.from(this)) {
            notify(notificationId, builder.build())
            notificationId += 1
        }
    }
    override fun onDestroy() {
        super.onDestroy()
        realm.close()
    }
}

自分で試したこと

以下のサイトを参考しました。

0

No Answers yet.

Your answer might help someone💌