2013-07-09

Android跨平台應用(一) - 運用AD登入

人永遠是不會滿足的,而且老闆更不容易滿足,這是真的!QQ"

老闆不滿足,他也不會讓你滿足(薪水),所以當一個稱職的員工,就要盡力滿足他

好了,廢話說完了,再來進入正題.....

當Android原生寫到一定程度時通常都會想還有什麼可以應用

跨平台應用是會被用到也很常會被使用到的,所以就來往這方式研究

這次來研究如果運用在公司內很常見的AD來登入自己開發的Android應用程式

AD是什麼?AD(Active Directory)說明在這裡

也可以在左邊用Active Directory進維基百科查詢,這裡就不再說明

這樣的目的當然是為了SSO(Single-Sign-On單一登入),不用重覆建立登入資料

看起來好像很方便,實際上.........也是很方便,哈!而且如果不這樣做,老闆是不會滿足的xd

先來說一下原理好了:




佈局:

1.Android應用程式放在Android手機內(廢話..)

2.Web Service放在可對外的Server主機內

3.AD Server放在公司內部Server主機內


說明:

我的設計是手機端經由Web Service傳送帳號密碼給AD Server進行驗證

其實也是可以直接傳給AD Server進行驗證,但為什麼要這樣設計呢?

因為兩個原因:1.可以加密確保帳密的安全
                            2.AD Server IP位置改變時不用重新修改Android應用程式,使用者還要更新
                               只需修改Web Service對應的AD Server 的IP位置即可

光原因二就有必要用這種設計方式了,因為AD Server IP改變後如果使用者沒有更新新的apk檔,基本上這個程式就會出錯,所以中間加一個Web Service彈性是比較高的

再來看一下程式碼:

Web Service
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Data.OleDb;
using System.Collections;
using System.Data;
using System.DirectoryServices;

/// <summary>
/// Search 的摘要描述
/// </summary>
[WebService(Namespace = "http://WebServiceForApp/")]//必須和android手機內的Namespace對應
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
// 若要允許使用 ASP.NET AJAX 從指令碼呼叫此 Web 服務,請取消註解下一行。
// [System.Web.Script.Services.ScriptService]
public class Search : System.Web.Services.WebService {
    string _path;
    string _filterAttribute;

    public OleDbConnection Conn = new OleDbConnection(System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);

    public Search () {

        //如果使用設計的元件,請取消註解下行程式碼 
        //InitializeComponent(); 
    }

    [WebMethod]
    public bool Verification(string username,string pwd)
    {
        string domain = "192.168.2.211";//AD Server IP位置
        bool V = true;
        _path = "LDAP://" + domain;
        string domainAndUsername = domain + @"\" + username;
        DirectoryEntry entry = new DirectoryEntry(_path, domainAndUsername, pwd);

        try
        {
            //Bind to the native AdsObject to force authentication.            
            object obj = entry.NativeObject;
            DirectorySearcher search = new DirectorySearcher(entry);

            search.Filter = "(SAMAccountName=" + username + ")";
            search.PropertiesToLoad.Add("cn");
            SearchResult result = search.FindOne();

            //帳號是:it01
            //回覆驗證資料,無為null
            //有Data內容會是這個樣子:LDAP://192.168.2.211/CN=it01,OU=資訊部,OU=管理處,DC=goldjoint,DC=com
            if ((result == null))
            {
                V = false;
            }

            //Update the new path to the user in the directory.
            _path = result.Path;
            _filterAttribute = (string)result.Properties["cn"][0];

        }
        catch (Exception ex)
        {
            //throw new Exception("Error authenticating user. " + ex.Message);
            V = false;
        }


        return V;
    }
}


注意:
手機端我是有使用到ksoap2
所以必須先掛載ksoap2的jar檔進來,以便連結Web Service
網路上掛載的方法很多都有寫,所以這裡就不再重覆,請先掛載。



Android手機端
void WebData()
{
//從網路上獲取資料
String NAMESPACE = "http://WebServiceForApp/";//必須和Web Service內的Namespace對應
String URL = "http://你的WebService位置/AppWebService/Search.asmx";
String SOAP_ACTION = "http://WebServiceForApp/Verification";//NAMESPACE+WebService METHOD_NAME
String METHOD_NAME = "Verification";  

//Data
SoapObject Request = new SoapObject(NAMESPACE, METHOD_NAME); 
PropertyInfo sayHelloPI = new PropertyInfo();
sayHelloPI.setName("username");//加入帳號
sayHelloPI.setValue(id);
sayHelloPI.setType(String.class);
Request.addProperty(sayHelloPI);

PropertyInfo sayHelloPI2 = new PropertyInfo();
sayHelloPI2.setName("pwd");//加入密碼
sayHelloPI2.setValue(pw);
sayHelloPI2.setType(String.class);
Request.addProperty(sayHelloPI2);

//Request.addProperty("ID",strSearch);
SoapSerializationEnvelope soapEnvelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
soapEnvelope.dotNet=true;
soapEnvelope.setOutputSoapObject(Request);
HttpTransportSE aht=new HttpTransportSE(URL);
//aht.debug=true;
try {
aht.call(SOAP_ACTION, soapEnvelope);
//SoapObject result = (SoapObject)soapEnvelope.getResponse();
SoapPrimitive result = (SoapPrimitive)soapEnvelope.getResponse();//單純Data用這個

//存入回傳資料(String Check存入True or False)
check = result.toString();//Check就能拿來檢查是否有AD驗證過了


} catch (SoapFault e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (XmlPullParserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}	
}

說明:

有幾個重點要注意:
1.Namespace對應,Web Service和Android手機端的Namespace一定要相同
2.我是有另外專為這個Web Service在IIS上新增一個網站做控管(這點好像不是什麼重點xd)
3.加不加密看狀況,我是走一般網路的80 port,也能走其他的port,但要另外開放和設定
   應用程式封裝成apk檔有一定的安全性了,因為Android 2.3.3以後的版本Google有加入亂碼
   ,程式碼會重排,所以要知道的人還是會知道(應該是自己人xd),如果還是要小心一點可以
   加密,反正可以在Web Service解密就好,這樣就能再送AD Server驗證,本人完全沒加密xd

以上程式碼是可以RUN的,而且也在RUN中,所以如果你不能RUN請留言我幫您看一下為什麼不能RUN。
 
我只取出部份的程式碼,其他部份可能要自己拼湊,不要跟我要全部的程式碼,因為那不是我的,所以我不能給你。


Java Script Window Print-另開視窗方式列印

Web表單設計時還蠻常需要用到列印的,一般都會用Reporting Service

這裡教你用Java Script的方式,另開一個視窗列印表單,順便幫自己記錄程式碼^^


先用DIV框定範圍
<div id="print" align="center">
  表單內HTML程式碼...
 .
 .
 .
 </div>


在Button加入列印OnClientClick事件
<asp:Button ID="Button7" runat="server" Text="列印" OnClientClick="myPrint(document.getElementById('print'));return false;" />


加入JavaScript列印事件
<script type="text/javascript">
        function myPrint(obj) {
            //打開一个新窗口newWindow
            var newWindow = window.open("打印窗口", "_blank");
            //要打印的div的内容
            var docStr = obj.innerHTML;
            newWindow.document.write('<div align="center"><asp:Label ID="lb_printTitle" runat="server" Font-Size="X-Large" style="font-family: 微軟正黑體; font-weight: 700" Text="部門領用統計表"></asp:Label></div>');
            //打印内容寫入newWindow文檔
            newWindow.document.write(docStr);
            //關閉文檔
            newWindow.document.close();
            //調用打印機
            newWindow.print();
            //關閉newWindow頁面
            newWindow.close();
        }
     </script>


畫面(瀏覽器:IE10)
表單

另開列印視窗


注意
因為另開視窗是一個全新的視窗,所以第一次用可能會發現為什麼格式什麼全跑了
那是因為CSS沒有一起過去,所以在newWindow.document.write(.......)要把CSS一起
傳過去,不然就是寫在表單中,這樣出現的表單才會和你想要的一樣。

2013-01-30

Android 手機資料庫(六) - 使用Transaction(交易)

在Activity使用新增、修改、刪除時,有時候都會遇到需要同時處理多筆資料的狀況

這時候如果用一般的寫法,如果在中間處理的資料出錯了,那麼資料就會不完整寫入資料庫了

怎麼辦呢?這個時候就需要用到Transaction(交易),Transaction在很多程式中都有用到

而且是一定會用到,所以我們下面就來看一下在Android系統中該怎麼使用Transaction交易

來達到多筆資料同時處理的目的,其實和其他程式一樣很簡單的。

如果您看過前幾篇資料庫的文章的話,應該會知道其中會有一段db = helper.getWritableDatabase();

只要在這個下面加入:db.beginTransaction();//建立交易

之後就可以正常的用db.insert、db.update等一般資料庫寫入

在最後面都寫完資料庫後得加入此程式碼:db.setTransactionSuccessful();//正式寫入資料庫中

然後我們一般會使用try{}catch{}來抓取出錯誤的訊息,只要在catch中加入db.endTransaction();//結束交易

只要在寫入的過程中有一個出錯了,交易就會中斷,以達到多筆資料同進同出,就這麼簡單

以上就是為您介紹在Android系統中怎麼使用Transaction的方法,謝謝。

2013-01-23

Android 實用程式碼片段(一) - 返回鍵退出(onKeyDown)、返回鍵退出確認

現在應用程式上應該都有按下返回鍵會詢問是否離開的訊息,但這是怎麼做到的呢?

下面為您介紹此實用程式碼:

public boolean onKeyDown(int keyCode, KeyEvent event) {//捕捉返回鍵
        if ((keyCode == KeyEvent.KEYCODE_BACK)) {   
        	ConfirmExit();//按返回鍵,則執行退出確認
        	return true;   
        }   
        return super.onKeyDown(keyCode, event);   
    }
    public void ConfirmExit(){//退出確認
    	AlertDialog.Builder ad=new AlertDialog.Builder(MyOpenDataActivity.this);
    	ad.setTitle("離開");
    	ad.setMessage("確定要離開?");
    	ad.setPositiveButton("是", new DialogInterface.OnClickListener() {//退出按鈕
			public void onClick(DialogInterface dialog, int i) {
				// TODO Auto-generated method stub
				MyOpenDataActivity.this.finish();//關閉activity
 
			}
		});
    	ad.setNegativeButton("否",new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int i) {
				//不退出不用執行任何操作
			}
		});
    	ad.show();//示對話框
    }

只要在onCreate之外加入上面這段程式碼,程式就會在該Activity加入按下返回鍵時的詢問。


2012-12-16

利用檢視原始碼了解在臉書上誰最關注你(妳)

網路上流傳一種用『檢視原始碼』就能知道誰最關注你(妳)的方法

我來給它實作看看:


步驟一:登入你()Facebook到個人首頁


步驟二:在空白處按右鍵,選取『檢視原始碼』




步驟三:搜尋『InitialChatFriendsList


步驟四:List後面一串一串的數字第一個就是最關注你()的人


步驟五:把此串數字加到後面”www.facebook.com/”放到網址上去就知道是誰了



實作的結果真的是我朋友沒錯,不過是不是最關注我的我就不知道了

反正好玩就好了,您說對不對!





2012-12-10

Android下拉選單(spinner)應用(五) - 更換字體大小、顏色

一般網路上都會教一些基本下拉選單(spinner),套用simple_spinner_dropdown_item或

simple_spinner_item這些基本模板,但有時想改變Spinner內的文字大小及顏色又不知從哪下手

今天就來教大家怎麼改變Spinner內的文字大小及顏色,當然也包含對齊方式

我用比較簡單的方法直接由Layout下手去修改Spinner內文字的字體大小及顏色

步驟一:

在res-->layout內新增一個myspinner.xml的android xml檔,貼上下列程式碼

myspinner.xml
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/text1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:ellipsize="marquee"
    android:gravity="center"
    android:paddingLeft="8dip"
    android:singleLine="true"
    android:textColor="#8B008B"
    android:textSize="32sp"
    android:textStyle="bold" >
</TextView>


步驟二:

回到java程式碼,假設我們已經在main.xml中加入一個下拉選單spinner1了

基本的下拉選單都是這樣寫的:
//將可選内容與ArrayAdapter連接起來 
adapter = new ArrayAdapter<String>(this,android.R.layout.simple_spinner_item,Blood_group);
//對應控件
spinner = (Spinner) findViewById(R.id.spinner1);
//設置下拉列表的風格
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
//將adapter 添加到spinner中  
spinner.setAdapter(adapter); 

換成下面這個樣子:
//將可選内容與ArrayAdapter連接起來 
adapter = new ArrayAdapter<String>(this,R.layout.myspinner,Blood_group);
//對應控件
spinner = (Spinner) findViewById(R.id.spinner1);
//設置下拉列表的風格
adapter.setDropDownViewResource(R.layout.myspinner);
//將adapter 添加到spinner中  
spinner.setAdapter(adapter);


為什麼有兩個地方是要換成myspinner的呢?

因為adapter是代表內容(也就是下拉時)

setDropDownViewResource是代表靜止未點選下拉時的樣式(感謝網友指教)

setDropDownViewResource是代表點選下拉時彈出的樣式

執行後畫面



文字被我改為紫色、字體大小變32、置中對齊

這樣簡簡單單兩個步驟就能改變下拉選單的三種樣式設定了

以上介紹,謝謝各位!!

ps:貼上一些參數(spinner、adapter、Blood_group)的宣告,不然新手會對應不起來
private Spinner spinner;  
 private ArrayAdapter<String> adapter;  
 private static final String[] Blood_group={"A型","B型","O型","AB型","其他"};

2012-12-01

Android TextView應用(一) - 跑馬燈

一般的HTML有跑馬燈功能,那Android應用程式能否用跑馬燈功能呢?可以的!

只要用TextView文字列就可以做出跑馬燈功能了,今天來做的比較特別一點

就是我改用EditText輸入文字後,傳給TextView後做自輸入型的跑馬燈功能

先說一下我的開發環境吧,雖然沒什麼太大影響

我用的Android版本是4.0.3,作業系統是Window 7 64位元,eclipse當然也是for 64位元的

接下來就來看看程式碼吧!


main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

    <TextView
        android:id="@+id/tv_ouput"
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="15dp"
        android:textSize="30sp"
        android:singleLine="true"
        android:ellipsize="marquee"
        android:marqueeRepeatLimit="marquee_forever"
        android:focusableInTouchMode="true"
        android:focusable="true"
        android:text="@string/hello_world" />

    <EditText
        android:id="@+id/et_input"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/tv_ouput"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="17dp"
        android:ems="10"
        android:hint="請輸入跑馬燈訊息..." >
    </EditText>

    <Button
        android:id="@+id/btn_submit"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/et_input"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="28dp"
        android:text="@string/submit" />

</RelativeLayout>






TripleSpinnerActivity
package jim.demo.rundemo;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends Activity {

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  final TextView tv=(TextView)findViewById(R.id.tv_ouput);
  
  
  final EditText et = (EditText)findViewById(R.id.et_input);
  
  Button btn = (Button)findViewById(R.id.btn_submit);
  btn.setOnClickListener(new OnClickListener(){

   @Override
   public void onClick(View v) {
    tv.setText(et.getText().toString());
    tv.setSelected(true);
   }
   
  });
 }

 @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_main, menu);
  return true;
 }

}


執行後畫面









說明:

1‧TextView在xml上說明如下:
//單行文本顯示,
android:singleLine="true"
//跑馬燈效果
android:ellipsize="marquee"
//重複次數的設定,默認是無窮次
android:marqueeRepeatLimit="marquee_forever"
//取得焦點,這是讓跑馬燈一開始就可以跑
android:focusableInTouchMode="true"
android:focusable="true"

2.Activity中只差在onClick中設定完文字後
需要用.setSelected(true);讓焦點回到TextView上

3.注意:輸入的文字必須大於TextView的寬度,跑馬燈才會動作
所以如果發現跑馬燈不動作,可以試著在XML中把android:layout_width改小

以上是為你做的說明,有問題歡迎提問,謝謝。

2012-11-06

Android下拉選單(spinner)應用(四) - 三層連動式下拉選單

因為很多人看完了上篇連動式下拉選單後開始問我怎麼再加一層做三層連動下拉選單

而三層下拉在很多地方都會用到,如:最常用到的縣市鄉鎮選取,所以就抽空寫這篇好了

本人用的是最白痴的寫法(因為我懶),其實還有其他寫法,不過這個寫法最快(最懶)

而且最直覺,就直接把二層連動下拉選單中的二維陣列再加一個三維陣列的而已

夠簡單也夠直覺吧(夠懶),下面就直接po程式碼,看完您就會覺得就這樣而已喔

其實也就是這麼簡單而已,我直接從連動式下拉選單改來的,看程式碼吧。

main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="#FFFFFF"
    >
    <Spinner android:id="@+id/type" 
        android:layout_width="fill_parent" 
          android:layout_height="45dp"
          android:layout_marginLeft="75dp"
          android:layout_marginRight="20dp"
        android:layout_marginTop="7dp" 
         android:drawSelectorOnTop="true"
         android:layout_alignParentRight="true" 
    />
       <Spinner android:id="@+id/type2" 
        android:layout_width="fill_parent" 
          android:layout_height="45dp"
          android:layout_marginLeft="75dp"
          android:layout_marginRight="20dp"
          android:layout_marginTop="3dp" 
         android:drawSelectorOnTop="true"
         android:layout_alignParentRight="true" 
         android:layout_below="@id/type" 
         />


       <Spinner
           android:id="@+id/type3"
           android:layout_width="fill_parent"
           android:layout_height="45dp"
           android:layout_marginLeft="75dp"
           android:layout_marginRight="20dp"
           android:layout_marginTop="3dp"
           android:drawSelectorOnTop="true"
           android:layout_alignParentRight="true"
           android:layout_below="@+id/type2" />
      
</RelativeLayout>



TripleSpinnerActivity
package jim.demo.TripleSpinner;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.widget.AdapterView.OnItemSelectedListener;

public class TripleSpinnerActivity extends Activity {
 private String[] type = new String[] {"茶類", "果汁類"};//載入第一下拉選單
    private String[] tea = new String[]{"紅茶","綠茶","烏龍綠","青茶"};//起始畫面時預先載入第二下拉選單
    private String[] tea2 = new String[]{"紅茶超好喝","紅茶喝完臉會紅"};//起始畫面時預先載入第三下拉選單
    //第一下拉選取後載入第二下拉選單
    private String[][] type2 = new String[][]{{"紅茶","綠茶","烏龍綠","青茶"},{"柳丁汁","西瓜汁","烏梅汁"}};
    //第二下拉選取後載入第三下拉選單
    private String[][][] type3 = new String[][][]{{{"紅茶超好喝","紅茶喝完臉會紅"},{"綠茶超好喝","綠茶喝完臉會綠"},{"烏龍茶超好喝","烏龍茶超烏龍"},{"青茶超好喝","青茶很尚青"}},{{"柳丁汁超好喝","柳丁汁好棒"},{"西瓜汁超好喝","西瓜汁還可以"},{"烏梅汁超好喝","烏梅汁還可以"}}};
    private Spinner sp;//第一個下拉選單
    private Spinner sp2;//第二個下拉選單
    private Spinner sp3;//第三個下拉選單
    private Context context;

    ArrayAdapter<String> adapter ;

    ArrayAdapter<String> adapter2; 
    
    ArrayAdapter<String> adapter3; 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
         context = this;
        
        //程式剛啟始時載入第一個下拉選單
        adapter = new ArrayAdapter<String>(this,android.R.layout.simple_spinner_item, type); 
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 
        sp = (Spinner) findViewById(R.id.type); 
        sp.setAdapter(adapter);
        sp.setOnItemSelectedListener(selectListener);
        
        //因為下拉選單第一個為茶類,所以先載入茶類群組進第二個下拉選單
        adapter2 = new ArrayAdapter<String>(this,android.R.layout.simple_spinner_item, tea); 
        adapter2.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 
        sp2 = (Spinner) findViewById(R.id.type2);
        sp2.setAdapter(adapter2);
        sp2.setOnItemSelectedListener(selectListener2);
        
      //因為下拉選單第二個為紅茶,所以先載入紅茶群組進第三個下拉選單
        adapter3 = new ArrayAdapter<String>(this,android.R.layout.simple_spinner_item, tea2); 
        adapter3.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 
        sp3 = (Spinner) findViewById(R.id.type3);
        sp3.setAdapter(adapter3);
        
    }
    
    //第一個下拉類別的監看式
    private OnItemSelectedListener selectListener = new OnItemSelectedListener(){
        public void onItemSelected(AdapterView<?> parent, View v, int position,long id){
         //讀取第一個下拉選單是選擇第幾個
            int pos = sp.getSelectedItemPosition();
            //重新產生新的Adapter,用的是二維陣列type2[pos]
            adapter2 = new ArrayAdapter<String>(context,android.R.layout.simple_spinner_item, type2[pos]);
            //載入第二個下拉選單Spinner
            sp2.setAdapter(adapter2);
        }
      
        public void onNothingSelected(AdapterView<?> arg0){

        }

    };
    
  //第二個下拉類別的監看式
    private OnItemSelectedListener selectListener2 = new OnItemSelectedListener(){
        public void onItemSelected(AdapterView<?> parent, View v, int position,long id){
         //讀取第一個下拉選單是選擇第幾個
            int pos = sp.getSelectedItemPosition();
         //讀取第二個下拉選單是選擇第幾個
            int pos2 = sp2.getSelectedItemPosition();
            //重新產生新的Adapter,用的是三維陣列type3[pos][pos2]
            adapter3 = new ArrayAdapter<String>(context,android.R.layout.simple_spinner_item, type3[pos][pos2]);
            //載入第三個下拉選單Spinner
            sp3.setAdapter(adapter3);
        }
      
        public void onNothingSelected(AdapterView<?> arg0){

        }

    };
}



執行後畫面


選取第二個下拉選單

點選後第二個下拉和第三個下拉選單改變

第三個下拉選單內容也改變了

第一個下拉選單改變會連動其他二個下拉選單改變

說明:
          1.和連動式下拉選單其實改變的沒有很多,只是加入一個Spineer和一個三維陣列

          2.主要的內容要照著三維陣列內的設定,第一個下拉是類別、第二個下拉是品項

             、第三個下拉是評價,所以一開始下拉選單內的預設值因為第一個下拉的類別

             會預設為茶類,而第二下拉會是紅茶,所以第三個下拉就給它一維陣列紅茶的評價

          3.新增的第二個下拉選單選取監看式,new ArrayAdapter<String>產出的是一維陣列

             括號逗點前第一區只是下拉的樣式,所以不用管它,第二區帶入三維陣列

             給三維陣列type3第一和第二下拉的選取項就會產出一維陣列選項讓ArrayAdapter載入

             Spineer3中。

後記:

           以上說明應該清楚了,如有問題歡迎來信指教,謝謝。

2012-10-10

PhoneGap到底是什麼?

最近在忙著幫公司做表單電子化,一個月(11月前)要把兩個表單(外出申請單、忘刷卡單)電子化

忙到我都忘了我有blog這件事了<---有點虎爛!!

今天完成一個表單後為了有在focus我的blog的朋友們

所以今天特別上來寫了這一篇文章<---因為也有人在問!

讓不是很了解PhoneGap的人能再更了解PhoneGap到底是什麼玩意兒?

PhoneGap到底是什麼?是Mobile App?IPhone?App?HTML5?

還有人說是手機應用程式,PhoneGap到底是什麼?

用最簡單再簡單,簡單到一句話就說完的說法就是:

PhoneGap是網頁(HTML5、CSS3)和手機底層功能的中介溝通層套件

請把這句話表框起來,然後放到你的腦海深處不要忘記了

為什麼說它是中介層套件,下面開始為你說明你就會了解:

我們都知道手機應用程式開發分為兩種:Native App和Mobile App

Native App是用原生程式碼,如Android用Java、iPhone用ObjectC...等

Mobile App是用HTML5+手機瀏覽器

Native App我就不廢話直接跳過了

我們針對Mobile App來說明為什麼PhoneGap是Mobile App開發的一個中介溝通層套件

所有的手機應用程式都是APP(廢話),APP 就會需要封裝,這樣才好各別下載(好免費分享...誤)

而PhoneGap也不是開發APP的工具,因為以開發Android是用Eclipse

Eclipse才是開發工具,PhoneGap只能算是開發中的一個套件

而Mobile App有一個大缺點,就是雖然網頁有共通性,不過只要用到手機瀏覽器

手機上的功能你就完全不能用,就算手機能發出七彩霓虹燈、一秒內打電話給林志玲或如花

你也不能用,這是Mobile App最大的缺點,那你會問這跟PhoneGap有什麼關係

怎麼會沒關係,PhoneGap就是在改善這一點的中介溝通層套件(終於說到了!)

在HTML5中用寫JavaScrip的型式就能去呼叫手機內建的功能

這樣你說有沒有很帥,雖然它也不是萬能的,不過最少能加減用點功能也好

以上說明應該夠清楚了,希望不會再有人看完這篇還不知道PhoneGap是什麼?能吃嗎?才好!

最後還是不了解的歡迎寫信問題,我再幫您加強說明,謝謝。

PS:如果以上有錯誤的地方,小弟我也歡迎指教,教學相長,我會很感謝您的。

2012-09-04

PhoneGap API應用:Camera相機(二) - 選取手機內照片用img顯示出來

上篇-用相機拍照後,這篇就不得不說說怎麼從手機內取出照片了

鬼月廢話還是不要太多,不然別人會覺得我是在"鬼話連篇",直接PO上程式碼


JavaScript程式碼
<script type="text/javascript" charset="utf-8" src="phonegap-1.0.0.js"></script>
<script type="text/javascript" charset="utf-8">
       
      var pictureSource;   //圖片的來源
    var destinationType;  //返回值的格式設置

    // Wait for PhoneGap to connect with the device
    document.addEventListener("deviceready",onDeviceReady,false);

    // PhoneGap 剛onload時
    function onDeviceReady() {
        pictureSource=navigator.camera.PictureSourceType;
        destinationType=navigator.camera.DestinationType;
    }
//一個按鈕將調用這個函數
//Android的怪癖:pictureSource.PHOTOLIBRARY和pictureSource.SAVEDPHOTOALBUM是相同的
//所以點選getPhoto(pictureSource.PHOTOLIBRARY)
//或是getPhoto(pictureSource.SAVEDPHOTOALBUM)功能是相同的
    function getPhoto(source) {
      // 取得圖像(成功事件 ,失敗事件,{圖片設定});
      // getpicture(cameraSuccess,cameraError,{cameraOptions});
      navigator.camera.getPicture(onPhotoURISuccess, onFail, { quality: 50, 
        destinationType: destinationType.FILE_URI,
        sourceType: source });
    }
//照片是成功檢索時調用
    function onPhotoURISuccess(imageURI) {
      //取消註釋,以查看base64編碼的圖像數據
      // console.log(imageURI);

      //獲取的圖像處理
      var largeImage = document.getElementById('largeImage');

      //取消隱藏的圖像元素
      largeImage.style.display = 'block';

      //顯示取得的照片
      // The inline CSS rules are used to resize the image
      largeImage.src = imageURI;
    }

    //錯誤發生時 
    function onFail(message) {
      alert('Failed because: ' + message);
    }

      </script>



html元件
<button onclick="getPhoto(pictureSource.PHOTOLIBRARY);">從相片的檔案庫</button><br>
<button onclick="getPhoto(pictureSource.SAVEDPHOTOALBUM);">從相片簿</button><br>
<img style="display:none;width:60px;height:60px;" id="largeImage" src="" />


實作出來的畫面:






說明:

雖然有兩個功能按鈕可以作出這個功能,而且帶入的參數不同

但其實做出來的功能是一樣的,原因是Android的怪癖

Camera.PictureSourceType.PHOTOLIBRARY和PictureSourceType.SAVEDPHOTOALBUM

會被視為相同,都會都出現相同的相冊,官網說明文件中有提到

以上是為您做的簡單介紹,謝謝。