jjzjj

android - 从另一个应用程序在 Osmand 中打开 gpx 文件

coder 2023-12-16 原文

我有一个 Android 应用程序,它主要存储保存在用户手机上的 gpx 文件列表。当用户单击应用程序中的文件名时,它应提示用户使用手机上可用的任何路由应用程序打开 gpx 文件。现在我正在测试在 Osmand 中打开文件。问题是,Osmand 正在打开,但随后立即崩溃。

尝试打开文件的代码是这样的:

File gpxFile = new File(Path);

Intent intent = new Intent();
intent.setAction(android.content.Intent.ACTION_VIEW);

Uri gpxUri = FileProvider.getUriForFile(view.getContext(), AUTHORITY, gpxFile);
intent.setDataAndType(gpxUri, "application/gpx+xml");

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

gpx 文件都是这样的:

<?xml version="1.0"?>
<gpx creator="{CREATOR}" version="1.1" xmlns="http://www.topografix.com/GPX/1/1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd">
<wpt lat="{LAT_1}" lon="{LON_1}">
    <name>{WPT_NAME_1}</name>
</wpt>
...
<wpt lat="{LAT_N}" lon="{LON_N}">
    <name>{WPT_NAME_N}</name>
</wpt>
<trk>
  <name>{TRACK_NAME}</name>
  <trkseg>
    <trkpt lat="{LAT_1}" lon="{LON_1}"></trkpt>
    ...
    <trkpt lat="{LAT_N}" lon="{LON_N}"></trkpt>
  </trkseg>
</trk>
</gpx>

起初我以为 gpx 文件的格式有问题,但如果我手动打开 Osmand 并尝试使用“配置 map ”->“Gpx 轨迹”导入文件,轨迹在 map ,包括航路点。

LE:这是我在 Osmand 尝试启动时遇到的错误:

08-16 17:28:00.524 5681-5762/? E/net.osmand: RenderingRuleProperty Rendering parse  in strokeWidth_2
08-16 17:28:00.524 5681-5762/? E/net.osmand: RenderingRuleProperty Rendering parse  in strokeWidth_2
08-16 17:28:01.259 5681-5681/? E/AndroidRuntime: FATAL EXCEPTION: main
                                             Process: net.osmand, PID: 5681
                                             java.lang.RuntimeException: Unable to resume activity {net.osmand/net.osmand.plus.activities.MapActivity}: java.lang.SecurityException: Permission Denial: opening provider android.support.v4.content.FileProvider from ProcessRecord{3ddadf4 5681:net.osmand/u0a203} (pid=5681, uid=10203) that is not exported from uid 10275
                                                 at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3788)
                                                 at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3828)
                                                 at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2991)
                                                 at android.app.ActivityThread.-wrap14(ActivityThread.java)
                                                 at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1635)
                                                 at android.os.Handler.dispatchMessage(Handler.java:102)
                                                 at android.os.Looper.loop(Looper.java:154)
                                                 at android.app.ActivityThread.main(ActivityThread.java:6692)
                                                 at java.lang.reflect.Method.invoke(Native Method)
                                                 at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1468)
                                                 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1358)
                                              Caused by: java.lang.SecurityException: Permission Denial: opening provider android.support.v4.content.FileProvider from ProcessRecord{3ddadf4 5681:net.osmand/u0a203} (pid=5681, uid=10203) that is not exported from uid 10275
                                                 at android.os.Parcel.readException(Parcel.java:1693)
                                                 at android.os.Parcel.readException(Parcel.java:1646)
                                                 at android.app.ActivityManagerProxy.getContentProvider(ActivityManagerNative.java:4861)
                                                 at android.app.ActivityThread.acquireProvider(ActivityThread.java:5958)
                                                 at android.app.ContextImpl$ApplicationContentResolver.acquireUnstableProvider(ContextImpl.java:2452)
                                                 at android.content.ContentResolver.acquireUnstableProvider(ContentResolver.java:1521)
                                                 at android.content.ContentResolver.query(ContentResolver.java:520)
                                                 at android.content.ContentResolver.query(ContentResolver.java:478)
                                                 at net.osmand.plus.helpers.GpxImportHelper.getNameFromContentUri(GpxImportHelper.java:108)
                                                 at net.osmand.plus.helpers.GpxImportHelper.handleContentImport(GpxImportHelper.java:69)
                                                 at net.osmand.plus.activities.MapActivity.onResume(MapActivity.java:617)
                                                 at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1277)
                                                 at android.app.Activity.performResume(Activity.java:7058)
                                                 at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3765)
                                                 at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3828) 
                                                 at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2991) 
                                                 at android.app.ActivityThread.-wrap14(ActivityThread.java) 
                                                 at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1635) 
                                                 at android.os.Handler.dispatchMessage(Handler.java:102) 
                                                 at android.os.Looper.loop(Looper.java:154) 
                                                 at android.app.ActivityThread.main(ActivityThread.java:6692) 
                                                 at java.lang.reflect.Method.invoke(Native Method) 
                                                 at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1468) 
                                                 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1358) 

最佳答案

Osmand 是否没有从 FileProvider 读取该文件的权限?换句话说,在调用 startActivity 之前在 Intent 中授予读取权限是否有帮助:

intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

(我不知道 Osmand 是否也需要写权限。您也可以尝试添加它:FLAG_GRANT_WRITE_URI_PERMISSION)。

我还建议仔细检查 filepaths.xml(在“xml”资源目录中)中的 FileProvider 配置。大概是这样的:

<paths>
    <files-path path="images/" name="myimages" />
</paths>

例如您的文件路径属性是否指向正确的目录?该目录中是否有所需的 gpx 文件? (https://developer.android.com/training/secure-file-sharing/setup-sharing.html)

另一件要记住的事情是,provider 元素中的权限字符串在设备上必须是唯一的。因此,在您的 AndroidManifest 的这一部分,确保您已将“com.example.myapp.fileprovider”替换为您的应用程序独有的内容:

<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="com.example.myapp.fileprovider"
    android:grantUriPermissions="true"
    android:exported="false">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/filepaths" />
</provider>

如果这没有帮助,我只能建议观察设备的 logcat 输出,看看 Osmand 是否为这次崩溃写了堆栈跟踪。

--- 编辑 2017 年 8 月 17 日 ---

只是为了在这个答案的正文中加入一些细节:作为 A.M.在下面的评论中得到证明和描述,实际的修复是通过在循环中重复调用 context.grantUriPermission 来显式授予设备上多个特定包的必要权限,如下所示:

//grant permisions for all apps that can handle given intent
List<ResolveInfo> resInfoList = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo resolveInfo : resInfoList) {
    String packageName = resolveInfo.activityInfo.packageName;
    context.grantUriPermission(packageName, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
}

此方法在此处有更多记录:https://stackoverflow.com/a/18332000/3482621

是否需要调用 grantUriPermission(而不是仅仅依赖 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION))似乎取决于设备上安装的 Android 平台版本。这在此处的问题报告中进行了描述:https://issuetracker.google.com/issues/37005552

关于android - 从另一个应用程序在 Osmand 中打开 gpx 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45541013/

有关android - 从另一个应用程序在 Osmand 中打开 gpx 文件的更多相关文章

  1. ruby - 在 Ruby 程序执行时阻止 Windows 7 PC 进入休眠状态 - 2

    我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0

  2. ruby - 将差异补丁应用于字符串/文件 - 2

    对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl

  3. ruby - 如何指定 Rack 处理程序 - 2

    Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack

  4. ruby - 使用 Vim Rails,您可以创建一个新的迁移文件并一次性打开它吗? - 2

    使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta

  5. ruby-on-rails - Rails - 一个 View 中的多个模型 - 2

    我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何

  6. ruby-on-rails - 渲染另一个 Controller 的 View - 2

    我想要做的是有2个不同的Controller,client和test_client。客户端Controller已经构建,我想创建一个test_clientController,我可以使用它来玩弄客户端的UI并根据需要进行调整。我主要是想绕过我在客户端中内置的验证及其对加载数据的管理Controller的依赖。所以我希望test_clientController加载示例数据集,然后呈现客户端Controller的索引View,以便我可以调整客户端UI。就是这样。我在test_clients索引方法中试过这个:classTestClientdefindexrender:template=>

  7. ruby - 在 Ruby 中编写命令行实用程序 - 2

    我想用ruby​​编写一个小的命令行实用程序并将其作为gem分发。我知道安装后,Guard、Sass和Thor等某些gem可以从命令行自行运行。为了让gem像二进制文件一样可用,我需要在我的gemspec中指定什么。 最佳答案 Gem::Specification.newdo|s|...s.executable='name_of_executable'...endhttp://docs.rubygems.org/read/chapter/20 关于ruby-在Ruby中编写命令行实用程序

  8. ruby-on-rails - Rails 应用程序之间的通信 - 2

    我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此

  9. ruby - 无法运行 Rails 2.x 应用程序 - 2

    我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby​​:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r

  10. ruby-on-rails - Rails 应用程序中的 Rails : How are you using application_controller. rb 是新手吗? - 2

    刚入门rails,开始慢慢理解。有人可以解释或给我一些关于在application_controller中编码的好处或时间和原因的想法吗?有哪些用例。您如何为Rails应用程序使用应用程序Controller?我不想在那里放太多代码,因为据我了解,每个请求都会调用此Controller。这是真的? 最佳答案 ApplicationController实际上是您应用程序中的每个其他Controller都将从中继承的类(尽管这不是强制性的)。我同意不要用太多代码弄乱它并保持干净整洁的态度,尽管在某些情况下ApplicationContr

随机推荐