寫教學的最大目的是教會未來的自己

Android&JAVA

在Eclipse透過JNI 跑C/C++ for android-Hello_world篇

繼上一篇(http://www.pupuliao.info/2013/05/在eclipse透過jni-跑cc-for-android-基礎安裝篇/) 安裝好後

要開始進行測試和設定,這部分比較麻煩,(在這裡我卡了很久)

因為是事後結圖,所以有些地方跳過

 

  1. 先開啟一個android專案
    2013-05-26_165735

     

     

     

  2. 在專案上右鍵選擇 Android Tools->add Native Support
    2013-05-26_170111
  3. 就會要你輸入so 名稱
    2013-05-26_170346
  4. 確認後就會產生jni 和lib 資料夾
    2013-05-26_170358
  5. 其中Android.mk 是 編譯的設定檔,包括要編譯哪些東西,現在用預設的就可以了
    LOCAL_PATH := $(call my-dir) 
    include $(CLEAR_VARS) 
    LOCAL_MODULE := HelloNDK 
    LOCAL_SRC_FILES := HelloNDK.cpp 
    include $(BUILD_SHARED_LIBRARY
  6. 之後開始編輯我們的JAVA 程式
     

     

     

    package com.example.hellondk;
    
    import android.os.Bundle;
    import android.app.Activity;
    import android.view.Menu;
    import android.widget.TextView;
    
    public class MainActivity extends Activity {
    	private TextView testString;
    	static
    
    	{
    
    		System.loadLibrary("HelloNDK");
    
    	}
    
    	public native String helloString();
    
    	public native int plus(int a, int b);
    
    	public native int multiply(int a, int b);
    
    	@Override
    	public void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_main);
    		testString = (TextView) findViewById(R.id.test);
    		String tempString;
    		tempString = helloString() + "\n3+5=" + String.valueOf(plus(3, 5))
    				+ "\n3*5=" + String.valueOf(multiply(3, 5));
    		testString.setText(tempString);
    		// testString.setText(helloString());
    	}
    
    	@Override
    	public boolean onCreateOptionsMenu(Menu menu) {
    		getMenuInflater().inflate(R.menu.activity_main, menu);
    		return true;
    	}
    }

      其中所有用native 宣告的function 都是等一下要透過C/C++ 來撰寫的程式,所以只需要宣告不需要寫code

  7. 打開剛剛系統生成的在jni 下的cpp檔
    #include <jni.h>
    #include <string.h>
    
    extern "C"
    {
    JNIEXPORT jstring Java_com_example_hellondk_MainActivity_helloString(JNIEnv* env,
    		jobject thiz) {
    	return env->NewStringUTF("My first JNI!");
    }
    JNIEXPORT jint Java_com_example_hellondk_MainActivity_plus(JNIEnv* env,
    		jobject thiz, jint a, jint b) {
    	jint total = a + b;
    
    	return total;
    }
    JNIEXPORT jint Java_com_example_hellondk_MainActivity_multiply(JNIEnv* env,
    		jobject thiz, jint a, jint b) {
    	jint total = a * b;
    	return total;
    }
    
    }
    

    先簡單說明我搞懂的部分
    首先因為檔案是使用cpp 所以當在裡面寫C code 的時候 要把程式碼用extern "C"{…} 包起來,如果是.C檔就不需要,不過寫法部台一樣 這部分請自行翻資料
    再來是資料型態的部分,所有JAVA的基本變數名稱 都是j+原先變數
    例如 int->jint 這部分在http://j796160836.pixnet.net/blog/post/31583827-%5Bandroid%5D-安裝ndk與使用jni呼叫系統底層native的c- 有更近一步的說明
    另外在function 名稱的命名上就是 JAVA_[package名稱]_[class名稱]_[function名稱] 所有的 . 改成 _
    在function () 中的變數加上預設的兩個變數,這應該是用來在JAVA 和C之間的變數轉換使用

  8. 接下來開始麻煩的設定
  9. 專案上按右鍵->內容->建制器->新建->程式->確定
    2013-05-26_173313
  10. 依照參考下圖設定,其中名稱隨意,位置和工作目錄就是你安置裝cygwin 的位置,其中引數的內容是重點
    –login -c "cd [專案位置] &&  rm -r obj && $NDK/ndk-build" 
    要注意的是 位置的斜線和windows 提供的是相反的 請注意
    這短程式碼簡單說明就是,移動到專案->刪除前一次編譯資料->開始編譯 ,其中&&  rm -r obj 是我自己加進去的

    2013-05-26_173713

  11. 接下來請參考這兩張圖設定
    2013-05-26_1742402013-05-26_174220
  12. 這樣設定後 每次修改後存檔系統將會自動編譯
  13. 之後存檔後出現下圖,那就成功了,如果跳出錯誤訊息….去翻資料吧,看看gcc 編譯錯誤說明
    2013-05-26_174427
  14. 開始測試吧
    2013-05-26_174556

Post to Twitter Post to Plurk Post to Facebook Send Gmail

在Eclipse透過JNI 跑C/C++ for android-基礎安裝篇

首先,這是一個很複雜的問題…..因為 我搞了好久才搞定

這一篇應該算是經驗談,所以如有錯誤麻煩告知

 

參考資料:

http://ibuzzlog.blogspot.tw/2012/07/android-jni_20.html

http://zhoujianghai.iteye.com/blog/897212

http://j796160836.pixnet.net/blog/post/31583827-%5Bandroid%5D-安裝ndk與使用jni呼叫系統底層native的c-

 

環境準備

一開始你要先有eclipse+ android SDK

這是android 程式開發的基礎環境,相信大部分的人都是用這個環境來寫作

我目前是使用eclipse JUNO 中文化版本 教學也以中文化版本為主,英文版 可以看上面參考資料

 

所需安裝軟體

  1. androoid NDK  這是要讓android 能透過JNI 來執行C語言時所必需的套件
  2. eclipse CDT    這是讓eclipse 有C/C++ 的開發環境
  3. eclipse NDK   這是把NDK 引入eclipse 的套件
  4. cygwin            這是C/C++的compiler

 

其中最難搞 的是第四項,其他的很簡單….

安裝androoid NDK

  1. http://developer.android.com/tools/sdk/ndk/index.html 下載最新版本
  2. 解壓縮到硬碟,可以放在和android SDK 相同資料夾下方便管理
  3. 搞定

 

安裝eclipse CDT

  1. 在eclipse 下開啟 說明->Install New Software
  2. 在work with 中搜尋http://download.eclipse.org/tools/cdt/releases/indigo,如下徒選想CDT相關的安裝,應該是只要第一個就好,不過我連第二個也順便了 沒差
    2013-05-26_130016
  3. 接下來就是和android ADT 的安裝程序相同,就一路 下一部,同意 OK等等…我就不截圖了,因為我都安裝過了….
  4. 結束後eclipse 會要你重新啟動軟體,選YES

 

閱讀全文

Post to Twitter Post to Plurk Post to Facebook Send Gmail

android 上傳檔案到電腦的方法

這篇文章 主要是給有寫android程式的人看得,如果只是普通使用者,去找APP吧XD

首先 這個功能我研究了四天,今天終於有了成果
到最後 我找到另一個 相當完整的code,為了避免人別人說我抄襲

我就直接貼連結了
http://www.cnblogs.com/greatverve/archive/2011/12/23/android-upload.html

簡單來說,android 如果要傳輸檔案,在預設的API中 並不支援 FTP(雖然似乎有人寫出來,但我還沒嘗試成功)
所以比較簡單的解決方法,就是模擬普通網頁傳輸表格的方式用POST 來傳輸
連結裡的方法就是這樣

另外,伺服器接收端可以用更簡單的方式製作
用PHP 的就可以了 這部分我改天再PO

Post to Twitter Post to Plurk Post to Facebook Send Gmail

JAVA的UTF-8 繁簡互轉的方法

首先 要先感謝來自PTT JAVA版的 ClareQ (人比人Cheese人)

他的方法讓我大開眼界,比我上一篇使用replace 的方法更為快速,他使用了 hashmap

也感謝他允許我發了這篇文章

 

 

 

public class Encoding {

	public Encoding() {

	}

	public String StoT(String data) {
		return translate(data, S2T);
	}

	public String TtoS(String data) {
		return translate(data, T2S);
	}

	private static final Map T2S = new HashMap();
	private static final Map S2T = new HashMap();
	static {
                final char[] UTF8T ="繁體字表...".toCharArray();
                final char[] UTF8S ="簡體字表...".toCharArray();
                for (int i = 0, n = Math.min(UTF8T.length, UTF8S.length); i < n; i++) {
			final Character cT = Character.valueOf(UTF8T[i]);
			final Character cS = Character.valueOf(UTF8S[i]);
			T2S.put(cT, cS);
			S2T.put(cS, cT);
		}
	}

	private static String translate(String text,
			Map dictionary) {
		final char[] chars = text.toCharArray();
		for (int i = 0, n = chars.length; i < n; i++) {
			final Character found = dictionary.get(chars[i]);
			if (null != found)
				chars[i] = found;
		}
		return String.valueOf(chars);
	}

 

其中繁體字跟簡體字字字表,後面附上,因為大約有兩千五百字…..

他的方法和我以前的想法不一樣,因為我只是換字,不是換詞,所以他把字串拆開成陣列後,把文章帶進字碼表去搜尋,大概是hashmap 在這方面的高效率,所以可以快速提升執行效率

這是和上一篇同樣的樣本做的測試

總共花費 96089.0ms ;其中下載花費95658.0ms 資料處理花費  431.0ms

效率大概是使用JAVA 內建的replace()的80倍

簡繁字碼轉換表

 

看來我現在是要想辦法提高下載效率

Post to Twitter Post to Plurk Post to Facebook Send Gmail

JAVA提高String.replace() 執行速度的方法

繼續上一篇的內容,為了這些問題,我詢問了PTT 的 JAVA版,也很感謝有人替我解答,並教我如何提高replace 的效率

參考資料 https://www.facebook.com/java.tw 的 5月8日的文章

這個方法經過測試,應該可以使用正規表示式,但我測試的次數不夠多,也不保證其效率 <-免責聲明XD

 

簡單來說 就是 JAVA 官方提供的 String 中的 replace() 把所有的任務都當成正規表示式來處理,所以效率不彰,而如果我們只是要做單純的文字置換,顯然不需要那些步驟。

以下是程式碼+口語化只有我自己懂得演算法

 

public class Replace {
	public Replace() {
		// TODO Auto-generated constructor stub
	}

	public static String replace(String str, String patten, String replacement) {
		// str 要置換的字串 把patten換成 replacement
		int pos = str.indexOf(patten);
		return pos < 0 ? str : _replace(str, patten, replacement, pos);
	}
/**演算法說明
 * 
 * @param str 資料
 * @param patten 要換掉的文字
 * @param replacement 要改成的文字
 * @param pos 那段文字在哪
 * @return 
 * 1. 從頭開始找出符合的字串,並且標示第幾個字放進pos
 * 2. 先把在pos前面的字放進結果區(newContent)
 * 3. 再放進replacement
 * 4. 再去找下一個字的位置放進pos 
 * 5. 接續步驟三直到全部找完為止
 */
	public static String _replace(String str, String patten,
			String replacement, int pos) {
		int len = str.length();
		int plen = patten.length();
		StringBuilder newContent = new StringBuilder(len);

		int lastPos = 0;

		do {
			newContent.append(str, lastPos, pos);
			newContent.append(replacement);
			lastPos = pos + plen;
			pos = str.indexOf(patten, lastPos);
		} while (pos > 0);
		newContent.append(str, lastPos, len);
		return newContent.toString();
	}
}

經過我在小說下載器上的實際測試結果

效率提高的8倍左右

以下是測試數據,以一部124頁的小說當作測試樣本

使用String.repalce() :總共花費 112890.0ms ;其中下載花費80601.0ms  資料處理花費 32289.0ms

使用新的方法             :總共花費 71188.0ms ;其中下載花費67008.0ms 資料處理花費  4180.0 ms

下載花費時間取決於測試當下的網路狀況

 

Post to Twitter Post to Plurk Post to Facebook Send Gmail

JAVA 的字串替換

參考資料

http://satellite.iteye.com/blog/224820

http://lbs.iteye.com/blog/208056

http://hehome.blogspot.tw/2011/06/java.html

 

最近為了我的小說下載器,找了很多相關的資料

 

首先 String 的 replace() 和 replaceAll()的差別

這兩個都是做string 大量置換,只是 replace() 就只是單純的置換,而replaceAll() 支援 使用正規表示式

以下是例子(抱歉引用了 參考文章的)

         
        String src = new String("ab43a2c43d");
        System.out.println(src.replace("3","f"));=>ab4f2c4fd.
        System.out.println(src.replace('3','f'));=>ab4f2c4fd.
        System.out.println(src.replaceAll("\\d","f"));=>abffafcffd.
        System.out.println(src.replaceAll("a","f"));=>fb43fc23d.
        System.out.println(src.replaceFirst("\\d,"f"));=>abf32c43d
        System.out.println(src.replaceFirst("4","h"));=>abh32c43d. .

再來就是 另一種 使用 正規表示式的 大規模置換的方法,下面的範例是用來 過濾所有的HTML 的

 
          java.util.regex.Pattern p_html;
          java.util.regex.Matcher m_html; 

          String regEx_html = "<[^>]+>"; //定義HTML標籤的正則表達式 
          p_html = Pattern.compile(regEx_html,Pattern.CASE_INSENSITIVE);
          m_html = p_html.matcher(htmlStr);
          htmlStr = m_html.replaceAll(""); //過濾html標籤 


我剛剛理解了 兩者之間的差別
前者的作法,每次都要重新分析一次正規表示式,而後者可以指分析一次就重複使用

Post to Twitter Post to Plurk Post to Facebook Send Gmail

如何控制閃光燈的開啟與關閉

最近繼續研究android 的影像處理

繼續想辦法偷吃步XD

喔 不 今天不是樣講這個

今天要說的是 我研究出如何讓使用者自行控制閃光燈

但是因為 部分程式 是別人寫的…我無法說明原因(無法完全理解)

 

首先,簡單來說就是 處理 案件觸發,我把它放在手機上的 search 鍵(KeyEvent.KEYCODE_SEARCH:)

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        switch(keyCode)
        {
        case KeyEvent.KEYCODE_DPAD_CENTER: // DPAD_CENTER
            mPreview.mCamera.autoFocus(null);
            break;
            
        case KeyEvent.KEYCODE_MENU: // MENU
            mDrawOnTop.mDrawEdges = !mDrawOnTop.mDrawEdges;
            break;
        case KeyEvent.KEYCODE_SEARCH:
            mPreview.changeTheFlash();
            break;
        }
        
            
        return super.onKeyDown(keyCode, event);
    }

 

再來就是 開啟予關閉,這部分是寫在 相機這個 class 底下,這部分大部分的code 是我同學寫的,我只是拿來增加功能

public void changeTheFlash(){
        Camera.Parameters parameters=mCamera.getParameters();
        if(flashMod==true)
        {
            turnOfTheFlash();
            flashMod=false;
        }
        else
        {
            turnOnTheFlash();
            flashMod=true;
        }
    }
    
    public void turnOnTheFlash(){//開閃光燈
        Camera.Parameters parameters=mCamera.getParameters();
        parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
        mCamera.setParameters(parameters);
    }
    public void turnOfTheFlash(){//關閃光燈
        Camera.Parameters parameters=mCamera.getParameters();
        parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
        mCamera.setParameters(parameters);
    }

詳細請參閱http://developer.android.com/index.html

 

不知如何說明,自己研究吧

 

Post to Twitter Post to Plurk Post to Facebook Send Gmail

Vector 與 ArrayList的速度

Vector 與 ArrayList 是兩個常用的動態陣列class

在JAVA 中,當我們要使用到不確定大小的變數陣列的時候

通常都是使用到這兩個

那這兩者有什麼差異呢?

以使用方法來說,兩者一模一樣

 

速度方面

這兩個 再增加資料地的時間複雜度是 1

刪除一筆資料是 n (第n個)

Vector 會做同步處理,速度會比較慢(看說明是說,當一個程式多執行緒,兩個執行緒都用同一筆資料時,會保證兩邊資料同步)

因此 如果是跑單執行緒的,可以用ArrayList

另外,因為刪除資料速度比較慢,我通常是直接開新的array 存放,在一次釋放原有的

 

 

最後

引用JAVA 原來工程師 所說

如果速度是最大考量的話,這兩個都不要用,請自己寫,因為這樣只會增加開發時間

 

Post to Twitter Post to Plurk Post to Facebook Send Gmail

Copyright © 2024. All Rights Reserved.

歡迎光臨
初音