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

如何用C++Builder实现Androidapi::Jni::Location的LocationListener?

在C++Builder 11中实现Android GPS LocationListener的问题解决

我正在用FireMonkey/C++Builder 11开发首个Android应用,参考Delphi的GPS示例实现LocationListener时遇到两个关键错误,同时不知道如何实现Delphi中的弱引用。

问题详情

错误1:抽象类实例化失败

创建locationListener时执行locationListener = new TLocationListener::TLocationListener();,报错:

[bccaarm Error] HeaderFooterFormwithNavigation.cpp(311): allocating an object of abstract class type 'TLocationListener::TLocationListener'

错误2:类型转换失败

调用requestLocationUpdates时报错:

[bccaarm Error] HeaderFooterFormwithNavigation.cpp(1143): cannot cast 'TLocationListener' to its private base class 'Androidapi::Jni::Location::JLocationListener'

我的现有代码

主窗体代码(FormCreate)

void __fastcall THeaderFooterwithNavigation::FormCreate(TObject *Sender)
{
    if(FLocationManager==NULL)
    {
        _di_JLocationManager LocationManager;    
        _di_JObject LocationManagerService = SharedActivityContext()->getSystemService(TJContext::JavaClass->LOCATION_SERVICE);
                
        FLocationManager = TJLocationManager::Wrap((_di_IJavaInstance)LocationManagerService);
                
        FLocationManager->requestLocationUpdates(TJLocationManager::JavaClass->GPS_PROVIDER,10000,10,locationListener,TJLooper::JavaClass->getMainLooper());
    }
}

TLocationListener头文件声明

class TLocationListener : public TJavaLocal, JLocationListener
{
public :
    __fastcall TLocationListener();
    void __fastcall onLocationChanged(JLocation *location);
    void __fastcall onProviderDisabled(JString provider);
    void __fastcall onProviderEnabled(JString provider);
    void __fastcall onStatusChanged(JString provider,int status, JBundle extras);
    __fastcall ~TLocationListener();
};

解决方案

1. 修正TLocationListener的继承与方法签名

在C++Builder中,实现JNI接口时必须严格匹配方法的调用约定,并且接口继承需要使用公有继承,同时确保所有接口方法正确实现:

// 头文件中修正后的声明
#include <Androidapi.JNIBridge.hpp>
#include <Androidapi.Jni.Location.hpp>
#include <System.WeakRef.hpp>

class THeaderFooterwithNavigation; // 前向声明

class TLocationListener : public TJavaLocal, public JLocationListener // 公有继承JLocationListener
{
private:
    TWeakRef<THeaderFooterwithNavigation> FParent; // 实现弱引用
public :
    __fastcall TLocationListener(THeaderFooterwithNavigation* Parent);
    void __fastcall onLocationChanged(JLocation* location) override; // 添加override确保方法匹配
    void __fastcall onProviderDisabled(JString provider) override;
    void __fastcall onProviderEnabled(JString provider) override;
    void __fastcall onStatusChanged(JString provider, jint status, JBundle* extras) override; // 参数类型匹配Java的int(对应jint)
    __fastcall ~TLocationListener();
};
// cpp文件中的实现
__fastcall TLocationListener::TLocationListener(THeaderFooterwithNavigation* Parent)
    : TJavaLocal(), FParent(Parent)
{
}

void __fastcall TLocationListener::onLocationChanged(JLocation* location)
{
    // 调用父窗体的位置处理逻辑
    if (auto Parent = FParent.Resolve()) {
        // Parent->HandleLocationChanged(location);
    }
}

void __fastcall TLocationListener::onProviderDisabled(JString provider)
{
    // 处理定位Provider禁用逻辑
}

void __fastcall TLocationListener::onProviderEnabled(JString provider)
{
    // 处理定位Provider启用逻辑
}

void __fastcall TLocationListener::onStatusChanged(JString provider, jint status, JBundle* extras)
{
    // 处理定位状态变化逻辑
}

__fastcall TLocationListener::~TLocationListener()
{
}

2. 修正主窗体代码

在FormCreate中正确初始化监听器,确保参数传递与类型转换正确:

void __fastcall THeaderFooterwithNavigation::FormCreate(TObject *Sender)
{
    if(FLocationManager == NULL)
    {
        _di_JObject LocationManagerService = SharedActivityContext()->getSystemService(TJContext::JavaClass->LOCATION_SERVICE);
        FLocationManager = TJLocationManager::Wrap((_di_IJavaInstance)LocationManagerService);
        
        // 初始化监听器
        if (locationListener == NULL) {
            locationListener = new TLocationListener(this);
        }
        
        // 调用requestLocationUpdates,确保监听器类型正确转换
        FLocationManager->requestLocationUpdates(
            TJLocationManager::JavaClass->GPS_PROVIDER,
            10000,
            10.0f, // 距离参数为float类型,注意与Delphi的整数参数区分
            static_cast<_di_JLocationListener>(locationListener),
            TJLooper::JavaClass->getMainLooper()
        );
        
        // 获取最后已知位置
        _di_JLocation LastLocation = FLocationManager->getLastKnownLocation(TJLocationManager::JavaClass->GPS_PROVIDER);
        if (LastLocation) {
            // HandleLocationChanged(LastLocation);
        }
    }
}

3. 弱引用实现说明

C++Builder中没有Delphi的[weak]属性,可通过TWeakRef类实现弱引用,避免循环引用导致内存泄漏。FParent.Resolve()会返回有效的父指针(若对象未被销毁),否则返回nullptr。

关键注意事项

  • 所有JNI接口方法必须添加override关键字,确保与父类接口签名完全匹配,包括参数类型(如Java的int对应C++的jint)。
  • 继承JLocationListener时必须使用公有继承,否则编译器会禁止向下类型转换。
  • requestLocationUpdates的距离参数为float类型,不要传入整数,避免参数不匹配。

内容的提问来源于stack exchange,提问作者Tim Beurk

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 11:06:48