2014年11月25日 星期二

Android NFC tag 近距離無線通訊

需有NFC功能手機與感應卡(悠遊卡、學生證之類的)
首先在權限上將minSdkVersion修改為10並加入

1.AndroidManifest.xml



2.layout的activity_main.xml需有一個TextView顯示

3.MainActivity.java
public class Inventory extends Activity {
 
 /* NFC */
 // list of NFC technologies detected:
 private final String[][] techList = new String[][] { new String[] {
   NfcA.class.getName(), NfcB.class.getName(), NfcF.class.getName(),
   NfcV.class.getName(), IsoDep.class.getName(),
   MifareClassic.class.getName(), MifareUltralight.class.getName(),
   Ndef.class.getName() } };

 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.inventory);

 }

 /* NFC */
 @Override
 protected void onResume() {
  super.onResume();
  // creating pending intent:
  PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
    new Intent(this, getClass())
      .addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
  // creating intent receiver for NFC events:
  IntentFilter filter = new IntentFilter();
  filter.addAction(NfcAdapter.ACTION_TAG_DISCOVERED);
  filter.addAction(NfcAdapter.ACTION_NDEF_DISCOVERED);
  filter.addAction(NfcAdapter.ACTION_TECH_DISCOVERED);
  // enabling foreground dispatch for getting intent from NFC event:
  NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
  nfcAdapter.enableForegroundDispatch(this, pendingIntent,
    new IntentFilter[] { filter }, this.techList);
 }

 @Override
 protected void onPause() {
  super.onPause();
  // disabling foreground dispatch:
  NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
  nfcAdapter.disableForegroundDispatch(this);
 }
 //將tag到的ID顯示出來
 @Override
 protected void onNewIntent(Intent intent) {
  if (intent.getAction().equals(NfcAdapter.ACTION_TAG_DISCOVERED)) {
   ((TextView) findViewById(R.id.tag)).setText("Tag ID(16-14):"
     + ByteArrayToHexString(intent
       .getByteArrayExtra(NfcAdapter.EXTRA_ID))
     + "\n Tag ID (16-8):"
     + getHex(intent.getByteArrayExtra(NfcAdapter.EXTRA_ID))
     + "\n Tag ID (dec):"
     + getDec(intent.getByteArrayExtra(NfcAdapter.EXTRA_ID))
     + "\n ID (reversed):"
     + getReversed(intent.getByteArrayExtra(NfcAdapter.EXTRA_ID)));
  }
 }
 //16進位14碼
 private String ByteArrayToHexString(byte[] inarray) {
  int i, j, in;
  String[] hex = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A",
    "B", "C", "D", "E", "F" };
  String out = "";
  for (j = 0; j < inarray.length; ++j) {
   in = (int) inarray[j] & 0xff;
   i = (in >> 4) & 0x0f;
   out += hex[i];
   i = in & 0x0f;
   out += hex[i];
  }
  return out;
 }
 //16進位8碼
 private String getHex(byte[] bytes) {
  StringBuilder sb = new StringBuilder();
  for (int i = bytes.length - 1; i >= 0; --i) {
   int b = bytes[i] & 0xff;
   if (b < 0x10)
    sb.append('0');
   sb.append(Integer.toHexString(b));
   if (i > 0) {
    sb.append(" ");
   }
  }
  return sb.toString();
 }
 //12進位10碼
 private long getDec(byte[] bytes) {
  long result = 0;
  long factor = 1;
  for (int i = 0; i < bytes.length; ++i) {
   long value = bytes[i] & 0xffl;
   result += value * factor;
   factor *= 256l;
  }
  return result;
 }
 //12進位10碼反轉
 private long getReversed(byte[] bytes) {
  long result = 0;
  long factor = 1;
  for (int i = bytes.length - 1; i >= 0; --i) {
   long value = bytes[i] & 0xffl;
   result += value * factor;
   factor *= 256l;
  }
  return result;
 }
} 
參考連結
https://gist.github.com/luixal/5768921
https://github.com/nadam/nfc-reader
 

2014年11月20日 星期四

Android SQLite db檔案匯入與基本指令 SQLite data copy to app and instruction

假設已經有一個SQLite檔,要將其匯入app
1.首先在專案res資料夾建立一個raw資料夾,將SQLite檔案放入此資料夾
2.接著建立一個DBManager.java檔案


public class DBManager {

 private final int BUFFER_SIZE = 400000;
 public static final String DB_NAME = "db2.db"; // 保存的資料庫檔案名
 public static final String PACKAGE_NAME = "tw.android";
 public static final String DB_PATH = "/data"
   + Environment.getDataDirectory().getAbsolutePath() + "/"
   + PACKAGE_NAME;// 在手機裡存放資料庫的位置(/data/data/tw.android/db2.db)

 private SQLiteDatabase database;
 private Context context;

 public DBManager(Context coNtext) {
  this.context = coNtext;
 }

 public SQLiteDatabase getDatabase() {
  return database;
 }

 public void setDatabase(SQLiteDatabase database) {
  this.database = database;
 }

 public void openDatabase() {
  this.database = this.openDatabase(DB_PATH + "/" + DB_NAME);
 }

 private SQLiteDatabase openDatabase(String dbfile) {

  try {
   if (!(new File(dbfile).exists())) {
    Log.i("have db2????????", "no");
    // 判斷資料庫檔案是否存在,若不存在則執行導入,否則直接打開資料庫
    InputStream is = this.context.getResources().openRawResource(
      R.raw.db2); // 欲導入的資料庫
    FileOutputStream fos = new FileOutputStream(dbfile);
    byte[] buffer = new byte[BUFFER_SIZE];
    int count = 0;
    while ((count = is.read(buffer)) > 0) {
     fos.write(buffer, 0, count);
    }
    fos.close();
    is.close();
   }
   SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(dbfile,
     null);
   return db;

  } catch (FileNotFoundException e) {
   Log.e("Database", "File not found");
   e.printStackTrace();
  } catch (IOException e) {
   Log.e("Database", "IO exception");
   e.printStackTrace();
  }
  return null;
 }

 public void closeDatabase() {
  this.database.close();

 }
}
3.主要檔案Main.java搭配基本SQLite指令
public class Main extends Activity {

 private SQLiteDatabase db;

 private EditText mEdtName, mEdtAddr, mEdtUpdate1, mEdtUpdate2, mEdtDelete,
   mEdtSQL;

 private TextView mTextList1, mTextList2;

 private Button mBtnAdd, mBtnUpdate, mBtnDelete, mBtnSQL;

 public DBManager dbHelper;

 /** Called when the activity is first created. */
 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);

  setupViewComponent();

  dbHelper = new DBManager(this);
  dbHelper.openDatabase();
  db = dbHelper.getDatabase();
  queryList();
 }

 private void setupViewComponent() {
  mTextList1 = (TextView) findViewById(R.id.textList1);
  mTextList2 = (TextView) findViewById(R.id.textList2);

  mEdtName = (EditText) findViewById(R.id.edtName);
  mEdtAddr = (EditText) findViewById(R.id.edtAddr);
  mEdtUpdate1 = (EditText) findViewById(R.id.edtUpdate1);
  mEdtUpdate2 = (EditText) findViewById(R.id.edtUpdate2);
  mEdtDelete = (EditText) findViewById(R.id.edtDelete);
  mEdtSQL = (EditText) findViewById(R.id.edtSQL);

  mBtnAdd = (Button) findViewById(R.id.btnAdd);
  mBtnUpdate = (Button) findViewById(R.id.btnUpdate);
  mBtnDelete = (Button) findViewById(R.id.btnDelete);
  mBtnSQL = (Button) findViewById(R.id.btnSQL);

  mBtnAdd.setOnClickListener(onClickBtnAdd);
  mBtnUpdate.setOnClickListener(onClickBtnUpdate);
  mBtnDelete.setOnClickListener(onClickBtnDelete);
  mBtnSQL.setOnClickListener(onClickBtnSQL);

 }

 /* 新增 */
 private Button.OnClickListener onClickBtnAdd = new Button.OnClickListener() {
  @Override
  public void onClick(View v) {
   // TODO Auto-generated method stub

   /* 方法1 直接下指令 */
   if (mEdtName.getText().toString().isEmpty() == false) { // name有值
    db.execSQL("insert into user('name') values ('"
      + mEdtName.getText().toString() + "')");
   }
   if (mEdtAddr.getText().toString().isEmpty() == false) { // address有值
    db.execSQL("insert into location('address') values ('"
      + mEdtAddr.getText().toString() + "')");
   }

   /* 方法2 */
   // if(mEdtName.getText().toString().isEmpty() == false){ // name有值
   // ContentValues newRow = new ContentValues();
   // newRow.put("name", mEdtName.getText().toString());
   // db.insert("user", null, newRow);
   // }
   // if (mEdtAddr.getText().toString().isEmpty() == false) {
   // //address有值
   // ContentValues newRow = new ContentValues();
   // newRow.put("address", mEdtAddr.getText().toString());
   // db.insert("location", null, newRow);
   // }
   queryList();
  }
 };

 /* 修改 */
 private Button.OnClickListener onClickBtnUpdate = new Button.OnClickListener() {
  @Override
  public void onClick(View v) {
   // TODO Auto-generated method stub

   /* 方法1 直接下指令 */
   db.execSQL("UPDATE location SET address='"
     + mEdtUpdate2.getText().toString() + "' WHERE address='"
     + mEdtUpdate1.getText().toString() + "'");

   /* 方法2 */
   // ContentValues newRow3 = new ContentValues();
   // newRow3.put("address", mEdtUpdate2.getText().toString());
   // db.update("location", newRow3,
   // "address='"+mEdtUpdate1.getText().toString()+"'", null);

   queryList();
  }
 };

 /* 刪除 */
 private Button.OnClickListener onClickBtnDelete = new Button.OnClickListener() {
  @Override
  public void onClick(View v) {
   // TODO Auto-generated method stub

   /* 方法1 直接下指令 */
   db.execSQL("DELETE FROM location WHERE address='"
     + mEdtDelete.getText().toString() + "'");

   /* 方法2 */
   // db.delete("location",
   // "address='"+mEdtDelete.getText().toString()+"'", null);

   queryList();
  }
 };

 private Button.OnClickListener onClickBtnSQL = new Button.OnClickListener() {
  @Override
  public void onClick(View v) {
   // TODO Auto-generated method stub

   Cursor cursor = db.rawQuery(mEdtSQL.getText().toString(), null); // 搜尋用rawQuery
   cursor.moveToFirst();
   mTextList1.setText(cursor.getString(0) + cursor.getString(1));
   while (cursor.moveToNext())
    mTextList1.append("\n" + cursor.getString(0) + "    "
      + cursor.getString(1));
  }
 };

 /* 搜尋 */
 void queryList() {

  /* 方法1 直接下指令 */
  String queryUser = "SELECT * FROM user";
  Cursor cursor1 = db.rawQuery(queryUser, null); // 搜尋用rawQuery
  String queryLocation = "SELECT * FROM location";
  Cursor cursor2 = db.rawQuery(queryLocation, null); // 搜尋用rawQuery
  /* 方法2 */
  // Cursor cursor1 = db.query("user", new String[] { "Id", "name"},
  // null, null, null, null, null);
  // Cursor cursor2 = db.query("location", new String[] { "Id",
  // "address"},
  // null, null, null, null, null);

  cursor1.moveToFirst();
  mTextList1
    .setText(cursor1.getString(0) + "    " + cursor1.getString(1));
  while (cursor1.moveToNext())
   mTextList1.append("\n" + cursor1.getString(0) + "    "
     + cursor1.getString(1));

  cursor2.moveToFirst();
  mTextList2
    .setText(cursor2.getString(0) + "    " + cursor2.getString(1));
  while (cursor2.moveToNext())
   mTextList2.append("\n" + cursor2.getString(0) + "    "
     + cursor2.getString(1));
 }

 /* 離開程式 */
 public boolean onKeyDown(int keycode, KeyEvent event) {
  if (keycode == KeyEvent.KEYCODE_BACK) {
   // 關閉資料庫
   dbHelper.closeDatabase();
   finish();
   return true;
  }
  return super.onKeyDown(keycode, event);
 }

 @Override
 public void onDestroy() {
  super.onDestroy();
  // Kill myself
  android.os.Process.killProcess(android.os.Process.myPid());
 }

}
4.main.xml配置


    

        

        
    

    

        

        
    

    

    

        

        

        

        
    

   

    

        

        

        
    

    

    

        

        
    

    

    

        

            

                

                
           
        
    


5.完成如圖


SQLite db2.db 檔案下載
參考來源:
http://fecbob.pixnet.net/blog/post/43610863
http://hscc.cs.nctu.edu.tw/~lincyu/Android/Chapter11.pdf

2014年11月3日 星期一

Android RatingBar Customize 自製 評分

Android內建評分星星系統,可自行製作圖案代替星星
1.activity_main.xml
android:numStars="5" ----- 總數量
android:rating="2.5" ----- 初始值
android:stepSize="0.5" " -----評分單位
style="?android:attr/ratingBarStyleIndicator" ----- 指標(無法拉動)
style="?android:attr/ratingBarStyleSmall" ----- 小指標
style="@style/foodRatingBar" ----- 自製圖案
 




                

                

                

                

                

                

               
            
2.在res -> value -> styles.xml檔案內加上

3.在res -> drawable-hdpi 建立三個檔案
food_ratingbar_full.xml
food_ratingbar_full_empty.xml
food_ratingbar_full_filled.xml
並將圖片

下載至drawable-hdpi此資料夾內
food_ratingbar_full.xml

    
    
    


food_ratingbar_full_empty.xml


    
    
    
    


food_ratingbar_full_filled.xml


 
    
 
    
 
    
 
    
 

4.MainActivity.java
public class MainActivity extends FragmentActivity {

 private RatingBar ratingBar4;
 private TextView txtRatingValue;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  addListenerOnRatingBar();
 }

 //滑動直接顯示分數
 public void addListenerOnRatingBar() {
   
  ratingBar4 = (RatingBar) findViewById(R.id.ratingBar4);
  txtRatingValue = (TextView) findViewById(R.id.txtRatingValue);
  
  //if rating value is changed,
  //display the current rating value in the result (textview) automatically
  ratingBar4.setOnRatingBarChangeListener(new OnRatingBarChangeListener() {
   public void onRatingChanged(RatingBar ratingBar, float rating,
    boolean fromUser) {
  
    txtRatingValue.setText(String.valueOf(rating));
  
   }
  });
   }
}


參考來源:
http://www.mkyong.com/android/android-rating-bar-example/
http://kozyr.zydako.net/2010/05/23/pretty-ratingbar/
https://github.com/kozyr/foody-memories