2013年8月23日 星期五

[Android] 基本FaceBook發布塗鴉牆功能



1. 將facebook專案加入lib













2. 設定manifest.xml
<uses-permission android:name="android.permission.INTERNET"/>

<meta-data android:name="com.facebook.sdk.ApplicationId" android:value="@string/app_id"/>
<activity android:name="com.facebook.LoginActivity"/>

3. 取得key hashes
C:\Program Files\Java\jdk1.6.0_37\bin>keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore | "
C:\openssl-0.9.8k_X64\bin\openssl.exe" sha1 -binary | "C:\openssl-0.9.8k_X64\bin\openssl.exe" base64

4. button的onClick()實作login及發佈的功能
Session.openActiveSession(MainActivity.this, true, new Session.StatusCallback() {
			    	   
	@Override
	public void call(Session session, SessionState state,Exception exception) {
	    if (session.isOpened()) {
	        Log.d("fbt",session.getAccessToken()); // get token
	        publishFeedDialog();
	    }			    	
        }
			    	
});

private void publishFeedDialog() {
	    Bundle params = new Bundle();
	    params.putString("name", "Facebook SDK for Android");
	    params.putString("caption", "Build great social apps and get more installs.");
	    params.putString("description", "The Facebook SDK for Android makes it easier and faster to develop Facebook integrated Android apps.");
	    params.putString("link", "https://developers.facebook.com/android");
	    params.putString("picture", "https://raw.github.com/fbsamples/ios-3.x-howtos/master/Images/iossdk_logo.png");
	    
	    WebDialog feedDialog = (
	        new WebDialog.FeedDialogBuilder(MainActivity.this,
	        		Session.getActiveSession(),
	            params))
	        .setOnCompleteListener(new WebDialog.OnCompleteListener() {

	            @Override
	            public void onComplete(Bundle values,
	                FacebookException error) {
	                if (error == null) {
	                    // When the story is posted, echo the success
	                    // and the post Id.
	                    final String postId = values.getString("post_id");
	                    if (postId != null) {
	                        Toast.makeText(MainActivity.this,
	                            "Posted story, id: "+postId,
	                            Toast.LENGTH_SHORT).show();
	                    } else {
	                        // User clicked the Cancel button
	                        Toast.makeText(MainActivity.this, 
	                            "Publish cancelled", 
	                            Toast.LENGTH_SHORT).show();
	                    }
	                } else if (error instanceof FacebookOperationCanceledException) {
	                    // User clicked the "x" button
	                    Toast.makeText(MainActivity.this, 
	                        "Publish cancelled", 
	                        Toast.LENGTH_SHORT).show();
	                } else {
	                    // Generic, ex: network error
	                    Toast.makeText(MainActivity.this, 
	                        "Error posting story", 
	                        Toast.LENGTH_SHORT).show();
	                }
	            }

	        })
	        .build();
	    feedDialog.show();
	}

2013年4月13日 星期六

[筆記] 如何設定 tomcat 的網頁資源路徑 與 顯示歡迎畫面

安裝tomcat的目錄/conf/server.xml
在<Hostname="localhost" debug="0" appBase="webapps"......> </Host>標籤之間添加:
<Context path="A1" docBase="A2" debug="0" reloadable="true" />
A1:不填則輸入ip就顯示A2目錄下的資源;若為/test,則要輸入http://ip:8080/test才可以。
A2:預設為tomcat/webapps/ROOT,也就是網頁資源的路徑。
ex: http://127.0.0.1:8080/haha 取得jsp-examples下的資源。










安裝tomcat的目錄/conf/web.xml
<welcome-file-list>
<welcome-file>A3</welcome-file>
.
.
.
</welcome-file-list>
A3:要當做首頁的html或jsp放最上面




2013年4月10日 星期三

[ORACLE] ORACLE SQL DEVELOPER 連接 SQL SERVER 2008

需要jtds這個第三方jdbc driver,
但版本還不能太新,試過1.3版不行,
改為1.2.2版就可以......
下載後解壓縮 jtds-1.2.2.jar 檔案並置於 SQL Developer安裝目錄\jdbc\lib ,
之後在偏好設定>資料庫>協力廠商第三方jdbc驅動,加入 jtds-1.2.2.jar就ok囉!

jtds官方下載連結

2013年4月9日 星期二

[閱讀筆記] HEAD FIRST 深入淺出 SQL

DES(a,b) a:數字的總位數 b:小數點後的位數

DESC table_name; 顯示資料表的格式

NULL是不能互相比較的,它只代表未定義的值

DEFAULT a(預設值,型態要與欄位相同)

字串內若有單引號要加上跳脫字元\,SQL才能辨認單引號的起始與結束,亦可在單引號前面再加一個單引號,效果相同

SELECT drink_name FROM drink_info WHERE drink_name>='L' AND drink_name<'M';
/*尋找drink_name為L字母開頭的*/

SELECT drink_name FROM drink_info WHERE drink_name BETWEEN 'L' AND 'M';
/*尋找drink_name為L到M字母開頭的*/



欄位沒有=NULL,必須使用IS NULL關鍵字,例如WHERE calories IS NULL

萬用字元(wildcard)
%表示任意數量的未知字元
_表示1個未知字元

萬用字元(wildcard)搭配LIKE可用於比對部分字串,例如WHERE location LIKE '%CA'
/*尋找location欄以CA為結尾的*/

IN (a,b,c,...)只要符合期中ㄧ個值,避免使用OR的冗長,例如WHERE rating IN ('A','B','D');
NOT IN (a,b,c,...)不在a,b,c...之中

NOTㄧ定接在WHERE後面,除了NOT IN,IS NOT NULL等變形例外

DELETE不能刪除單ㄧ欄位裡的值,或是資料表裡某ㄧ欄的所有值

UPDATE drink_info SET cost=cost+1
WHERE drink_name='Blue Moon'
OR WHERE drink_name='Oh My Gosh'
OR WHERE drink_name='Lime Fizz';
/*這三種飲料的價錢都加1元*/

下圖說明WHERE子句中的字串比對要全相符才OK......

單元性資料表是正規化(Normalization)的第一步驟,加上主鍵後又稱1NF狀態(first normal form,第一正規化)。
單元性資料表兩特色:
(i)資料欄內不會有多個同類型的值
(ii)不會有多個同類型的資料欄

SHOW CREATE TABLE table_name; 顯示當初CREATE的語法
SHOW CREATE DATABASE database_name;
SHOW COLUMNS FROM table_name;
SHOW INDEX FROM table_name;
SHOW WARNINGS;


ALTER TABLE drink_info
ADD COLUMN drink_id INT NOT NULL AUTO_INCREMENT FIRST,
ADD PRIMARY KEY(drink_id);
/*為資料表加入遞增主鍵並放在第一欄*/


(ALTER)修改資料表,常搭配下列使用......
CHANGE 可同時改變現存資料欄的名稱與型別。
MODIFY 修改現存資料欄的型別或位置。
ADD 在目前的資料表裡新增一欄。
DROP 從資料表裡卸除某欄。
RENAME TO table_new_name 更改資料表名稱。

ALTER TABLE table_name
CHANGE COLUMN 舊欄名 新欄名 型別 NOT NULL etc......;
/*新欄名與型別都要定義,否則會報錯,如下圖......*/



ALTER TABLE table_name
MODIFY COLUMN 欄名 型別 NOT NULL etc...... AFTER column_xxx;
MODIFY只能用AFTER才能成功與RDBMS軟體有關,有些軟體甚至只有在插入新資料欄時才能改變順序。事實上,MODIFY的改變順序是軟體的幕後操作,如果欄位內已經有資料或是不確定軟體是否支持此功能,盡量不要對欄位的位置動手動腳。總而言之,最好於設計資料表時,就構思欄位的最佳順序。

RIGHT(col_name,2)    右邊算起的2個字元
LEFT(col_name,2)    左邊算起的2個字元
SUBSTRING_INDEX(col_name, ',' ,1)    第1個逗號之前的所有字元
SUBSTRING(your_string, start_position, length)    指定起始位置和長度的子字串
UPPER(your_string)    轉換成大寫
LOWER(your_string)    轉換成小寫
REVERSE(your_string)    將字串順序反轉
LTRIM(your_string)    消除左側空白
RTRIM(your_string)    消除右側空白
LENGTH(your_string)    取得字串長度,即字元數量

UPDATE movie_table
SET category=
CASE
    WHEN drama='T' AND rating='R' THEN 'drama-r'

    WHEN comedy='T' AND rating='R' THEN 'comedy-r'
    WHEN action='T' AND rating='R' THEN 'action-r'

    WHEN gore='T' AND rating='R' THEN 'horror-r'
    WHEN scifi='T' AND rating='R' THEN 'scifi-r'
    WHEN category='misc' AND rating='G' THEN 'family'
    (ELSE......沒有可不加)
END;

ORDER的強大效果......(順序可能因RDBMS不同而異)


ORDER BY column_name1 ASC,column_name2 DESC;
ASC(升冪,ASCENDING) : SQL預設排序方式,可不寫。
DESC(降冪,DESCENDING) : 可以反轉查詢結果的順序。
須注意,這個DESC與查看資料表欄位資訊的DESC(DESCRIBE)不同,且不能使用完整的寫法。

DISTINCT關鍵字可以選出獨一無二的值。
SELECT DISTINCT sale_date FROM cookie_sales ORDER BY sale_date;

LIMIT可以限制查詢數量。
SELECT first_name,SUM(sales) FROM cookie_sales GROUP BY first_name ORDER BY SUM(sales) DESC LIMIT 2; 表示只選出頭兩筆。
LIMIT 1,2 則表示選出第二筆和第三筆,前表index(第一筆index為0)後表筆數。

schema(綱要),用於表達資料庫內的結構,包括資料表與資料欄,還有各種資料構造相互連接的方式。

foreign key(外鍵),是資料表裡的某一欄,它參照的另一個資料表的主鍵。

第二正規化(2NF)
規則ㄧ : 符合1NF
規則二 : 沒有部分功能相依性

第三正規化(3NF)
規則ㄧ : 符合2NF
規則二 : 沒有遞移功能相依性

某某某改變了而我也要跟著改變,這稱做我對某某某具有功能相依性......

非關聯性子查詢(noncorrelated subqueries)--子查詢可以獨立執行,且不會參照外層查詢的任何結果。

關聯性子查詢(correlated subqueries)--內層查詢的解譯,需依賴外層查詢的結果。

SQL說 : 交叉連結是件非常浪費時間的事,關聯性子查詢也會拖慢速度。連結比子查詢有效率。

當看到自我參照的外鍵時,通常是使用自我連結的時機(透過別名的使用......)。

UNION--真正意義上的聯集,只接受ㄧ個ORDER BY,且須位於敘述末端,因為UNION已經把許多個查詢的結果串連起來,並區分了群組。

UNION ALL--同UNION,但包括所有重複的值。

任何ㄧ種SELECT查詢都可用於建立新資料表(搭配CREATE TABLE table_name AS......)。


2013年4月1日 星期一

[學習筆記] jLIVE

jLIVE所產生的專案為*.jlv,匯入時亦是採此檔案類型

任何的設定修改後必須存檔。

"/servlet/com.probe.jslive.ProbeServlet" 這一個字串並不允許任何修改否則會無法執行應用程式。


[閱讀筆記] Oracle+SQL必備參考 p.161

SQL是宣告式的語法,不是過程化的,因此不提供過程控制。

SQL語法告訴Oracle要做啥,而不是該如何做。

SELECT name || ' ' || lastName FROM friendList ;
/* 得到姓名+空格+姓氏 */
NULL 連接 NULL 會得到NULL

兩張或多張表所共同擁有的column稱為key column,可以將兩張或多張表連接成單ㄧ結果集

DDL-Data Definition Language-通常由句權限的DBA使用
DML-Data Manipulation Language

GRANT-同意
REVOKE-廢除

DATABASE四種狀態
dismounted-未安裝的
mounted-安裝的
opened-開放的
closed-關閉的

ENABLE RESTRICTED SESSION-只允許具有限制權限的用戶登入
DISABLE RESTRICTED SESSION-停用此功能

AUDIT UPDATE ON scott.bonus;-對此表的UPDATE語句進行審核
AUDIT ALL ON scott.bonus WHENEVER NOT SUCCESSFUL;-審核此表未完成的操作
AUDIT SELECT scott.bonus NOT SUCCESSFUL;-對不成功的SELECT審核,常用在訪問者沒有權限時

SEQUENCE-創見序號產生器的關鍵字
ALTER SEQUENCE ord_seq
START WITH 101
MINVALUE 1
MAXVALUE 9999
CYCLE
ORDER;

INCREMENT BY-指定増量,不能為0,默認值為1
START WITH-指定被產生的第一個序列號
MAXVALUE-指定序列號到達的最大值,預設是不指定,也就是10^27
MINVALUE-指定序列號的最小值,預設值是不指定,也就是1
CYCLE-指定序列號到達最大值時,將從最小值開始
NOCYCLE-序列號到達最高值時,不產生另外的序列號
CACHE-指定緩存中的序列號,預設20,但資料庫重啟將遺失
NOCACHE
ORDER-指定序列號按要求的次序產生,預設是NOORDER
NOORDER

CREATE [PUBLIC] SYNONYM FOR XXX;-為XXX創造別名,PUBLIC沒寫表示僅架構擁有者可使用此別名
DROP [PUBLIC] SYNONYM XXX;-刪除別名

ALTER TABLE scott.emp ADD(bonus NUMBER(7,2));-為此TABLE增加一個bonus欄位
ALTER TABLE scott.emp MODIFY(bonus NUMBER(9,2))-將bonus欄位改為9位數

ALTER SESSION SET SQL_TRACE=TRUE;-開啟SQL追蹤功能會降低效能,平常應該關閉

DELETE FROM scott.emp WHERE sal>(SELECT AVG(sal) FROM scott.emp);-刪除薪水大於平均水的列

如果使用TABLE_ALIAS,在語句中引用ㄧ定要使用ALIAS

SCHEMA-架構名,如省略就為前用戶ID

@DBLINK-資料庫連接名

PARTITION-插入到TABLE的特定分區中

SUBPARTITION-插入到TABLE的特定子分區中

INSERT INTO emp(empno,empname,hiredate,mgr,sal) VALUES (7999,'JACK','10-JUN-00',7839,500);
/*ㄧ般插入用法*/

INSERT INTO newemp SELECT * FROM scott.emp WHERE comm>0;
/*使用子查詢,newemp每ㄧ列都接受子查詢的值,子查詢中不包含FOR, UPDATE*/

SELECT ename,dname,hiredate,sal,comm FROM scott.emp,scott.dept WHERE emp.deptno=dept.deptno;
/*由此可見SELECT也可以在FROM後面填入多個表單來取值*/

SELECT ename,dname,hiredate,sal comm FROM scott.emp a,scott.dept WHERE a.deptno=dept.deptno
AND sal>(SELECT AVG(sal) FROM scott.emp) ORDER BY sal;
/*列出同deptno且sal大於平均的,並且以sal由低到高排序*/

SELECT dname Department,MAX(sal) Maximum,MIN(sal) Minimum FROM scott.emp,scott.dept WHERE emp.deptno=dept.deptno GROUP BY dname;
/*每ㄧ個部門檢索最高最低的薪水*/












2013年3月26日 星期二

EXECEL 實用技巧(一)


以上方法用於本應相同的兩個SHEET,但其中一個SHEET的順序被打亂時,可以快速筆對填入該有的資料。


2013年3月24日 星期日

ORACLE SQL 常用語法 常見問題

參考自

如何讓id(自動增加的流水號)再刪除後保持連續(MYSQL)?
select min(a.id)+1 from BookList a left join BookList b on a.id=b.id-1 where b.id is null;

SYNONYM:創建別名
CREATE   SYNONYM   TABLE_A   FOR   A.TABLE_A;

SUBSTR
SUBSTR("ABCDEFG",0,3): ABC
SUBSTR("ABCDEFG",2): CDEFG
SUBSTR("ABCDEFG",0,100): ABCDEFG 

ROWID     REFERENCE
1.rowid 是由object number + file number + block number + row number 四個項目所組成的,
也就是說記錄每一筆列的位置,存在於某一個 block,所以根本不需要搜尋就可以指定讀取某一列,因此它的查詢速度是最快的..

2.而建立index就是把你的主鍵對應一個rowid,所以可以增快查詢速度

3.rowid 是會變動的,所以以rowid當查詢條件並不適當;建index會是比較好的方式,因為oracle會去維護index,當rowid變動時,index中的rowid也會跟著變動





2013年3月22日 星期五

Java 連接MySQL (五) 新增、移除、修改資料、ResultSetMetaData

無法查看此摘要。請 按這裡查看文章。

Java 連接MySQL (四) ResultSet游標控制

參自: 語言技術: Java Gossip (二) <<<超連結

使用無參數的createStatement(),prepareStatement()其執行SQL後所得之ResultSet物件,只能透過next()方法逐筆查詢(沒參數預設就是第一個)。

現在我們指定resultSetType,參數有ResultSet.TYPE_FORWARD_ONLY,
ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.TYPE_SCROLL_SENSITIVE。

SENSITIVE與否差異在於能否取得ResultSet改變值後的資料。

另外必須指定resultSetConcurrency,參數有ResultSet.CONCUR_READ_ONLY與ResultSet.CONCUR_UPDATABLE。

不給參數情況,預設為 ResultSet.TYPE_FORWARD_ONLY,ResultSet.CONCUR_UPDATABLE。

範例
Statement st=con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
                                                              ResultSet.CONCUR_READ_ONLY);
ResultSet rs=st.executeQuery(SELETE * FROM FriendList);
rs.afterLast();     //最後一筆的下一筆
while(rs.previous()){
     System.out.print(rs.getString("name")+"\t");
     System.out.print(rs.getString("age")+"\t");
     System.out.println(rs.getString("email")+"\t");
}
st.close();
con.close();

其他用法
rs.absolute(5);    //移動到第五筆資料
rs.absolute(10);  // ...............十............
rs.absolute(-5);   //倒數第五筆

rs.relative(5);    //若原是第25筆資料,則表示第30筆
rs.relative(-5);   //若原是第25筆資料,則表示第20筆

rs.beforeFirst();  //移動到第一筆資料之前
rs.first();             //移動到第一筆資料
rs.last();              //移動到最後一筆資料


Java 連接MySQL (三) 存入檔案類型的資料

參自: 語言技術: Java Gossip (二) <<<超連結

在欄位上使用BLOB或CLOB資料型態。
BLOB: Binary Large Object,大量的二進位資料。(JDBC提供Blob類別)
CLOB: Character Large Object,大量的文字資料。(JDBC提供Clob類別)

可以使用的PreparedStatement方法,包括setBinaryStream(),setObject(),setAsciiStream,setUnicodeStream()等。

File file=new File("c:/xsd.jpg");
int length=(int)file.length();
FileInputStream fis=new FileInputStream(file);

PreparedStatement ps=con.prepareStatement("INSERT INTO MovieList VALUES(?,?,?)");
ps.setString(1,"下水道");
ps.setString(2,"2010/10/10");
ps.setBinaryStream(3,fis,length);

ps.executeUpdate();
ps.clearParameters();
ps.close();
fis.close();

取得檔案
Statement st=con.createStatement();
ResultSet resultSet=st.executeQuery("SELECT * FROM MovieList");
resultSet.next();
Blob blob=resultSet.getBlob(3);     搭配blob.getBinaryString(), blob.getBytes()使用
Clob clob=resultSet.getClob(3);     搭配clob.getCharacterStream(), clob.getSubString()使用

寫入檔案
FileOutputStream fos=new FileOutputStream("c:/xsd1.jpg");
fos.write(blob.getBytes(1,(int)blob.length());
fos.flush();
fos.close();

For Oracle
Oracle 9i之前,要先建立Blob/Clob的空欄位以取得Blob/Clob游標。
(i)
PreparedStatement ps=con.prepareStatement("INSERT INTO MovieList(id,des,pic) VALUES(?, EMPTY_CLOB(), EMPTY_BLOB())");
ps.setInt(1,1);
ps.executeUpdate();

(ii)
PreparedStatement ps=con.prepareStatement("INSERT INTO MovieList(id,des,pic) VALUES(?, ?, ?)");
ps.setInt(1,1);
ps.setClob(2,CLOB.empty_lob());
ps.setBlob(3,BLOB.empty_lob());
ps.executeUpdate();

小範例
String driver="oracle.jdbc.driver.OracleDriver";
String url="jdbc:oracle:thin:@localhost:1521:demo";
String user="ted";
String password="12345";

Class.forName(driver);
Connection con=null;
PreparedStatement ps=null;

con=DriverManager.getConnection(url,user,password);
con.setAutoCommit(false);

//存入Blob/Clob空欄位
ps=con.prepareStatement("INSERT INTO MovieList(id,des,pic) VALUES(?, EMPTY_CLOB(), EMPTY_BLOB())");
ps.setInt(1,1);
ps.executeUpdate();
ps.close();

//查詢Blob/Clob欄位以取得游標
ps=con.prepareStatement("SELECT des,pic FROM MovieList WHERE id=? for update");
ps.setInt(1,1);
ResultSet rs=ps.executeQuery();
rs.next();

Clob clob=(Clob)rs.getClob(1);
Blob blob=(Blob)rs.getBlob(2);

clob.putString(1,"...ABC...");

File file=new File("c:/xsd.jpg");
FileInputStream fis=new FileInputStream(file);
OutputStream os=blob.getBinaryOutputStream();

Byte[] buffer=new Byte[1024];
while(fis.read(buffer) > 0)
      os.write(buffer);
fis.close();
os.close();

ps=con.prepareStatement("UPDATE MovieList SET des=?,pic=? WHERE id=?");
ps.setClob(1,clob);
ps.setBlob(2,blob);
ps.setInt(3,1);
ps.executeUpdate();

ps.close();
con.commit();


2013年3月21日 星期四

Java 連接MySQL (二) Statement 處理方式

無法查看此摘要。請 按這裡查看文章。

Java 連接MySQL (一)

無法查看此摘要。請 按這裡查看文章。

JavaScript 事件處理

onFocus: 用戶為了輸入而選擇(點擊)select、text、textArea等位置時。

onBlur: 於select、text、password、textArea失去焦點時。

onChange: 在select、text、textArea的值被改變且失去焦點時。

onClick: 當一個對象被點擊時。

onLoad: 完成載入時,通常寫在body內。

onUnload: 退出時,通常寫在body內。

onMouseOver: 滑鼠覆蓋到對象時。

onMouseOut: 滑鼠從對象上移開時。

onSelect: 當form對象中的內容被選中時。

onSubmit: 透過提交按鈕提交一個表單時。
               
        <form name="xxx" action="xxx.html" onSubmit="JavaScript:return true;"></form>
                                                                                       return false則不動作。

JavaScript的3種框兒

alert : 警告框,沒有回傳值。

prompt : 輸入(詢問)框,回傳輸入的內容,但並不常用。

confirm : 確認框,傳回boolean值,按下確定傳回true,取消傳回false。

<script language="JavaScript">
     alert("ok");
</script>



<script language="JavaScript">
     var name;
     name=prompt("請輸入你的名字");
     document.write("hello"+name);
</script>



<script language="JavaScript">
     if(confirm("確定要刪除?")){
          document.xxx.submit();
     }
</script>



2013年2月27日 星期三

讓EditText不被小鍵盤遮住

原來只要在AndroidManifest.xml的activity節點中加個屬性即可

android:windowSoftInputMode="stateHidden|adjustPan"

如此便可以在載入activity時不會預設打開小鍵盤,也可以讓小鍵盤打開時將畫面自動往上推,而不會遮住edittext,有些人說一定要把最頂層layout改成scrollView或listView等帶卷軸的,其實不用..

另外茶道一些相關用法

"stateUnspecified" 未指定小鍵盤隱藏或可見,由系統自訂。這是小鍵盤的默認設定(有打等於沒打?)。
 
"stateUnchanged" 小鍵盤保持上次的狀態。
 
"stateHidden" 隱藏小鍵盤。
"stateAlwaysHidden" 小鍵盤總是被隱藏。
 
"stateVisible" 小鍵盤是可見的。
 
"stateAlwaysVisible" 小鍵盤總是可見的。
 
"adjustUnspecified" 已默認的方式調整?
 
"adjustResize" 該Activity自動調整大小留空間給小鍵盤。
 
"adjustPan" 該Activity" 不 "自動調整大小留空間給小鍵盤。相反,視窗將自動移動以避免小鍵盤遮到東西。

Android系統16進位色碼

android:textColor="#000000"
基本的紅綠藍

android:textColor="#ff000000"
最前面兩碼表示整體透明度(0~255個等級)

2013年2月23日 星期六

使用ContentProvider_20130223


package com.example.booksystem_testcontentprovider_20130223;

import android.net.Uri;
import android.os.Bundle;
import android.app.Activity;
import android.content.ContentResolver;
import android.database.Cursor;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class TestContentProviderActivity extends Activity {
private ContentResolver myContentResolver;
//建立好用來連結的URI物件,內容就是ContentProvider中的Authority+TableName
private Uri myUri=Uri.parse("content://tw.com.jimbo.FindBook/BooksInfo");
private Button btn1;
private TextView tv1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test_content_provider);
//在onCreate()階段取得ContentProvider實體
myContentResolver=getContentResolver();
findView();

btn1.setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View v) {
// TODO Auto-generated method stub
//呼叫query方法回傳Cursor物件
Cursor myCursor=myContentResolver.query(myUri, null, null, null, null);
if(myCursor != null && myCursor.getCount() > 0){
tv1.setText("");
while(myCursor.moveToNext()){
String isbn=myCursor.getString(1);
String bookName=myCursor.getString(2);
String author=myCursor.getString(3);
tv1.append(isbn+"|"+bookName+"|"+author+"\n");
}
}
}
});
}

private void findView(){
btn1=(Button)findViewById(R.id.button1);
tv1=(TextView)findViewById(R.id.textView1);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_test_content_provider, menu);
return true;
}

}

建立ContentProvider_20130223


package com.example.booksystem_20130219;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.net.Uri;

//在含有資料庫的App中建立一個class繼承ContentProvider
public class BookDBContentProvider extends ContentProvider{
//建立獨一無二的域名
private final static String AUTHORITY="tw.com.jimbo.FindBook";
//供查詢資料表名稱
private final static String DB_TABLE_NAME="BooksInfo";
//建立連此資料庫的路徑(URI物件),注意是public
public final static Uri CONTENT_URI=Uri.parse("content://"+AUTHORITY+"/"+DB_TABLE_NAME);
//建立URI根目錄及資料表的子目錄(節點)
private final static int URI_ROOT=0,DB_TABLE_BOOKS=1;
//建立URI比對物件,建構式放入URI根目錄(節點)的int值
private final static UriMatcher myUriMatcher=new UriMatcher(URI_ROOT);
private BookHelper myBookHelper;
//預先載入區塊加入URI到這個比對物件
static{
myUriMatcher.addURI(AUTHORITY, DB_TABLE_NAME, DB_TABLE_BOOKS);
}

@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
// TODO Auto-generated method stub
return 0;
}

@Override
public String getType(Uri uri) {
// TODO Auto-generated method stub
return null;
}

@Override
public Uri insert(Uri uri, ContentValues values) {
// TODO Auto-generated method stub
return null;
}

//於onCreate()時期產生BookHelper的物件,產生後回傳true
@Override
public boolean onCreate() {
// TODO Auto-generated method stub
myBookHelper=new BookHelper(getContext());
return true;
}

//覆寫query方法
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
// TODO Auto-generated method stub
//檢查是否為查詢的節點,不是則回傳null
if(myUriMatcher.match(uri) != DB_TABLE_BOOKS){
return null;
}
Cursor myCursor=myBookHelper.query();
return myCursor;
}

@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
// TODO Auto-generated method stub
return 0;
}

}
記得在manifest的application中加入
<provider 
android:name="com.example.booksystem_20130219.BookDBContentProvider"
 android:authorities="tw.com.jimbo.FindBook">            
</provider>