2014年1月19日 星期日
從html上截取JSON出現轉換錯誤...
需求:從HTML上截取內容轉換為JSONObject
使用方式如下:
JSONObject json = new JSONObject(html);
卻出現exception:
org.json.JSONException: Value of type java.lang.String cannot be converted to JSONObject
解決:
我遇到的問題是,此截取的html為UTF-8編碼,因此開頭出現了UTF-8編碼字元如下圖:
而我存取的這個html存檔類型為UTF-8,最後我使用nopad++將檔案另外保存為『檔首無BOM』的形式就可以了.
使用nopad++『編輯』->『編譯成UTF-8碼(檔首無BOM)』
2014年1月3日 星期五
Android - 如何讓安裝的APP不出現在手機的『程式列表』中( all apps list)
參考:Display message after Package install
Creating a Main Activity which DOES NOT appear in the launcher list
需求:之前客戶有提出,希望有一個APP為主體,這裡稱之為MAIN_APP,然後之後其他安裝附屬APP(B_APP,C_APP...)都是一定要靠MAIN_APP才能啟動,且不能讓這些其他已安裝的APP顯示在『程式列表』中:
解法:
其實很簡單,只要將
改為:
也就是說將原先的android.intent.category.LAUNCHER替換為android.intent.category.INFO就可以囉
android.intent.category.LAUNCHER我們都清楚是幹嘛的,至於android.intent.category.INFO是做什麼的呢?以下截取自官方DOC:
而依照此篇文章所說,如果要讓googl play這些附屬APP(B_APP,C_APP...)的google play專屬頁也要能顯示『開啟』按鈕,似乎就是得靠加上
Creating a Main Activity which DOES NOT appear in the launcher list
需求:之前客戶有提出,希望有一個APP為主體,這裡稱之為MAIN_APP,然後之後其他安裝附屬APP(B_APP,C_APP...)都是一定要靠MAIN_APP才能啟動,且不能讓這些其他已安裝的APP顯示在『程式列表』中:
解法:
其實很簡單,只要將
改為:
也就是說將原先的android.intent.category.LAUNCHER替換為android.intent.category.INFO就可以囉
android.intent.category.LAUNCHER我們都清楚是幹嘛的,至於android.intent.category.INFO是做什麼的呢?以下截取自官方DOC:
Provides information about the package it is in; typically used if a package does not contain a
CATEGORY_LAUNCHER to provide a front-door to the user without having to be shown in the all apps list.
Constant Value: "android.intent.category.INFO"
<action android:name="android.intent.action.MAIN" />來幫忙,不過這部分我還沒測試過,之後測試過再確定更新吧(希望我還記得...)
2013年12月15日 星期日
android - actionBar中的Overflow Menu(海苔條)出現的時機
參考:Adapting Android 4.0 to Older Hardware and Apps
http://developer.android.com/design/patterns/actionbar.html
發現有時候Overflow Menu(海苔條)會出現有時候又不會出現,後來看了上方參考的官方文件終於懂了:
首先解釋一下,Action OverFlow也就是俗稱的『海苔條』就是這個東西:
也就是上圖編號『4』最右邊的那個三個垂直排列點的按鈕啦~
依照官方文件說明,當裝置擁有『實體menuKey』時,那麼這條就不會出現,而要出現menu選單就是在手機上按下『實體menuKey』;當裝置沒有『實體menuKey』時,ActionBar的最右方(如上圖),就會出現Overflow Menu(海苔條),替代『實體menuKey』
以下是官方說明截取:
以這篇文章來說似乎不推薦強制去變更這個規則讓Overflow Menu(海苔條)一定要出現,畢竟這違反了android的設計想法(不過我就是有遇到客戶希望能出現,後來被我說這個是android的規範給打退想法的<其實是因為我不知道要如何讓她強制出現啦...汗,臺北等公車就有實現這個做法,不過我還沒成功就是...)
http://developer.android.com/design/patterns/actionbar.html
發現有時候Overflow Menu(海苔條)會出現有時候又不會出現,後來看了上方參考的官方文件終於懂了:
首先解釋一下,Action OverFlow也就是俗稱的『海苔條』就是這個東西:
也就是上圖編號『4』最右邊的那個三個垂直排列點的按鈕啦~
依照官方文件說明,當裝置擁有『實體menuKey』時,那麼這條就不會出現,而要出現menu選單就是在手機上按下『實體menuKey』;當裝置沒有『實體menuKey』時,ActionBar的最右方(如上圖),就會出現Overflow Menu(海苔條),替代『實體menuKey』
以下是官方說明截取:
Phones with physical navigation keys
Android phones with traditional navigation hardware keys don't display the virtual navigation bar at the bottom of the screen. Instead, the action overflow is available from the menu hardware key. The resulting actions popup has the same style as in the previous example, but is displayed at the bottom of the screen.
我拿手邊的三個裝置試驗,試驗的app為『play商店』,『gmail』的確平板沒有『menuKey』的狀況下就會出現Overflow Menu(海苔條),反之另外兩隻手機因為有『menuKey』所以就沒顯示了
google查詢actionbar overflow force還有不少討論,看來有不少人都需要這種需求呢。
以這篇文章來說似乎不推薦強制去變更這個規則讓Overflow Menu(海苔條)一定要出現,畢竟這違反了android的設計想法(不過我就是有遇到客戶希望能出現,後來被我說這個是android的規範給打退想法的<其實是因為我不知道要如何讓她強制出現啦...汗,臺北等公車就有實現這個做法,不過我還沒成功就是...)
android - 使用ActionBar時啟動出現 java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity...
參考:ActionBarCompat: java.lang.IllegalStateException: You need to use a Theme.AppCompat
使用ActionBar如下:
啟動時出現以下錯誤:
12-15 17:27:09.154: E/AndroidRuntime(422): FATAL EXCEPTION: main
12-15 17:27:09.154: E/AndroidRuntime(422): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.androidtest/com.example.androidtest.MainActivity}: java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity.
12-15 17:27:09.154: E/AndroidRuntime(422): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2663)
12-15 17:27:09.154: E/AndroidRuntime(422): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)
使用ActionBar如下:
public class MainActivity extends ActionBarActivity
...
12-15 17:27:09.154: E/AndroidRuntime(422): FATAL EXCEPTION: main
12-15 17:27:09.154: E/AndroidRuntime(422): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.androidtest/com.example.androidtest.MainActivity}: java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity.
12-15 17:27:09.154: E/AndroidRuntime(422): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2663)
12-15 17:27:09.154: E/AndroidRuntime(422): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)
解決方式:
將res/values/styles.xml下的parent屬性改為Theme.AppCompat的其中之一,例如:
"@style/Theme.AppCompat.Light"
"@style/Theme.AppCompat.Light"
<style name="AppBaseTheme" parent="@style/Theme.AppCompat.Light">
...
2013年11月23日 星期六
hsqldb - 使用date型態時一直出現錯誤java.sql.SQLDataException: data exception: invalid datetime format: yyyyMMdd...
參考:Chapter 10. Built In Functions
使用hsqldb+mybatis執行以下的sql cmd:
使用hsqldb+mybatis執行以下的sql cmd:
UPDATE TABLE SET TRANS_NET_DIS=0,TRANS_SALES=0,TRANS_ADJ_DIS=0,TRANS_FEE=0,TRANS_DIS=0,TRANS_NET_SALES=0,TRANS_ADJ_SALES=0,TRANS_RECEIPT=0 WHERE STMT_DATE=to_date('20121230','yyyyMMdd') AND SEQE='00' AND MERCH='999160691' AND ORGG='822'
然後出現以下的錯誤:
### Cause: java.sql.SQLDataException: data exception: invalid datetime format: yyyyMMdd
at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:23)
at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:150)
at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:49)
at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:43)
at com.sun.proxy.$Proxy6.updateIsKeyData(Unknown Source)
at com.ctbc.transfile.sql.mybatis.UpdateIsKeyData.execute(UpdateIsKeyData.java:21)
at com.ctbc.transfile.sql.mybatis.UpdateIsKeyData.execute(UpdateIsKeyData.java:1)
at com.ctbc.util.sql.MyBatisUtil.execute(MyBatisUtil.java:42)
at com.ctbc.transfile.loadtask.check.KeyChecker.rmvAndUpdateKeyExistsBeans(KeyChecker.java:89)
at ut.com.ctbc.transfile.loadtask.check.KeyCheckerTest.testRmvKeyExistsBeans_Exists(KeyCheckerTest.java:211)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: java.sql.SQLDataException: data exception: invalid datetime format: yyyyMMdd
at org.hsqldb.jdbc.Util.sqlException(Unknown Source)
at org.hsqldb.jdbc.Util.sqlException(Unknown Source)
at org.hsqldb.jdbc.JDBCPreparedStatement.fetchResult(Unknown Source)
at org.hsqldb.jdbc.JDBCPreparedStatement.execute(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.apache.ibatis.logging.jdbc.PreparedStatementLogger.invoke(PreparedStatementLogger.java:55)
at com.sun.proxy.$Proxy8.execute(Unknown Source)
at org.apache.ibatis.executor.statement.PreparedStatementHandler.update(PreparedStatementHandler.java:41)
at org.apache.ibatis.executor.statement.RoutingStatementHandler.update(RoutingStatementHandler.java:66)
at org.apache.ibatis.executor.SimpleExecutor.doUpdate(SimpleExecutor.java:45)
at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:100)
at org.apache.ibatis.executor.CachingExecutor.update(CachingExecutor.java:75)
at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:148)
... 33 more
Caused by: org.hsqldb.HsqlException: data exception: invalid datetime format: yyyyMMdd
at org.hsqldb.error.Error.error(Unknown Source)
at org.hsqldb.error.Error.error(Unknown Source)
at org.hsqldb.HsqlDateTime.toJavaDatePattern(Unknown Source)
at org.hsqldb.HsqlDateTime.toDate(Unknown Source)
at org.hsqldb.FunctionCustom.getValue(Unknown Source)
at org.hsqldb.FunctionSQL.getValue(Unknown Source)
at org.hsqldb.RangeVariable$RangeIteratorMain.getFirstRow(Unknown Source)
at org.hsqldb.RangeVariable$RangeIteratorMain.initialiseIterator(Unknown Source)
at org.hsqldb.RangeVariable$RangeIteratorMain.next(Unknown Source)
at org.hsqldb.StatementDML.executeUpdateStatement(Unknown Source)
at org.hsqldb.StatementDML.getResult(Unknown Source)
at org.hsqldb.StatementDMQL.execute(Unknown Source)
at org.hsqldb.Session.executeCompiledStatement(Unknown Source)
at org.hsqldb.Session.execute(Unknown Source)
... 47 more
後來找到hsqldb的官方說明,直接找到下方的Table 10.1. TO_CHAR, TO_DATE and TO_TIMESTAMP format elements部分,可以看到允許的都是『大寫』,因此將上述執行的yyyyMMdd改為YYYYMMDD,就可以解決這個問題了.
2013年11月18日 星期一
mybatis - 使用Oracle時出現Error updating database. Cause: java.sql.SQLSyntaxErrorException: ORA-00911: 字元無效
假設我有以下的Mapper.xml:
INSERT INTO UPDATETIME (FILE_NAME, LASTUPDATED) VALUES ( #{filename}, SYSDATE);
執行時出現錯誤:
### The error may involve com.ctbc.transfile.sql.mybatis.IKeyCheckMapper.updateUpdateTime-Inline
### The error occurred while setting parameters
### SQL: UPDATE UPDATETIME SET LASTUPDATED = SYSDATE WHERE FILE_NAME=?;
### Cause: java.sql.SQLSyntaxErrorException: ORA-00911: 字元無效
原因很簡單,尾端不要加上分號(;)即可.
(不知道為什麼oracle語法明明就是要加分號在mybatis上卻不需要加...)
mybatis - Mapper.xml語法參數使用方式
參考:Mapper XML Files
有兩種使用方式:
有兩種使用方式:
- 使用#{data}
使用$就等同使用JDBC中的PreparedStatement方式設定參數,如下:
< select id="selectPerson" parametertype="int" resulttype="hashmap"> SELECT * FROM PERSON WHERE ID = #{id} </ select>
類似於我們直接使用以下的方式:
// Similar JDBC code, NOT MyBatis… String selectPerson = "SELECT * FROM PERSON WHERE ID=?"; PreparedStatement ps = conn.prepareStatement(selectPerson); ps.setInt(1,id);
此種方式最明顯的好處就是防止SQL injection - 使用${data}
此種方式等於簡單的字串相加,所以假設以上的ID是字串形態的參數,那麼我們就必須在前後加上單引號('):
< select id="selectPerson" parameterType="int" resultType="hashmap"> SELECT * FROM PERSON WHERE ID = '${id}' < /select>
所以上述的方式僅僅是組成SQL COMMAND:SELECT * FROM PERSON WHERE ID = 'iddata'直接送到sql去執行,
最明顯的問題就是SQL injection,因此在mybatis的官方說明上也標注僅可能避免使用此方式.
訂閱:
文章 (Atom)

