▲ 1 r/AndroidStudio+1 crossposts

My app won't open from tapping the notification?

I've been trying to get it to work for about an hour, no amount of AI is helping me and no errors are displayed. I am using the official android development program to make an app and after getting the notifications working, I cannot get it to open the app from the notification, what could be the problem?

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.wordoftheday">

    <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="Word of the Day"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.AppCompat.DayNight.NoActionBar">

        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:launchMode="singleTop"> <!-- Add this attribute here -->
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <!-- Receiver definition -->
        <receiver
            android:name=".DailyNotificationReceiver"
            android:enabled="true"
            android:exported="false" />

    </application>

</manifest>
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.wordoftheday">

    <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="Word of the Day"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.AppCompat.DayNight.NoActionBar">

        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:launchMode="singleTop"> <!-- Add this attribute here -->
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <!-- Receiver definition -->
        <receiver
            android:name=".DailyNotificationReceiver"
            android:enabled="true"
            android:exported="false" />

    </application>

</manifest>

DailyNotificationReceiver.kt

package com.example.wordoftheday

import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.os.Build
import androidx.core.app.NotificationCompat
import androidx.core.app.TaskStackBuilder
import java.io.BufferedReader
import java.io.InputStreamReader
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale

class DailyNotificationReceiver : BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) {
        val sharedPref = context.getSharedPreferences("WebViewSettings", Context.MODE_PRIVATE)
        val currentLevel = sharedPref.getString("word_cefr_level", "A1") ?: "A1"

        val (headword, definition) = getWordForToday(context, currentLevel)
        showNotification(context, "$currentLevel Word of the Day:\n$headword", definition)
    }

    private fun getWordForToday(context: Context, level: String): Pair<String, String> {
        try {
            val prefs = context.getSharedPreferences("WordAppPrefs", Context.MODE_PRIVATE)
            val todayStr = SimpleDateFormat("yyyy-MM-dd", Locale.US).format(Date())
            var firstDateStr = prefs.getString("word_app_first_date", null)

            if (firstDateStr == null) {
                firstDateStr = todayStr
                prefs.edit().putString("word_app_first_date", firstDateStr).apply()
            }

            val format = SimpleDateFormat("yyyy-MM-dd", Locale.US)
            val firstDate = format.parse(firstDateStr) ?: Date()
            val currentDate = format.parse(todayStr) ?: Date()

            // Clean, fixed date math calculation without any stray characters
            val diffDays = ((currentDate.time - firstDate.time) / (1000 * 60 * 60 * 24)).toInt()
            val dayNumber = Math.max(1, diffDays + 1)

            val inputStream = context.assets.open("$level.csv")
            val reader = BufferedReader(InputStreamReader(inputStream))
            val lines = reader.readLines().drop(1).filter { it.isNotBlank() }

            if (lines.isEmpty()) return Pair("Vocabulary", "Check today's new word in the app!")

            val wordIndex = (dayNumber - 1) % lines.size
            val parsedRow = parseCSVLine(lines[wordIndex])

            if (parsedRow.size >= 4) {
                return Pair(parsedRow[1], parsedRow[3])
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return Pair("Word of the Day", "Tap to learn your new word for today!")
    }

    private fun parseCSVLine(line: String): List<String> {
        val row = mutableListOf<String>()
        var inQuotes = false
        var currentVal = StringBuilder()

        for (i in line.indices) {
            val char = line[i]
            if (char == '"') {
                inQuotes = !inQuotes
            } else if (char == ',' && !inQuotes) {
                row.add(currentVal.toString().trim().removeSurrounding("\""))
                currentVal = StringBuilder()
            } else {
                currentVal.append(char)
            }
        }
        row.add(currentVal.toString().trim().removeSurrounding("\""))
        return row
    }

    private fun showNotification(context: Context, title: String, message: String) {
        val channelId = "daily_word_channel"
        val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val channel = NotificationChannel(
                channelId,
                "Daily Word Reminders",
                NotificationManager.IMPORTANCE_DEFAULT
            )
            notificationManager.createNotificationChannel(channel)
        }

        // 1. Explicitly point to MainActivity and apply clear/single flags
        val resultIntent = Intent(context, MainActivity::class.java).apply {
            flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP
        }

        // 2. Generate a valid, safe PendingIntent directly from the intent
        val pendingIntent = PendingIntent.getActivity(
            context,
            1001, // Use a distinct request code instead of 0
            resultIntent,
            PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
        )

        // 3. Build and fire the notification
        val builder = NotificationCompat.Builder(context, channelId)
            .setSmallIcon(android.R.drawable.ic_popup_reminder)
            .setContentTitle(title)
            .setContentText(message)
            .setStyle(NotificationCompat.BigTextStyle().bigText(message))
            .setPriority(NotificationCompat.PRIORITY_DEFAULT)
            .setContentIntent(pendingIntent) // Passes the valid intent
            .setAutoCancel(true)

        notificationManager.notify(1001, builder.build())
    }

}package com.example.wordoftheday

import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.os.Build
import androidx.core.app.NotificationCompat
import androidx.core.app.TaskStackBuilder
import java.io.BufferedReader
import java.io.InputStreamReader
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale

class DailyNotificationReceiver : BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) {
        val sharedPref = context.getSharedPreferences("WebViewSettings", Context.MODE_PRIVATE)
        val currentLevel = sharedPref.getString("word_cefr_level", "A1") ?: "A1"

        val (headword, definition) = getWordForToday(context, currentLevel)
        showNotification(context, "$currentLevel Word of the Day:\n$headword", definition)
    }

    private fun getWordForToday(context: Context, level: String): Pair<String, String> {
        try {
            val prefs = context.getSharedPreferences("WordAppPrefs", Context.MODE_PRIVATE)
            val todayStr = SimpleDateFormat("yyyy-MM-dd", Locale.US).format(Date())
            var firstDateStr = prefs.getString("word_app_first_date", null)

            if (firstDateStr == null) {
                firstDateStr = todayStr
                prefs.edit().putString("word_app_first_date", firstDateStr).apply()
            }

            val format = SimpleDateFormat("yyyy-MM-dd", Locale.US)
            val firstDate = format.parse(firstDateStr) ?: Date()
            val currentDate = format.parse(todayStr) ?: Date()

            // Clean, fixed date math calculation without any stray characters
            val diffDays = ((currentDate.time - firstDate.time) / (1000 * 60 * 60 * 24)).toInt()
            val dayNumber = Math.max(1, diffDays + 1)

            val inputStream = context.assets.open("$level.csv")
            val reader = BufferedReader(InputStreamReader(inputStream))
            val lines = reader.readLines().drop(1).filter { it.isNotBlank() }

            if (lines.isEmpty()) return Pair("Vocabulary", "Check today's new word in the app!")

            val wordIndex = (dayNumber - 1) % lines.size
            val parsedRow = parseCSVLine(lines[wordIndex])

            if (parsedRow.size >= 4) {
                return Pair(parsedRow[1], parsedRow[3])
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return Pair("Word of the Day", "Tap to learn your new word for today!")
    }

    private fun parseCSVLine(line: String): List<String> {
        val row = mutableListOf<String>()
        var inQuotes = false
        var currentVal = StringBuilder()

        for (i in line.indices) {
            val char = line[i]
            if (char == '"') {
                inQuotes = !inQuotes
            } else if (char == ',' && !inQuotes) {
                row.add(currentVal.toString().trim().removeSurrounding("\""))
                currentVal = StringBuilder()
            } else {
                currentVal.append(char)
            }
        }
        row.add(currentVal.toString().trim().removeSurrounding("\""))
        return row
    }

    private fun showNotification(context: Context, title: String, message: String) {
        val channelId = "daily_word_channel"
        val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val channel = NotificationChannel(
                channelId,
                "Daily Word Reminders",
                NotificationManager.IMPORTANCE_DEFAULT
            )
            notificationManager.createNotificationChannel(channel)
        }

        // 1. Explicitly point to MainActivity and apply clear/single flags
        val resultIntent = Intent(context, MainActivity::class.java).apply {
            flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP
        }

        // 2. Generate a valid, safe PendingIntent directly from the intent
        val pendingIntent = PendingIntent.getActivity(
            context,
            1001, // Use a distinct request code instead of 0
            resultIntent,
            PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
        )

        // 3. Build and fire the notification
        val builder = NotificationCompat.Builder(context, channelId)
            .setSmallIcon(android.R.drawable.ic_popup_reminder)
            .setContentTitle(title)
            .setContentText(message)
            .setStyle(NotificationCompat.BigTextStyle().bigText(message))
            .setPriority(NotificationCompat.PRIORITY_DEFAULT)
            .setContentIntent(pendingIntent) // Passes the valid intent
            .setAutoCancel(true)

        notificationManager.notify(1001, builder.build())
    }
reddit.com
u/Adamstrad — 3 days ago
▲ 5 r/AppBuilding+1 crossposts

Converting HTML(+ jscript) file to google play app?

I want to convert an app I made for myself and put it on the play store, what is the easiest and cheapest way for a beginner to do this?

reddit.com
u/Adamstrad — 12 days ago
▲ 0 r/lua

Looking for a video to help me learn the basics in LUA for making game add ons (already familiar with jscript, python and web coding)

reddit.com
u/Adamstrad — 14 days ago

People who overcame struggling with neuralgia or nerve pain, how did you do it?

Most of the things I read online seem to give suggestions but very few success stories, tell me about your positive experiences!

reddit.com
u/Adamstrad — 15 days ago

I always die before level 10

I had hardcore characters about 10 times and the only time I survived past level 10 was on a lock... Of course I died about level 16.

What am I probably doing wrong? I don't go after hard monsters, but I always seem to be fighting something that hits too hard for me to survive. Should i be grinding easy things and avoiding quests? What could be the problem

reddit.com
u/Adamstrad — 28 days ago

Searching for an API which pronounces a word, can you recommend a good one?

To be used in English html pages which uses JavaScript to deliver the data, . Ideally an API which doesn't require a key since I'm building a web app for distribution

reddit.com
u/Adamstrad — 1 month ago

I have a web app that I want to keep in a mobile sized box, with a safe zone to accout for different sizes but scrolling is okay

I have a web app that I want to keep in a mobile sized box, with a safe zone to account for different sizes but scrolling is okay. how can I achieve this?

reddit.com
u/Adamstrad — 1 month ago

What platforms are easy for ESL tutors to join all year round?

I use one of the largest platforms but I have had problems finding others with availability for English tutors

reddit.com
u/Adamstrad — 1 month ago

How do you find time to work on your microsaas?

I feel like I never have the time or mind-space to work on it consistently

reddit.com
u/Adamstrad — 1 month ago

How complex does a saas need to be?

I want to make useful apps to sell but everything I see is miles better than anything that I can come up with, both the idea and design, what are the simplest ones you've seen (and simple to build) I'm not looking to copy them, just wondering if I have what it takes

reddit.com
u/Adamstrad — 1 month ago

I see a lot of things about people who make money botting in games, but what are some real life profitable and legal applications of botting?

reddit.com
u/Adamstrad — 1 month ago

Tips for styling app after finishing the functional code?

I'm making an app with html JavaScript and I don't want to use a load of programs to download and package it but I want it to be presentable. Does anyone have some tips for me?

reddit.com
u/Adamstrad — 1 month ago

Anybody who started a tourguide business (solo or with a group of friends)?

Was it successful?

How did you go about starting it, learning the skills and marketing it?

reddit.com
u/Adamstrad — 1 month ago

Best online CELTAs, are alternative courses widely accepted?

I'm thinking about doing the CELTA since I have some experience tutoring and a tefl, are course like the level 5 course at tefl academy usually accepted internationally or is it better to pay all the extra money for an official CELTA?

reddit.com
u/Adamstrad — 1 month ago