2017年6月29日 星期四

Java:Reflection映射

在java裡有個技術叫做Reflection,能夠在程式執行期間得知自己的外觀長相,並自我修改,甚至至我複製,未使用Reflection的程式碼,物件所需類別無法在執行時再決定,靈活度相對較低,但是使用reflction機制可破壞原有程式碼的封裝機制,它的動態讓程式碼不需寫死,能夠更彈性的執行程式。

Reflection機制透過Class的Object,可以描述每個類別的相關資訊,包括隸屬哪個Package,類別本身的修飾詞,繼承自誰,成員變數以及方法,除了描述相關資訊外,還提供你可以透過它來來進行操作。


public class Employee {
	private int id;
	private String name;
	private String address;
	
	public Employee() {
		
	}
	
	public Employee(int id, String name,String address) {
		super();
		this.id = id;
		this.name = name;
		this.address=address;
	}

	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getAddress() {
		return address;
	}
	public void setAddress(String address) {
		this.address = address;
	}
	
	
}

 
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class Main {
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		Class c = Employee.class;

		Field[] fields = c.getDeclaredFields();                   //取得Employee裡的成員變數
		
		Constructor con = c.getDeclaredConstructors()[1];         //取得Employee裡有參數的建構子
		
		System.out.println(Modifier.toString(c.getModifiers()));  //列印出class:Employee的修飾詞,也就是public
		System.out.println(c.getName());                          //列印出class:Employee的名稱
		
		try {
			Object o = con.newInstance(1,"Mary","高雄");    //形成物件

			//Field成員變數的實做
			Field fieldName = c.getDeclaredField("name");  //取得Employee裡的成員變數name
			fieldName.setAccessible(true);         //利用reflection機制把private改成public
			System.out.println(fieldName.get(o));  //印出物件o的name,也就是印出Mary
			fieldName.set(o, "Tom");               //把物件o裡的name,從Mary改成Tom
			System.out.println(fieldName.get(o));  //印出物件o的name,變成了Tom

			//方法的實做
			Method method = c.getMethod("getName", null);  //取得Employee裡的getName方法
			System.out.println(method.invoke(o, null));    //執行getName的方法,印出Tom

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
		
	}

}
執行結果:
public
Employee
Mary
Tom
Tom

2017年6月27日 星期二

Java :HttpUrlConnection發送GET取得Json

Http協定是遊客戶端與伺服器建立一個TCP連線之後,客戶端發出Http請求(封包)與伺服器建立可靠的連線,伺服器在收到請求後,針對請求的內容進行處理後,在將狀態資訊發送回給客戶端,此資訊可能是客戶請求的檔案或是錯誤訊息(Json/xml格式)。

Http協定定義了12種方法提供客戶端請求至伺服器,分別為(GET,POST,HEAD,PUT,PATCH,COPY,MOVE,DELETE,LINK,UNLIKE,OPTION)最常見的方法為GET與POST。

GET與POST的差別 :
兩者的差別在於傳送封包裡的內容,Http封包內包含header(標頭)與data(資訊),header就像是信封上的地址,data就是裡面的資訊。
header:http://xxx.xxx
data:id=201

GET:把data直接加在在header後面,像是http://xxx?id=201,這種方法不適合放有安全疑慮的資訊。

POST:把header與data分開放,此方法適合有安全疑慮的資訊

程式碼(使用GET):
 
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import javax.net.ssl.HttpsURLConnection;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
public class JsonReader {
 
 public static String getJSON(String url, int timeout) throws IOException {

     URL u = new URL(url);
     HttpURLConnection c = (HttpURLConnection) u.openConnection();
     c.setRequestMethod("GET");
     c.setUseCaches(false);
     c.setAllowUserInteraction(false);
     c.setConnectTimeout(timeout);   //设置连接主机超时(单位:毫秒) 
     c.setReadTimeout(timeout);      //设置从主机读取数据超时(单位:毫秒) 
     c.setRequestProperty("User-Agent","Mozilla/5.0");
     c.connect();
     int status = c.getResponseCode();

     switch (status) {
         case 200:
         case 201:
             BufferedReader br = new BufferedReader(new InputStreamReader(c.getInputStream(),"utf-8"));
             StringBuilder sb = new StringBuilder();
             String line;
             while ((line = br.readLine()) != null) {
                 sb.append(line + "\n");
             }
             br.close();
             return sb.toString();
     }

     return null;
 }
    public static void main(String[] args) throws IOException {
     
     String s = getJSON("http://data.ntpc.gov.tw/od/data/api/18621BF3-6B00-4A07-B49C-0C5CCABFE026?$format=json&$filter=routeNameZh%20eq%20637",9000);
     try {
   JSONArray jsonarray = new JSONArray(s);
   JSONObject obj = jsonarray.getJSONObject(0);
   System.out.println(obj.get("latitude"));
  } catch (JSONException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
     
    }
}

2017年6月25日 星期日

Java:String、StringBuffer與StringBuilder差別

Java常會用到String來做字串的處理,但是如果要連結字串進去只能在後面用+的方式加進去,所以要做字串的連結時不建議使用String,因為String是不可變的對象, 因此在每次對 String 類型進行改變的時候,都會生成一個新的 String 對象,然後將指針指向新的 String 對象,這種方式相當耗費資源,所以要經常改變字串的內容的話最好不要用 String。


下面介紹StringBuffer與StringBuilder的差別:

兩者在使用時的差別在於是否使用多執行緒,多執行緒的情況下使用StringBuffer來讓類別自動處理同步的問題,而不需考量多執行緒同步的時候我們使用StringBuilder來獲得最佳的效率。並且兩者都有insert()、reverse()、replace()、append()等操作字串的方法。


2017年6月24日 星期六

Android:Content Provider範例

Content Provider 內容提供者,是Andoird提供應用程式存取資料的機制,Android提供許多類型的內容,像是聯絡人名稱、電話、手機上的圖片等,皆是以Content Provider提供存取。


以下例子是以存取手機上的聯絡人為範例


要存取聯絡人必須取得權限,請在AndroidMainifest.xml裡新增

 
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />

PS:在Andoird 6.0之後,如果在AndroidMainifest加入的是危險權限,會執行的應用程式裡要求使用者允許存取資料

MainActivity.xml:


 
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.user.contentprovidertest.MainActivity"
    android:orientation="vertical"
    android:gravity="center">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="查詢聯絡人資料"
        android:id="@+id/btnread"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="新增聯絡人資料"
        android:id="@+id/btninsert"/>

</LinearLayout>

MainActivity.java:
 
import android.content.Intent;
import android.content.pm.PackageManager;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

import static android.Manifest.permission.READ_CONTACTS;
import static android.Manifest.permission.WRITE_CONTACTS;

public class MainActivity extends AppCompatActivity {

    private  int REQUEST_CONTACTS = 1;
    private Button btnread,btninsert;



    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        findviewById();

        //檢查使用者是否已經允許了權限
        int permission = ActivityCompat.checkSelfPermission(this, READ_CONTACTS);
        if (permission != PackageManager.PERMISSION_GRANTED){
            //如果未取得權限,向使用者要求允許
            ActivityCompat.requestPermissions(this,new String[]{READ_CONTACTS,WRITE_CONTACTS},REQUEST_CONTACTS);
        }
        else {
            //如果已有權限,進行下面工作
            btnread.setOnClickListener(btnlistener);
        }

    }
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        btnread.setOnClickListener(btnlistener);
    }

    private void findviewById() {
        btnread = (Button)findViewById(R.id.btnread);
        btninsert = (Button)findViewById(R.id.btninsert);
        btnread.setOnClickListener(btnlistener);
        btninsert.setOnClickListener(btnlistener);

    }
    private View.OnClickListener btnlistener = new View.OnClickListener()
    {
        @Override
        public void onClick(View v) {
            if (v.getId()==R.id.btnread){
                startActivity(new Intent(MainActivity.this,readContent.class));
            }
            if (v.getId()==R.id.btninsert){
                startActivity(new Intent(MainActivity.this,insertContent.class));
            }
        }
    };
}

insertContent.xml:

 
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.user.contentprovidertest.insertContent"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="姓名 :"/>
        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/edtname"/>
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="電話 :"/>
        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/edtphone"/>
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:gravity="center">
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="新增"
            android:id="@+id/btninsert"/>
        
    </LinearLayout>
</LinearLayout>

insertContent.java:
 
import android.content.ContentProviderOperation;
import android.content.DialogInterface;
import android.content.OperationApplicationException;
import android.os.RemoteException;
import android.provider.ContactsContract;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

import java.util.ArrayList;

public class insertContent extends AppCompatActivity {

    private EditText edtname,edtphone;
    private Button btninsert;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_insert_content);

        findviewById();

    }

    private void findviewById() {
        edtname = (EditText)findViewById(R.id.edtname);
        edtphone = (EditText)findViewById(R.id.edtphone);
        btninsert = (Button)findViewById(R.id.btninsert);
        btninsert.setOnClickListener(btnlistener);
    }

    private View.OnClickListener btnlistener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            ArrayList list = new ArrayList(); //建立一個集合,存放操作指令
            int index = list.size();

            //新增一個資料操作,並加到操作集合中,資料對象是RawContacts,新增成功後會得到ID值
            list.add(ContentProviderOperation
                    .newInsert(ContactsContract.RawContacts.CONTENT_URI)
                    .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE,null)
                    .withValue(ContactsContract.RawContacts.ACCOUNT_NAME,null).build());

            //此段主要是寫入聯絡人姓名
            list.add(ContentProviderOperation
                    .newInsert(ContactsContract.Data.CONTENT_URI)
                    .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID,index)
                    .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
                    .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME,edtname.getText().toString().trim()).build());

            //利用第一個新增RawContacts操作後得到的ID值,建立新增到Phone的電話號碼操作
            list.add(ContentProviderOperation
                    .newInsert(ContactsContract.Data.CONTENT_URI)
                    .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID,index)
                    .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
                    .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER,edtphone.getText().toString().trim())
                    .withValue(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE).build());

            try {
                getContentResolver().applyBatch(ContactsContract.AUTHORITY,list);
                new AlertDialog.Builder(insertContent.this)
                        .setMessage("新增成功")
                        .setPositiveButton("確定", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                edtphone.setText("");
                                edtname.setText("");
                            }
                        })
                        .show();
            } catch (RemoteException e) {
                e.printStackTrace();
            } catch (OperationApplicationException e) {
                e.printStackTrace();
            }
        }
    };
}

readContent.xml:

 
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.user.contentprovidertest.readContent">

    <ListView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/listread"></ListView>

</RelativeLayout>

readContent.java:
 
import android.content.ContentResolver;
import android.content.Intent;
import android.database.Cursor;
import android.provider.ContactsContract;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;

import java.util.ArrayList;

public class readContent extends AppCompatActivity {

    private ListView listread;
//    SimpleCursorAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_read_content);

        listread = (ListView) findViewById(R.id.listread);
        listread.setOnItemClickListener(listlistener);
        query();

    }

    private void query() {

        ContentResolver resolver = getContentResolver();

        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
            String[] projection = {ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER};
            //query(欲查詢的Uri,查詢回傳的表格欄位,SQL的Where語法,where中的參數,排序ASC OR DESC)
            Cursor cursor = resolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, projection, null, null, null, null);

            ArrayList alname = new ArrayList();
            ArrayList alphone = new ArrayList();
            while (cursor.moveToNext()) {
                alname.add(cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)));
                alphone.add(cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)));
            }

            ArrayList listMockData = new ArrayList();

            for (int i = 0; i < alname.size(); i++) {

                listItem newsData = new listItem();
                newsData.setName((String) alname.get(i));
                newsData.setPhone((String) alphone.get(i));
                listMockData.add(newsData);
            }
            listread.setAdapter(new listAdapter(readContent.this,listMockData));

            //            while (cursor.moveToNext()){
            //                int id = cursor.getInt(cursor.getColumnIndex(ContactsContract.Contacts._ID));
            //                String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
            //                Log.d("TAG",id+"/"+name);
            //            }


//            adapter = new SimpleCursorAdapter(this,
//                    android.R.layout.simple_list_item_2,
//                    cursor,
//                    new String[]{ContactsContract.Contacts.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER},
//                    new int[]{android.R.id.text1,android.R.id.text2},
//                    1);
//            listread.setAdapter(adapter);

        }

    }

    private AdapterView.OnItemClickListener listlistener = new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView adapterView, View view, int position, long id) {


            listItem bs = (listItem) adapterView.getItemAtPosition(position);
            Intent it = new Intent();
            it.setClass(readContent.this, updateContacts.class);
            Bundle bd = new Bundle();
            bd.putString("name", bs.getName());
            bd.putString("phone",bs.getPhone());
            it.putExtras(bd);
            startActivity(it);

        }
    };

    //當update完資料後,回到readContacts時,刷新listview
    protected void onRestart(){
        super.onRestart();
        query();
    }
}

updateContacts.xml:


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.user.contentprovidertest.updateContacts"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="姓名 :"/>
        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/edtname"/>
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="電話 :"/>
        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/edtphone"/>
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:gravity="center">
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="更新"
            android:id="@+id/btnupdate"/>
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="刪除"
            android:id="@+id/btndelete"/>

    </LinearLayout>
    
</LinearLayout>

updateContacts.java:

import android.content.ContentProviderOperation;
import android.content.DialogInterface;
import android.content.OperationApplicationException;
import android.os.RemoteException;
import android.provider.ContactsContract;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import java.util.ArrayList;

public class updateContacts extends AppCompatActivity {

    private EditText edtname,edtphone;
    private Button btnupdate,btndelete;
    String name;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_update_contacts);

        findviewById();

        Bundle bd = getIntent().getExtras();
        name = bd.getString("name");
        String phone = bd.getString("phone");
        edtname.setText(name);
        edtphone.setText(phone);
    }

    private void findviewById() {
        edtname = (EditText)findViewById(R.id.edtname);
        edtphone = (EditText)findViewById(R.id.edtphone);
        btnupdate = (Button)findViewById(R.id.btnupdate);
        btnupdate.setOnClickListener(btnlistener);
        btndelete = (Button)findViewById(R.id.btndelete);
        btndelete.setOnClickListener(btnlistener);

    }
    private View.OnClickListener btnlistener = new View.OnClickListener() {


        @Override
        public void onClick(View v) {

            if (v.getId()==R.id.btnupdate) {
                //where的條件敘述,name=? AND 資料格式=?
                String wherename = ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?";
                //條件敘述中的資料值,對應到上面的兩個問號位置
                String[] paramsname = new String[]{name, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE};

                String wherephone = ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?";
                String[] paramsphone = new String[]{edtname.getText().toString().trim(), ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE};

                ArrayList alList = new ArrayList();

                alList.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
                        .withSelection(wherename, paramsname)
                        .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, edtname.getText().toString().trim())
                        .build());

                alList.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
                        .withSelection(wherephone, paramsphone)
                        .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, edtphone.getText().toString().trim())
                        .build());


                try {
                    getContentResolver().applyBatch(ContactsContract.AUTHORITY, alList);
                    new AlertDialog.Builder(updateContacts.this)
                            .setMessage("更新成功")
                            .setPositiveButton("確定", new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    finish();
                                }
                            })
                            .show();
                } catch (RemoteException e) {
                    e.printStackTrace();
                } catch (OperationApplicationException e) {
                    e.printStackTrace();
                }
            }
            else {
                String where = ContactsContract.Data.DISPLAY_NAME + "= ? ";
                String[] params = new String[]{name};
                ArrayList alist = new ArrayList();
                alist.add(ContentProviderOperation.newDelete(ContactsContract.RawContacts.CONTENT_URI)
                .withSelection(where,params)
                .build());

                try {
                    getContentResolver().applyBatch(ContactsContract.AUTHORITY,alist);
                    new AlertDialog.Builder(updateContacts.this)
                            .setMessage("刪除成功")
                            .setPositiveButton("確定", new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    finish();
                                }
                            })
                            .show();

                } catch (RemoteException e) {
                    e.printStackTrace();
                } catch (OperationApplicationException e) {
                    e.printStackTrace();
                }
            }
        }
    };

}

listItem.java:

public class listItem {

    private String name;
    private String phone;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }
}

listAdapter.java:

public class listAdapter extends BaseAdapter {
    private ArrayList<listItem> listData;
    private LayoutInflater layoutInflater;
    public listAdapter(Context context, ArrayList<listItem> listData) {
        this.listData = listData;
        layoutInflater = LayoutInflater.from(context);
    }
    @Override
    public int getCount() {
        return listData.size();
    }
    @Override
    public Object getItem(int position) {
        return listData.get(position);
    }
    @Override
    public long getItemId(int position) {
        return position;
    }
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        if (convertView == null) {
            convertView = layoutInflater.inflate(R.layout.listlayout, null);
            holder = new ViewHolder();
            holder.nameView = (TextView) convertView.findViewById(R.id.txtname);
            holder.phoneView = (TextView) convertView.findViewById(R.id.txtphone);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        listItem newsItem = listData.get(position);
        holder.nameView.setText(newsItem.getName());
        holder.phoneView.setText(newsItem.getPhone());
        return convertView;
    }
    static class ViewHolder {
        TextView nameView;
        TextView phoneView;

    }
}

listlayout.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/txtname"/>
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/txtphone"/>

</LinearLayout>

2017年6月19日 星期一

Android : 第三方應用FireBase信箱登入+DataBase

之前有寫過一篇用sharepreference做的帳號密碼登入程式,其實本來就不應該用sharepreference做登入例子的,所以這次就來寫一個用FireBase第三方平台做的帳號密碼登入程式+資料庫的使用範例。
FireBase被Google收購後,推出了網路管理介面和新的SDK類別庫,並推出許多新功能,FireBase提供了API讓開發人員儲存或同步不同平台的資料,開發人員不需要自己建構資料庫與設計伺服器端的程式,也就是說不用寫一堆PHP了,真的相當方便!


前置步驟:


步驟一:更新SDK工具,必須將Google play services更新到版本30以上和Google Repository更新到版本26以上。

步驟二:建好FireBase,詳細如何建立firebase就不在這裡說明,如下圖


    在FireBase建立好App要用的專案


     這是到Authentication開啟用Email登入的設定畫面,可以認證的方式有Email、FaceBook、Twitter等

     這是FireBase資料庫的畫面



步驟三:在Android studio裡的專案導入好FireBase


     導入完成後可以看到已經幫你加入到了Gradle裡了


             還有在Project目錄底下的app裡的google-services.json檔,也都幫你自動加入了


     導入好FireBase到Android Studio裡後回去FireBase網業管理介面裡可以看到已經幫你跟專案      連結好了,以上都確定已經設定好後就可以開始寫程式碼了。  



情境描述:


1. MainActivty:帳號密碼登入頁面,如果已經登入過了,下次就會自動登入,除非登出了。

2. Register:註冊的頁面


3 .ShowData:用Listview顯示資料庫資料,和登出功能

程式碼:



MainActivity.xml :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.user.firebasetest.MainActivity"
    android:orientation="vertical"
    android:gravity="center">

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="帳號:"/>
        <EditText
            android:layout_width="250dp"
            android:layout_height="wrap_content"
            android:hint="請輸入帳號"
            android:id="@+id/edtemail"/>
    </LinearLayout>

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="密碼:"/>
        <EditText
            android:layout_width="250dp"
            android:layout_height="wrap_content"
            android:hint="請輸入密碼"
            android:id="@+id/edtpassword"/>
    </LinearLayout>

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="登入"
            android:id="@+id/btnlogin"/>
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="註冊"
            android:id="@+id/btnregister"/>
    </LinearLayout>

</LinearLayout>

MainActivity.java:


import android.content.Intent;
import android.nfc.Tag;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;

public class MainActivity extends AppCompatActivity {

    private Button btnlogin,btnregister;
    private EditText edtemail,edtpassword;

    private FirebaseAuth mAuth;
    private FirebaseAuth.AuthStateListener mAuthListener;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        findviewById();

        mAuth = FirebaseAuth.getInstance();

        mAuthListener = new FirebaseAuth.AuthStateListener() {
            @Override
            public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
                FirebaseUser user = firebaseAuth.getCurrentUser();
                if (user != null) {
                    // User is signed in
                    Log.d("TAG",user.getUid());
                    startActivity(new Intent(MainActivity.this,ShowData.class));
                } else {
                    // User is signed out
                    Log.d("Tag","user ==null");
                }
                // ...
            }
        };
    }
    private View.OnClickListener btnListener = new View.OnClickListener(){

        @Override
        public void onClick(View view) {
            if (view.getId()==R.id.btnlogin){
                String email = edtemail.getText().toString();
                String password = edtpassword.getText().toString();
                mAuth.signInWithEmailAndPassword(email,password)
                        .addOnCompleteListener(new OnCompleteListener() {
                            @Override
                            public void onComplete(@NonNull Task task) {
                                if (task.isSuccessful()){
                                    Log.d("TAG","登入成功");
                                }
                            }
                        });
            }
            if (view.getId()==R.id.btnregister){
                startActivity(new Intent(MainActivity.this,Register.class));
            }
        }
    };

    private void findviewById() {
        btnlogin = (Button)findViewById(R.id.btnlogin);
        btnregister = (Button)findViewById(R.id.btnregister);
        edtemail = (EditText)findViewById(R.id.edtemail);
        edtpassword = (EditText)findViewById(R.id.edtpassword);
        btnlogin.setOnClickListener(btnListener);
        btnregister.setOnClickListener(btnListener);

    }

    public void onStart() {
        super.onStart();
        mAuth.addAuthStateListener(mAuthListener);
    }
    public void onStop() {
        super.onStop();
        if (mAuthListener != null) {
            mAuth.removeAuthStateListener(mAuthListener);
        }
    }
}

Register.xml:


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.user.firebasetest.Register"
    android:orientation="vertical"
    android:gravity="center">

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="帳號:"/>
        <EditText
            android:layout_width="250dp"
            android:layout_height="wrap_content"
            android:hint="請輸入帳號"
            android:id="@+id/edtemail"/>
    </LinearLayout>

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="密碼:"/>
        <EditText
            android:layout_width="250dp"
            android:layout_height="wrap_content"
            android:hint="請輸入密碼"
            android:id="@+id/edtpassword"/>
    </LinearLayout>

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="註冊"
            android:id="@+id/btnregister"/>
    </LinearLayout>

</LinearLayout>

Register.java:
 
import android.content.DialogInterface;
import android.support.annotation.NonNull;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.FirebaseAuth;

public class Register extends AppCompatActivity {

    private Button btnregister;
    private EditText edtemail,edtpassword;

    private FirebaseAuth mAuth;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_register);

        mAuth = FirebaseAuth.getInstance();

        setTitle("註冊");
        findviewById();
    }

    private void findviewById() {
        edtemail = (EditText)findViewById(R.id.edtemail);
        edtpassword = (EditText)findViewById(R.id.edtpassword);
        btnregister = (Button)findViewById(R.id.btnregister);
        btnregister.setOnClickListener(registerListener);
    }

    private View.OnClickListener registerListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (v.getId()==R.id.btnregister){
                String email = edtemail.getText().toString();
                String password = edtpassword.getText().toString();
                mAuth.createUserWithEmailAndPassword(email, password)
                        .addOnCompleteListener(new OnCompleteListener() {
                            @Override
                            public void onComplete(@NonNull Task task) {
                                if (task.isSuccessful()){
                                    new AlertDialog.Builder(Register.this)
                                            .setMessage("註冊成功")
                                            .setPositiveButton("確定", new DialogInterface.OnClickListener(){
                                                @Override
                                                public void onClick(DialogInterface dialog, int which) {
                                                    finish();
                                                }

                                            })
                                            .show();

                                }
                                else {
                                    new AlertDialog.Builder(Register.this)
                                            .setMessage("註冊失敗")
                                            .setPositiveButton("確定",null)
                                            .show();
                                }
                            }
                        });

            }
        }
    };
}

ShowData.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.user.firebasetest.ShowData"
    android:orientation="vertical">


        <ListView
            android:layout_width="wrap_content"
            android:layout_height="450dp"
            android:id="@+id/listview">
        </ListView>

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="登出"
            android:id="@+id/btnlogout"
            android:layout_gravity="center"/>

</LinearLayout>

ShowData.java:
 
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;

import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;

import java.util.ArrayList;
import java.util.List;

public class ShowData extends AppCompatActivity {

    private Button btnlogout;
    private ListView listview;

    ArrayAdapter adapter;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_show_data);

        setTitle("ShowData");

        btnlogout = (Button)findViewById(R.id.btnlogout);
        listview = (ListView)findViewById(R.id.listview);
        adapter = new ArrayAdapter(this,android.R.layout.simple_list_item_1);



        btnlogout.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                FirebaseAuth.getInstance().signOut();
                finish();
            }
        });

        getData();
    }

    private void getData() {
        final FirebaseDatabase database = FirebaseDatabase.getInstance();
        DatabaseReference myRef = database.getReference("員工");
        myRef.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                adapter.clear();

                for (DataSnapshot contact : dataSnapshot.getChildren()){
                    adapter.add(contact.getKey().toString()+"-"+contact.child("phone").getValue().toString());
                }

                listview.setAdapter(adapter);

            }

            @Override
            public void onCancelled(DatabaseError databaseError) {

            }

        });

    }
} 

2017年6月7日 星期三

Android :Adapter

在設計清單元件時(ListView、Spinner、GridView),我們都一定會用到Adapter,那麼Adapter倒底是甚麼呢?從英文翻譯來看意思是轉接器或叫適配器,顧名思義就是它的功能就是用來轉接東西的,那麼到底要轉接甚麼和轉接到哪裡呢?來源當然就是清單元件的資料,那麼清單元件就是要轉接到的目的地瞜,簡單來說就是資料透過Adapter傳至清單元件顯示出來。但是我們的資料種類不一定只有一種,所以必須使用不同種類的Adapter,就像是變壓器一樣,必須根據電壓大小來使用不同的變壓器。

Android :選單Menu

在android 6.0開始使用的Toolbar元件的右方,可以看到有三個小點的圖示,那就是選單按鈕,按下之後會出現Menu。



準備項目:在res底下建立一個menu資料夾,並且新增一個menu.xml,如下圖:

如果沒有menu資料夾,在res按右鍵,選Android Resource Directory後,在Resource Type選擇Menu。

程式碼:

menu_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="@+id/setting"
    android:title="設定"
    app:showAsAction="ifRoom">  <!-- showAsAction 用來設定在Toolbar上的顯示原則
                                     如果沒寫就會以三個點的圖示出現,按下之後才會出現選單項目
                                     屬性除了ifRoom還有never、、always、withTest-->
</item>
</menu>


MainActivity.java:


import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


    }
    public boolean onCreateOptionsMenu(Menu menu){
        getMenuInflater().inflate(R.menu.menu_main,menu);
        return true;
    }
    public boolean onOptionsItemSelected(MenuItem item){
        int id = item.getItemId();
        if(id == R.id.setting){
            Intent it = new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
            startActivity(it);
        }
        return true;
    }
}

因為寫了Intent,所以按下menu的設定後,會跳到定位設定畫面


2017年6月3日 星期六

Android :登入程式(Sharedpreferences+AlertDialog+Notification)範例

程式情境描述:MainActivity1可以讓使用者登入和註冊,如果註冊過了就會出現警告;MainActivity2是使用者的註冊畫面;MainActivity3登入後的畫面,用來顯示資訊和會發出通知(Notification)。

Android :SnackBar

Android 5.0開始,因應實感設計(Material Design)而推出的許多新元件,例如:FloatingButton、SnackBar、TabLayout、ToolBar等等,這些元件都是以扁平化設計為基礎,跟以前的仿物化設計是完全不同的設計概念。要使用這類實感設計的元件,必須導入com.android.support.design函式庫。

SnackBar與Toast非常相似,與之不同的是可以設定Action,下面介紹如何使用SnackBar。

1.導入com.android.support.design函式庫



2. 下面程式是一個可以前往開啟定位設定的SnackBar


import android.content.Intent;
import android.graphics.Color;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {

    private Button btn123;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        btn123 = (Button)findViewById(R.id.btn123);
        btn123.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view,"前往開啟定位設定",Snackbar.LENGTH_LONG)
                        .setAction("確定", new View.OnClickListener() {
                            @Override
                            public void onClick(View view) {
                                Intent it = new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                                startActivity(it);
                            }
                        })
                        .setActionTextColor(Color.YELLOW)
                        .show();

            }
        });
    }
}

點選確定後就會觸發ACTION,跳頁到可以設定定位的頁面

2017年6月2日 星期五

Android :多國語系

Android 應用程式可以在不同語言的環境中顯示不同介面的語系,當使用者的手機使用英文環境時,應用程式介面就以英文顯示;當使用者的手機使用中文環境時,應用程式介面就以中文顯示。