2016年5月31日 星期二

android studio 無法自動較正錯誤及語法提示


Android Studio 無法自動較正錯誤及語法提示
原因很簡單:

在Android Studio 的 File/Power Save Mode
的勾拿掉即可.

Read more...

HP TX2500 安裝windows 8.1工作記錄

有兩個問題
顯卡不支援opengl
無線網卡, 速率只能跑1M左右

以上兩個問題都是驅動的問題, 其中無線網卡用最新的驅動,
反而有問題, 必須改用較舊的驅動, 但在設備管理員中, 無法讓你
安裝較舊的驅動, 後來改用驅動人生安裝, 才解決問題.
而顯卡驅動雖然較新, 但同樣在驅動人生中才能安裝.

2016/06/14 更新
後來重新安裝,發現驅動人生也無法安裝無線網卡了。
找到資料,要先刪除C:\Windows\System32\DriverStore\FileRepository
netbc63.inf_x86開頭的一個文件夾,才能安裝自訂的驅動。

要安裝以下的檔案:
sp45524.exe

2016/8/12
顯卡部分要安裝 ati driver 64bit
openGL 才能正確執行


Read more...

2016年5月29日 星期日

android 讀取excel xlsx 格式資料--未使用poi

修改以下例子:
https://code.google.com/archive/p/sjxslx/
https://github.com/davidpelfree/sjxlsx

因為我是使用在android上, 而以上兩個範例都是java的例子

執行時會一直出現com.bea.xml.stream.MXParserFactory找不到的錯誤

edu.usf.cutr.javax.xml.stream.FactoryConfigurationError: Provider om.bea.xml.stream.MXParserFactory not found

但這個class事實上存在 stax-1.2.0.jar 中, 無論在gradle中, 使用
compile file 或 provided file 的方法或直接加到 libs 都無法找到
此class, 我甚至把com.bea.xml.stream.MXParserFactory
直接抽出, 重新打包到stax-api-android-1.0-2.jar這個原來就存
在且可使用的 jar 裡也一樣找不到.

找到source code 想要改寫MXParserFactory但發現裡面又牽扯太廣太深,
不好改寫

修改 XMLInputFactory 成 MyXMLInputFactory, find函數,裡面
第二個參數 由com.bea.xml.stream.MXParserFactory 改成
edu.usf.cutr.javax.xml.stream.XMLEventFactory
如下:
MyFactoryFinder.find("edu.usf.cutr.javax.xml.stream.XMLInputFactory", "edu.usf.cutr.javax.xml.stream.XMLEventFactory");

錯誤訊息變成:
 Provider edu.usf.cutr.javax.xml.stream.XMLEventFactory could not be instantiated:
可見已經找到了, 只是無法instantiated
可見只有com.bea.xml.stream 開頭的class找不到, 不知是否一樣要改成
edu.usf.cutr才可以
(見 http://save-coco.blogspot.tw/2016/05/javaxxmlstreamandroidlibraries.html)

                                                           
另外在FactoryFinder中有使用到"META-INF/services/", 可能因為
android 不會把 META-INF 內的文件安裝到apk, 也會出問題

(update:確定不是此原因)


所以總之放棄此作法

https://pan.baidu.com/s/1o7HoY3w

update:20160605

經過幾天的努力, 終於可以成功讀取了.
provider com.bea.xml.stream.MXParserFactory 找不到的問題終於解決了


參考 http://stackoverflow.com/questions/30968735/using-com-bea-xml-stream-package-on-android

原文
I believe the main issue here is that Apache POI depends on JSR173
Streaming API for XML, which depends on the platform (in our case Android)
being able to provide an implementation and underlying XML parsing provider. Android doesn't support JSR173, so it can't find a provider - com.bea.xml.stream.EventFactory is the default provider, and it can't even find that one (see JAXB marshalling exception javax.xml.stream.FactoryConfigurationError running with Java 5 for more details on this topic).
Aalto is an open-source JSR173 provider, so you should be able to use this in place of the BEA implementation (com.bea.xml.stream.EventFactory). The Aalto archive (JAR file) includes the necessary registration (under META-INF/services/javax.xml.stream.XMLInputFactory file, that points to the Aalto class com.fasterxml.aalto.stax.InputFactoryImpl) that should allow a Java platform to recognize it as a JSR173 implementation. As a result, you should no longer get the edu.usf.cutr.javax.xml.stream.FactoryConfigurationError: Provider com.bea.xml.stream.EventFactory not found error, because Android should recognize that Aalto is an available provider, and use Aalto instead.

大意是說:Apache POI  必須依賴JSR173 Streaming API for XML 作為
 provider , 但 android 不支援 JSR173 , 所以才會出現找不到作為 provider的 com.bea.xml.stream.EventFactory .而必須改用Aalto , 而且
android 支援 Aalto .

所以在android想要讀取xlsx資料, 必須更改使用的provider, 將
stax-api中stax-api-1.0-2.jar 換成Aalto 的 aalto-xml-android-0.9.8.jar

Aalto有幾個不同的 class
com.fasterxml.aalto.stax.EventFactoryImpl
com.fasterxml.aalto.stax.InputFactoryImpl
com.fasterxml.aalto.stax.OutputFactoryImpl
必須查看原程式碼傳回那一個物件來決定採用那個 provider

所以要在android 讀 excel 的重點就是
1.必須修改原始碼, 更改 provider
2.還有必須將 javax.xml.stream 更名



修改原始碼, 更改 provider 舉例如下:
修改 aavax.xml.stream.XMLEventFactory 的原始碼
(aavax是javax更名而來的,見:將 javax.xml.stream 更名)
(找 stax-api-fix-1.0-2.jar 的source來改)

把原來的 com.bea.xml.stream.EventFactory 改成
com.fasterxml.aalto.stax.EventFactoryImpl

(不是 com.fasterxml.aalto.stax.InputFactoryImpl, 因為原程式碼必須傳

回 XMLEventFactory 而不是 XMLInputFactory , 使用 XMLInputFactory 會出

現型別轉換錯誤)


//注意1: XMLEventFactory 配合 EventFactoryImpl

public static XMLEventFactory newInstance() throws FactoryConfigurationError {
//原來的 source
//  return (XMLEventFactory)FactoryFinder.find

//("aavax.xml.stream.XMLEventFactory", "com.bea.xml.stream.EventFactory");

//改成這樣
    return (XMLEventFactory)FactoryFinder.find
("aavax.xml.stream.XMLEventFactory", "com.fasterxml.aalto.stax.EventFactoryImpl");
}

再將source 重新compile , 重新打包


修改 class 重新打包, 請參考:
http://save-coco.blogspot.tw/2016/06/java-android-jar-class.html

將 javax.xml.stream 更名 請參考
http://save-coco.blogspot.tw/2016/06/jar-class.html

完成的專案


Read more...

如何將 java class 打包成 jar


要打包的資料夾(D:\stax-api-android-1.0-2)內有如下的子資
料夾, 內含有*.class的檔案

2016/05/28  上午 11:09  

         com                
2016/05/28  上午 11:09  
         edu                
2006/08/01  下午 03:46  
         META-INF           

在C切換到含有 jar.exe 的目錄內
C:\Program Files\Java\jdk1.8.0_91\bin>

在D切換到要打包的資料夾內, 下達如下指令
D:\stax-api-android-1.0-2>c:jar -cvf ttt.jar *

那麼就會產生 ttt.jar 的檔案


Read more...

修改javax.xml.stream.*成android可用的libraries

Modifying XML libraries for Android


javax.xml.stream.* 這個java libraries在android是不被支援的, 以上
連結提到如何修改成android 可支援的library
先下載此檔

解壓縮, 在解壓縮目錄下, 建立output資料夾

執行 generate_android_jars.bat , 在output內的libraries即可用來供
android  使用.

使用時要將javax.xml.stream.* 改成 edu.usf.cutr.javax.xml.stream.*:

另外以下還提到, 使用repackage javax.*的方法, 或使用android支援的
XmlSerializer

XMLStreamWriter is in the javax.xml.stream.* package. This package is not included in the default Android build. You can use it, but you have to repackage it in your app.
Description of your problem and a guide on how to repackage javax.* packages:http://code.google.com/p/dalvik/wiki/JavaxPackagesIf you don't want to repackage XMLStreamWriter in your app, try using XmlSerializer which is included in Android. Excellent example right here on SO: Writing XML on Android

Read more...

2016年5月25日 星期三

Apache Commons IO 常用函數


ArrayUtils

int n = ArrayUtils.indexOf(displayItem, "abc");
傳回String[] displayItem中含有字串"abc"的位置

if ( ArrayUtils.contains( displayItem, "abc" ) ) {
    // Do some stuff.
}
String[] displayItem中含有字串"abc"則傳回真值

FileUtils
FileUtils.cleanDirectory("/abc"); 清除整個資料夾及子資料夾, 但不含資料夾abc本身 FileUtils.deleteDirectory("/abc"); 清除整個資料夾及子資料夾, 含資料夾abc本身


File f = new File("/sd/abc.txt");
String str = FileUtils.readFileToString(f, code);
將文字檔案f整個讀入一個字串內, code是該檔案的編碼格式(utf-8,big5...)

FileUtils.writeStringToFile(f, fileContent, "big5"); 
將字串fileContent寫出到f


File file = new File("c:/test.txt");  
List lines = FileUtils.readLines(file, "UTF-8");  
將test.txt一行一行讀入List內


File src = new File("src.txt");  
File dest = new File("dest.txt");  
FileUtils.copyFile(src, dest);  
複製檔案並重命名
File srcfile = new File("c:\\Test.java"); File destDir = new File("D:\\"); FileUtils.copyFileToDirectory(srcfile, destDir);
複製檔案到目錄下
InputStream in = new URL("http://www.baidu.com/img/baidu_logo.gif").openStream(); byte [] gif = IOUtils.toByteArray(in); //IOUtils.write(gif,new FileOutputStream(new File("c:/test.gif"))); FileUtils.writeByteArrayToFile(new File("c:/test.gif"),gif); IOUtils.closeQuietly(in);
下载文件到本地
URL url = new URL("http://www.163.com"); File file = new File("c:\\163.html"); FileUtils.copyURLToFile(url, file);
網頁保存成本地文件

FilenameUtils
String ext = FilenameUtils.getExtension(file.toString()); 取得副檔名 String baseName = FilenameUtils.getBaseName(f.toString()); 取得主檔名(不含副檔名及小數點)


IOUtils

將inputStream轉成字串
InputStream in = new URL( "http://laoyu.info" ).openStream();  
 try {  
   System.out.println( IOUtils.toString( in ) );  
 } finally {  
   IOUtils.closeQuietly(in);  
 }  

Read more...

用熱風槍修復筆電獨立顯卡故障

筆電獨立顯卡是筆電最容易故障的一個地方, 很多可以過電, 但沒畫面,
的筆電, 有很大的比例是顯卡故障, 而原因有可能是焊鍚因長時間高溫,
造成接觸不良.

通常的維修方法是用重新植鍚球的方式, 但這樣做技術層次比較高, 而且
需要一些專業的設備.

於是有些人就想到一個方法, 就是用熱風槍直接對顯卡晶片加熱, 直到焊鍚
可以熔化的溫度, 於是就可以修好這個顯卡, 但事實上這個做法, 只是治標
不治本, 過個幾天, 也許一星期, 可能又會因為高溫或熱脹冷縮的原因而再
次故障.

我有兩台筆電, 都是因為這個原因故障, 在網路上買一個便宜的工業用的熱風
槍, 只花了八百元左右, 而且還可控制溫度, 並顯示溫度. 看來頗物超所值.
上網尋找一些文章, 大概知道作法.

首先拆下筆電, 取出主機板, 準備一張鍚鉑紙, 中間剪出一個正方形的洞,
用鍚鉑紙蓋住主機板的其他部分, 只露出顯卡晶片.

因為必須控制溫度, 熱風槍顯示的溫度, 和顯卡晶片實際受熱的溫度, 一定
有差距, 因此我拿一個廚房用的溫度計, 最大溫度可顯示250度, 這個是在一
般五金雜貨店買的. 先用熱風槍對著溫度計吹, 得知熱風槍顯示380度時,
貼近溫度計, 大約是220度, 而熱風槍顯示480度時, 貼近溫度計, 大約是
270度. (估計值, 因為溫度計最多只顯示到250度)

根據查來的資料, 先用熱風槍對著顯示晶片吹(注意這是一打開熱風槍就開
始吹, 不是等熱風槍達到380度時才吹), 一直到溫度到達380度為止, 然後
控制溫度保持在380度左右(晶片實際受熱溫度220度), 從開始吹的時間到大約
二到三分鐘為止(我大約吹了二分半鐘), 然後調高溫度, 讓熱風槍跑到480
度(實際受熱溫度270度), 大約再吹一分鐘, 所以一共吹了三分半鐘, 然後
移開熱風槍, 慢慢等待冷卻.

這樣的方法, 兩台筆電均成功修復, 目前其中一台已運作二星期. 另一台還沒
使用.




Read more...

android 重新啟動Activity的方法

有兩個方法
1. recreate()
不是完全重新啟動, 再次啟動時, 會保留上一次啟動的SaveInstanceState

2.

Intent intent = getIntent();
finish();
startActivity(intent);
用這種方法, 不會保留SaveInstanceState

Read more...

2016年5月24日 星期二

onPostCreate 說明

個人感覺的使用時機:
1.當Activity徹底運行起來之後回調onPostCreate方法,如果是比較需要時
間的作業, 例如開啟app後,立即copy一些檔案到某處, 這個copy的動作, 
好像寫在onPostCreate比較好, 如果寫在onCreate, 有時似乎不執行(個人印象
, 不知是否正確).  

2.在onCreate 建立一個 Thread :
indexThread = new IndexThread();
indexThread.start();

當indexThread啟動以後, indexThread.handler會在一段時間才能建立, 在之
前會是null, 如果是null, 則對indexThread的所有操作都會失敗, 所以我加了
一個空迴圈判斷, 當indexThread.handler不是null的時候才往下執行.

while (indexThread.handler == null) {
}


但這樣的結果, 在某些情況下(android 6 release的版本)這個空迴圈會跑不出來. 
所以後來我取消空迴圈的作法, 把對indexThread的所有操作, 都放到onPostCreate, 
目前為止似乎一切都正常.

3.另外如果要用到 savedInstanceState, 除了onCreate之外, 也只
onPostCreate有提供savedInstanceState這個參數, onStart沒有.



從官方解釋可以看出 "Called when activity start-up is complete (after on
Start() and onRestoreInstanceState(Bundle) have been called)."

一個正常的Activity生命週期如下: onPause onStop onDestory onCreate onStart onPostCreate onResume onPostResume

Read more...

genymotion android 6.0 /data/data中的權限無法讀取更改

因為必須在/data/data內刪除設定檔的目錄, 以前都是直接在genymotion內的模擬
器, 直接刪除, 但換到6.0以後, 不知為何這個目錄無權讀取, 想到一個變通的方法

直接在virtualbox中開啟虛擬機

用adb連到虛擬機

adb connect 192.168.56.101

直接到shell操作
adb shell

給序全部權限
chmod 777 /data/data

查看是否成功更改
ls /data/data/ -ld

更改成功, 但回到genymotion中開啟虛擬機, 結果權限又被改回無法讀取的狀態

再想一個方法, 這次不改權限, 改直接在adb shell內刪除/data/data/內的檔案
刪除完成, 而且在genymotion內的模擬器內, 該檔案也消失不見了.


後來又發現一個比較好的方法

在android studio 或 eclipse 中的 Android device monitor 中的file explore
可以用 把/data/data內的檔案下載到pc端檢視, 也可以刪除, 但有時會失敗, 如果失敗
的時候, 在Tool/Android/Enable ADB Integration 把打勾的地方拿掉, 就可正常下載.



update 20160619
原來用 adb 一直無法連到genymotion的模擬器, 會出現
ADB server didn't ACK
* failed to start daemon *
的錯誤.

後來發現使用 genymotion 目錄下的 adb 就可連上
C:\Program Files\Genymobile\Genymotion\tools>adb devices
會出現一個 ip 
C:\Program Files\Genymobile\Genymotion\tools>adb connect ip

update 20161011

讀取未root手機, data/data內資料夾的兩個方法
http://stackoverflow.com/questions/13006315/how-to-access-data-data-folder-in-android-device

If the application is debuggable you can use the run-as command in adb shell
adb shell
run-as com.your.packagename 
cp /data/data/com.your.packagename/
Alternatively you can use Android's backup function.

adb backup -noapk com.your.packagename
You will now be prompted to 'unlock your device and confirm the backup operation'. It's best NOT to provide a password, otherwise it becomes more difficult to read the data. Just click on 'backup my data'. The resulting 'backup.ab' file on your computer contains all application data in android backup format. Basically it's a compressed tar file. This page explains how you can use OpenSSL's zlib command to uncompress it. You can use the  adb restore backup.db command to restore the backup.




Read more...

genymotion無法啟動的可能原因

顯示卡的問題, 必須支援openGL 2.0以上, 而顯卡不支援openGL有可能是驅動程式未更新, 或驅動有問題.

另一個原因是virtualbox版本的問題, 試著更新到最新版或還原到較舊的版本, 都有可能可以解決問題

如果想查看錯誤的更多細節, 查看:
C:\Users\使用者名稱\AppData\Local\Genymobile\genymotion.log

Read more...

android 6.0 新權限管理方式對sdcard讀取的設計方法

    android 6.0 採對個別app的權限管理方式, 如果使用者未開放權限, 則app訪問sdcard的功能將出問題

            所以如果使用者未開放權限的話, 可在app中要求使用者開放

    在activity中的oncreate寫如下程式碼:
    boolean hasPermission = (ContextCompat.checkSelfPermission(this,
            Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED);
    if (!hasPermission) {
        ActivityCompat.requestPermissions(this,
                new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                REQUEST_WRITE_STORAGE);
    }
    上面的程式碼, 會引發以下事件
    @Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode)
        {
            case REQUEST_WRITE_STORAGE: {
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
                {

//如果同意, 則重啟acitvity, 正常執行
                    recreate();
                } else {

//如果不同意, 則再次請求, 若使用者同意考慮, 則再重啟activity, 會再訽問一次
                    TextApp.YesNoListener ynListener=new TextApp.YesNoListener() {
                        @Override
                        public void onYes() {
                            recreate();
                        }
                        //若不同意再考慮, 則退出程序
                        @Override
                        public void onNo() {
                            finish();
                        }
                    };

                    TextApp.showOkCancelDialog("The app was not allowed to write to your storage. Hence, it cannot function properly. Do you want to consider granting it this permission again?",this,ynListener);

                }

            }
        }
    }



    TextApp中顯示訽問視窗的函數


    public static void showOkCancelDialog(String msg, Context _ac,
                                          YesNoListener _yesnoListener) {

        final YesNoListener yesnoListener = _yesnoListener;

        AlertDialog.Builder ssa = new AlertDialog.Builder(_ac);
        ssa.setMessage(msg);
        ssa.setIcon(R.drawable.ic_noti_dict);
        ssa.setPositiveButton(
                getContext().getResources().getString(R.string.strOk),
                new DialogInterface.OnClickListener() {

                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        yesnoListener.onYes();
                    }
                }).setNegativeButton(
                getContext().getResources().getString(R.string.strCancel),
                new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        System.out.println("cancel");
                        yesnoListener.onNo();
                        // AnswerIsOK = false;                }
                    });

                    AlertDialog alert = ssa.create();
                    alert.show();
                }
   

Read more...

記憶體不足造成 java.exe finished with n on-zero exit value 1

個人感覺出現這個問題, 大部分是ram的原因

在dos命令列, project的根目錄
下gradlew assembleDebug --info命令
可以見到更多原因


All input files are considered out-of-date for increm
ental task ':app:transformClassesWithDexForDebug'.
Allocated dexExecutorService of size 4            
To run dex in process, the Gradle daemon needs a larg
er heap.
It currently has approximately 989 MB.
For faster builds, increase the maximum heap size for
 the Gradle daemon to more than 3072 MB.
To do this set org.gradle.jvmargs=-Xmx3072M in the pr
oject gradle.properties.
For more information see https://docs.gradle.org/curr
ent/userguide/build_environment.html
Dexing out-of-process.                            
Starting process 'command 'C:\Program Files\Java\jdk1
.8.0_91\bin\java.exe''. Working directory: D:\Android
\Studio\docSearcher\app Command: C:\Program Files\Jav
a\jdk1.8.0_91\bin\java.exe -Djava.awt.headless=true -
Xmx2g -Dfile.encoding=UTF-8 -Duser.country=TW -Duser.
language=zh -Duser.variant -cp C:\Users\mayr\Android\
sdk\build-tools\23.0.3\lib\dx.jar com.android.dx.comm
and.Main --dex --verbose --num-threads=4 --multi-dex
--main-dex-list D:\Android\Studio\docSearcher\app\bui
ld\intermediates\multi-dex\debug\maindexlist.txt --ou
tput D:\Android\Studio\docSearcher\app\build\intermed
iates\transforms\dex\debug\folders\1000\1f\main D:\An
droid\Studio\docSearcher\app\build\intermediates\tran
sforms\jarMerging\debug\jars\1\1f\combined.jar

Successfully started process 'command 'C:\Program Fil
es\Java\jdk1.8.0_91\bin\java.exe''
Error occurred during initialization of VM        
Could not reserve enough space for 2097152KB object h
eap
:app:transformClassesWithDexForDebug FAILED      
:app:transformClassesWithDexForDebug (Thread[Daemon w
orker,5,main]) completed. Took 0.218 secs.
           
FAILURE: Build failed with an exception.
           
* What went wrong:
Execution failed for task ':app:transformClassesWithD
exForDebug'.
> com.android.build.api.transform.TransformException:
 com.android.ide.common.process.ProcessException: jav
a.util.concurrent.ExecutionException: com.android.ide
.common.process.ProcessException: org.gradle.process.
internal.ExecException: Process 'command 'C:\Program
Files\Java\jdk1.8.0_91\bin\java.exe'' finished with n
on-zero exit value 1
           
* Try:      
Run with --stacktrace option to get the stack trace.
Run with                                            -
-debug      
option to get more log output.
           
BUILD FAILED
           


上面紅字部分就是原因所在
我在build.gradle為dex保留2G的heapsize:

dexOptions {
    javaMaxHeapSize "2g"}

結果ram 不夠, 所以造成
java.exe finished with n on-zero exit value 1的錯誤

不過奇怪的是, 我用windows 8.1 64bit 卻不會造成此一問題, 觀察工作管理員ram變化的情形
, 發現java.exe 會跑到高達2G左右, 但別的應用ram卻一直減少, 甚至android studio 也只佔幾十mb而已, 所以別的應用程序, 全部都卡死不動, 只有android studio 的compile 在跑而已.(我一共只有4G ram), 但compile的過程非常久, 可能與ram不足有關.

而windows 8.1 32bit 卻直接報告上面的錯誤, 中止compile程序.

本來已為用32bit的系統, 比較省資源, 但直接就退出來, 所以恐怕得重新評估了.

Read more...

2016年5月22日 星期日

windows 8.1 32bit 記憶體使用超過4G的方法





Windows 8.1 32bit 記憶體完全攻破!RAM 裝多少用多少不浪費



Read more...

gradle wrapper 是什麼?

參考了一些資料:

android studio希望你能在電腦上不安裝gradle的情況下,依然使用gradle管理android項目,因此通過AS創建的每個項目都會內嵌一個gradle wrapper,作用是檢查你當前的共工作環境是否安裝了創建本項目時所用的gradle版本。
如果沒有,它會自動下載相應的gradle放在~/.gradle/wrapper.目錄下。這樣當你在你的項目裡使用gradle時,可以通過gradlw命令使用當前項目環境的gradle版本,而不受環境變量的影響。

文/有魚飛過海(簡書作者)
原文鏈接:http://www.jianshu.com/p/01320be02ad5
著作權歸作者所有,轉載請聯繫作者獲得授權,並標註“簡書作者”。



gradle wrapper的命令

上面大家接触了一些命令如 ./gradlew -v ./gradlew clean ./gradlew build, 这里注意是./gradlew, ./代表当前目录,gradlew代表 gradle wrapper,意思是gradle的一层包装,大家可以理解为在这个项目本地就封装了gradle,即gradle wrapper, 在9GAG/gradle/wrapper/gralde-wrapper.properties文件中声明了它指向的目录和版本。只要下载成功即可用grdlew wrapper的命令代替全局的gradle命令。

理解了gradle wrapper的概念,下面一些常用命令也就容易理解了。

./gradlew -v 版本号

./gradlew clean 清除9GAG/app目录下的build文件夹

./gradlew build 检查依赖并编译打包

这里注意的是 ./gradlew build 命令把debug、release环境的包都打出来,如果正式发布只需要打Release的包,该怎么办呢,下面介绍一个很有用的命令 **assemble**, 如

./gradlew assembleDebug 编译并打Debug包

./gradlew assembleRelease 编译并打Release的包

來源:

Read more...

2016年5月20日 星期五

apache poi 移植到 android 的問題

本來想移植apache poi 到 android, 但遇到很多困難, 所以放棄,
但記錄如下:(update :經過努力, 終於找到了方向, 見下說明)

apache poi 移植到 android 的問題

however it will not work straighforwardly because xmlbeans jar in
 maven is defective and contains duplicates of classes, [...] it is 
easier just to prepare jars once and put them into libs directory 
(as described above)

大意是說xmlbeans 包含重覆的class, 在android 是不允許的

以下這兩個連結有實作, 但大概試了一下, 不是很順利, 所以放
棄, 最大的問題是noclassdeffounderror無所不在, 還有jar重覆的
問題, 用到android不支持的jdk等


Reading XLSX on Android 4


不同msoffice格式所用的的poi jar

POIFSOLE2 Filesystempoi
HPSFOLE2 Property Setspoi
HSSFExcel XLSpoi
HSLFPowerPoint PPTpoi-scratchpad
HWPFWord DOCpoi-scratchpad
HDGFVisio VSDpoi-scratchpad
HPBFPublisher PUBpoi-scratchpad
HSMFOutlook MSGpoi-scratchpad
XSSFExcel XLSXpoi-ooxml
XSLFPowerPoint PPTXpoi-ooxml
XWPFWord DOCXpoi-ooxml
OpenXML4JOOXMLpoi-ooxml-schemas, ooxml-schemas


2016/05/31 更新

上次提到連結:


因為上次花了太多時間, 在別的方面, 所以沒仔細看, 後來得空, 再次檢視, 終於成功的找
到在 android 使用poi 的方法.
這個必須分兩方面說明:
1. 在 android 4.4(含) 以前比較麻煩
範例下載點, 下載完後, example 資料夾內就是android studio 的project
2. 在 android 5(含) 以後比較簡單
範例下載點, 下載完後, example 資料夾內就是android studio 的project
雖然第二種方法比較簡單, 但為了相容於 android 4.4 以前的版本, 所以決定採第一種
方法. (其實因為原作者, 己經把範例都做好了, 所以只要下載範例照著做就好了)
但是以上的範例有一個問題, 就是如果照著範例提供的 excel 檔(格式比較簡單),
可以正確讀取, 但我自己下載的 excel 檔, 卻出了問題, 

經過努力, 終於找到了方向
請參考以下:
http://save-coco.blogspot.tw/2016/05/android-excel-xlsx-poi.html
1. provider 的問題
2. javax.xml.stream , android不支援的問題

Read more...

build.gradle 中 dependencies 的命令用法(排除某些module不編譯)

dependencies {
 compile fileTree(include: ['*.jar'], dir: 'libs')
 testCompile 'junit:junit:4.12'
compile project(':library')
compile files('libs/dropbox-android-sdk-1.6.3.jar')
compile files('libs/json_simple-1.1.jar')
compile files('libs/ksoap2-android-assembly-2.4-jar-with-dependencies.jar')
compile project(':lucene-analyzers-common-4.7.2')
compile project(':lucene-core-4.7.2')


compile fileTree(include: ['*.jar'], dir: 'libs')
 compile 'com.android.support:appcompat-v7:23.2.1'
 compile 'com.android.support:multidex:1.0.1'
 compile('org.apache.tika:tika-parsers:1.13') {
 exclude module: 'poi-ooxml' exclude module: 'poi' }
 }


compile project(':library')

編譯另一個專案, library為另一個專案的根目錄名稱



compile files('libs/dropbox-android-sdk-1.6.3.jar')

編譯一個jar檔案



compile fileTree(include: ['*.jar'], dir: 'libs')

編譯一整個 libs 目錄中所有 *.jar 檔



 compile('org.apache.tika:tika-parsers:1.13') {
 exclude module: 'poi-ooxml' exclude module: 'poi' }

其中tika-parsers:1.13這個jar, 要排除兩個module不編譯
 可能module如下: poi-ooxml-3.11-beta2.jar
poi-3.11.jar
(只寫出module名, 所有的版本均排除3.11, 4.1, ....)

'org.apache.tika:tika-parsers:1.13'表示這個jar是maven倉
庫的jar, 並非本地的jar
 compile('org.apache.tika:tika-parsers:1.13')
{ exclude module: 'poi-ooxml' exclude module: 'poi'


Read more...

dexDebug ExecException finished with non-zero exit value 2

這個問題, 好像大都是超過65536個函數所引起, 所以只要想辦法減少函數數目或在build.gradle中宣告
multiDexEnabled true 即可解決

android {
    compileSdkVersion 23    buildToolsVersion "23.0.2"
    defaultConfig {
        applicationId "com.myapplication"        minSdkVersion 16        targetSdkVersion 23        versionCode 1        versionName "1.0"        multiDexEnabled true    }
....

Read more...

Finished with Non Zero Exit Value 3

 
You most likely have a duplicate dependency in one of your compile project
極可能是兩個以上的library重覆使用在一個project內


在gradle中將
"compile fileTree(dir: 'libs', include: ['*.jar'])"

改成

"provided fileTree(dir: 'libs', include: ['*.jar'])".

可以解決問題

Read more...

使用jdk中android不支持的api,造成 java.exe finished with non-zero exit value 1

發生Android java.exe finished with non-zero exit value 1的問題, 很多人提到很有可能是ram的問題, 或是clean project, rebuild project, 或是重開系統, 可解決, 但我在處理 poi 轉到 android 時發生此一問題, 並且有一大串訊息如下:


在dos視窗project的根目錄下 執行 gradlew assembleDebug --info
可見以下訊息:


java.exe
Ill-advised or mistaken usage of a core class (java.* or javax.*)
when not building a core library.

This is often due to inadvertently including a core library file
in your application's project, when using an IDE (such as
Eclipse). If you are sure you're not intentionally defining a
core class, then this is the most likely explanation of what's
going on.

However, you might actually be trying to define a class in a core
namespace, the source of which you may have taken, for example,
from a non-Android virtual machine project. This will most
assuredly not work. At a minimum, it jeopardizes the
compatibility of your app with future versions of the platform.
It is also often of questionable legality.

If you really intend to build a core library -- which is only
appropriate as part of creating a full virtual machine
distribution, as opposed to compiling an application -- then use
the "--core-library" option to suppress this error message.

If you go ahead and use "--core-library" but are in fact
building an application, then be forewarned that your application
will still fail to build or run, at some point. Please be
prepared for angry customers who find, for example, that your
application ceases to function once they upgrade their operating
system. You will be to blame for this problem.

If you are legitimately using some code that happens to be in a
core package, then the easiest safe alternative you have is to
repackage that code. That is, move the classes in question into
your own package namespace. This means that they will never be in
conflict with core system classes. JarJar is a tool that may help
you in this endeavor. If you find that you cannot do this, then
that is an indication that the path you are on will ultimately
lead to pain, suffering, grief, and lamentation.



查找了一下原因, 原文如下:
Dalvik JVM does not support the entire API of Oracle JDK. I think javax.* packages aren't available to Android. For example there's no AWT or Swing or Graphics2D of Java on Android.

From the error, it looks like you app is using this Class:http://docs.oracle.com/javase/7/docs/api/javax/xml/namespace/QName.html

This shouldn't happen If you set up your IDE to use Android SDK instead of JDK.

大意是因為Android並不支持全部JDK的api, 例如 AWT, Swing, 還有部分javax開頭的api 等, 所以以上的訊息就是因為poi用到了這些不支持android的api,

加上"--core-library"的參數, 可避免出現以上訊息


Read more...

NoClassDefFoundError有時不是class找不到,而是其他問題

java.lang.NoClassDefFoundError, 一般只認為是因為某個class找不到, 但其實很多時候class是存在的, 而是在初始這個類的時候出現錯誤, 特別是static區塊出錯的時候, 這就必須深入這個類去除錯, 才能解決問題.

另外ClassLoader載入class出錯, 也會報java.lang.NoClassDefFoundError的錯誤


(The ClassLoader ran into an error while reading the class definition when trying to read the class. Put a try/catch inside your static initializer and look at the exception. )
使用try catch找出錯誤
static {
  try {

    ... your init code here

  } catch (Throwable t) {
    LOG.error("Failure during static initialization", t);
    throw t;
  }
}


而 ClassNotFoundException 比較可能是單純的class找不到的情況


以下這一篇個人認為講的還不錯

關於NoClassDefFoundError和ClassNotFoundException異常


2016/05/31 update

出現 NoClassDefFoundError : org.apache.tika.parse.xml.DcXMLParser

org.apache.tika.parse.xml.DcXMLParser明明是存在的, 所以深入追踪原始碼:


EpubParser epubParser = null;
if (type.equals("epub")) {

//NoClassDefFoundError出現在下面這一行
    epubParser = new EpubParser();
    epubParser.parse(inputstream, handler, metadata, pcontext);
}



找到 EpubParser 的原始碼:
public class EpubParser extends AbstractParser {
    private static final long serialVersionUID = 215176772484050550L;
    private static final Set SUPPORTED_TYPES 
= Collections.unmodifiableSet(new HashSet(Arrays.asList
(new MediaType[]{MediaType.application("epub+zip"), 
MediaType.application("x-ibooks+zip")})));

//DcXMLParser 找不到
    private Parser meta = new DcXMLParser();
    private Parser content = new EpubContentParser();

    public EpubParser() {
    }

    public Parser getMetaParser() {
        return this.meta;
    }

    public void setMetaParser(Parser meta) {
        this.meta = meta;
    }

    public Parser getContentParser() {
        return this.content;
    }

    public void setContentParser(Parser content) {
        this.content = content;
    }

    public Set getSupportedTypes(ParseContext context) {
// 在這一行出錯, 但這是最後一行返回值, 可見不是這一行的原因, 而是上
//方定義 private Parser meta = new DcXMLParser();時出錯
        return SUPPORTED_TYPES;
    }



找出 DcXMLParser 的原始碼:
原來是下面有幾個import的元件未加入library中, 
將未加入的部分加入就解決了

import org.apache.tika.metadata.Metadata;
import org.apache.tika.metadata.Property;
import org.apache.tika.metadata.TikaCoreProperties;
import org.apache.tika.parser.ParseContext;
import org.apache.tika.parser.xml.ElementMetadataHandler;
import org.apache.tika.parser.xml.XMLParser;
import org.apache.tika.sax.TeeContentHandler;
import org.xml.sax.ContentHandler;

public class DcXMLParser extends XMLParser {
    private static final long serialVersionUID = 4905318835463880819L;

    public DcXMLParser() {
    }

    private static ContentHandler getDublinCoreHandler(Metadata metadata, Property property, String element) {
        return new ElementMetadataHandler("http://purl.org/dc/elements/1.1/", element, metadata, property);
    }

    protected ContentHandler getContentHandler(ContentHandler handler, Metadata metadata, ParseContext context) {
        return new TeeContentHandler(new ContentHandler[]{super.getContentHandler(handler, metadata, context), getDublinCoreHandler(metadata, TikaCoreProperties.TITLE, "title"), getDublinCoreHandler(metadata, TikaCoreProperties.KEYWORDS, "subject"), getDublinCoreHandler(metadata, TikaCoreProperties.CREATOR, "creator"), getDublinCoreHandler(metadata, TikaCoreProperties.DESCRIPTION, "description"), getDublinCoreHandler(metadata, TikaCoreProperties.PUBLISHER, "publisher"), getDublinCoreHandler(metadata, TikaCoreProperties.CONTRIBUTOR, "contributor"), getDublinCoreHandler(metadata, TikaCoreProperties.CREATED, "date"), getDublinCoreHandler(metadata, TikaCoreProperties.TYPE, "type"), getDublinCoreHandler(metadata, TikaCoreProperties.FORMAT, "format"), getDublinCoreHandler(metadata, TikaCoreProperties.IDENTIFIER, "identifier"), getDublinCoreHandler(metadata, TikaCoreProperties.LANGUAGE, "language"), getDublinCoreHandler(metadata, TikaCoreProperties.RIGHTS, "rights")});
    }
}
2016/06/01 update
令天又遇到一個 NoClassDefFoundError 的問題
基本上與昨天遇到的問題差不多, 同樣是 import 的地方沒把 class 加進來而出問題. 
但今天的問題, 即使把 import 的地方的 class 加進來, 一樣報錯. 

NoClassDefFoundError錯誤的是這個 org.apache.tika.io.TikaInputStream class
追踪TikaInputStream 的原始碼:


package org.apache.tika.io;

//以下三個 import 的class 都加入了, 仍然報錯
import org.apache.tika.io.TaggedInputStream;
import org.apache.tika.io.TemporaryResources;
import org.apache.tika.metadata.Metadata;

//原來問題出在 TaggedInputStream , 因為 TikaInputStream 是繼承 TaggedInputStream
//所以要把 TaggedInputStream 的原始碼也挖出來看
 
public class TikaInputStream extends TaggedInputStream {
    private static final int BLOB_SIZE_THRESHOLD = 1048576;
    private Path path;
    private final TemporaryResources tmp;
    private long length;
    private long position = 0L;

//TikaInputStream 以下原始碼省略...

}


TaggedInputStream 的原始碼:

//把以下兩個 class 加入(ProxyInputStream及TaggedIOException), 就解決了, 
//所以不止看出問題的 class, 如果它繼承自別的 class , 連父類的 class 
//也要查看是否有import 的 class 未加入.
import org.apache.tika.io.ProxyInputStream;
import org.apache.tika.io.TaggedIOException;

public class TaggedInputStream extends ProxyInputStream {
    private final Serializable tag = UUID.randomUUID();

    public TaggedInputStream(InputStream proxy) {
        super(proxy);
    }


還有一種情況:所有的 import 都己加入 library 中, 但在程碼中, 卻直接引用
class 如下面的 org.apache.xmlbeans.SchemaComponent.Ref 也要加進來


public void setContainerFieldRef(org.apache.xmlbeans.SchemaComponent.Ref ref) {
    this.assertUnresolved();
    this._containerFieldRef = ref;
    this._containerFieldCode = 0;
}

Read more...

2016年5月19日 星期四

查找java某個class在那個jar裡面

http://www.findjar.com/

輸入 class的全名
例如 org.apache.poi.xwpf.usermodel.XWPFDocument
按下 右方的jar/class search, 會出現你查的class
點按進入, 即可見查找的jar名

Read more...

2016年5月18日 星期三

java subString 取字的位置問題

mString="abcdefghijk"
mString.subString(0,5) : 並不是從第一個取到第六個, 而是從第一個取到第五個
結果:abcde

那如果要接下去取fgh, 一般會以為是mString.subString(6,9)
, 但不對, 應該是mString.subString(5,8)

Read more...

android spinner setSelection有時無作用

想在spinner開啟時,自動選定其中一個項目,但如果直接setSelection, 可能不會有作用,必須放到post內才可


private Spinner sort_spinner;

sort_spinner = (Spinner) layout.findViewById(R.id.sort_item);
//如果直接setSelection, 可能不會有作用
//sort_spinner.setSelection(sortField);
//必須放到post內才會有作用
sort_spinner.post(new Runnable() {
    public void run() {
        sort_spinner.setSelection(sortField);
    }
});


Read more...

讓scrollview不能捲動的三種方法



方法一
推薦此種方法
public class BlockScrollView extends ScrollView {
    //private boolean shouldWindowFocusWait;

    public BlockScrollView(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
    }

    public BlockScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public BlockScrollView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }
    // true if we can scroll (not locked)
    // false if we cannot scroll (locked)
    private boolean mScrollable = true;

    public void setScrollingEnabled(boolean enabled) {
        mScrollable = enabled;
    }

    public boolean isScrollable() {
        return mScrollable;
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                // if we can scroll pass the event to the superclass
                if (mScrollable) return super.onTouchEvent(ev);
                // only continue to handle the touch event if scrolling enabled
                return mScrollable; // mScrollable is always false at this point
            default:
                return super.onTouchEvent(ev);
        }
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        // Don't do anything with intercepted touch events if
        // we are not scrollable
        if (!mScrollable) return false;
        else return super.onInterceptTouchEvent(ev);
    }

}



方法二
但此一方法,會使scrollview裡面的元件(例如textview),也不能動作(fling,swipe,click等...)
        scrollView.setOnTouchListener(new View.OnTouchListener() {

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            // TODO Auto-generated method stub
            return isBlockedScrollView;
        }
    });





方法三
如果scrollview裡面有textview有時會出現一些奇怪現象(畫面顯示不全,空白等)
import android.content.Context;
import android.text.Selection;
import android.text.Spannable;
import android.util.AttributeSet;
import android.widget.TextView;

public class BlockScrollView extends ScrollView {
    //private boolean shouldWindowFocusWait;
    public boolean isScroll =true;

    public BlockScrollView(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
    }

    public BlockScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public BlockScrollView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public void scrollTo(int x, int y) {
        if (isScroll) {
            super.scrollTo(x,y);
        }
        //do nothing
    }
}


Read more...

  © Blogger templates Psi by Ourblogtemplates.com 2008

Back to TOP