我正在为运行 Ubuntu touch 的 Nexus 4 编写 QML 应用程序。我必须访问存储在 /home/phablet/Documents 中的一些文件。正如我在这里读到的: 在 Ubuntu Touch 的 QML 中使用图片作为图像对象这是不可能的。在 AppArmor-File 中,我输入了“content-exchange”和“content-exchange-source”。我仍然无法访问一些本地文件。
是否有可能读取这些文件?我想一定有办法,音乐应用程序也可以访问音乐文件!?
感谢你帮助 Jens
我尝试了这个代码:
Audio {
id: player
source: "file:///home/phablet/Documents/filename"
}
答案1
你不能,至少根据应用商店分发规则你不能。
正如您链接的问题中所述,Ubuntu Touch 上的默认应用程序限制将应用程序限制为访问其自身孤岛内的文件。您可以更改应用程序的限制设置,但应用商店可能不接受此设置。您也可以放弃直接访问这些文件并通过内容中心导入它们。详情如下:
1)通过内容中心导入文件
这内容中心提供一种将文件从一个应用程序孤岛传输到另一个应用程序孤岛的机制。它可以以多种不同的方式使用,但您需要请求导入类型文档。另一个可以充当文档源的应用程序将打开并显示文档列表。在用户选择一个(或多个)后,您的应用程序将恢复并接收一个信号,其中包含有关文档的信息,这些文档已被复制到您可以访问它们的位置。
当然,大多数其他应用程序也受到应用程序限制问题的影响,无法访问~/Documents
。但是,文档查看器和文件管理器受到特殊对待,并被授予访问这些文件的权限。两者都可以充当文档的内容中心源。请注意,文档查看器仅支持某些类型的文件。文件管理器会将任何类型的文件导出为文档,但默认情况下不会安装它。
(顺便说一句,同样的机制允许音乐应用程序访问中的文件~/Music
。我发现对默认应用程序进行特殊处理的决定相当成问题,尤其是因为这意味着应用程序作者研究它们的代码是无用的。)
我还没有找到一个好的使用 Content Hub 的教程。相反,我会发布一些我自己尝试理解 Content Hub 时编写的代码。它允许您从默认提供程序或从“ContentPeerPicker”中选择的提供程序导入文档。
清单.json
{
"name": "chtest.rschroll",
"architecture": "all",
"title": "chtest",
"hooks": {
"chtest": {
"apparmor": "chtest.apparmor",
"desktop": "chtest.desktop"
}
},
"version": "0.1",
"framework" : "ubuntu-sdk-14.10"
}
chtest.apparmor
{
"policy_groups": [
"networking",
"webview",
"content_exchange"
],
"policy_version": 1.2
}
主文件
import QtQuick 2.0
import Ubuntu.Components 0.1
import Ubuntu.Components.ListItems 0.1 as ListItem
import Ubuntu.Components.Popups 0.1
import Ubuntu.Content 0.1
MainView {
id: mainView
applicationName: "chtest.rschroll"
width: units.gu(100)
height: units.gu(75)
PageStack {
id: pageStack
Component.onCompleted: pageStack.push(root)
Page {
id: root
title: i18n.tr("Import Content...")
visible: false
property var activeTransfer
Column {
anchors.fill: parent
spacing: units.gu(2)
Row {
height: units.gu(6)
anchors {
left: parent.left
right: parent.right
horizontalCenter: parent.horizontalCenter
}
spacing: units.gu(3)
Button {
text: i18n.tr("... From default provider")
onClicked: {
root.activeTransfer = peer.request();
}
}
Button {
text: i18n.tr("... From choosen provider")
onClicked: {
pageStack.push(picker);
}
}
}
Label {
id: label
width: parent.width
}
}
function importItems(items) {
var string = "";
for (var i = 0; i < items.length; i++) {
string += i + ") " + items[i].url + "\n";
/* You may want to use items[i].move() to put the content somewhere permanent. */
}
label.text = string;
}
/* The ContentPeer sets the kinds of content that can be imported. For some reason,
handler must be set to Source to indicate that the app is importing. This seems
backwards to me. */
ContentPeer {
id: peer
contentType: ContentType.Documents
handler: ContentHandler.Source
selectionType: ContentTransfer.Multiple
}
/* This is a GUI element that blocks the rest of the UI when a transfer is ongoing. */
ContentTransferHint {
anchors.fill: root
activeTransfer: root.activeTransfer
}
/* Watch root.activeTransfer to find out when content is ready for our use. */
Connections {
target: root.activeTransfer
onStateChanged: {
if (root.activeTransfer.state === ContentTransfer.Charged)
root.importItems(root.activeTransfer.items);
}
}
}
Page {
id: picker
visible: false
/* This presents a grid of icons for apps that can give you content of the
specified type. */
ContentPeerPicker {
id: peerPicker
visible: parent.visible
handler: ContentHandler.Source // Source to get content, for some reason
contentType: ContentType.Documents
onPeerSelected: {
peer.selectionType = ContentTransfer.Multiple;
root.activeTransfer = peer.request();
pageStack.pop();
}
}
}
}
}
2)直接访问这些文件
如果这看起来工作量太大,您可以修改应用程序防护配置文件以授予对文件系统的额外访问权限。例如,要授予应用程序对的读取权限~/Documents
,您需要在应用程序防护 JSON 文件中添加以下行
"read_path": ["@{HOME}/Documents/"]
这将阻止您的应用在提交到官方应用商店时自动获得批准。相反,必须由人工查看并决定是否批准您的应用。有时他们会批准(日志查看器)。有时他们不会批准(我自己的电子书阅读器 Beru)。我还没有找到任何解释,说明为什么有些应用被接受,而其他的则不被接受。
如果你不想和审核员赌博,或者你赌博输了,你可以将你的应用提交给开放商店,发布无法在官方商店发布的应用程序。
答案2
使用来源:http://bazaar.launchpad.net/~music-app-dev/music-app/refactor/files
apparmor.json 中有:
{
"policy_version": 1.3,
"policy_groups": [
"audio",
"content_exchange",
"music_files_read",
"networking",
"usermetrics"
],
"read_path": [
"@{HOME}/.cache/media-art/",
"@{HOME}/.cache/mediascanner-2.0/",
"/media/*/*/"
],
"write_path": [
"@{HOME}/Music/Imported/"
]
}