in my MainActivity.java
// ─────────────────────────────────────────────
// OneSignal Identity + Permission Handling
// ─────────────────────────────────────────────
private IUserStateObserver identityObserver = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SharedPreferences prefs = getSharedPreferences("biratbazar_prefs", Context.MODE_PRIVATE);
boolean isLoggedIn = prefs.getBoolean("is_logged_in", false);
String savedUserId = prefs.getString("user_id", null);
// Observe user identity state
identityObserver = state -> {
String currentExternalId = state.getCurrent().getExternalId();
String currentOnesignalId = state.getCurrent().getOnesignalId();
Log.d("OneSignal", "User State Change: ExternalID="
+ currentExternalId + ", OneSignalID=" + currentOnesignalId);
boolean isIdentified = isLoggedIn
? (currentExternalId != null && currentExternalId.equals(savedUserId))
: (currentOnesignalId != null);
if (isIdentified && identityObserver != null) {
Log.d("OneSignal", "Identity confirmed. Requesting permission...");
IUserStateObserver toRemove = identityObserver;
identityObserver = null;
OneSignal.getUser().removeObserver(toRemove);
runOnUiThread(this::requestOneSignalPermission);
}
};
OneSignal.getUser().addObserver(identityObserver);
// Debug: subscription state
OneSignal.getUser().getPushSubscription().addObserver(state -> {
boolean hasToken = state.getCurrent().getToken() != null
&& !state.getCurrent().getToken().isEmpty();
Log.d("OneSignal", "Subscription Changed: ID="
+ state.getCurrent().getId()
+ ", OptedIn=" + state.getCurrent().getOptedIn()
+ ", HasToken=" + hasToken);
});
// Login with external ID if available
if (isLoggedIn && savedUserId != null) {
OneSignalManager.getInstance().login(savedUserId);
}
}
// ─────────────────────────────────────────────
// Request Permission
// ─────────────────────────────────────────────
private void requestOneSignalPermission() {
OneSignal.getNotifications().requestPermission(true, Continue.with(result -> {
if (result.isSuccess() && Boolean.TRUE.equals(result.getData())) {
Log.d("OneSignal", "Permission granted → opting in");
OneSignal.getUser().getPushSubscription().optIn();
} else {
Log.d("OneSignal", "Permission not granted or failed: " + result);
}
}));
}
// ─────────────────────────────────────────────
// Ensure opt-in on resume
// ─────────────────────────────────────────────
@Override
protected void onResume() {
super.onResume();
if (OneSignal.getNotifications().getPermission()) {
OneSignal.getUser().getPushSubscription().optIn();
}
}
in my BiratBazarApp.java
package com.officersiam.biratbazar;
import android.app.Application;
import android.util.Log;
import com.google.firebase.FirebaseApp;
import com.onesignal.Continue;
import com.onesignal.OneSignal;
import com.onesignal.debug.LogLevel;
public class BiratBazarApp extends Application {
private static final String ONESIGNAL_APP_ID = "58eeb5a7-3adf-4d9d-8915-f45c6a542284";
@Override
public void onCreate() {
super.onCreate();
// 1. Initialize Firebase first
try {
FirebaseApp.initializeApp(this);
} catch (Exception e) {
Log.e("Firebase", "Firebase init error", e);
}
// 2. Initialize OneSignal
OneSignalManager.getInstance().initialize(this, ONESIGNAL_APP_ID);
}
}
in my OneSignalManager.java
package com.officersiam.biratbazar;
import android.content.Context;
import android.util.Log;
import com.onesignal.OneSignal;
import com.onesignal.debug.LogLevel;
import com.onesignal.user.subscriptions.IPushSubscriptionObserver;
import com.onesignal.user.subscriptions.PushSubscriptionChangedState;
import com.onesignal.inAppMessages.IInAppMessageLifecycleListener;
import com.onesignal.inAppMessages.IInAppMessageWillDismissEvent;
import com.onesignal.inAppMessages.IInAppMessageDidDismissEvent;
import com.onesignal.inAppMessages.IInAppMessageWillDisplayEvent;
import com.onesignal.inAppMessages.IInAppMessageDidDisplayEvent;
import java.util.concurrent.Executors;
import androidx.annotation.NonNull;
public class OneSignalManager {
private static OneSignalManager instance;
private boolean isInitialized = false;
private OneSignalManager() {}
public static synchronized OneSignalManager getInstance() {
if (instance == null) {
instance = new OneSignalManager();
}
return instance;
}
public void initialize(Context context, String appId) {
if (isInitialized) return;
// Set log level for debugging
OneSignal.getDebug().setLogLevel(LogLevel.VERBOSE);
// Initialize OneSignal
OneSignal.initWithContext(context, appId);
isInitialized = true;
Log.d("OneSignalManager", "OneSignal initialized with App ID: " + appId);
}
public void login(String externalId) {
Executors.newSingleThreadExecutor().execute(() -> OneSignal.login(externalId));
}
public void logout() {
Executors.newSingleThreadExecutor().execute(() -> OneSignal.logout());
}
public void addPushSubscriptionObserver(IPushSubscriptionObserver observer) {
OneSignal.getUser().getPushSubscription().addObserver(observer);
}
public void addTrigger(String key, String value) {
Executors.newSingleThreadExecutor().execute(() -> OneSignal.getInAppMessages().addTrigger(key, value));
}
public void addIAMLifecycleListener(IInAppMessageLifecycleListener listener) {
OneSignal.getInAppMessages().addLifecycleListener(listener);
}
public void removeIAMLifecycleListener(IInAppMessageLifecycleListener listener) {
OneSignal.getInAppMessages().removeLifecycleListener(listener);
}
}
in my BiratBazarNotificationService.java
package com.officersiam.biratbazar.notification;
import com.onesignal.notifications.INotificationReceivedEvent;
import com.onesignal.notifications.INotificationServiceExtension;
/**
* Declared in AndroidManifest with:
* <action android:name="com.onesignal.NotificationServiceExtension"/>
*
* Allows us to intercept / modify notifications before they are displayed.
*/
public class BiratBazarNotificationService implements INotificationServiceExtension {
@Override
public void onNotificationReceived(INotificationReceivedEvent event) {
// Display all notifications as-is.
// To suppress a notification call event.preventDefault() without display().
event.getNotification().display();
}
}
in my progaurd-rules.pro
# ============================================================
# BiratBazar — ProGuard Rules
# ============================================================
# ── App classes ─────────────────────────────────────────────
-keep class com.officersiam.biratbazar.** { *; }
# ── OneSignal ───────────────────────────────────────────────
-keep class com.onesignal.** { *; }
-keepclassmembers class com.onesignal.** {
public <init>(...);
}
-keep class com.onesignal.OSRemoteNotificationReceivedHandler { *; }
-dontwarn com.onesignal.**
# ── Firebase / FCM ──────────────────────────────────────────
-keep class com.google.firebase.** { *; }
-keepclassmembers class com.google.firebase.** {
public <init>(...);
}
-keep class com.google.android.gms.** { *; }
-dontwarn com.google.firebase.**
-dontwarn com.google.android.gms.**
# ── AndroidX WorkManager (OneSignal background jobs) ────────
-keep class androidx.work.** { *; }
-keepclassmembers class androidx.work.** {
public <init>(...);
}
-dontwarn androidx.work.**
# ── WebView JavaScript Interface ────────────────────────────
-keepclassmembers class * {
@android.webkit.JavascriptInterface <methods>;
}
# ── ViewBinding ─────────────────────────────────────────────
-keep class * implements androidx.viewbinding.ViewBinding {
public static * inflate(...);
public static * bind(android.view.View);
}
# ── Material / BottomSheet ──────────────────────────────────
-keep class com.google.android.material.** { *; }
-dontwarn com.google.android.material.**
# ── Lottie ──────────────────────────────────────────────────
-keep class com.airbnb.lottie.** { *; }
-dontwarn com.airbnb.lottie.**
# ── General Android safety nets ─────────────────────────────
# Preserve all native method names
-keepclasseswithmembernames class * {
native <methods>;
}
# Preserve custom View constructors (used by XML inflation)
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet);
public <init>(android.content.Context, android.util.AttributeSet, int);
}
# Keep Parcelable implementations
-keepclassmembers class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
# Keep Serializable implementations
-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
private static final java.io.ObjectStreamField[] serialPersistentFields;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}
# Keep R class fields (referenced by name in some libs)
-keepclassmembers class **.R$* {
public static <fields>;
}
# Keep enums
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
# ── Debugging (remove/disable in production if preferred) ───
-keepattributes SourceFile,LineNumberTable
-renamesourcefileattribute SourceFile
in my AndroidMenifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<application
android:name=".BiratBazarApp"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/Theme.BiratBazar"
android:networkSecurityConfig="@xml/network_security_config"
android:usesCleartextTraffic="true"
tools:targetApi="31">
<!-- OneSignal configuration -->
<meta-data android:name="onesignal_app_id" android:value="58eeb5a7-3adf-4d9d-8915-f45c6a542284" />
<meta-data
android:name="com.onesignal.NotificationServiceExtension"
android:value="com.officersiam.biratbazar.notification.BiratBazarNotificationService" />
<!-- Honor/EMUI FCM workaround -->
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="@string/default_notification_channel_id" />
</application>
</manifest>
in my build.gradle (app)
plugins {
id 'com.android.application'
id 'com.google.gms.google-services'
}
dependencies {
// Firebase
implementation platform('com.google.firebase:firebase-bom:34.12.0')
implementation 'com.google.firebase:firebase-messaging'
implementation 'com.google.firebase:firebase-analytics'
// OneSignal
implementation 'com.onesignal:OneSignal:[5.6.1, 5.9.99]'
}
in my build.gradle (project)
plugins {
id 'com.android.application' version '8.2.2' apply false
id 'com.android.library' version '8.2.2' apply false
id 'com.google.gms.google-services' version '4.4.4' apply false
}



after all that onesignal dashboard showing never subscribed even after i click on allow button on push permission prompt, enable notifications to get news instantly. that status never changing to subscribe

Your Firebase setup is probably not the main problem here.
In your OneSignal dashboard, the important part is this:
Status details: Permission Not Granted
So OneSignal is creating a subscription record, but Android notification permission is still not granted according to OneSignal.
The issue is mostly in this part of your code:
identityObserver = state -> {
...
if (isIdentified) {
runOnUiThread(this::requestOneSignalPermission);
}
};
You are waiting for the OneSignal identity observer before asking notification permission. If that observer does not fire, or the user state is already created before the observer is added, then requestOneSignalPermission() may never run.
Keep it simple. Initialize OneSignal in Application, then ask permission directly from your Activity.
Like this:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestOneSignalPermission();
SharedPreferences prefs = getSharedPreferences("biratbazar_prefs", Context.MODE_PRIVATE);
boolean isLoggedIn = prefs.getBoolean("is_logged_in", false);
String savedUserId = prefs.getString("user_id", null);
if (isLoggedIn && savedUserId != null) {
OneSignal.login(savedUserId);
}
OneSignal.getUser().getPushSubscription().addObserver(state -> {
Log.d("OneSignal", "Subscription ID: " + state.getCurrent().getId());
Log.d("OneSignal", "Token: " + state.getCurrent().getToken());
Log.d("OneSignal", "OptedIn: " + state.getCurrent().getOptedIn());
});
}
private void requestOneSignalPermission() {
OneSignal.getNotifications().requestPermission(true, result -> {
Log.d("OneSignal", "Permission result: " + result);
if (Boolean.TRUE.equals(result.getData())) {
Log.d("OneSignal", "Permission granted");
OneSignal.getUser().getPushSubscription().optIn();
} else {
Log.d("OneSignal", "Permission denied");
}
});
}
Also make sure you have this permission in AndroidManifest.xml:
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
For Android 13+, this permission is required.
Your Application class can stay simple:
public class BiratBazarApp extends Application {
private static final String ONESIGNAL_APP_ID = "58eeb5a7-3adf-4d9d-8915-f45c6a542284";
@Override
public void onCreate() {
super.onCreate();
FirebaseApp.initializeApp(this);
OneSignal.getDebug().setLogLevel(LogLevel.VERBOSE);
OneSignal.initWithContext(this, ONESIGNAL_APP_ID);
}
}
Also check these things:
google-services.json must be inside the app/ folder.
The package name in Firebase must exactly match: com.officersiam.biratbazar
Run on a real device with Google Play Services.
Uninstall and reinstall the app after changing Firebase / OneSignal config.
Check Logcat for this:
Token: something_here
OptedIn: true
If Token is null, then FCM token is not being generated. In that case the issue is Firebase/FCM configuration, not OneSignal permission code.
The main fix: do not wait for the identity observer to request notification permission. Ask permission directly from the Activity after OneSignal initialization.