2016年6月22日 星期三

如何在android, java中修改別人的原始碼

如果要修改別人己寫好的原始代碼, 如果是簡單的修改
某一個函數, 最簡單的方式, 應該就是用繼承的方式, 直
接覆寫(override)其中一個函數. 但是override的方式, 有
時會受到限制, 例如如果該class 被原作者定義為 final,
那麼它所含的函數是不允許覆寫的.

還有覆寫的內容, 如果有用到被定義為private的部分, 也是
不允許的.

遇到以上情況, 就不能用覆寫的方式來處理.
我的處理方法:
把 原來的A class , 複製一份, 變成 B class, 直接更改B class
, 但是注意B class的 package 名稱, 必須和A class 一樣,也就是
如果 A class package 名稱為 com.test.myfile 那麼你的project
內, 要建立一個 com/test/myfile 的路徑, 將 class 放在底下,

否則可能會出現
Classes cannot be accessed from outside package
的問題.
然後將所有對A class 的作業, 都更換為B class

另一個方法是直接去改A class , 再把它 compile 成A.class 檔
直接放到 jar 去置換原來的class. (重新打包). 可參考:

java android修改變更jar中的某個class的source




Read more...

2016年6月21日 星期二

lucene analyzer tokenizer(分詞) 的工作記錄

因為最近必須對lucene 的特殊字元進行搜尋(lucene 分詞時
預設是排除特殊字元的, 除了WhiteSpaceAnalyzer), 所以研
究了lucene 分詞的原始碼.

記錄如下:

先說說StandardAnalyzer

StandardAnalyzer extends 自 StopwordAnalyzerBase

當 writer.add(doc) 之後, 會先進入 Analyzer
(所有Analyzer的父類)

然後再根據所選擇的 Analyzer 進入該 Analyzer 執行
CreateComponents 這個函數

CreateComponents 在每一個子類的Analyzer都有不同的實
現方式

例如, 其中StandardAnalyzer 的 CreateComponents 代碼
如下:

@Override
protected TokenStreamComponents createComponents
(final String fieldName, final Reader reader) {
  final StandardTokenizer src =
  new StandardTokenizer(matchVersion, reader);
  src.setMaxTokenLength(maxTokenLength);
  TokenStream tok = new StandardFilter(matchVersion, src);
  tok = new LowerCaseFilter(matchVersion, tok);
  tok = new StopFilter(matchVersion, tok, stopwords);
  return new TokenStreamComponents(src, tok) {
    @Override
    protected void setReader(final Reader reader)
throws IOException {
      src.setMaxTokenLength(StandardAnalyzer.this.maxTokenLength);
      super.setReader(reader);
    }
  };
}

由以上代碼可看出StandardAnalyzer 進行 StandardTokenizer
/StandardFilter/LowerCaseFilter/StopFilter 等程序



再看看WhiteSpaceAnalyzer

  @Override
  protected TokenStreamComponents createComponents
  (final String fieldName,
      final Reader reader) {
    return new TokenStreamComponents(new
WhitespaceTokenizer(matchVersion, reader));
  }

以上可看出 WhiteSpaceAnalyzer, 它的 CreateComponents,
就只有進行WhitespaceTokenizer而己.


以上的StandardTokenizer是進行分詞的程序, 看看它做些什麼
StandardTokenizer中有一個init的函數, 執行
StandardTokenizerImpl 

StandardTokenizerImpl 會實際對全文進行分詞. 這個函數相
當複雜, 很難理解, 我只理解一小部分

其中
private static final char [] ZZ_CMAP = 
zzUnpackCMap(ZZ_CMAP_PACKED);

ZZ_CMAP 存放每一個字元一個值, 用來判斷該字元是分詞時要納入的
正常值,或是不納入的分割字元. 
例如 35是#的ascii內碼
當 ZZ_CMAP[35]=0 時, 代表#在分詞時會被排除
"#abc #def ghi" 分詞後=>abc, def, ghi

當 ZZ_CMAP[35]='~' (十進位為126, 為何是126?不解) 時, 
代表#在分詞時會被納入
"#abc #def ghi" 分詞後=>#abc, #def, ghi

所以想讓#被含在分詞中, 只要 ZZ_CMAP[35]='~' 即可


Read more...

2016年6月19日 星期日

android studio todo list filter 的功能

按下 todo list 視窗右方的filter圖示/Edit filters

上方pattern的地方按+

輸入\btodo: 2016\b.* 代表過濾 開頭為todo: 2016
的所有文字.  \b 是固定需要的.

在下方 filter 的地方輸入一個任意名稱, 再勾選剛才
輸入的pattern , 按 ok 退出

現在按下 todo list 視窗右方的filter圖示/選擇剛才輸
入的名稱, 就可以過濾 todo list的內容.




Read more...

RelativeLayout由右向左橫向排列, 最左邊的 textview 文字靠左的方法

使用 RelativeLayout , 由右向左橫向排列, 但要讓最左邊的
textview 文字可以靠左的方法

就是不要以下樣式:

|                 文字文字文字文字 button1 button2|

而是要這樣:

|文字文字文字文字                  button1 button2|



關鍵是利用一個 FrameLayout 套在 textview的外面即可


           android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

                    android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_toLeftOf="@+id/btnAdd">

                            android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:paddingLeft="5dp"
                android:text="@string/strSupport"
                android:textSize="14sp">

       


       

Read more...

2016年6月18日 星期六

StandardCharsets.UTF_8 API 19 以下的替代用法

StandardCharsets.UTF_8 是API 19 以上的 class
在 api 19 以下要改成 Charset.forName("UTF-8")

API 19 (含)以上
byte[] postData = urlParameters.getBytes(StandardCharsets.UTF_8);

API 19 以下
byte[] postData = urlParameters.getBytes(Charset.forName("UTF-8"));

Read more...

android java 中 Exception Error Throwable的分別

Throwable、Error、Exception、RuntimeException 区别 联系

參考上文

實際的經驗:

我有一個 pipeline thread , 就是把一個接一個的 task 丟到 pipeline
裡去執行, 它是一個 queue , 是 fifo 模式, 為的是避免兩個 thread
同時執行, 會有獲取資源衝突的問題, 但當其中某一個 task 出錯
的時候, 也會造成整個 pipeline thread 死掉, 因而後面的 task 也跟
著停止.

今天在解決一個api 16 (android 4.1)誤用 api 19 的
class (StandardCharsets.UTF_8 )時, 突然發現這個錯誤可以用
Throwable 來捕捉, 但用 exception 卻沒辦法.

使用 exception 會因無法捕捉到錯誤, 使整個 pipeline thread 中止,
而用 throwable 來捕捉, 則pipeline thread可繼續存在, 而不影響後
續 task 的執行.

這個誤用api的錯誤, 可能是 error 級的錯誤, 只用 exception 是無法
捕捉的.
所以以後再遇到無法用 exception 捕捉的錯誤, 可試著用 throwable
來試看看.

try {

something...
} catch (Throwable t) {
   Log.e(TAG, "Error in Pipeline Thread", t);
}



Read more...

try, catch, finally 結構中finally的作用

在 try catch 結構中, 並非所有的 exception 都能捕捉,
所以如果無論有無 catch 到錯誤, 都必須執行的程序,
可以將它放在 finally 裡面, 這樣就不用擔心, 因 catch 沒
有捕獲錯誤, 而漏掉一定要執行的部分.

例如:

try {


 writer.open;    
 something....

} catch (IOException e) {
   e.printStackTrace();
}finally {
          try {
              writer.close();
          } catch (IOException e) {
              e.printStackTrace();
          }
}

將writer.close() 置於 finally 可確保有無錯誤發生, 
也無論有無 catch 到錯誤, 都能保證 writer 能被 close.

Read more...

Android Studio 變更執行時期 breakpoint line 的樣式

執行時, 當停駐在中斷點時, 因背景顏色太深,常
常看不清楚文字, 所以進行更改.


File/Settings/Editor/Color&Fonts/Debugger
先 save as 另存一個樣式名稱

選擇 Execution Point 進行變更

如果不是執行期, 要改變  breakpoint line 的樣式
直接選擇  breakpoint line 進行變更

inlined values for breakpoint line 可以更改執行時
每行用到的變數值的樣式

如果變更之後, 又想更改, 必須先刪整個樣式,
再重新執行上面整個步驟, , 不能直接變更,
不知是不是bug

Read more...

2016年6月14日 星期二

open source 授權模式的理解比較 (BSD, Apache, GPL, LGPL)

五種開源授權規範的比較 (BSD, Apache, GPL, LGPL, MIT)



看了上文, 因為有些文字表達, 像是法律用語, 不是很口語,
不容易理解, 所以整理個人的理解的內容如下:


BSD
應該是最自由的, 就是你可以使用別人的原始代碼來用,
也可以修改, 改完以後還可以當成是自己的產品來賣. 而且也不
必公開自己的原始碼.

但是必須注意三個條件:

1. 如果再發佈的產品中有原始代碼,必須在代碼中, 加上'原來代
碼的BSD協議。
如果再發佈的是二進制函式庫/軟件(library, dll, exe, apk 或jar),
則需要在函式庫/軟件的文件和版權聲明中(例如readme.txt, notice.txt等)
包含原來代碼中的BSD協議。

2. 不可以用原來代碼作者/機構名字和原來產品的名字行銷。

3. BSD 代碼鼓勵代碼共享,但需要尊重代碼作者的著作權。



Apache Licence 2.0

Apache Licence是著名的非盈利開源組織Apache採用的協議, 該
協議和BSD差不多。

注意事項:
發佈的代碼, 程式, library, 必須包含一份Apache Licence
如果修改代碼,要在被修改的文件中說明。也必須要包含原
來代碼中的協議,商標,專利聲明和其他原來作者規定。
如果在發佈的產品中有Notice文件,則在Notice文件中需要帶
有Apache Licence。你可以在Notice中增加自己的許可,但不可
以修改Apache Licence。



GPL(GNU General Public License)

使用GPL協議的代碼, 你所開發的產品, 也必須遵守GPL協議, 
也就是同樣要開放原始碼, 不允許修改後和衍生的代碼做為
閉源的商業軟件發佈和銷售。所以商業軟件或者對代碼有保
密要求, 就不適合採用作為函式庫和二次開發的基礎。

其它細節如再發佈的時候需要伴隨GPL協議等和BSD/Apache
等類似。



LGPL(GNU Lesser General Public License)

LGPL與GPL的不同點, 就是如果只是引用, 呼叫, 調用一個函
式庫(DLL,Library, JAR), 而不修改或使用原始代碼. 那麼LGPL
允許商業軟件使用該函式庫, 這使得採用LGPL協議的開源代
碼可以被商業軟件作為函式庫來引用, 發佈和銷售. 且不用
開放自己的代碼.


以上總之GPL對開放原始碼的要求最嚴格, BSD及Apache 最自由,
 LGPL 剛好在兩者的中間.


以上僅僅是個人的理解, 更精準的條文內容, 還請參考原文.

Read more...

2016年6月8日 星期三

重新打包(repackage) tika jar

我的app用到tika的一個小功能, 但是把整個tika的jar大約佔了40MB
, 原來我的app只有3MB, 但把tika加入以後, 即使使用 proguard 減少體
積, 但居然還是變成了10MB, 而且整個編譯執行又慢又卡.

最後實在是受不了了, 於是想把tika重新打包, 只抽出我所需要的
class就好.

程序如下:

1. 先做出兩個目錄
d:\sourcejar : 存放所有tika.jar的解壓class
d:\objectjar : 將需要的class複製到此

2.將 objectjar 內的 class 打包

3.用 jarjar 把 tika 內, 用到 javax.xml.stream 的部分改名
(為了打包後, 包含poi , 而poi 用到javax.xml.stream  android 不支援)

4. 將第3步驟的 jar 檔, 複製到 android studio 的 project 中的 libs 目錄內

以上第二及第三步驟沒什麼問題, 但第一步驟如何判斷那些 class 是需要
的呢? 我不知道有沒有更好的方法, 但我是使用較笨的方法, 一次一次的
執行, 然後查看錯誤訊息, 看缺那些 class , 就把那些 class 放進來.

其實我一開始的時候, 是編譯 release 版本, 使用 proguard 來看缺少那些
class, 但 proguard 所顯示的 class 實在太多了, 如果照著加進來, 可能也會
佔太多空間.

本來有成功打包成精簡版的 tika , 後來又加入 poi 後, 因為牽扯的 class 太
複雜了, 所以最後還是放棄加入 poi 的想法.


打包用的 dos batch file bat 如下

echo -------------------------------
rem dos batch file %1 path name %2 file name

rem 目的目錄如果己存在的 class 則結束
if exist "d:\objectjar\%1\%2.class" goto A


md "d:\objectjar\%1"

d:
cd \objectjar
del *.jar

copy "d:\sourcejar\%1\%2.class" "d:\objectjar\%1"

rem 打包
"C:\Program Files\Java\jdk1.8.0_91\bin\jar" -cf d:\objectjar\neat-tika-1.12.jar *

rem ** according to rules.txt to mend content of class, then output to libs

rem 依 rules.txt 的內容修正class名稱
java -jar d:\jar\jarjar-1.3.jar process d:\jar\rules.txt D:\objectjar\neat-tika-1.12.jar  D:\Android\StudioProjects\MyApplication\app\libs\neat-tika-1.12.jar

goto done
:A
echo File %2 Exists!
:done



rule.txt內容如下:

rule javax.xml.stream.** aavax.xml.stream.@1

下載:精簡 tika 1.12

未完成poi移植專案

Read more...

2016年6月6日 星期一

對 android studio 的專案更名

Android Studio 不允許對 root 的名稱重新命名


先關閉 Android Studio 
在檔案總管中, 更改專案的目錄名
打開 Android Studio , 
在 File/New/Import Project 中將新改的專案 import 進來



Read more...

java android修改變更jar中的某個class的source

以修改 stax-api-android-1.0-2.jar 這個 jar 檔中的 
aavax.xml.stream.XMLInputFactory 的 source 為例

在 android studio 的 project 中, new 一個新 package, 名為
aavax.xml.stream然後在該package之下, 再 new 一個新 class,
名為 XMLInputFactory

找到 stax-api-android-1.0-2.jar 的 aavax.xml.stream.XMLInputFactory 的source, 
從原來的 source code 中, 複製到你所新建的 XMLInputFactory.java 內, 修改
你想改的部分.


然後建立 release 版的 APK (build/Generate signed apk)

解壓 stax-api-android-1.0-2.jar 

在 project release 的資料夾中找到編譯過的 XMLInputFactory.class
複製到解壓後
\libs\stax-api-android-1.0-2\aavax\xml\stream  的文件夾內

在命令列中重新打包, 並改名為 stax-api-fix-1.0-2.jar

jar -cvf stax-api-fix-1.0-2.jar *

Read more...

對 jar 內的 class 名稱進行更名

為什麼要對 jar 內的 class 名稱進行更名呢? 因為有些 jdk
內的 class , android 並不支持. 例如 javax.xml.stream 開頭
的 class

而這個 javax.xml.stream 卻是 apache poi 會用到的. 所以要
將 poi 移植到 android , 就必須更名.

更名的方法很簡單, 使用 jarjar 這個工具.

指令如下:
java -jar d:\jar\jarjar-1.3.jar process d:\jar\rules.txt D:\objectjar\neat-tika-1.12.jar output\neat-tika-1.12.jar

其中 d:\jar\rules.txt D:\objectjar\neat-tika-1.12.jar 是原來的 jar 檔
output\neat-tika-1.12.jar 是更名後的 jar 檔 (output 目錄必須先建立)

而 d:\jar\rules.txt 是更名的規則, 內容只有一行, 如下:

rule javax.xml.stream.** aavax.xml.stream.@1

就是把 javax.xml.stream 開頭的 class , 更改成
aavax.xml.stream

jarjar download











Read more...

2016年6月5日 星期日

CMD dos 快捷键


Win鍵+R 可顯示執行視窗
tab鍵,補全路徑。
Ctrl+←和「Ctrl+→」, 跳到前一個單詞和後一個單詞。

F1: 功能相當於「→」,對上一條命令逐字顯示。

F2: 按下此鍵後,會在中間反白提示「輸入可複製的字符數量」。
此時直接按下上次輸入命令中包含的字元(區別大小寫)後,將自動輸入到按鍵字元為止。
e.g. 先執行命令:cd "C:/Documents and Settings/Administrator"
然後再輸入F2 A, 便會得到:「cd "C:/Documents and Settings/」

實際使用心得: 使用時必須先按向上鍵, 叫出上一次命令, 記住要按那個字母, 然後再
用 esc 清掉, 再按F2, 再按那個字母, 而且還只能打一個字母, 重覆性太高, 不是很好
用. 

F3: 重複上一條命令

F4: 與F2相對應,按下會提示:提示「輸入可刪除的字符數量」。
刪除當前游標到符合條件的第一個字元的前一字元之間的文字

F5: 相當於"↑", 在歷史記錄中逐條上查「前一條命令」

F6: 相當於CTER+z「 如下「^Z」

F7: 列出所有歷史記錄。 並支持使用每條命令的首字母搜索。

F8: 在命令列下輸入文字,此時按下F8快捷鍵,會在歷史記錄中逐條上查「以剛才輸入那部分字符開始的命令」 所以當什麼都不輸入的時候,他的功能相當於F5,

但是如果你的歷史記錄中有這些記錄:
cd C:/A
dir
cd C:/B
cls
cd C:/C
此時輸入CD,再按F8,便會依次定位到:cd C:/C, cd C:/B和cd C:/A,

F9: 輸入按下F7時,顯示的歷史記錄的編號,可以直接執行該命令。

總結:

F1-F4:

這一組快捷鍵配合」Ctrl+←「以及「Ctrl+→」使用。 可以實現對當前命名的的快速編輯 功能。
所以我現在習慣先用F3,或者F8調出我想要執行的歷史命令。然後對這條命令使用」Ctrl+←「,「Ctrl+→」,F2,F4進行修改

F7,F8,F9:

這三個命令配合,可以最為bash中Ctrl+R的一個簡單替代品。實現對歷史記錄中的命令進行搜索 的功能。

我現在的習慣用法是:
或者,輸入命令的開頭,再按F8定位,
或者,按F7,使用命令首字母定位(或者配合F9)。

ESC:清除當前命令行;
Ctrl+H:刪除游標左邊的一個字符;
Ctrl+C 或者Ctrl+Break,強行中止命令執行;
Ctrl+M:表示 enter 確認鍵;
Alt+F7:清除所有曾經輸入的命令歷史記錄
Alt+PrintScreen:截取屏幕上當前命令窗裡的內容。
Tab鍵:在命令提示符狀態下,我們可以按下Tab鍵來選擇當前目錄下面的文件和文件夾,它的選擇是按照一定順序來進行的,按下Shift+Tab組合鍵還可以進行反方向選擇,非常方便。注意,此時我們所選擇的文件還包括隱藏文件在內
Alt+鼠標雙擊 打開當前文件的屬性
ALT+Enter全屏再按退出


來源 http://www.jianshu.com/p/fa3fde3f9f10

依台灣用語改寫

Read more...

2016年6月4日 星期六

windows 10 如何顯示休眠按鍵

升級到 windows 10 時, 發現關機時的休眠按鍵不見了, 如何顯示
休眠按鍵.

一、用(系統管理員)模式打開「命令提示字元」。
(在「命令提示字元」按右鍵/更多/以系統管理員身分執行)

二、鍵入 powercfg /H on,執行,再鍵入 exit 退出程式。

三、再回到電源設定畫面

到控制台內的電源選項
左方(選擇按下電源按鈕時的行為)
變更目前無法使用的設定
休眠選項打勾
儲存變更
休眠選項就出現了

Read more...

在 DialogFragment 中顯示 ProgressDialog 的時機

class SyncAsset extends AsyncTask
class ReIndexDialog extends DialogFragment 

ReIndexDialog 是一個繼承 DialogFragment 物件
SyncAsset是一個繼承AsyncTask物件, 運用時常會以 progress dialog
來顯示程序處理的進度.

如果運用在 DialogFragment 內, 顯示一個 ProgressDialog
但如果在 onCreateDialog中show出 progressDialog, 則因rotate screen
會使onCreateDialog 再次執行,導致顯示一個空 progressDialog 的錯誤.

所以將prgDialog.show();
移到 SyncAsset的constructor中執行 

protected Dialog onCreateDialog(int id, Bundle args) {
   switch (id) {
   case 0:

//將以下這段移到 SyncAsset的constructor中執行 

      prgDialog = new ProgressDialog(this);
      prgDialog.setMessage("");
      // true 會顯示一個閃爍的進度條
      // prgDialog.setIndeterminate(false);
      // prgDialog.setMax(100);
      prgDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
      prgDialog.setCancelable(false);
      prgDialog.show();
      return prgDialog;
   default:
      return null;   
}

Read more...

2016年6月3日 星期五

設定android studio 提示語法時不區分大小寫

使用android studio 時, 有時候發現提示用法時, 找不到某個函數
後來才發現, 原來它是區分大小寫的.

如何讓提示語法時不區分大小寫:


File/Settings/Editor/General/Code Completion

case sensitive completion 選 none 即可

Read more...

  © Blogger templates Psi by Ourblogtemplates.com 2008

Back to TOP