Androidの本当にあった怖い話
-
Upload
yusuke-yamamoto -
Category
Technology
-
view
22.679 -
download
2
description
Transcript of Androidの本当にあった怖い話
Copyright(c) Yusuke Yamamoto All rights reserved.
Androidの怖い話2011/1/17
山本 裕介 @yusukey
本当にあった
Copyright(c) Yusuke Yamamoto All rights reserved.
山本 裕介http://samuraism.jp/@yusukey
http://tinyurl.com/android-java
Copyright(c) Yusuke Yamamoto All rights reserved.
↑を開発していますJava用Twitter APIライブラリ
サポートプラットフォーム• JDK1.4.2~•Google App Engine
•Android
Copyright(c) Yusuke Yamamoto All rights reserved.
AndroidとJavaの非互換性について話します
Copyright(c) Yusuke Yamamoto All rights reserved.
Androidで使えないパッケージの怖い話
Copyright(c) Yusuke Yamamoto All rights reserved.
発生した問題
02-20 18:03:59.843: WARN/dalvikvm(526): VFY: unable to resolve new-instance 105 (Lsun/misc/BASE64Encoder;) in Ltwitter4j/http/HttpClient; 02-20 18:03:59.843: WARN/dalvikvm(526): VFY: rejecting opcode 0x22 at 0x0011
怖い話その1:Androidではsun.misc.* / com.sun.* が使えない
new sun.misc.BASE64Encoder().encode(buf);
Copyright(c) Yusuke Yamamoto All rights reserved.
施した対策• BASE64のエンコーダーを自前で用意
(Commons-Codec利用でもok)
• sun.misc.* だけでなく com.sun.* 等も使えないので注意
Copyright(c) Yusuke Yamamoto All rights reserved.
XMLの怖い話
Copyright(c) Yusuke Yamamoto All rights reserved.
XML
// XML をテキスト形式に変換private String toString(Element doc){ StringWriter output = new StringWriter(); Transformer t = TransformerFactory.newInstance()
.newTransformer(); t.transform(new DOMSource(doc),
new StreamResult(output)); return output.toString();}
• Twitter4Jにあったデバッグ用のコード
Copyright(c) Yusuke Yamamoto All rights reserved.
発生した問題
07-07 23:55:42.993: ERROR/dalvikvm(11182): Could not find method javax.xml.transform.TransformerFactory.newInstance, referenced from method twitter4j.TwitterResponse.toString
怖い話その2:AndroidにはXSLTが内蔵されていない
Copyright(c) Yusuke Yamamoto All rights reserved.
施した対策// XML をテキスト形式に変換private static String toString(Element doc){ StringWriter output = new StringWriter(); try{ Transformer t = TransformerFactory.newInstance().newTransformer(); t.transform(new DOMSource(doc),
new StreamResult(output)); return output.toString(); }catch(ClassNotFoundException cnfe){ // javax.xml.transform.TransformerFactory がなければ // “”を返す return “”; }}
Copyright(c) Yusuke Yamamoto All rights reserved.
発生した問題01-16 23:20:58.637: ERROR/AndroidRuntime(209): Uncaught handler: thread main exiting due to uncaught exception01-16 23:20:58.668: ERROR/AndroidRuntime(209): java.lang.VerifyError: com.example.MyActivity at java.lang.Class.newInstanceImpl(Native Method) at java.lang.Class.newInstance(Class.java:1472) at android.app.Instrumentation.newActivity(Instrumentation.java:1097) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2316) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2417) at android.app.ActivityThread.access$2100(ActivityThread.java:116) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1794) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:123) at android.app.ActivityThread.main(ActivityThread.java:4203) 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:791) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:549) at dalvik.system.NativeStart.main(Native Method)
怖い話その3:クラスが見つからないとVerifyErrorが発生
Copyright(c) Yusuke Yamamoto All rights reserved.
施した対策-- // XML をテキスト形式に変換-- private static String toString(Element doc){-- StringWriter output = new StringWriter();-- try{-- Transformer t = TransformerFactory.newInstance().newTransformer();-- t.transform(new DOMSource(doc),-- new StreamResult(output));-- return output.toString();-- }catch(ClassNotFoundException cnfe){-- // javax.xml.transform.TransformerFactory がなければ-- // “”を返す-- return “”;-- }--}
Transformerを使わない・・・
Copyright(c) Yusuke Yamamoto All rights reserved.
XMLの日本語問題String xml = "<title>English & 日本語</title>";DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();dbf.setCoalescing(true);dbf.setExpandEntityReferences(true);ByteArrayInputStream stream = new ByteArrayInputStream( xml.getBytes());DocumentBuilder builder = null;builder = dbf.newDocumentBuilder();Document doc = builder.parse(stream);
Node titleNode = doc.getFirstChild();NodeList children = titleNode.getChildNodes();System.out.println(children.item(0).getTextContent());
Copyright(c) Yusuke Yamamoto All rights reserved.
発生した問題String xml = "<title>English & 日本語</title>";DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();dbf.setCoalescing(true);dbf.setExpandEntityReferences(true);ByteArrayInputStream stream = new ByteArrayInputStream( xml.getBytes());DocumentBuilder builder = null;builder = dbf.newDocumentBuilder();Document doc = builder.parse(stream);
Node titleNode = doc.getFirstChild();NodeList children = titleNode.getChildNodes();System.out.println(children.item(0).getTextContent());
怖い話その4:XMLパーサが使い物にならない
期待値: “English & 日本語”
実際: “English”
Copyright(c) Yusuke Yamamoto All rights reserved.
施した対策
XMLを使わない・・・
Copyright(c) Yusuke Yamamoto All rights reserved.
• Twitterはxml, JSON, atom, rssをサポート
• JSON
• JavaScript Object Notation
• Web APIで標準となりつつあるフォーマット
Twitter4JをJSONへ移行
Copyright(c) Yusuke Yamamoto All rights reserved.
JSONの怖い話
Copyright(c) Yusuke Yamamoto All rights reserved.
JSONの例
JSONObject json = new JSONObject
("{\"foo\":null,\"longvalue\":\"13857270119014401\"}");
// true を期待
System.out.println(json.isNull("foo"));
// true を期待
System.out.println(null == json.getString("foo"));
// false を期待
System.out.println("null".equals(json.getString("foo")));
// 13857270119014401 を期待
System.out.println(json.getLong("longvalue"));
(“foo”:null, “longvalue”:”13857270119014401”}
Copyright(c) Yusuke Yamamoto All rights reserved.
JSONObject json = new JSONObject
("{\"foo\":null,\"longvalue\":\"13857270119014401\"}");
// true を期待
System.out.println(json.isNull("foo"));
// true を期待
System.out.println(null == json.getString("foo"));
// false を期待
System.out.println("null".equals(json.getString("foo")));
// 13857270119014401 を期待
System.out.println(json.getLong("longvalue"));
発生した問題
true
true
true
13857270119014400
怖い話その5:jsonのライブラリが古すぎてバグバグ
Copyright(c) Yusuke Yamamoto All rights reserved.
施した対策
json.orgの最新ライブラリをパッケージを変えて使用twitter4j.internal.org.json.*
Copyright(c) Yusuke Yamamoto All rights reserved.
怖い話のまとめ• XSLTは使えない(Froyoで修正済み)
• クラスが見つからない場合にVerifyError• Eclair(Android 2.1)で修正済み
• XMLの日本語、外部エンティティ解決問題
• Froyo(Android 2.2)で修正
• JSONライブラリのバグ
• 修正されない・・・• Sunのパッケージは使えない
Copyright(c) Yusuke Yamamoto All rights reserved.
public static final boolean IS_DALVIK;
static{
try {
// dalvik.system.VMRuntime class should be existing on
Android platform.
// @see http://developer.android.com/reference/dalvik/
system/VMRuntime.html
Class.forName("dalvik.system.VMRuntime");
dalvikDetected = true;
} catch (ClassNotFoundException cnfe) {
dalvikDetected = false";
}
IS_DALVIK = dalvikDetected;
}
オマケ• Android環境の検出
Copyright(c) Yusuke Yamamoto All rights reserved.
- Issue 2607 - android - org.apache.harmony.xml.parsers.DocumentBuilderImpl does not resolve unicode entity refshttp://code.google.com/p/android/issues/detail?id=2607
- Issue 9244 - android - org.json packages out of datehttp://code.google.com/p/android/issues/detail?id=9244
- Issue 13830 - JSONObject.getString() returns "null" string literal for null value instead of null object.http://code.google.com/p/android/issues/detail?id=13830
- Issue 13831 - JSONObject.getLong() returns rounded and inaccurate valuehttp://code.google.com/p/android/issues/detail?id=13831
関連リンク