You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android光线传感器应用通知无法正常显示问题求助

光线传感器应用通知不显示的解决思路

问题描述

我正在开发一款简单的光线传感器应用,但通知始终无法显示。我已经测试了SharedPreferences的非过时方法,求可行的解决思路。

相关代码

manifest.xml

<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.POST_NOTIFICATIONS" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Base.Theme.Lightsensorreader">
        <activity android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service
            android:name=".MyService"
            android:enabled="true"
            android:exported="false" />
    </application>

</manifest>

MainActivity.java(接收MyService数据并展示)

private TextView lightValueTextView;
private SharedPreferences sharedPreferences;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    lightValueTextView = findViewById(R.id.lightValueTV);
    sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);

    Intent serviceIntent = new Intent(this, MyService.class);
    startService(serviceIntent);
}

@Override
protected void onResume() {
    super.onResume();

    float lightValue = sharedPreferences.getFloat("light_value", 0);
    lightValueTextView.setText("Light sensor value: " + lightValue);
}

MyService.java(包含通知逻辑与SharedPreferences操作)

private SensorManager sensorManager;
private Sensor lightSensor;
private SharedPreferences sharedPreferences;
private SharedPreferences.Editor editor;

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

    sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
    lightSensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
    sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
    editor = sharedPreferences.edit();

    if (lightSensor != null) {
        sensorManager.registerListener(this, lightSensor, SensorManager.SENSOR_DELAY_NORMAL);
    }

    createNotificationChannel();
}

@Override
public void onDestroy() {
    super.onDestroy();
    sensorManager.unregisterListener(this);
}

@Override
public void onSensorChanged(SensorEvent event) {
    if (event.sensor.getType() == Sensor.TYPE_LIGHT) {
        float lightValue = event.values[0];

        editor.putFloat("light_value", lightValue);
        editor.apply();
    }
}

@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}

@Override
public IBinder onBind(Intent intent) {
    return new Binder();
}

private void createNotificationChannel() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        String channelId = "light_sensor_notification_channel";
        String channelName = "Light Sensor Notification Channel";
        int importance = NotificationManager.IMPORTANCE_DEFAULT;
        NotificationChannel channel = new NotificationChannel(channelId, channelName, importance);
        channel.enableLights(true);
        channel.setLightColor(Color.RED);

        NotificationManager notificationManager = getSystemService(NotificationManager.class);
        notificationManager.createNotificationChannel(channel);
    }
}

private void sendNotification(String title, String message) {
    Intent intent = new Intent(this, MainActivity.class);
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

    NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "light_sensor_notification_channel")
            .setSmallIcon(R.mipmap.ic_launcher)
            .setContentTitle(title)
            .setContentText(message)
            .setContentIntent(pendingIntent)
            .setAutoCancel(true);

    NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);

    notificationManager.notify(0, builder.build());
}

解决思路

1. 触发sendNotification方法

你的代码已经实现了sendNotification方法,但从未在传感器数值变化时调用它。修改onSensorChanged方法,添加通知触发逻辑,比如每次数值更新时发送通知:

@Override
public void onSensorChanged(SensorEvent event) {
    if (event.sensor.getType() == Sensor.TYPE_LIGHT) {
        float lightValue = event.values[0];

        editor.putFloat("light_value", lightValue);
        editor.apply();

        // 调用通知方法传递光线值
        sendNotification("光线数值更新", "当前光线值: " + lightValue);
    }
}

2. 请求POST_NOTIFICATIONS运行时权限

Android 13(API 33)及以上版本,POST_NOTIFICATIONS权限需要在运行时主动请求,仅在manifest中声明无法获取权限。在MainActivity的onCreate中添加权限请求:

private static final int REQUEST_NOTIFY_PERM = 1001;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    lightValueTextView = findViewById(R.id.lightValueTV);
    sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);

    // Android 13+ 请求通知权限
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.POST_NOTIFICATIONS}, REQUEST_NOTIFY_PERM);
        }
    }

    Intent serviceIntent = new Intent(this, MyService.class);
    startService(serviceIntent);
}

3. 适配PendingIntent的Flag(Android 12+)

Android 12(API 31)及以上版本,创建PendingIntent必须指定FLAG_IMMUTABLE或FLAG_MUTABLE。修改sendNotification中的PendingIntent创建代码:

int pendingFlags;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
    pendingFlags = PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE;
} else {
    pendingFlags = PendingIntent.FLAG_UPDATE_CURRENT;
}
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, pendingFlags);

4. 将服务设为前台服务(Android 8+)

Android 8(API 26)及以上版本,后台服务会被系统限制甚至杀死。将MyService改为前台服务,在onCreate中调用startForeground:

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

    sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
    lightSensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
    sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
    editor = sharedPreferences.edit();

    if (lightSensor != null) {
        sensorManager.registerListener(this, lightSensor, SensorManager.SENSOR_DELAY_NORMAL);
    }

    createNotificationChannel();
    
    // 启动前台服务
    NotificationCompat.Builder foregroundBuilder = new NotificationCompat.Builder(this, "light_sensor_notification_channel")
            .setSmallIcon(R.mipmap.ic_launcher)
            .setContentTitle("光线传感器运行中")
            .setContentText("正在监测光线数值")
            .setPriority(NotificationCompat.PRIORITY_DEFAULT);
    
    startForeground(1, foregroundBuilder.build());
}

5. 规范通知图标

避免使用mipmap目录下的图标作为通知小图标,建议使用drawable目录下的单色图标(符合Android通知图标规范),否则部分设备可能无法正常显示通知。

内容的提问来源于stack exchange,提问作者Nikollas Ohta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 02:27:06