2015年3月1日 星期日

Eclipse也可以像VS一樣全開自動完成功能

這幾天才知道Eclipse的自動完成功能是被限制住的,

其實它可以像VS一樣,每個字元都可以當作提示自動完成功能的關鍵字,

不需要再使用Alt + /快捷鍵了



步驟:

1. Window -> Preferences

2. Java -> Editor -> Content Assist

3. "Enable auto-activation" 選項請勾選起來
    (a) Auto activation delay 為提示出現的延遲時間,建議可以設為 0
    (b) Auto activation triggers for Java 為 IDE 遇到何種字元會自動啟動提示,預設只有 dot,請改為 .abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ(,
    (c) Auto activation triggers for Javadoc 在註解區塊中遇到何種字元會啟動提示,預設是 @ 及 #
改完後 Apply -> OK


資料參考來源:
(1).開啟eclipse自動完成功能

2014年7月25日 星期五

java & Android SQLite database 基礎功能

這次因為老闆要用到手機APP能夠使用的資料庫(SQLite),所以我先使用java project進行資料庫的生成。
我:java project的寫完了,那我要轉交資料庫給阿睡處理了喔?
老闆:你能不能再寫個手機APP自動建立資料庫的版本?
我:.......

Java版本:


public class SQLiteHelper
{
public static String DataBase_NAME = "temp.db";
....
....
/for AndroidMatadata
private static String DataBase_TableName_AndroidMatadata = "android_metadata";
private static String DataBase_Col_Locale = "locale";
....
....
/*
* 因為java的專案本身不會附帶SQLite的lib,所以需要自己去jdbc提供處下載並引入java專案
* https://bitbucket.org/xerial/sqlite-jdbc
*/
public Connection getConnection() throws SQLException
    {
SQLiteConfig config = new SQLiteConfig();
// config.setReadOnly(true);
config.setSharedCache(true);
config.enableRecursiveTriggers(true);

SQLiteDataSource ds = new SQLiteDataSource(config);
ds.setUrl("jdbc:sqlite:" + this.DataBase_NAME);
return ds.getConnection();
//ds.setServerName("sample.db");
}
/*
* 給Anroid APP使用的資料庫,必須要先建立Matadata的"表格"與"內容",Android版本的會自動建立,Java需要手動建立
* 其中"DROP TABLE IF EXISTS " + TableName 的SQL指令,應該有碰過的都知道。這次是用來洗掉前一次舊的內容。
*/
public void PrapareTable_Android_Matadata(Connection con) throws SQLException
{
//建立表格
String sql = "DROP TABLE IF EXISTS " + this.DataBase_TableName_AndroidMatadata + "; "
        + "create table " + this.DataBase_TableName_AndroidMatadata + " ("
        + this.DataBase_Col_Locale + " TEXT"
        + ");";
                Statement stat = null;
                stat = con.createStatement();
                stat.executeUpdate(sql);
                //插入內容
                sql = "insert into " + this.DataBase_TableName_AndroidMatadata + " ("
        + this.DataBase_Col_Locale + ") values (?)";
                PreparedStatement pst = null;
                 pst = con.prepareStatement(sql);
                int idx = 1 ;
                pst.setString(idx++, "en_US");
                pst.executeUpdate();
}
/*
* 以下是新增單筆的內容
*/
public void insert_temptable(Connection con, DataRows inputdata) throws SQLException
       {
//插入內容
            String sql = "insert into " + this.DataBase_TableName + " ("
        + this.DataBase_Col_Id + ", "
        + this.DataBase_Col_routingId + ", "
        + this.DataBase_Col_SeqNo + ", "
        + this.DataBase_Col_GoingBack + ") values (?, ?, ?, ?)";
PreparedStatement pst = null;
                pst = con.prepareStatement(sql);
                int idx = 1 ;
                pst.setString(idx++, inputdata.Id);
                pst.setString(idx++, inputdata.routeId);
                pst.setString(idx++, inputdata.seqNo);
                pst.setString(idx++, inputdata.GoBack);
                pst.executeUpdate();
}
/*
     * 以下是新增多筆的內容,適合用於筆數較多的資料於新增操作。
     * 這裡需要注意的地方是 setAutoCommit(false) 的部分,因為要能夠快速塞入多筆內容,需要將資料庫的限制解除。
     * 一般情況大多都是一筆一筆的資料插入進資料表,這邊改成false的意思是讓commit變成非自動提交,
     * 如此一來,最後提交的時候就可以多筆資料一次性提交,而不會一筆一筆的進行提交。
     * setAutoCommit(false) → commit() or rollback();
     * 一般的使用到setAutoCommit()的情況,後面一定要進行commit() 或是 rollback()的防呆,以防資料庫提交的時候爆炸。
*
     * 使用setAutoCommit()的時候,一定要注意 PRIMARY KEY ASC AUTOINCREMENT 跟 UNIQUE的屬性與欄位對應。
     * 以防新增時出錯
     */
public void insert_BusStationLine(Connection con, ArrayList<BusStationInfo> inputdata) throws SQLException
    {
    String sql = "insert into " + this.DataBase_TableName + " ("
        + this.DataBase_Col_Id + ", "
        + this.DataBase_Col_routeId + ", "
        + this.DataBase_Col_SeqNo + ", "
        + this.DataBase_Col_GoBack + ") values (?, ?, ?, ?)";
        PreparedStatement pst = null;
        pst = con.prepareStatement(sql);
        con.setAutoCommit(false);
        for(int i = 0; i < inputdata.size(); i++)
        {
       int idx = 1 ;
       pst.setString(idx++, inputdata.get(i).Id);
       pst.setString(idx++, inputdata.get(i).routeId);
       pst.setString(idx++, inputdata.get(i).seqNo);
       pst.setString(idx++, inputdata.get(i).GoBack);
       pst.executeUpdate();
       pst.clearParameters();
        }
        con.setAutoCommit(true);
    }
}

Android版本:

public class DBHelper extends SQLiteOpenHelper
{
public static String DataBase_NAME = "StationInfo.db";
....
....
public String DatabasePath;
private Context mContext;
public SQLiteDatabase SQLite_DB;
public int DataBase_Version;
public String ProcessMsg;
/*
* 設定建構子
*/
public DBHelper(Context context, int version) 
{
super(context, DataBase_NAME, null, version);
mContext = context;
DataBase_Version = version;
DatabasePath = "/data/data/" + mContext.getPackageName() + "/databases/";
}
/*
* 外部開啟資料庫
*/
public boolean CheckDatabaseExist()
{
try{
SQLite_DB = SQLiteDatabase.openDatabase(DatabasePath + DataBase_NAME, null, SQLiteDatabase.OPEN_READONLY);
}catch(Exception e)
{
e.printStackTrace();
}
return SQLite_DB != null ? true: false;
}
/*
* SQLite的onCreate並不會隨著建構子的啟動而隨之開起。
* onCreate的執行主要是跟於getWritableDatabasec和getReadableDatabase之後執行。
* 執行條件:資料庫尚未建立!
* 假如資料庫已經建立的情況之下,即使執行了getWritableDatabasec和getReadableDatabase,也不會再次進入onCreate之中。
* 倒是可以外部或內部直接呼叫onCreate()強制執行。
*/
@Override
public void onCreate(SQLiteDatabase db) 
{
/*
* 創建三個表Busline、BusStation、BusStationLine
*/
SQLite_DB = db;
/*//for Android Matadata 因為Android會自己建立 所以這裡不用
String sql = "DROP TABLE IF EXISTS " + DataBase_TableName_AndroidMatadata + "; "
        +"create table " + DataBase_TableName_AndroidMatadata + " (" 
        + DataBase_Col_Locale + " TEXT"
        + ");";
db.execSQL(sql);*/
//for Table BusStationLine
sql = "CREATE TABLE " + DataBase_TableName + " (" 
+ DataBase_Col_Id + " VARCHAR,"
        + DataBase_Col_routeId + " VARCHAR,"
        + DataBase_Col_seqNo + " VARCHAR,"
        + DataBase_Col_GoBack + " VARCHAR"
        + ");";
db.execSQL(sql);
Log.e("OnCreate", "Table Create Finish!");
}
/*
* 單筆資料的新增
*/
public long insert_BusStationLine(BusStationInfo temp) 
{
SQLite_DB = getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put(DataBase_Col_Id, temp.Id);
cv.put(DataBase_Col_routeId, temp.routeId);
cv.put(DataBase_Col_seqNo, temp.seqNo);
cv.put(DataBase_Col_GoBack, temp.GoBack);
return SQLite_DB.insert(DataBase_TableName_BusStationLine, null, cv);
}
/*
* 以多載形式使用相同Func名稱來大量塞入資料。
* 同java專案的setAutoCommit(false)功能。
* 這裡是使用db.beginTransaction()、db.setTransactionSuccessful()、endTransaction();
* 將要處理的大量資料包於beginTransaction與setTransactionSuccessful之間即可。
*/
public void insert_BusStationLine(ArrayList<BusStationInfo> temp) 
{
SQLite_DB = getWritableDatabase();
String sql = "insert into " + this.DataBase_TableName_BusStationLine + " ("
        + this.DataBase_Col_Id + ", "
        + this.DataBase_Col_routeId + ", "
        + this.DataBase_Col_seqNo + ", "
        + this.DataBase_Col_GoBack + ") values (?, ?, ?, ?)";
SQLite_DB.beginTransaction();
SQLiteStatement stmt = SQLite_DB.compileStatement(sql);
for(int i = 0; i < temp.size(); i++)
{
       int idx = 1 ; 
       stmt.bindString(idx++, temp.get(i).Id);
       stmt.bindString(idx++, temp.get(i).routeId);
       stmt.bindString(idx++, temp.get(i).seqNo);
       stmt.bindString(idx++, temp.get(i).GoBack);
       stmt.execute();
       stmt.clearBindings();
       //Log.d("BusStationLine: ",Integer.toString(i+1));
       ProcessMsg = "BusStationLine: " + Integer.toString(i+1);
}
        SQLite_DB.setTransactionSuccessful();
        SQLite_DB.endTransaction();
}
/*
*/
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) 
{
db = getWritableDatabase();
DataBase_Version = newVersion;
String sql = "DROP TABLE IF EXISTS " + this.DataBase_TableName_BusLine;
db.execSQL(sql);
sql = "DROP TABLE IF EXISTS " + this.DataBase_TableName_BusStation;
db.execSQL(sql);
sql = "DROP TABLE IF EXISTS " + this.DataBase_TableName_BusStationLine;
db.execSQL(sql);
//reset table
onCreate(db);
}
/*
* 以下是以前寫的code,其實內容很簡單,看看就好。
*/
public Cursor SearchNumberByKey(String Radical, String x)
{
//SQLiteDatabase dbc = this.getReadableDatabase();
//String[] columns = new String[]{FIELD_Number};
//String[] selectionArgs = {"%" + x + "%"};
//Number like ? 模糊搜尋、Number = ? 對照搜尋、(%'、'_' 符號便是 SQL 的萬用字元,前者代表任意長度字元,後者代表任意一個字元)
//return dbc.query(DataBase_TableName, columns, "Sum = "+ Radical +" and Number like ?", selectionArgs, null, null, null);
return null;
}
/*
* 以某欄位所指定的值來搜尋表的資料
*/
public Cursor SelectById(int position)
{
SQLite_DB = this.getReadableDatabase();
String Columns_ID = "_id";
return SQLite_DB.query(DataBase_TableName, null, Columns_ID + "=" +position, null, null, null, null);
}
/*
* 搜尋表的全部內容
*/
public Cursor SelectAll()
{
SQLite_DB = this.getReadableDatabase();
return SQLite_DB.query(DataBase_TableName, null, null, null, null, null, null);
//return db.query(TABLE_NAME, new String[] {"_id", "Space_set", "Sum", "Number", "word"}, null, null, null, null, null);
}
/*
* 更新
*/
public void UpdateHitPoint(int position, String HitPoint) 
{
SQLite_DB = this.getWritableDatabase();
String Columns_ID = "_id";
String Columns_HitPoint = "HitPoint";
ContentValues CV = new ContentValues();
CV.put(Columns_HitPoint, HitPoint);
SQLite_DB.update(DataBase_TableName, CV, Columns_ID + "=" +position, null);
}

2014年7月14日 星期一

Android XML DOM

此次要處理的是網路上的XML檔案,藉由Android APP 上網將XML下載回來,並使用Dom parser將內容擷取出來。

XML檔案來源:高雄市腳踏車 (OpenData)
<BIKEStationData>
<BIKEStation>
<Station>
<StationID>1</StationID>
<StationNO>0019</StationNO>
<StationPic>http://www.c-bike.com.tw/Uploads/Station/1_s.JPG</StationPic>
<StationPic2>http://www.c-bike.com.tw/Uploads/Station/1_m.JPG</StationPic2>
<StationPic3>http://www.c-bike.com.tw/Uploads/Station/1_l.JPG</StationPic3>
<StationMap>http://www.c-bike.com.tw/Uploads/Station/1_map.png</StationMap>
<StationName>生態園區站</StationName>
<StationAddress>高雄市左營區博愛三路捷運R15生態園區站2號出口旁</StationAddress>
<StationLat>22.676995542475076</StationLat>
<StationLon>120.30648350715637</StationLon>
<StationDesc>生態園區站(R15-2號出口)來源引用-高雄市政府工務局.</StationDesc>
<StationNums1>26</StationNums1>
<StationNums2>2</StationNums2>
</Station>
<Station>
......
<BIKEStation>
<BIKEStationData>

程式碼內文:
private void doDataHandle()
{
new DataHandleAsyncTask().execute();
}

private class DataHandleAsyncTask extends AsyncTask<Void, Void, String>
{
@Override
protected void onPreExecute()
{
//這裡放背景執行之前要處理的事情。
}

@Override
protected String doInBackground(Void... params)
{
//這裡是整個非同步任務的核心所在,把要花時間執行的內容放在這裡。
try 
{
//使用URL直接連結網址
URL urlUpdate = new URL("http://網址.xml");
//建立文件樣本
DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
//將URL所指向的網址導入文件檔案
Document document = documentBuilder.parse(urlUpdate.openStream());
//針對xml文檔的元素做normalize
document.getDocumentElement().normalize();  
  
Element root = document.getDocumentElement(); //取得檔案的"根"標籤
NodeList nodes = root.getElementsByTagName("BIKEStation"); //將"根"標籤進行指定項目的指派
Element SecondlevelElement = (Element) nodes.item(0); //取得第二層標籤
nodes = SecondlevelElement.getElementsByTagName("Station");  //將第二層進行指定標籤項目的指派

StationInfo temp = new StationInfo();
for(int i = 0; i < nodes.getLength(); i++)
{
Element thirdlevel = (Element)nodes.item(i); //取得第三層標籤
//接下來將要取得的第三層內容,藉由getElementsByTagName進行個別項目內容的抽取
temp.mStationID = Integer.valueOf(thirdlevel.getElementsByTagName("StationID").item(0).getTextContent());
temp.mStationNumber = Integer.valueOf(thirdlevel.getElementsByTagName("StationNO").item(0).getTextContent());
}
} catch (Exception e) 
{ e.printStackTrace(); }
return null;
}

protected void onPostExecute()
{
//當doInBackground方法中的程式執行完畢後,接下來就會執行這裡。
}

}

注意項目:
(1). 要利用Android App擷取網路資源,就必須要另外開一個Thread來使用。由於作為測試的檔案資料並不是很大,所以使用AsyncTask(非同步任務)來進行抓取作業。
(2). xml文件裡面較常見的標籤位置有Attribute跟TextContent
<StationID>test</StationID>的test要以getTextContent來取得;
<StationID id="1001">test</StationID>要以getAttribute來取得。

參考來源:
(1).使用AsyncTask執行非同步任務
(2).[Java]Parsing XML Data with DOM
(3).http://www.mkyong.com/java/how-to-read-xml-file-in-java-dom-parser/

MTU 修改

MTU查看:netsh interface ipv4 show subinterfaces

MTU修改方式:etsh interface ipv4 set subinterface "你的網路" mtu=你想要的數值 store=persistent

Android Layout Menu的處理優先順序


參考Activity的生命週期  ↓
Android應用程式的生命週期(Life Cycle)

順序流程:OnCreate() -> OnStart() -> OnResume().

但是以上只有先處理框架內畫面的部分,而 Menu 的部分卻還沒做處理

所以提前更動 MenuItem 的話,會進入 Exception的情況

所以兩個串接的流程情況是

OnCreate() → OnStart() → OnResume() → 
onCreateOptionsMenu() → onPrepareOptionsMenu(Menu menu) → onOptionsItemSelected(MenuItem item) 

                                                                                                                            以上.....

Android FB API 3.x

1.需要 OpenSSL、CMD、Eclipse的debug keystore聯合運作取出key

請在CMD中 key入
keytool -exportcert -alias androiddebugkey -keystore C:\Users\Yi\.android\debug.keystore | C:\openssl\bin\openssl.exe sha1 -binary | C:\openssl\bin\openssl.exe base64
注意:其中有些路徑需要根據自己本機電腦的路徑做設定

2.Key in 之後 會需要金鑰儲存庫的密碼,請接續key入 android (預設密碼)


3.接著複製下如  "CcyZbB/wkKSQoAhLQmz/p+kfoCU="  般的hashKey,到已經建立好的Facebook Developer Site,創建新的應用程式,在於Key Hashes位置貼上。
(記得也要填入所使用的package name跟Activity名稱 ← 可以在manifrst裡頭查看)



4.註冊完網站的部分,還剩下APP的部分也要套上權限。打開專案的Manifest.xml,在於meta的部分加上應用程式的ID。(跟Google Map 的API key 應用類似)
<meta-data 
      android:name="com.facebook.sdk.ApplicationId"          
      android:value="@string/app_id"/>

5.除了meta-data之外,還要再加上所要使用的Activity
<activity 
      android:name="com.facebook.LoginActivity"/>

6.如此就大概結束了 ,接下來就要看如何的運用FB的sdk,加入所應用的Activity。
(參考來源:三十而立 [Android] Facebook SDK for Android 3.0)





2013年10月19日 星期六

BT軟體與特徵碼

現在的BT軟體已經變成了
不用只依靠.torrent的種子黨來取得下載列表內容

磁力連結:magnet

那特徵碼的用法是


magnet:?xt=urn:btih:加上特徵碼

將上述字串貼入可使用網址連接的BT軟體
以utorrent為例子↓


在其中貼入字串即可