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

Android开机启动前台服务失败,BroadcastReceiver触发空指针异常

问题根源

你代码里存在两个直接触发报错的核心错误:

  1. 你直接通过new location()创建Service实例,Android四大组件(Activity、Service、BroadcastReceiver、ContentProvider)必须由系统调度创建,自行new出来的实例没有绑定系统上下文,调用startForeground时会触发空指针
  2. 创建PendingIntent时传入了空的emptyIntent,系统找不到目标Activity类名,这就是报错日志中class name is null的直接触发原因

修复步骤

1. 修改BroadcastReceiver代码

不要自行创建Activity和Service实例,通过系统API启动服务

public class client extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
            Intent serviceIntent = new Intent(context, location.class);
            // Android 8.0及以上必须使用startForegroundService启动前台服务
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
                context.startForegroundService(serviceIntent);
            } else {
                context.startService(serviceIntent);
            }
        }
    }
}

2. 修改Service代码

将前台服务初始化逻辑移到系统回调的onStartCommand中,修正PendingIntent配置

public class location extends Service implements LocationListener {
    public static double lon, lat;

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // 创建通知渠道
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
            NotificationChannel serviceChannel = new NotificationChannel(
                    "locationService",
                    "位置上报服务",
                    NotificationManager.IMPORTANCE_DEFAULT
            );
            NotificationManager manager = getSystemService(NotificationManager.class);
            manager.createNotificationChannel(serviceChannel);
        }

        // PendingIntent指向实际的主页面Activity,不要传空Intent
        Intent contentIntent = new Intent(this, MapsActivity.class);
        int pendingFlag = PendingIntent.FLAG_IMMUTABLE;
        if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.M) {
            pendingFlag = 0;
        }
        PendingIntent pendingIntent = PendingIntent.getActivity(
                this,
                0,
                contentIntent,
                pendingFlag
        );

        Notification notification = new NotificationCompat.Builder(this, "locationService")
                .setSmallIcon(R.drawable.common_google_signin_btn_icon_dark)
                .setContentTitle("位置上报中")
                .setContentIntent(pendingIntent)
                .build();
        // 启动前台服务
        startForeground(1, notification);

        // 补充位置监听的初始化逻辑
        LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
        try {
            locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 3000, 10, this);
        } catch (SecurityException e) {
            e.printStackTrace();
        }

        return START_STICKY;
    }

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

    @Override
    public void onLocationChanged(Location location) {
        if (location != null) {
            lat = location.getLatitude();
            lon = location.getLongitude();
            // 这里补充向服务端上报位置的逻辑
        }
    }
}

3. 补充AndroidManifest.xml配置

必须添加对应的权限和组件声明,否则无法接收开机广播、启动服务

<!-- 开机广播权限 -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<!-- 前台服务权限 -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<!-- 安卓12及以上位置前台服务权限 -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" />
<!-- 位置权限 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- 安卓10及以上后台位置权限 -->
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />

<application ...>
    <!-- 注册开机广播Receiver -->
    <receiver
        android:name=".client"
        android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>

    <!-- 注册位置服务 -->
    <service
        android:name=".location"
        android:foregroundServiceType="location"
        android:exported="false" />
</application>

4. 额外注意事项

  • 安卓6.0及以上需要在应用内主动弹窗申请位置权限,用户授权后服务才能正常获取位置
  • 安卓10及以上需要用户额外授权后台位置权限
  • 必须保证用户至少主动打开过一次应用,否则安卓系统会限制应用接收开机广播
  • 国内定制ROM普遍有自启动权限限制,需要手动给应用开启自启动权限才能正常收到开机广播启动服务

内容的提问来源于stack exchange,提问作者m mardis

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 14:15:03