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

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 © 2026. All Rights Reserved.

歡迎光臨
初音