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

Android中HereMap离线地图无法下载,主线程任务过载问题排查

Android HereMap离线地图下载无法启动问题

我尝试在Android应用中下载HereMap离线地图,但自定义的HereMapClass初始化正常,下载却无法启动。出现的错误日志如下:

I/Choreographer: Skipped 1390 frames!  The application may be doing too much work on its main thread.
I/OpenGLRenderer: Davey! duration=23246ms; Flags=0, IntendedVsync=541429044228998, Vsync=541452210894738, OldestInputEvent=9223372036854775807, NewestInputEvent=0, HandleInputStart=541452219847929, AnimationStart=541452220213815, PerformTraversalsStart=541452220244856, DrawStart=541452273514752, SyncQueued=541452286173554, SyncStart=541452287155273, IssueDrawCommandsStart=541452287225898, SwapBuffers=541452289434856, FrameCompleted=541452291323711, DequeueBufferDuration=140261, QueueBufferDuration=1621927, GpuCompleted=0, 
I/OpenGLRenderer: Davey! duration=23290ms; Flags=0, IntendedVsync=541429044228998, Vsync=541452210894738, OldestInputEvent=9223372036854775807, NewestInputEvent=0, HandleInputStart=541452219847929, AnimationStart=541452220213815, PerformTraversalsStart=541452220244856, DrawStart=541452321017669, SyncQueued=541452332492773, SyncStart=541452332826783, IssueDrawCommandsStart=541452332910273, SwapBuffers=541452333750690, FrameCompleted=541452335195690, DequeueBufferDuration=159479, QueueBufferDuration=935885, GpuCompleted=0, 
V/FA: Inactivity, disconnecting from the service

主类代码

public class LoginActivity extends AppCompatActivity {
...
    private HereMapClass hereMap;
    private ProgressBar downloadProgressBar;
...
}

 public void downloadMap() {
            downloadProgressBar = (ProgressBar) findViewById(R.id.ext_progressBar);
            hereMap = new HereMapClass(LoginActivity.getAppContext());
            hereMap.onDownloadButtonClicked(downloadProgressBar);
}

HereMapClass代码

public class HereMapClass {
    private  MapEngine mapEngine;
    private MapLoader mapLoader;
...

  public HereMapClass(Context context){
        this.context=context;
    }

  // listener for MapLoader
    private MapLoader.Listener mapLoaderHandler = new MapLoader.Listener() {
            @Override
            public void onProgress(int progress) {
                Log.i(TAG, "Progress " + progress + "%");
                downloadProgressBar.setProgress(progress);
            }

            @Override
            public void onInstallationSize(long diskSize, long networkSize) {
                Log.i(TAG, "Map data require " + diskSize);
            }

            @Override
            public void onGetMapPackagesComplete(MapPackage rootMapPackage,
                                                 MapLoader.ResultCode resultCode) {
                if (resultCode == MapLoader.ResultCode.OPERATION_SUCCESSFUL) {
                    Log.i(TAG, "Map packages received successful: " + rootMapPackage.getTitle());

                    currentInstalledMaps = new ArrayList<>(1);
                    populateInstalledMaps(rootMapPackage);
                } else {
                    Log.e(TAG, "Can't retrieve map packages: " + resultCode.name());
                    Toast.makeText(context,
                            "Error: " + resultCode.name(), Toast.LENGTH_SHORT).show();
                    return;
                }

                StringBuilder sb = new StringBuilder();
                for (MapPackage pac : currentInstalledMaps) {
                    sb.append(pac.getTitle());
                    sb.append("\n");
                }

                currentInstalledMapsString = sb.toString();
            }


            private void populateInstalledMaps(MapPackage pac) {
                // only take installed root package, so if e.g. Germany is installed,
                // don't check for children states
                if (pac.getInstallationState() == MapPackage.InstallationState.INSTALLED) {
                    Log.i(TAG, "Installed package found: " + pac.getTitle() + " id " + pac.getId());
                    currentInstalledMaps.add(pac);
                } else if (pac.getChildren() != null && pac.getChildren().size() > 0) {
                    for (MapPackage p : pac.getChildren()) {
                        populateInstalledMaps(p);
                    }
                }
            }

            @Override
            public void onCheckForUpdateComplete(boolean updateAvailable, String currentMapVersion,
                                                 String newestMapVersion, MapLoader.ResultCode resultCode) {
                Log.i(TAG, "onCheckForUpdateComplete. Update available: " + updateAvailable +
                        " current version: " + currentMapVersion);

                AlertDialog.Builder builder = new AlertDialog.Builder(context, R.style.AppCompatAlertDialogStyle);

                builder.setTitle("Map version checked");
                builder.setMessage("Current map version: " + currentMapVersion + "\n\n"
                        + (updateAvailable ? "Update found to " + newestMapVersion : "No update found")
                        + "\n\n" + "Installed maps:\n" + currentInstalledMapsString);
                builder.setNegativeButton("close", null);

                if (updateAvailable) {
                    builder.setPositiveButton("Update", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            Log.i(TAG, "Update triggered");
                            downloadProgressBar.setProgress(0);
                            downloadProgressBar.setVisibility(View.VISIBLE);
                            MapLoader.getInstance().performMapDataUpdate();
                        }
                    });
                }

                builder.show();
            }

            @Override
            public void onPerformMapDataUpdateComplete(MapPackage rootMapPackage,
                                                       MapLoader.ResultCode resultCode) {
                Log.i(TAG, "onPerformMapDataUpdateComplete");
                downloadProgressBar.setVisibility(View.INVISIBLE);
                String message;
                if (resultCode == MapLoader.ResultCode.OPERATION_SUCCESSFUL) {
                    message = "Map updated successfully";
                } else {
                    message = "Map update failed: " + resultCode.name();
                }
                Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onInstallMapPackagesComplete(MapPackage rootMapPackage,
                                                     MapLoader.ResultCode resultCode) {
                downloadProgressBar.setVisibility(View.INVISIBLE);
                String message;
                if (resultCode == MapLoader.ResultCode.OPERATION_SUCCESSFUL) {
                    message = "Maps installed successfully";
                    Log.i(TAG, "Package is installed: " + rootMapPackage.getId() + " " + rootMapPackage.getTitle());
                    MapLoader.getInstance().getMapPackages();
                } else {
                    message = "Map installation failed: " + resultCode.name();
                    Log.e(TAG, "Failed to install package: " + rootMapPackage.getId() + " " + rootMapPackage.getTitle());
                }
                Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onUninstallMapPackagesComplete(MapPackage rootMapPackage,
                                                       MapLoader.ResultCode resultCode) {
                Log.i(TAG, "onUninstallMapPackagesComplete");
                String message;
                if (resultCode == MapLoader.ResultCode.OPERATION_SUCCESSFUL) {
                    message = "Maps removed successfully";
                } else {
                    message = "Map removal failed: " + resultCode.name();
                }
                //  Toast.makeText(HereMap.this, message, Toast.LENGTH_SHORT).show();

                // update packages and get installation state
                MapLoader.getInstance().getMapPackages();
            }
        };


   public void onDownloadButtonClicked(ProgressBar downloadProgressBar2) {
this.downloadProgressBar = downloadProgressBar2;

        mapEngine = MapEngine.getInstance();
        ApplicationContext appContext = new ApplicationContext(context);
        mapEngine.init(appContext, new OnEngineInitListener() {
            @Override
            public void onEngineInitializationCompleted(Error error) {
                if (error == OnEngineInitListener.Error.NONE) {
                    // Post initialization code goes here
                    Log.d(TAG, "Downloading new map data...");

                    List<Integer> downloadList = new ArrayList<>(1);
                    downloadList.add(120214);    //Id:120002 Berlin  Id:120214, Name: Andalucia, Size:231504 Cherche l'id avec l'application iOS map-downloader-ios-swift
        downloadProgressBar.setProgress(0);
        downloadProgressBar.setVisibility(View.VISIBLE);
            //START TEST
    AsyncTask.execute(new Runnable() {
        @Override
        public void run() {
                    MapLoader.getInstance().installMapPackages(downloadList);
        }}); //=> LINE WITH PROBLEMS
                } else {
                    // handle factory initialization failure
                }
            }
        });
    }

请问我是否存在操作错误?


问题分析与修正方案

你存在几处关键操作错误,导致下载无法启动:

  • 未给MapLoader设置监听器:你定义了mapLoaderHandler但从未将其注册到MapLoader实例,因此下载的回调(进度、完成状态)都无法触发,也无法确认下载是否真正执行。
  • 主线程操作UI风险:虽然你用AsyncTask.execute执行下载,但onProgress回调会直接在子线程更新ProgressBar,这会触发UI线程异常,导致界面卡顿(日志中的Skipped 1390 frames就是这个原因)。
  • MapEngine初始化后未正确获取MapLoader实例:你声明了mapLoader变量但未初始化,直接调用MapLoader.getInstance()可能存在初始化顺序问题。

修正后的关键代码调整

1. 初始化MapLoader并设置监听器

在MapEngine初始化成功后,添加监听器注册:

mapEngine.init(appContext, new OnEngineInitListener() {
    @Override
    public void onEngineInitializationCompleted(Error error) {
        if (error == OnEngineInitListener.Error.NONE) {
            Log.d(TAG, "Downloading new map data...");
            // 初始化MapLoader并设置监听器
            mapLoader = MapLoader.getInstance();
            mapLoader.addListener(mapLoaderHandler);
            
            List<Integer> downloadList = new ArrayList<>(1);
            downloadList.add(120214);    
            downloadProgressBar.setProgress(0);
            downloadProgressBar.setVisibility(View.VISIBLE);
            
            AsyncTask.execute(new Runnable() {
                @Override
                public void run() {
                    mapLoader.installMapPackages(downloadList);
                }
            });
        } else {
            Log.e(TAG, "MapEngine初始化失败: " + error.name());
        }
    }
});

2. 修正UI更新线程问题

在onProgress回调中切换到主线程更新ProgressBar:

@Override
public void onProgress(int progress) {
    Log.i(TAG, "Progress " + progress + "%");
    // 切换到主线程更新UI
    ((Activity) context).runOnUiThread(new Runnable() {
        @Override
        public void run() {
            downloadProgressBar.setProgress(progress);
        }
    });
}

3. 避免重复初始化与资源泄漏

在HereMapClass销毁时移除监听器:

public void destroy() {
    if (mapLoader != null) {
        mapLoader.removeListener(mapLoaderHandler);
    }
}

并在LoginActivity的onDestroy中调用:

@Override
protected void onDestroy() {
    super.onDestroy();
    if (hereMap != null) {
        hereMap.destroy();
    }
}

额外注意点

  • 确保LoginActivity.getAppContext()返回的是应用上下文而非Activity上下文,避免内存泄漏。
  • 检查地图包ID120214是否有效,可通过HereMap官方工具确认当前可用的地图包ID。
  • 确认应用已申请INTERNET、WRITE_EXTERNAL_STORAGE等必要权限,且运行时权限已授予。

内容的提问来源于stack exchange,提问作者ΩlostA

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 21:09:30