我正在研究将 Gboard 图像支持添加到我们的应用程序中。
下面我有三个具体问题。
看过官方文件https://developer.android.com/guide/topics/text/image-keyboard.html
不过有些奇怪的事情发生了。
当用户点击EditText时,编辑器将发送它在EditorInfo.contentMimeTypes中接受的MIME内容类型列表。
IME读取支持的类型列表,并在编辑器可以接受的软键盘中显示内容。
我读这个也意味着如果一个应用程序没有设置EditorInfo.contentMimeType,那么键盘将不会启用插入图像的UI。
然而,这并不是它在实践中的工作方式。
首先,我看到的是GBoard显示了几乎所有EditText的插入图像UI,大概是基于它的inputType。
我尝试创建一个EditText子类,覆盖onCreateInputConnection并确保EditorInfo.contentMimeType -
在不同的屏幕上,我们的应用程序中有几十个EditText输入字段(可能更多)。插入动画GIF对绝大多数人来说没有意义。
问题1——如何阻止这种情况(如果可以的话)?
顺便说一下,这是很容易检查几乎任何应用程序,几乎任何输入框。比如在Gmail app的搜索栏里。或者在谷歌浏览器的网址输入栏中。
这对于大多数应用都是无害的 - 如果您在不支持图像输入的输入字段中选择GIF(例如上面的示例,Gmail和Chrome),GBoard会显示“类似吐司”的消息,指出“此文本字段不支持从键盘插入GIF”。
好的,但是:
作为后备,当 G 板无法通过输入连接发送选定的 GIF 时 -
我们的应用程序(一个电子邮件应用程序)在其ACTION_SEND清单中确实有一个意图过滤器,使用户能够通过电子邮件消息共享“东西”。像图库图片、文件管理器中的文件等任何东西。
因此,GBoard最终启动了带有ACTION_SEND和图像URL的“电子邮件撰写屏幕”。
这会导致另外两个问题:
首先,它让用户感到困惑
假设他/她试图在应用程序的“某个”编辑文本中插入GIF。
然后,他/她将被带到应用程序的“消息撰写”屏幕,因为ACTION_SEND - “哇,发生了什么事”。
问题#2 -如何阻止这种情况(如果可以的话)?
其次,无法使用我所知道的任何方法打开图像的URI。
我尝试过:
cr.openFileDescriptor(uri, "r");
cr.openAssetFileDescriptor(uri, "r");
cr.openInputStream(uri);
cr.query(uri, null, null, null, null);
所有这些都以“无效URI”等等的变体失败了。
我确实理解,通过为我们想要支持GIF的一个或几个输入字段实现InputConnectionWrapper,我们可以直接从inputContentInfo请求权限,如文档中所述。
我说的是一个不同的情况 - 我会重申 - 当用户尝试将GIF插入到我们应用程序中的“其他”EditText中时,GBoard使用GIF的URI和ACTION_SEND启动我们的“消息撰写”活动。
目前,我们的代码试图以与其他任何URI相同的方式处理此URI(例如,当用户将来自Google Photos的照片共享到我们的应用程序中时),但打开此URI失败,因此用户不仅在撰写屏幕上意外结束,而且还收到一个错误,即我们无法打开/复制“附件”。
问题#3-是否可以使用“标准”ContentResolver方法打开用ACTION_SEND发送的GBoard图像URI?
4月12日,更新“问题#3”(无法打开流)。
我们的应用程序在其清单中使用sharedUserId。
移除sharedUserId并且不做其他更改,使得URI的动画图像现在可以很好地用cr.openInputStream打开,无论是在输入连接回调还是在ACTION_SEND中。
虽然可能有理由不使用sharedUserId,但我们的应用程序从2012年左右就开始使用了,并且不可能仅仅因为这个功能而删除它(因为这样会阻止更新)。
URI 如下所示,应用的程序包名称在参数中编码:
content://com.google.android.inputmethod.latin.inputcontent/inputContent?fileName=/data/user_de/0/com.google.android.inputmethod.latin/files/gif20152912710254894520
所以问题3现在被替换为
问题#4-我们如何向Google报告这个bug(sharedUserId使其无法打开图像URI)?
就像你说的,Gboard 在视图不接受 GIF
时发送 SEND
意向。问题是,我测试过的其他键盘也发生了同样的事情,所以它似乎不是Gboard的错误。
所以我想出的解决方案是忽略当前键盘上的SEND意图。
当我在接收器活动中收到意图时,我会检查数据是否来自键盘,为此我使用以下方法,这可能也可以为您提供帮助:
private boolean isClipDataAuthorityValid(@NonNull ClipData clipData) {
if (clipData.getItemCount() == 0) {
return true;
}
Uri uri = clipData.getItemAt(0).getUri();
if (uri == null) {
return true;
}
String authority = uri.getAuthority();
if (TextUtils.isEmpty(authority)) {
return true;
}
String defaultInputMethod = Settings.Secure.getString(getContentResolver(), "default_input_method");
if (TextUtils.isEmpty(defaultInputMethod)) {
return true;
}
String keyboardPackage = defaultInputMethod.split("/")[0];
try {
ProviderInfo[] providers = getPackageManager().getPackageInfo(keyboardPackage, PackageManager.GET_PROVIDERS).providers;
if (providers == null || providers.length == 0) {
return true;
}
//Check if the authority of the given clipdata's uri matches any of the keyboards's provider authority
for (ProviderInfo provider : providers) {
if (TextUtils.equals(authority, provider.authority)) {
return false;
}
}
} catch (PackageManager.NameNotFoundException e) {
//Do nothing
}
return true;
}
该方法接收剪辑数据,可以使用intent.getClipData()
轻松地从意图中提取剪辑数据。它获取当前键盘,检查提供者,将它们的权限与剪辑数据的Uri的权限匹配,如果剪辑数据来自键盘,则返回false。
目前,我无法找到另一种通用的解决方案,因为我测试的键盘显示不同的结果。
我希望这能有所帮助:)
我正在尝试使用不同的应用程序附加图像,代码如下: 附加的图像是使用以下代码生成的: 但当我试图打开GMAIL与此意图,只有文本显示应用程序与错误:. 我错过了什么? 编辑 这是另一个解决方案:android。操作系统。FileUrieExposedException:文件。jpg通过ClipData曝光了app之外的内容。项目getUri()
我写这封信是希望你能帮助我。出于某种原因,当我单击按钮时,我的应用程序不会启动谷歌地图,而是会将我发送回上一个活动/页面。当我再次按下该按钮时,应用程序会崩溃。 JAVA类(crkvalokacijamape.java) crkva\u lokacijamape。xml AndroidManifest.xml map_api.xml
主要内容:将图像插入PDF文档在前一章中,我们已经学习如何从现有的PDF文档中提取文本。 在本章中,将讨论如何将图像插入PDF文档。 将图像插入PDF文档 分别使用类的以及类的方法将图像插入到PDF文档中。 以下是从现有PDF文档中提取文本的步骤。 第1步:加载现有的PDF文档 使用类的静态方法加载现有的PDF文档。 此方法接受一个文件对象作为参数,因为这是一个静态方法,可以使用类名称调用它,如下所示。 第2步:检索页面 在P
好的,我对Java非常、非常陌生,而且是自学成才的,所以不要拿我糟糕的编码开玩笑;)我在玩弄JavaFX,试图将图像插入到边框窗格布局中。 这是控制器中的方法,我正在使用它来显示图像,但我无法让文件路径工作。它目前有“/图像/BrownBear.jpg”作为文件路径,但我尝试了相对路径- com/jaimependelbury/哺乳类动物/images/brownBear.jpg 完整的路径和中间
我有MainActivity上有一个片段,当用户点击片段时,用户会导航到另一个片段,在最后一个片段上有一个按钮来启动谷歌地图导航,这是代码: 问题是,在地图启动后,我希望用户在按下back时返回到我的应用程序,而不是Launcher。 有没有办法做到这一点。 这是我的完整代码: 主体活动 原木
我用谷歌地球创建了一个kml文件,它使用外部图像创建了一个覆盖层。它工作得很好,我想找到一种相当方便的转换kml的方法,这样谷歌地图就可以以类似的方式读取和显示它。 谷歌地图不能处理谷歌地球坐标,所以我试图自己转换它们。例如,我替换了地球坐标: 使用等效地图坐标: 不幸的是,两者并不完全“对等”。“地图覆盖”稍微关闭,旋转不正确。 以下是两张照片: 地球实例 地图示例 我明白为什么它不起作用,但我