使用 Google Data API for Java 更新 Picasa 上的元数据
我正在使用 Google Data API 从 Android 连接 Picasa。要检索图片和元数据,它效果很好,但是在解析 PATCH 的响应(相对于原始)时,我得到了 IllegalArgumentException。尽管 parseAsString 方法的输出提供了完美的 xml 字符串,但标头是“text/html”。这是一个错误还是我需要为“text/html”创建自己的解析器?
我也不介意使用 PUT 方法进行更新,有没有人有一个很好的例子如何使用 Java 进行更新?
这里是例外:
Uncaught handler: thread main exiting due to uncaught exception
java.lang.IllegalArgumentException: No parser defined for Content-Type: text/html; charset=UTF-8
at com.google.api.client.http.HttpResponse.parseAs(HttpResponse.java:277)
at com.unimelb.pt3.external.google.api.Entry.executePatchRelativeToOriginal(Entry.java:95)
at com.unimelb.pt3.external.google.api.PhotoEntry.executePatchRelativeToOriginal(PhotoEntry.java:67)
at com.unimelb.pt3.Picasa.updatePicture(Picasa.java:135)
at com.unimelb.pt3.Tools.updatePictureOnPicasa(Tools.java:209)
at com.unimelb.pt3.ui.WaterfallView.onDraw(WaterfallView.java:145)
at android.view.View.draw(View.java:6535)
at android.view.ViewGroup.drawChild(ViewGroup.java:1531)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1258)
at android.view.ViewGroup.drawChild(ViewGroup.java:1529)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1258)
at android.view.View.draw(View.java:6538)
at android.widget.FrameLayout.draw(FrameLayout.java:352)
at android.view.ViewGroup.drawChild(ViewGroup.java:1531)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1258)
at android.view.ViewGroup.drawChild(ViewGroup.java:1529)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1258)
at android.view.View.draw(View.java:6538)
at android.widget.FrameLayout.draw(FrameLayout.java:352)
at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:1830)
at android.view.ViewRoot.draw(ViewRoot.java:1349)
at android.view.ViewRoot.performTraversals(ViewRoot.java:1114)
at android.view.ViewRoot.handleMessage(ViewRoot.java:1633)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:4363)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
at dalvik.system.NativeStart.main(Native Method)
这里是条目中的代码:
Entry executePatchRelativeToOriginal(HttpTransport transport, Entry original)
throws IOException {
HttpRequest request = transport.buildPatchRequest();
request.setUrl(getEditLink());
request.headers.ifMatch = etag;
AtomPatchRelativeToOriginalContent content =
new AtomPatchRelativeToOriginalContent();
content.namespaceDictionary = Util.NAMESPACE_DICTIONARY;
content.originalEntry = original;
content.patchedEntry = this;
request.content = content;
Log.i(Prototype.TAG, request.url.toString());
HttpResponse response = request.execute();
// Log.i(Prototype.TAG, response.parseAsString());
return response.parseAs(getClass());
}
这里是主活动的相关代码:
public void updatePicture(String url, String description, String[] tags) throws IOException {
PhotoEntry photo = photos.get(url);
PhotoEntry patched = photo.clone();
patched.summary = description;
String keywords = "";
for(int i=0; i<tags.length; i++) {
keywords += tags[i] + ((i==tags.length-1) ? "" : ", ");
}
patched.mediaGroup.keywords = keywords;
photo = patched.executePatchRelativeToOriginal(transport, photo);
}
private HttpTransport setUpTransport() {
HttpTransport transport = GoogleTransport.create();
GoogleHeaders headers = (GoogleHeaders) transport.defaultHeaders;
headers.setApplicationName("google-picasaatomsample-1.0");
headers.gdataVersion = "2";
AtomParser parser = new AtomParser();
parser.namespaceDictionary = Util.NAMESPACE_DICTIONARY;
transport.addParser(parser);
return transport;
}
编辑: 我向 setUpTransport 方法添加了以下几行:
XmlHttpParser p2 = new XmlHttpParser();
p2.contentType = "text/html";
p2.namespaceDictionary = Util.NAMESPACE_DICTIONARY;
transport.addParser(p2);
这会导致该日志出现另一个 IllegalArgumentException:
Uncaught handler: thread main exiting due to uncaught exception
java.lang.IllegalArgumentException: expected start of XML element, but got something else (event type 4)
at com.google.api.client.xml.Xml.parseElementInternal(Xml.java:180)
at com.google.api.client.xml.Xml.parseElement(Xml.java:152)
at com.google.api.client.xml.XmlHttpParser.parse(XmlHttpParser.java:73)
at com.google.api.client.http.HttpResponse.parseAs(HttpResponse.java:280)
at com.unimelb.pt3.external.google.api.Entry.executePatchRelativeToOriginal(Entry.java:95)
at com.unimelb.pt3.external.google.api.PhotoEntry.executePatchRelativeToOriginal(PhotoEntry.java:67)
at com.unimelb.pt3.Picasa.updatePicture(Picasa.java:130)
at com.unimelb.pt3.Tools.updatePictureOnPicasa(Tools.java:209)
at com.unimelb.pt3.ui.WaterfallView.onDraw(WaterfallView.java:145)
at android.view.View.draw(View.java:6535)
at android.view.ViewGroup.drawChild(ViewGroup.java:1531)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:158)
at android.view.ViewGroup.drawChild(ViewGroup.java:1529)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1258)
at android.view.View.draw(View.java:6538)
at android.widget.FrameLayout.draw(FrameLayout.java:352)
at android.view.ViewGroup.drawChild(ViewGroup.java:1531)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1258)
at android.view.ViewGroup.drawChild(ViewGroup.java:1529)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1258)
at android.view.View.draw(View.java:6538)
at android.widget.FrameLayout.draw(FrameLayout.java:352)
at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:1830)
at android.view.ViewRoot.draw(ViewRoot.java:1349)
at android.view.ViewRoot.performTraversals(ViewRoot.java:1114)
at android.view.ViewRoot.handleMessage(ViewRoot.java:1633)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:4363)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
at dalvik.system.NativeStart.main(Native Method)
I'm using Google Data API to connect Picasa from Android. To retrieve the pictures and the metadata it works great, but I get an IllegalArgumentException on parsing the response of an PATCH (relative to original). The header is "text/html" although the ouput of the parseAsString-method delivers a perfect xml-string. Is that a bug or do I need to create my own Parser for "text/html"?
I also wouldn't mind updating with the PUT-method, does anyone have a good example how to do that with Java?
Here the exception:
Uncaught handler: thread main exiting due to uncaught exception
java.lang.IllegalArgumentException: No parser defined for Content-Type: text/html; charset=UTF-8
at com.google.api.client.http.HttpResponse.parseAs(HttpResponse.java:277)
at com.unimelb.pt3.external.google.api.Entry.executePatchRelativeToOriginal(Entry.java:95)
at com.unimelb.pt3.external.google.api.PhotoEntry.executePatchRelativeToOriginal(PhotoEntry.java:67)
at com.unimelb.pt3.Picasa.updatePicture(Picasa.java:135)
at com.unimelb.pt3.Tools.updatePictureOnPicasa(Tools.java:209)
at com.unimelb.pt3.ui.WaterfallView.onDraw(WaterfallView.java:145)
at android.view.View.draw(View.java:6535)
at android.view.ViewGroup.drawChild(ViewGroup.java:1531)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1258)
at android.view.ViewGroup.drawChild(ViewGroup.java:1529)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1258)
at android.view.View.draw(View.java:6538)
at android.widget.FrameLayout.draw(FrameLayout.java:352)
at android.view.ViewGroup.drawChild(ViewGroup.java:1531)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1258)
at android.view.ViewGroup.drawChild(ViewGroup.java:1529)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1258)
at android.view.View.draw(View.java:6538)
at android.widget.FrameLayout.draw(FrameLayout.java:352)
at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:1830)
at android.view.ViewRoot.draw(ViewRoot.java:1349)
at android.view.ViewRoot.performTraversals(ViewRoot.java:1114)
at android.view.ViewRoot.handleMessage(ViewRoot.java:1633)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:4363)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
at dalvik.system.NativeStart.main(Native Method)
Here the code in the Entry:
Entry executePatchRelativeToOriginal(HttpTransport transport, Entry original)
throws IOException {
HttpRequest request = transport.buildPatchRequest();
request.setUrl(getEditLink());
request.headers.ifMatch = etag;
AtomPatchRelativeToOriginalContent content =
new AtomPatchRelativeToOriginalContent();
content.namespaceDictionary = Util.NAMESPACE_DICTIONARY;
content.originalEntry = original;
content.patchedEntry = this;
request.content = content;
Log.i(Prototype.TAG, request.url.toString());
HttpResponse response = request.execute();
// Log.i(Prototype.TAG, response.parseAsString());
return response.parseAs(getClass());
}
Here the relevant code from the main Activity:
public void updatePicture(String url, String description, String[] tags) throws IOException {
PhotoEntry photo = photos.get(url);
PhotoEntry patched = photo.clone();
patched.summary = description;
String keywords = "";
for(int i=0; i<tags.length; i++) {
keywords += tags[i] + ((i==tags.length-1) ? "" : ", ");
}
patched.mediaGroup.keywords = keywords;
photo = patched.executePatchRelativeToOriginal(transport, photo);
}
private HttpTransport setUpTransport() {
HttpTransport transport = GoogleTransport.create();
GoogleHeaders headers = (GoogleHeaders) transport.defaultHeaders;
headers.setApplicationName("google-picasaatomsample-1.0");
headers.gdataVersion = "2";
AtomParser parser = new AtomParser();
parser.namespaceDictionary = Util.NAMESPACE_DICTIONARY;
transport.addParser(parser);
return transport;
}
EDIT:
I added to the setUpTransport method the following lines:
XmlHttpParser p2 = new XmlHttpParser();
p2.contentType = "text/html";
p2.namespaceDictionary = Util.NAMESPACE_DICTIONARY;
transport.addParser(p2);
That leads to another IllegalArgumentException with that log:
Uncaught handler: thread main exiting due to uncaught exception
java.lang.IllegalArgumentException: expected start of XML element, but got something else (event type 4)
at com.google.api.client.xml.Xml.parseElementInternal(Xml.java:180)
at com.google.api.client.xml.Xml.parseElement(Xml.java:152)
at com.google.api.client.xml.XmlHttpParser.parse(XmlHttpParser.java:73)
at com.google.api.client.http.HttpResponse.parseAs(HttpResponse.java:280)
at com.unimelb.pt3.external.google.api.Entry.executePatchRelativeToOriginal(Entry.java:95)
at com.unimelb.pt3.external.google.api.PhotoEntry.executePatchRelativeToOriginal(PhotoEntry.java:67)
at com.unimelb.pt3.Picasa.updatePicture(Picasa.java:130)
at com.unimelb.pt3.Tools.updatePictureOnPicasa(Tools.java:209)
at com.unimelb.pt3.ui.WaterfallView.onDraw(WaterfallView.java:145)
at android.view.View.draw(View.java:6535)
at android.view.ViewGroup.drawChild(ViewGroup.java:1531)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:158)
at android.view.ViewGroup.drawChild(ViewGroup.java:1529)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1258)
at android.view.View.draw(View.java:6538)
at android.widget.FrameLayout.draw(FrameLayout.java:352)
at android.view.ViewGroup.drawChild(ViewGroup.java:1531)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1258)
at android.view.ViewGroup.drawChild(ViewGroup.java:1529)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1258)
at android.view.View.draw(View.java:6538)
at android.widget.FrameLayout.draw(FrameLayout.java:352)
at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:1830)
at android.view.ViewRoot.draw(ViewRoot.java:1349)
at android.view.ViewRoot.performTraversals(ViewRoot.java:1114)
at android.view.ViewRoot.handleMessage(ViewRoot.java:1633)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:4363)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
at dalvik.system.NativeStart.main(Native Method)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
尝试使用 XmlHttpParser 并设置其 内容类型 为“text/html”。
顺便说一句,为了响应 PATCH,Picasa 数据 API 应返回内容类型“application/xml”,而不是“text/html”。所以这可能是一个错误。
编辑:我自己没有调查过这个问题,但我怀疑这个 IllegalArgumentException 是因为 text/html 内容不是格式良好的 XML 内容。我们实际上没有 HTML 解析器。我想知道为什么你觉得你需要解析 HTML 响应,因为 parseAsString 可以满足你的需要。顺便说一句,Picasa Data API 不应该返回 HTML 响应,因此这可能是他们的错误(除了提交错误报告之外,您没有什么可以做的)。
免责声明:我是 google-api-java-client 项目。
Try using XmlHttpParser and set its content type to "text/html".
By the way, in response to a PATCH, Picasa Data API should be returning content type "application/xml", not "text/html". So that's possibly a bug.
EDIT: I haven't investigated this myself, but I suspect this IllegalArgumentException is because the text/html content is not well-formed XML content. We don't actually have an HTML parser. I wonder though why you feel you need to parse the HTML response, given that parseAsString gives you what you need. By the way, Picasa Data API shouldn't be returning an HTML response, so that's probably a bug on their end (not that there's anything you can do about other than file a bug report).
Disclaimer: I'm an owner of the google-api-java-client project.