在频道“channel_id_here”上获取“发布通知失败”错误。

huangapple 未分类评论42阅读模式
英文:

Getting a failed to post notification on channel "channel_id_here" error

问题

以下是翻译好的代码部分:

我已经在过去的几天里苦苦挣扎试图在Android设备上显示本地通知通知根本不会显示出来我收到了开发者警告

"channel_id_here" 上发布通知失败

我查阅了许多教程和StackOverflow帖子看看是否有我错过的东西但我根本找不到请有人帮忙看看我在这里做错了什么或者是否有什么我遗漏的地方我会感谢一些帮助来解决这个问题

我的应用程序目标API 29我使用了这个[git][1]中的代码

[1]: https://github.com/mtraver/android-notifications

以下是我的应用程序中相关的代码

AppCompatPreferenceActivity.java

...

NotificationPublisher.java

...

NotificationSchedulerApplication.java

...

SettingsActivity.java

...

TimePreference.java

...

AndroidManifest.xml中的接收器

<receiver android:name=".activity.NotificationPublisher" />

请注意,上述内容仅为翻译的代码部分,不包含问题或其他文本。如果您需要进一步的帮助,请随时提问。

英文:

I have been struggling for days now to get local notifications to display on an Android device. Notifications simply do not show up and I'm getting a developer warning:

package Failed to post notification on channel &quot;channel_id_here&quot; error.

I went through many tutorials and StackOverflow posts to see if there's anything I missed, but I simply can't find it. Can someone please take a look if I did something wrong here or if there's something I'm missing. I would appreciate some assistance in sorting this out.

My app is targeting API 29 and I used code from this git

Here is the relevant code from my app:

AppCompatPreferenceActivity.java

public abstract class AppCompatPreferenceActivity extends PreferenceActivity {

    private AppCompatDelegate mDelegate;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        getDelegate().installViewFactory();
        getDelegate().onCreate(savedInstanceState);
        super.onCreate(savedInstanceState);
    }

    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        getDelegate().onPostCreate(savedInstanceState);
    }

    public ActionBar getSupportActionBar() {
        return getDelegate().getSupportActionBar();
    }

    public void setSupportActionBar(@Nullable Toolbar toolbar) {
        getDelegate().setSupportActionBar(toolbar);
    }

    @Override
    public MenuInflater getMenuInflater() {
        return getDelegate().getMenuInflater();
    }

    @Override
    public void setContentView(@LayoutRes int layoutResID) {
        getDelegate().setContentView(layoutResID);
    }

    @Override
    public void setContentView(View view) {
        getDelegate().setContentView(view);
    }

    @Override
    public void setContentView(View view, ViewGroup.LayoutParams params) {
        getDelegate().setContentView(view, params);
    }

    @Override
    public void addContentView(View view, ViewGroup.LayoutParams params) {
        getDelegate().addContentView(view, params);
    }

    @Override
    protected void onPostResume() {
        super.onPostResume();
        getDelegate().onPostResume();
    }

    @Override
    protected void onTitleChanged(CharSequence title, int color) {
        super.onTitleChanged(title, color);
        getDelegate().setTitle(title);
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        getDelegate().onConfigurationChanged(newConfig);
    }

    @Override
    protected void onStop() {
        super.onStop();
        getDelegate().onStop();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        getDelegate().onDestroy();
    }

    public void invalidateOptionsMenu() {
        getDelegate().invalidateOptionsMenu();
    }

    private AppCompatDelegate getDelegate() {
        if (mDelegate == null) {
            mDelegate = AppCompatDelegate.create(this, null);
        }
        return mDelegate;
    }
}

NotificationPublisher.java

public class NotificationPublisher extends BroadcastReceiver {
    public static String NOTIFICATION = &quot;notification&quot;;

    @Override
    public void onReceive(Context ctx, Intent intent) {
        NotificationManager notificationManager = (NotificationManager)
                ctx.getSystemService(Context.NOTIFICATION_SERVICE);

        // The notification may come from the received intent (see SettingsActivity for how to build
        // it and add it to the intent). If not then we&#39;ll build a notification here.
        Notification notification;
        if (intent.hasExtra(NOTIFICATION)) {
            notification = intent.getParcelableExtra(NOTIFICATION);
        } else {
            notification = buildNotification(ctx);
        }

        // notificationId is a unique int for each notification.
        // TODO Is the current time good enough?
        int notificationId = (int) System.currentTimeMillis();

        notificationManager.notify(notificationId, notification);
    }

    private Notification buildNotification(Context ctx) {
        Intent intent = new Intent(ctx, com.app.myapp.activity.MainActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        PendingIntent pendingIntent = PendingIntent.getActivity(ctx, 0, intent, 0);

        NotificationCompat.Builder builder = new NotificationCompat.Builder(ctx, CHANNEL_ID)
                .setSmallIcon(R.drawable.ic_stat_notification)
                .setContentTitle(&quot;Hello I&#39;m a notification!&quot;)
                .setContentText(&quot;Well look at that, it&#39;s content&quot;)
                .setContentIntent(pendingIntent)
                .setPriority(NotificationCompat.PRIORITY_DEFAULT)
                .setAutoCancel(true);

        return builder.build();
    }
}

NotificationSchedulerApplication.java

public class NotificationSchedulerApplication extends Application {

    public static final String CHANNEL_ID = &quot;1998882&quot;;

    @Override
    public void onCreate() {
        super.onCreate();
        createNotificationChannel();
    }

    private void createNotificationChannel() {
        // Create the NotificationChannel, but only on API 26+ because
        // the NotificationChannel class is new and not in the support library
        if (Build.VERSION.SDK_INT &gt;= Build.VERSION_CODES.O) {
            CharSequence name = getString(R.string.channel_name);
            String description = getString(R.string.channel_description);
            int importance = NotificationManager.IMPORTANCE_DEFAULT;
            NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance);
            channel.enableLights(true);
            channel.setLightColor(Color.RED);
            channel.enableVibration(true);
            channel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400});
            channel.setDescription(description);
            // Register the channel with the system; you can&#39;t change the importance
            // or other notification behaviors after this
            NotificationManager notificationManager = getSystemService(NotificationManager.class);
            notificationManager.createNotificationChannel(channel);
        }
    }
}

SettingsActivity.java

public class SettingsActivity extends AppCompatPreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener {

    private static final String ENABLE_NOTIFICATIONS_PREF_KEY = &quot;notifications_enable&quot;;
    private static final String NOTIFICATION_TIME_PREF_KEY = &quot;notifications_time&quot;;

    // This request code is used for all PendingIntents so that PendingIntents previously submitted
    // to the AlarmManager can be looked up for cancellation or modification.
    private static final int REQUEST_CODE = 0;

    /**
     * A preference value change listener that updates the preference&#39;s summary
     * to reflect its new value.
     */
    private static Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = new Preference.OnPreferenceChangeListener() {
        @Override
        public boolean onPreferenceChange(Preference preference, Object value) {
            if (preference instanceof ListPreference) {
                // For list preferences, look up the correct display value in
                // the preference&#39;s &#39;entries&#39; list.
                ListPreference listPreference = (ListPreference) preference;
                int index = listPreference.findIndexOfValue(value.toString());

                preference.setSummary(
                        index &gt;= 0
                                ? listPreference.getEntries()[index]
                                : null);
            } else if (preference instanceof TimePreference) {
                TimePreference timePreference = (TimePreference) preference;
                preference.setSummary(timePreference.valueToSummary((int) value));
            } else {
                // For all other preferences, set the summary to the value&#39;s
                // simple string representation.
                preference.setSummary(value.toString());
            }
            return true;
        }
    };

    /**
     * Helper method to determine if the device has an extra-large screen. For
     * example, 10&quot; tablets are extra-large.
     */
    private static boolean isXLargeTablet(Context context) {
        return (context.getResources().getConfiguration().screenLayout
                &amp; Configuration.SCREENLAYOUT_SIZE_MASK) &gt;= Configuration.SCREENLAYOUT_SIZE_XLARGE;
    }

    /**
     * Binds a preference&#39;s summary to its value. More specifically, when the
     * preference&#39;s value is changed, its summary (line of text below the
     * preference title) is updated to reflect the value. The summary is also
     * immediately updated upon calling this method. The exact display format is
     * dependent on the type of preference.
     *
     * @see #sBindPreferenceSummaryToValueListener
     */
    private static void bindPreferenceSummaryToValue(Preference preference) {
        preference.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener);

        // Trigger the listener immediately with the preference&#39;s current value.
        SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(
                preference.getContext());
        Object value;
        if (preference instanceof TimePreference) {
            value = sharedPrefs.getInt(preference.getKey(), 0);
        } else {
            value = sharedPrefs.getString(preference.getKey(), &quot;&quot;);
        }
        sBindPreferenceSummaryToValueListener.onPreferenceChange(preference, value);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setupActionBar();

        // Listen for changes to any preferences.
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
        prefs.registerOnSharedPreferenceChangeListener(this);
    }

    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String s) {
        // We only want to take action if these particular preferences change.
        if (!s.equals(ENABLE_NOTIFICATIONS_PREF_KEY) &amp;&amp; !s.equals(NOTIFICATION_TIME_PREF_KEY)) {
            return;
        }

        // If the preference was changed to false then we should cancel any pending notifications.
        if (s.equals(ENABLE_NOTIFICATIONS_PREF_KEY) &amp;&amp; !sharedPreferences.getBoolean(s, false)) {
            cancelIntents();
            return;
        }

        // Get the time at which to schedule notifications.
        Calendar startTime = TimePreference.valueToCalendar(
                sharedPreferences.getInt(NOTIFICATION_TIME_PREF_KEY, 0));

        // If the time has already passed today, start notifications tomorrow.
        Calendar now = Calendar.getInstance();
        if (now.after(startTime)) {
            startTime.add(Calendar.DATE, 1);
        }

        // Build a notification, add it to the intent we&#39;ll schedule, and schedule it.
//        Notification notification = buildNotification();
//        scheduleNotification(notification, startTime);

        // Schedule an intent, and build and publish the notification in the future whenever
        // the intent is received.
        scheduleNotification(startTime);
    }

    private PendingIntent getNotificationPublisherIntent(Notification notification) {
        Intent intent = new Intent(this, NotificationPublisher.class);
        if (notification != null) {
            intent.putExtra(NotificationPublisher.NOTIFICATION, notification);
        }

        return PendingIntent.getBroadcast(
                this, REQUEST_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT);
    }

    private Notification buildNotification() {
        Intent intent = new Intent(this, com.app.myapp.activity.MainActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);

        NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
                .setSmallIcon(R.drawable.ic_stat_notification)
                .setContentTitle(&quot;Hello I&#39;m a notification!&quot;)
                .setContentText(&quot;Well look at that, it&#39;s content 111&quot;)
                .setContentIntent(pendingIntent)
                .setPriority(NotificationCompat.PRIORITY_DEFAULT)
                .setAutoCancel(true);

        return builder.build();
    }

    private void scheduleNotification(Notification notification, Calendar startTime) {
        scheduleIntent(getNotificationPublisherIntent(notification), startTime);
    }

    private void scheduleNotification(Calendar startTime) {
        scheduleIntent(getNotificationPublisherIntent(null), startTime);
    }

    private void scheduleIntent(PendingIntent intent, Calendar startTime) {
        AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
        alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, startTime.getTimeInMillis(),
                AlarmManager.INTERVAL_DAY, intent);
    }

    private void cancelIntents() {
        AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
        alarmManager.cancel(getNotificationPublisherIntent(null));
    }

    /**
     * Set up the {@link android.app.ActionBar}, if the API is available.
     */
    private void setupActionBar() {
        ActionBar actionBar = getSupportActionBar();
        if (actionBar != null) {
            // Show the Up button in the action bar.
            actionBar.setDisplayHomeAsUpEnabled(true);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean onIsMultiPane() {
        return isXLargeTablet(this);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    public void onBuildHeaders(List&lt;Header&gt; target) {
        loadHeadersFromResource(R.xml.pref_headers, target);
    }

    /**
     * This method stops fragment injection in malicious applications.
     * Make sure to deny any unknown fragments here.
     */
    protected boolean isValidFragment(String fragmentName) {
        return PreferenceFragment.class.getName().equals(fragmentName)
                || NotificationPreferenceFragment.class.getName().equals(fragmentName);
    }

    /**
     * This fragment shows notification preferences only. It is used when the
     * activity is showing a two-pane settings UI.
     */
    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    public static class NotificationPreferenceFragment extends PreferenceFragment {
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            addPreferencesFromResource(R.xml.pref_notification);
            setHasOptionsMenu(true);

            // Bind the summary of the TimePreference to its value. When the value changes, the
            // summary is updated to reflect the new value, per the Android Design guidelines.
            bindPreferenceSummaryToValue(findPreference(&quot;notifications_time&quot;));
        }

        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            int id = item.getItemId();
            if (id == android.R.id.home) {
                startActivity(new Intent(getActivity(), SettingsActivity.class));
                return true;
            }
            return super.onOptionsItemSelected(item);
        }
    }
} 

TimePreference.java

public class TimePreference extends DialogPreference {

    // This is the same as the default value set in the XML. Keep them in sync.
    private static final int DEFAULT_TIME = 7 * 60;  // 0700

    // The currently chosen time stored as the number of minutes after midnight.
    private int time;

    private TimePicker picker;

    public TimePreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    public TimePreference(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public TimePreference(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public TimePreference(Context context) {
        super(context);
    }

    /**
     * valueToSummary takes the raw value of the preference and converts it into a human-readable
     * string fit for use in e.g. the preference&#39;s summary.
     *
     * @param value The raw value of the preference.
     * @return The time formatted according to the current settings (locale, 12/24 hour clock)
     */
    public String valueToSummary(int value) {
        return DateFormat.getTimeFormat(getContext()).format(valueToCalendar(value).getTime());
    }

    public static Calendar valueToCalendar(int value) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.HOUR_OF_DAY, getHours(value));
        calendar.set(Calendar.MINUTE, getMinutes(value));
        calendar.set(Calendar.SECOND, 0);

        return calendar;
    }

    private void setTime(int minAfterMidnight) {
        time = minAfterMidnight;
        persistInt(time);
        notifyChanged();
    }

    private static int getHours(int minAfterMidnight) {
        return minAfterMidnight / 60;
    }

    private static int getMinutes(int minAfterMidnight) {
        return minAfterMidnight % 60;
    }

    @Override
    protected View onCreateDialogView() {
        picker = new TimePicker(getContext());
        return picker;
    }

    @Override
    protected void onBindDialogView(View view) {
        super.onBindDialogView(view);

        picker.setIs24HourView(DateFormat.is24HourFormat(getContext()));
        if (Build.VERSION.SDK_INT &gt;= 23) {
            picker.setHour(getHours(time));
            picker.setMinute(getMinutes(time));
        } else {
            picker.setCurrentHour(getHours(time));
            picker.setCurrentMinute(getMinutes(time));
        }
    }

    @Override
    protected void onDialogClosed(boolean positiveResult) {
        super.onDialogClosed(positiveResult);

        if (positiveResult) {
            int hours, minutes;
            if (Build.VERSION.SDK_INT &gt;= 23) {
                hours = picker.getHour();
                minutes = picker.getMinute();
            } else {
                hours = picker.getCurrentHour();
                minutes = picker.getCurrentMinute();
            }

            int newTime = hours * 60 + minutes;
            if (callChangeListener(newTime)) {
                setTime(newTime);
            }
        }
    }

    @Override
    protected Object onGetDefaultValue(TypedArray a, int index) {
        return a.getInt(index, DEFAULT_TIME);
    }

    @Override
    protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) {
        super.onSetInitialValue(restorePersistedValue, defaultValue);
        setTime(restorePersistedValue ? getPersistedInt(time) : (int) defaultValue);
    }
}

The receiver in my AndroidManifest.xml:

&lt;receiver android:name=&quot;.activity.NotificationPublisher&quot; /&gt; 

I can set the time in my app and notifications are enabled for the app on the device. They simply don't display.

Note: I am developing with Android API 29.

答案1

得分: 1

在示例应用程序中,位于NotificationSchedulerApplication中:

    @Override
    public void onCreate() {
        super.onCreate();
        createNotificationChannel();
    }
    
    private void createNotificationChannel() {
        // 仅在 API 26+ 上创建 NotificationChannel,因为
        // NotificationChannel 类是新的,不在支持库中
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            CharSequence name = getString(R.string.channel_name);
            String description = getString(R.string.channel_description);
            int importance = NotificationManager.IMPORTANCE_DEFAULT;
            NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance);
            channel.setDescription(description);
            // 将通知渠道注册到系统;在此之后无法更改重要性
            // 或其他通知行为
            NotificationManager notificationManager = getSystemService(NotificationManager.class);
            notificationManager.createNotificationChannel(channel);
        }
    }

在 AndroidManifest.xml 中使 onCreate 在 Application 中被调用,然后跟随 createNotificationChannel 的部分是:

    <application
        android:name=".NotificationSchedulerApplication"
        .../>
    </application>

每当进行以下操作时,都会调用 Application 中的 onCreate:
Run -> Debug

只需点击 createNotificationChannel() 的左侧以设置断点。

英文:

In the sample app, in NotificationSchedulerApplication:

@Override
public void onCreate() {
    super.onCreate();
    createNotificationChannel();
}

private void createNotificationChannel() {
    // Create the NotificationChannel, but only on API 26+ because
    // the NotificationChannel class is new and not in the support library
    if (Build.VERSION.SDK_INT &gt;= Build.VERSION_CODES.O) {
        CharSequence name = getString(R.string.channel_name);
        String description = getString(R.string.channel_description);
        int importance = NotificationManager.IMPORTANCE_DEFAULT;
        NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance);
        channel.setDescription(description);
        // Register the channel with the system; you can&#39;t change the importance
        // or other notification behaviors after this
        NotificationManager notificationManager = getSystemService(NotificationManager.class);
        notificationManager.createNotificationChannel(channel);
    }
}

The bit in the AndroidManifest.xml that causes onCreate to be called in the Application followed by createNotificationChannel is this:

&lt;application
    android:name=&quot;.NotificationSchedulerApplication&quot;
    .../&gt;
&lt;/application&gt;

onCreate in the Application should be called every time you do:
Run -> Debug

Just click on the left of createNotificationChannel() to set a breakpoint.

答案2

得分: 0

在未创建频道 ID 我遇到了这个问题

import PushNotification, { Importance } from 'react-native-push-notification';
// ...
PushNotification.createChannel(
{
  channelId: "channel-id", // (required)
  channelName: "My channel", // (required)
  channelDescription: "用于对通知进行分类的通道", // (optional) 默认: undefined.
  playSound: false, // (optional) 默认: true
  soundName: "default", // (optional) 参见 `localNotification` 函数的 `soundName` 参数
  importance: Importance.HIGH, // (optional) 默认: Importance.HIGH。Android 通知重要性的整数值
  vibrate: true, // (optional) 默认: true。如果为 true,则创建默认振动模式。
},
(created) => console.log(`createChannel 返回 '${created}'`) // (optional) 回调返回通道是否已创建,false 表示它已存在。
);
英文:

I faced this problem when didn't create channel id

import PushNotification, {Importance} from &#39;react-native-push-notification&#39;;
...
PushNotification.createChannel(
{
  channelId: &quot;channel-id&quot;, // (required)
  channelName: &quot;My channel&quot;, // (required)
  channelDescription: &quot;A channel to categorise your notifications&quot;, // (optional) default: undefined.
  playSound: false, // (optional) default: true
  soundName: &quot;default&quot;, // (optional) See `soundName` parameter of `localNotification` function
  importance: Importance.HIGH, // (optional) default: Importance.HIGH. Int value of the Android notification importance
  vibrate: true, // (optional) default: true. Creates the default vibration pattern if true.
},
(created) =&gt; console.log(`createChannel returned &#39;${created}&#39;`) // (optional) callback returns whether the channel was created, false means it already existed.
);

huangapple
  • 本文由 发表于 2020年7月25日 00:53:50
  • 转载请务必保留本文链接:https://java.coder-hub.com/63078084.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定