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
相关产品推荐
相关产品推荐

