2011年12月14日 星期三

透過php與sql連結取得資料回來的方法

目的:
利用appserv與php從sql資料庫取得資料
例如我想搜尋一個名單資料表中編號欄位為「N01」的資料
就會打sql:select * from namelist where num='N01'
那N01就是我要從程式送出的變數
然後抓php印出來的結果
這裡示範程式回傳的是字串,不過它會把php裡echo出來的東西都存在同一個變數裡
我把要印的排好後echo出來、存回來後用split字串處理來分割存成陣列,再去運用

流程:
一個輸入條件的edittext、一個送出訊息的按鈕、一個印出結果的textView
按按鈕後用HttpPost送出post訊息、php取回資料、分割字串成陣列

sql的一些設定:
(1)下載並安裝appserv(我用2.5.10)
(2)若是從mysql取資料就不用特別設定,
若是從mssql則要:
1.下載mssql的驅動:Microsoft Drivers for PHP for SQL Server
2.解壓縮後裡面所有的dll檔案複製到C://Windows/System32還有C://Appserv/php5/ext裡面
3.改變appserv的php.ini檔,把以下的內容放到php.ini裡的Windows Extensions那邊的後面
(有一推extension=xxxx.dll的地方)

extension=php_pdo_sqlsrv_52_nts_vc6.dll
extension=php_pdo_sqlsrv_52_ts_vc6.dll
extension=php_pdo_sqlsrv_53_nts_vc6.dll
extension=php_pdo_sqlsrv_53_nts_vc9.dll
extension=php_pdo_sqlsrv_53_ts_vc6.dll
extension=php_pdo_sqlsrv_53_ts_vc9.dll
extension=php_sqlsrv_52_nts_vc6.dll
extension=php_sqlsrv_52_ts_vc6.dll
extension=php_sqlsrv_53_nts_vc6.dll
extension=php_sqlsrv_53_nts_vc9.dll
extension=php_sqlsrv_53_ts_vc6.dll
extension=php_sqlsrv_53_ts_vc9.dll

而且extension前面不能加『;』
並把裡面;extension=php_mssql.dll的分號去掉
4.記得重開appserv的服務
5.連mssql跟連mysql的語法也不一樣
<?
//連接資料庫
$serverName = "伺服器名稱";
//$connectionInfo寫法必須使用array
$connectionInfo = array("Database"=>"資料庫名稱","Uid"=>"帳號","Pwd"=>"密碼","CharacterSet" => "UTF-8");
//在這個版本,參數多了CharacterSet,可以選定UTF-8內碼

$conn = sqlsrv_connect( $serverName, $connectionInfo);
if ( $conn === false ) {
    sqlsrv_errors();
  }
?>
我試著把這段程式碼用include的來代替連結,不過不曉得為什麼好像行不通
所以我用另外一個php把伺服器名稱、資料庫名稱、帳號密碼等變數宣告在裡面
然後要連接的時候再把那個php用include載入,在這裡使用變數
就不用在把php放到別台的時候又要一個個改
6.執行mssql的語法範例
<?
//範例
$sql="select * from SystemUser";
//sqlsrv_query($conn,$sql) $conn是上面那段連結伺服器的變數
$result=sqlsrv_query($conn,$sql)or die("sql error".sqlsrv_errors());

//用迴圈印出內容,後面加一個分割用的辨識符號
while ($avc=sqlsrv_fetch_array($result)){
echo $avc["欄位名稱"].":";
}

?>

android程式:
public class phpTest extends Activity{

private EditText posttxt;
private Button postBtn;
private TextView postResult;
String msg;
String txt;
//php的網址

private String postUrl="http://localhost:8080/phptest.php";

 @Override
    public void onCreate(Bundle savedInstanceState) {
//中略
//按鈕點擊事件

postBtn.setOnClickListener(new OnClickListener(){
     public void onClick(View v) {


        msg = posttxt.getEditableText().toString();
        String result;
        result = sendPostDataToInternet(msg);
         //使用「:」進行切割
         String[] names = result.split(":");
        //組合結果
        for(int i=0;i<=names.length;i++){
        txt=txt+"和"+names[i];
    }
  postResult.setText(txt+"");
 }

}


private String sendPostDataToInternet(String strTxt)
    {
        /* 建立HTTP Post連線 */
        HttpPost httpRequest = new HttpPost(postUrl);
        /*
        * Post運作傳送變數必須用NameValuePair[]陣列儲存
        */
        List<NameValuePair> params = new ArrayList<NameValuePair>();
        params.add(new BasicNameValuePair("data", strTxt));
        try
        {
            /* 發出HTTP request */
            httpRequest.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));
            /* 取得HTTP response */
            HttpResponse httpResponse = new DefaultHttpClient()
                    .execute(httpRequest);
            /* 若狀態碼為200 ok */
            if (httpResponse.getStatusLine().getStatusCode() == 200)
            {
                /* 取出回應字串 */
                String strResult = EntityUtils.toString(httpResponse
                        .getEntity());

                // 回傳回應字串
                return strResult;
            }

        } catch (ClientProtocolException e)
        {
            Toast.makeText(this, e.getMessage().toString(), Toast.LENGTH_SHORT)
                    .show();
            e.printStackTrace();
        } catch (IOException e)
        {
            Toast.makeText(this, e.getMessage().toString(), Toast.LENGTH_SHORT)
                    .show();
            e.printStackTrace();
        } catch (Exception e)
        {
            Toast.makeText(this, e.getMessage().toString(), Toast.LENGTH_SHORT)
                    .show();
            e.printStackTrace();
        }
        return null;
    }}

2011年12月13日 星期二

實現系統設定時存使用者設定於手機內的功能-SharedPreferences

目的:
要有設定的功能,讓使用者調整一些變數,然後把設定存起來

作法:
使用SharedPreferences類別,存在這個物件裡的資料會變成xml檔案放在/data/data/<package name>/shared_prefs
在宣告的時候第一個欄位就是檔案名稱
然後在要用到這個變數的activity裡用getSharedPreferences抓值
系統設定的介面可以在按下項目後跳出一個有editText的dialog窗給使用者
或者按下項目後跳到有選項的畫面
可以存的值類型:
putBoolean(String key, boolean value)
putFloat(String key, float value)
putInt(String key, int value)
putLong(String key, long value)
putString(String key, String value)
putStringSet(String key, Set<String> values)
相對也有抓值的方式:
getAll()
getBoolean(String key, boolean defValue)
getFloat(String key, float defValue)
getInt(String key, int defValue)
getLong(String key, long defValue)
getString(String key, String defValue)
getStringSet(String key, Set<String> defValues)
程式碼:
//前略 以下是已經把dialog窗叫出來後的程式

//sys_pref=檔案名稱
//MODE_PRIVATE=若這個檔案不存在就創建一個此程式專屬的檔案,若存在就覆蓋
SharedPreferences sp = getSharedPreferences("sys_pref",MODE_PRIVATE);

//把要存的值丟到這個SharedPreferences檔
//SHARED_syssetting1=名稱,後面一欄則是內容值

sp.edit().putString("SHARED_syssetting1", text1.getText()).commit();

//取出設定值
//getString是取字串,前面是名稱,後面是當抓不到值要回傳的內容

text1.setText(sp.getString("SHARED_syssetting1", ""));

有自動完成功能的EditText-AutoCompleteTextView

狀況:
一個有一串名字的清單(ListView)
因為太長 想找某個項目要一直滑動很麻煩

目的:
在畫面上方放一個搜尋用的edittext,打第一個字就跑出搜尋選項,
然後點下選項後跑到該項

XML:
使用AutoCompleteTextView,其他無特別之處

程式碼:
//前略
public class AutoText extends Activity {

//宣告要用的清單字串陣列
        String[] namelist;
//宣告AutoCompleteTextView
        AutoCompleteTextView myAutoCompleteTextView;
/*--------------------------*/
/*然後把資料丟到陣列裡*/
/*--------------------------*/

@Override
    public void onCreate(Bundle savedInstanceState) {
//清單建立
        ListView list = (ListView)findViewById(R.id.nameListView);
//中略



//快速搜尋
//把namelist丟到一個ArrayAdapter,android.R.layout.simple_dropdown_item_1line是內建的一行用xml
        ArrayAdapter<String> qsadapter = new ArrayAdapter<String>(this,android.R.layout.simple_dropdown_item_1line,namelist);
//建立AutoCompleteTextView
        myAutoCompleteTextView = (AutoCompleteTextView) findViewById(R.id.qstextview);
//把內容丟進去
        myAutoCompleteTextView.setAdapter(qsadapter);
//聚焦於第一行,不做這行也沒差
        myAutoCompleteTextView.setThreshold(1);



//快速搜尋點擊事件
     myAutoCompleteTextView.setOnItemClickListener(new OnItemClickListener(){ 
            public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, 
                    long arg3) {
             
             //搜尋namelist,取得選項位置
               //從頭迴圈到尾,若內容等於所點項目則聚焦到該項
              //這裡可能有更好的搜尋法
             for(int i=0;i<namelist.length;i++){
              if(myAutoCompleteTextView.getText().toString().equals(namelist[i].toString())==true){
               list.setSelection(i);
              }              
             }             
            } 
        });

進入Activity時不要先出現小鍵盤

現象:
當activity有edittext時,一進入此activity就會自動聚焦於edittext而出現小鍵盤
但是edittext還是得用小鍵盤,又不能把這個edittext的鍵盤取消
而且改變edittext在xml的設定,把next focus left還有next focus up指定為其他地方的話
也只會在模擬器起作用
手機(野火)上跑還是一樣出現鍵盤

目的:不要一進入畫面就出現小鍵盤
作法:
1.打開AndroidManifest.xml
2.把頁籤切換到application
3.在application nodes選取想要取消聚焦的activity
4.右邊的window soft input mode選擇statehidden
就完成了

2011年5月25日 星期三

建立一個可以滑動的多圖片Gallary

1.目標:建立一個很多圖串起來能夠滑動的物件
2.xml:裡面要擺一個gallary物件,並且在drawable資料夾裡放入想擺的圖片
3.實作:
public class checkmain extends Activity {

@Override
public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);
setContentView(R.layout.checkmain);
//取得GALLARY物件
((Gallery) findViewById(R.id.photogallary)).setAdapter(new ImageAdapter2(this));
}

class ImageAdapter2 extends BaseAdapter
{ 
/* 類別成員 myContext為Context父類別 */ 
private Context myContext; 

/*使用R.drawable裡的圖片作為圖庫來源,型態為整數陣列*/
private int[] myImageIds =
{ 
//photoxx是圖片檔名,跟擺在drawable資料夾裡的一樣
R.drawable.photo1,
R.drawable.photo2,
R.drawable.photo3, 
R.drawable.photo4,
R.drawable.photo5,
}; 
/* 建構子只有一個參數,即要儲存的Context */ 
public ImageAdapter2(Context c) { this.myContext = c; } 

/* 回傳所有已定義的圖片總數量 */ 
public int getCount() { return this.myImageIds.length; } 

/* 利用getItem方法,取得目前容器中影像的陣列ID */ 
public Object getItem(int position) { return position; } 
public long getItemId(int position) { return position; }

/* 取得目前欲顯示的影像View,傳入陣列ID值使之讀取與成像 */ 
public View getView(int position, View convertView, ViewGroup parent)
{ 
/* 建立一個ImageView物件 */
ImageView i = new ImageView(this.myContext);

i.setImageResource(this.myImageIds[position]);
i.setScaleType(ImageView.ScaleType.FIT_XY); 

/* 設定這個ImageView物件的寬高,單位為dip */ 
i.setLayoutParams(new Gallery.LayoutParams(120, 120)); 
return i; 
} 

/*依據距離中央的位移量 利用getScale回傳views的大小(0.0f to 1.0f)*/
public float getScale(boolean focused, int offset)
{ 
/* Formula: 1 / (2 ^ offset) */ 
return Math.max(0,1.0f/(float)Math.pow(2,Math.abs(offset)));
} 
}
}

建立menu按鈕

1.目標:建立按下menu後下方浮出的按鈕列
2.xml:隨便一個
3.實作:

 public boolean onCreateOptionsMenu(Menu menu)
    //在啟動時建立menu選項

    {
      menu.add(0, 0, 0,"新增");
      //加入menu選項

      menu.add(0, 1, 1,"離開");
      return super.onCreateOptionsMenu(menu);
    }
    //當選項被選的時候的事件
    public boolean onOptionsItemSelected(MenuItem item)
    {
      super.onOptionsItemSelected(item);
      //switch case判斷點的是哪個鈕

      switch(item.getItemId())
      {
        case 0:
          Intent intent3 = new Intent(studenteditlist.this,studentadd.class);
         startActivity(intent3);
        break;
        case 1:
          finish();
          break;
      }
      return true;
    }

2011年5月17日 星期二

取得系統日期

1.目標:印出系統目前的年月日
2.XML設計:
   (1)1個XML:main.xml裡有1個textview:dateTextView
3.實作:
public class main extends Activity {
 /*宣告三個日期變數,用來抓年月日*/
 private int mYear;
 private int mMonth;
 private int mDay;
/*宣告物件變數tv,在程式碼裡指定tv到textview用的*/
 TextView tv;
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
     /*取得日期*/
     Calendar c=Calendar.getInstance();//建立抓日期物件c
     mYear=c.get(Calendar.YEAR);//年
     mMonth=c.get(Calendar.MONTH);//月
     mDay=c.get(Calendar.DAY_OF_MONTH);//日
     
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);//設定載入的xml
      
        tv= (TextView) findViewById(R.id.dateTextView);
        /*指定tv到xml中的textview元件*/
        
        updateDisplay();
        //呼叫自定方法,用來把日期丟到textview裡面
    } 


private void updateDisplay()
{//設定tv的字,用append()方法加入字串,數字用自定方法轉成二個字元
 tv.setText(
 new StringBuilder().append(mYear).append("年")
        .append(format(mMonth + 1)).append("月")
        .append(format(mDay)).append("日")
   ); 
}

//自定方法,如果只有一位數的時候就加入一個0
private String format(int i) {
 String s=" "+i;
 if(s.length()==1) s="0"+s;
 return s;
}
}

2011年5月16日 星期一

切換Activity

1.目標:按下按鈕後切換到另一個Activity
2.XML設計:
    (1)a.xml裡有按鈕b1,
    (2)b.xml裡有按鈕b2,
3.實作:
a.xml
public class a extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.a);//載入a.xml
        
        Button b1 = (Button) findViewById(R.id.button1);//宣告按鈕b1
        b1.setOnClickListener(new Button.OnClickListener()//於b1設定點擊監聽
        {
          public void onClick(View v)//設定click事件
          {
            Intent intent1 = new Intent(a.this,b.class);
            //透過intent呼叫b
           startActivity(intent1);//執行activity
          }
        });
     }
}
b.xml
public class b extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.b);//載入b.xml
       
        Button b2 = (Button) findViewById(R.id.button2);//宣告按鈕b2
        b2.setOnClickListener(new Button.OnClickListener()//於b2設定點擊監聽
        {
          public void onClick(View v)//設定click事件
          {
           finish();//關閉此activity
          //因為呼叫activity算是開啟一個form,若在此也使用呼叫activity來切回去的話,會變成現存兩個a的狀況,所以只用finish結束掉就好了。
          //當然若a那邊也設定執行b後finish就沒有這個問題。
          }
        });
    }    
}

至於建立新的activity時,一定要在AndroidManifest.xml內加上
<activity android:name=".(Activity的名字)"></activity>
讓系統啟動時認識到有這個activity存在,才能正常執行。