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

Flutter插件无法启动Android Intent服务,空指针异常求助

Flutter Android插件启动前台服务空指针问题修复

问题描述

开发连接手表的Flutter插件时,通过MethodChannel调用Android原生SDK实现后台数据同步,需要启动前台服务,但出现以下空指针错误:

E/MethodChannel#releep_watch_connect: Failed to handle method call
    java.lang.NullPointerException: Attempt to invoke virtual method 'android.app.Activity io.flutter.embedding.android.FlutterActivity.getActivity()' on a null object reference
        at com.achatsocial.releep_watch_connect.ReleepWatchConnectPlugin.onMethodCall(ReleepWatchConnectPlugin.java:130)
        at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:233)
        at io.flutter.embedding.engine.dart.DartMessenger.handleMessageFromDart(DartMessenger.java:84)
        at io.flutter.embedding.engine.FlutterJNI.handlePlatformMessage(FlutterJNI.java:865)
        at android.os.MessageQueue.nativePollOnce(Native Method)
        at android.os.MessageQueue.next(MessageQueue.java:335)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:8051)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:620)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1011)

同时onAttachedToActivity方法未正确触发,导致activity对象为空,无法启动Intent。

核心问题分析

  1. 初始化时机错误:onAttachedToEngine中提前调用activity.getSystemService(),但此时onAttachedToActivity还未执行,activity变量未赋值,直接触发空指针。
  2. Service启动逻辑冗余:代码中调用activity.getActivity(),但activity本身就是FlutterActivity实例,无需额外调用;且启动Service可使用ApplicationContext,不需要依赖Activity。
  3. Activity生命周期未处理:ActivityAware的部分回调未维护activity状态,可能导致内存泄漏或状态不一致。

修复步骤及代码修改

1. 调整Activity变量与生命周期管理

将FlutterActivity类型改为通用的Activity,并完善所有ActivityAware回调:

public class ReleepWatchConnectPlugin
    implements FlutterPlugin, MethodCallHandler, EventChannel.StreamHandler, ActivityAware {
  private Activity activity;
  private Context appContext; // 保存ApplicationContext,脱离对Activity的依赖
  private MethodChannel channel;
  private EventChannel stream_chanel;
  private NotificationManager notificationManager;

  // ... 其他变量定义

  @Override
  public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
    appContext = flutterPluginBinding.getApplicationContext();
    YCBTClient.initClient(appContext, true);
    YCBTClient.registerBleStateChange(bleConnectResponse);
    YCBTClient.deviceToApp(toAppDataResponse);

    channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "releep_watch_connect");
    channel.setMethodCallHandler(this);
    stream_chanel = new EventChannel(flutterPluginBinding.getBinaryMessenger(), "scan_releep_watch");
    stream_chanel.setStreamHandler(this);
  }

  @Override
  public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) {
    activity = binding.getActivity();
    notificationManager = (NotificationManager) activity.getSystemService(Context.NOTIFICATION_SERVICE);
    boolean backBoolean = PermissionUtils.checkPermissionArray(activity, permissionArray, 3);
  }

  @Override
  public void onDetachedFromActivityForConfigChanges() {
    this.activity = null;
  }

  @Override
  public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) {
    activity = binding.getActivity();
  }

  @Override
  public void onDetachedFromActivity() {
    this.activity = null;
  }

  // ... 其他方法
}

2. 修正Service启动逻辑

使用ApplicationContext启动Service,并适配Android 8.0+的前台服务要求:

@Override
public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
  if (call.method.equals("syncHeartRate")) {
    Intent intent = new Intent(appContext, MyBleService.class);
    intent.putExtra("text", "Hello");

    // 适配Android 8.0+启动前台服务
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
      appContext.startForegroundService(intent);
    } else {
      appContext.startService(intent);
    }

    // 绑定服务前先判断Activity是否存在
    if (activity != null) {
      activity.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
    } else {
      result.error("ACTIVITY_NULL", "Activity未绑定", null);
    }
  }
}

3. 实现前台服务的通知要求

在MyBleService中创建前台通知(Android 8.0+需先创建通知渠道):

public class MyBleService extends Service {
  private static final String CHANNEL_ID = "BLE_SYNC_CHANNEL";
  private static final int NOTIFICATION_ID = 1001;

  @Override
  public void onCreate() {
    super.onCreate();
    createNotificationChannel();
    Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
            .setContentTitle("手表数据同步")
            .setContentText("正在后台同步心率数据")
            .setSmallIcon(R.drawable.ic_notification)
            .build();
    startForeground(NOTIFICATION_ID, notification);
  }

  private void createNotificationChannel() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
      NotificationChannel channel = new NotificationChannel(CHANNEL_ID,
              "BLE同步服务", NotificationManager.IMPORTANCE_LOW);
      NotificationManager manager = getSystemService(NotificationManager.class);
      manager.createNotificationChannel(channel);
    }
  }

  // ... 其他服务逻辑
}

额外注意事项

  • 确保插件使用新版Flutter嵌入API注册,ActivityAware的回调才会被正确触发;旧版Activity注册方式需升级。
  • 权限申请必须在Activity绑定后执行,避免因activity为空导致权限请求失败。

内容的提问来源于stack exchange,提问作者Thananat Rueangchot

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 22:09:15