2015年2月10日 星期二

Android NFC Activity disable 關閉 近距離無線通訊

前篇有用到NFC使用方法,在可以使用NFC APP上,我們可能想要在一個頁面(Activity1)可以使用NFC,在下一個頁面(Activity2)不需要用到NFC,但是若沒有設定,仍會感應到tag資料,

所以需加上下列程式碼
/*此頁面關閉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);
  // enabling foreground dispatch for getting intent from NFC event:
  NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
  try {
//   nfcAdapter.enableForegroundDispatch(this, pendingIntent,
//     new IntentFilter[] { filter }, this.techList);  開啟nfc
   nfcAdapter.enableForegroundDispatch(this, pendingIntent,
     new IntentFilter[] {}, null); // 關閉nfc IntentFilter[] {}內設為空值, techList改為null空值
  } catch (NullPointerException e) {
  }
 }
參考資料: http://stackoverflow.com/questions/9748513/reading-nfc-tags-only-from-a-particuar-activity

2015年2月2日 星期一

Android camera flashlight 相機閃光燈

簡易手電筒app,開啟相機的閃光燈
1.AndroidManifest.xml 加入
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />

2.main.xml


    


2.MainActivity.java
package com.prgguru.com;

import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.hardware.Camera.Parameters;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends Activity {
 private boolean isFlashOn = false; //預設開關-關閉
 private Camera camera;
 private Button button;

 @Override
 protected void onStop() {
  super.onStop();

  if (camera != null) {
   camera.release();
  }
 }

 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);
  button = (Button) findViewById(R.id.buttonFlashlight);
  Context context = this;
  PackageManager pm = context.getPackageManager();

  
  if (!pm.hasSystemFeature(PackageManager.FEATURE_CAMERA)) { //判斷有無相機
   Toast.makeText(getApplicationContext(),
     "抱歉,您的手機無相機功能",
     Toast.LENGTH_SHORT).show();

   return;
  }

  camera = Camera.open();
  final Parameters p = camera.getParameters();

  button.setOnClickListener(new OnClickListener() {
   public void onClick(View arg0) {
    if (isFlashOn) { //false 關閉
     p.setFlashMode(Parameters.FLASH_MODE_OFF); //相機閃光燈模式
     camera.setParameters(p);     
     isFlashOn = false;
     button.setText("打開");
    } else { // true 開啟
     Log.i("info", "torch is turned on!");
     p.setFlashMode(Parameters.FLASH_MODE_TORCH); //相機閃光燈模式
     camera.setParameters(p);     
     isFlashOn = true;
     button.setText("關閉");
    }
   }
  });

 }
}
參考來源: http://programmerguru.com/android-tutorial/android-flashlight-example/

2014年12月24日 星期三

Android Camera AutoFocus list delete picture 拍照 自動對焦 列出照片 刪除照片

拍照功能參考在 Android 裡使用 Camera 照相
並加入自動對焦與列出照片並可刪除該照片檔案

1.AndroidManifest.xml加入權限


    

    
    

    
        
            
                

                
            
        
        
        
        
        
    


2.建立java檔與layout檔

TakeAPhotoActivity.java 拍照
package tw.android;

import android.app.Activity;
import android.content.Intent;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;

public class TakeAPhotoActivity extends Activity {

 private static final String TAG = "TakeAPhotoActivity";
 private SurfaceView sv;
 // private ImageView iv;
 private Button takePhotoBtn, hidePhotoBtn, autoFocus,picList;
 // 相機 callback
 private CameraCallback cc;
 // 快門 callback
 private ShCallback sc;
 // 處理 raw data callback
 private RawCallback rc;
 // 處理 jpg callback
 private JpgCallback jc;

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

  this.sv = (SurfaceView) this.findViewById(R.id.sv);
  this.takePhotoBtn = (Button) this.findViewById(R.id.takePhotoBtn);
  this.hidePhotoBtn = (Button) this.findViewById(R.id.hidePhotoBtn);
  this.autoFocus = (Button) this.findViewById(R.id.autoFocus);
  this.picList= (Button) this.findViewById(R.id.picList);
  
  this.cc = new CameraCallback();
  this.sc = new ShCallback();
  this.rc = new RawCallback();
  this.jc = new JpgCallback(this);

  Log.d(TAG, "設定預覽視窗...");
  SurfaceHolder sh = this.sv.getHolder();
  sh.addCallback(this.cc);
  sh.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

  Log.d(TAG, "設定拍照頁面...");
  this.hidePhotoBtn.setVisibility(View.GONE);

  // 按鈕外按自動對焦
  autoFocus.setOnClickListener(new Button.OnClickListener() {

   @Override
   public void onClick(View v) {
    cc.getCarema().autoFocus(new AutoFocusCallback() {
     @Override
     public void onAutoFocus(boolean success, Camera camera) {

     }
    });
   }
  });
  //前往照片列表
  picList.setOnClickListener(new Button.OnClickListener() {

   @Override
   public void onClick(View v) {
    goToPicList();
   }
  });
  
 }

 public void takePhoto(View v) {
  Log.d(TAG, "拍照...");
  // 需要三個 callback:快門、處理 raw data、處理 jpg
  // 拍照時自動對焦
  this.cc.getCarema().autoFocus(new AutoFocusCallback() {
   @Override
   public void onAutoFocus(boolean success, Camera camera) {
    if (success) {
     camera.takePicture(sc, rc, jc);
    }
   }
  });
 }

 public void hidePhoto(View v) {
  Log.d(TAG, "設定拍照頁面...");
  this.takePhotoBtn.setVisibility(View.VISIBLE);// 顯示拍照按鈕
  this.hidePhotoBtn.setVisibility(View.GONE); // 隱藏重拍按鈕

  Log.d(TAG, "回到拍照功能,需重新啟動預覽...");
  this.cc.getCarema().startPreview();
 }

 public void showPhoto(String picPath) {
  Log.d(TAG, "取得照片路徑:" + picPath);
  Log.d(TAG, "設定照片頁面...");
  this.takePhotoBtn.setVisibility(View.GONE);
  this.hidePhotoBtn.setVisibility(View.VISIBLE);

 }

 //前往照片列表
  public void goToPicList(){
   Intent intent=new Intent(this,PhotoList.class);
   startActivity(intent);
  }

}

CameraCallback.java
package tw.android;

import java.io.IOException;

import android.hardware.Camera;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;


public class CameraCallback implements Callback {

    private static final String TAG = "CameraCallback";
    private Camera carema;

    public Camera getCarema() {
        return this.carema;
    }

    public void surfaceCreated(SurfaceHolder holder) {
        Log.d(TAG, "啟動相機...");
        this.carema = Camera.open();
        try {
            Log.d(TAG, "設定預覽視窗");
            this.carema.setPreviewDisplay(holder);
        }
        catch (IOException e) {
            Log.e(TAG, e.getMessage(), e);
        }
    }

    public void surfaceChanged(SurfaceHolder holder, int format, int width,
            int height) {
        Log.d(TAG, "開始預覽...");
        this.carema.setDisplayOrientation(90); //相機旋轉90度
        this.carema.startPreview();
    }

    public void surfaceDestroyed(SurfaceHolder holder) {
        Log.d(TAG, "停止預覽...");
        this.carema.stopPreview();
        Log.d(TAG, "釋放相機資源...");
        this.carema.release();
        this.carema = null;
    }

 
}

JpgCallback.java
package tw.android;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import android.annotation.SuppressLint;
import android.content.SharedPreferences;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.os.Environment;
import android.util.Log;

public class JpgCallback implements PictureCallback {

    private static final String TAG = "JpgCallback";
    private String picPath;
    private TakeAPhotoActivity act;
    int number;
    public JpgCallback(TakeAPhotoActivity act) {
        super();
        this.act = act;
    }

    @Override
    public void onPictureTaken(byte[] data, Camera camera) {
        Log.d(TAG, "處理 JPG 資料,輸出 jpg 檔...");
        /*-- 2015-09-11 相機旋轉90度後,照片需要跟著旋轉90度 --*/
        Bitmap srcBmp, dstBmp;
        srcBmp= BitmapFactory.decodeByteArray(data, 0, data.length);
        Matrix matrix=new Matrix();
        matrix.reset();
        matrix.postRotate(90f);
        dstBmp= Bitmap.createBitmap(srcBmp, 0, 0, srcBmp.getWidth(), srcBmp.getHeight(), matrix, true);
        /*-- 2015-09-11 --*/
        FileOutputStream os = null;
        try {
            File pic = this.createPicFile();
            os = new FileOutputStream(pic);
            dstBmp.compress(Bitmap.CompressFormat.JPEG, 100, os); //2015-09-11 Bitmap 轉回 byte[]
            os.write(data);
        }
        catch (IOException e) {
            Log.e(TAG, e.getMessage(), e);
        }
        finally {
            if (os != null) {
                try {
                    os.close();
                }
                catch (IOException e) {
                }
            }
        }
        Log.d(TAG, "輸出 JPG 完成");
        // 顯示照片
        this.act.showPhoto(this.picPath);
    }

    @SuppressLint("DefaultLocale")
 private File createPicFile() {
        File sdDir = Environment.getExternalStorageDirectory();
        Log.d(TAG, "sdDir" + sdDir);
        File picDir = new File(sdDir, "takePic"); //建立放置照片資料夾
        if (!picDir.exists()) {
            picDir.mkdir();
        }
        long ctm =System.currentTimeMillis(); //照片名
        
        /* SharedPreferences */
        try {
   SharedPreferences preferencesGet = this.act
     .getSharedPreferences("takePic",
       android.content.Context.MODE_PRIVATE);
   number=preferencesGet.getInt("number", 0); //照片數量
   
  } catch (Exception e) {

  }
        
  SharedPreferences preferencesSave = this.act
    .getSharedPreferences("takePic",
      android.content.Context.MODE_PRIVATE);
  SharedPreferences.Editor editor = preferencesSave.edit();
  
  Log.d(TAG,number+"");
  number++; //照片數量+1
  editor.putInt("number", number);
  editor.putLong(Integer.toString(number), ctm); //儲存照片名
  editor.commit();
  
  
        String fileName = String.format("%d.jpg", ctm);
        File pic = new File(picDir, fileName);
        this.picPath = pic.getAbsolutePath();
        Log.d(TAG, "照片路徑:" + this.picPath);
        return pic;
    }
}
RawCallback.java
package tw.android;

import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.util.Log;

public class RawCallback implements PictureCallback {

    private static final String TAG = "RawCallback";

    @Override
    public void onPictureTaken(byte[] data, Camera camera) {
        Log.d(TAG, "處理 Raw data...");
    }

}

ShCallback.java
package tw.android;

import android.hardware.Camera.ShutterCallback;
import android.util.Log;

public class ShCallback implements ShutterCallback {

    private static final String TAG = "ShCallback";

    @Override
    public void onShutter() {
        Log.d(TAG, "啟動快門...");
    }
}

PhotoList.java 列出照片
package tw.android;

import java.io.File;

import android.app.Activity;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TableRow.LayoutParams;

public class PhotoList extends Activity {

 private Button[] detelPic;
 private String[] dataName;

private int number;

 private int id;

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


 // 排版
 public void setTable() {

  try {
   SharedPreferences preferencesGet = getApplicationContext()
     .getSharedPreferences("takePic",
       android.content.Context.MODE_PRIVATE);
   number=preferencesGet.getInt("number", 0);//取出照片數量
   dataName = new String[number];
   Log.i("number", number+"");
   for(int i = 0; i < number; i++){ 
    dataName[i]=String.valueOf(preferencesGet.getLong(Integer.toString(i+1), 0)); //放入照片名稱
    Log.i("dataName[i]", dataName[i]+"");
   }

  } catch (Exception e) {

  }
  
  
  TableLayout t1 = (TableLayout) findViewById(R.id.tableSet);
  t1.removeAllViews();
  TableRow.LayoutParams tP = new TableRow.LayoutParams(
    LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 1f);

  tP.setMargins(0, 0, 0, 20);

  detelPic = new Button[number];
  for (int i = 0; i < number; i++) { // 列
   TableRow row = new TableRow(this);
   ImageView iv = new ImageView(this);
   String picPath = "/storage/emulated/0/takePic/" + dataName[i]
     + ".jpg";
   Uri uri = Uri.fromFile(new File(picPath));
   iv.setLayoutParams(tP);
   iv.setImageURI(uri);
   row.addView(iv, 0);

   // 刪除button
   detelPic[i] = new Button(this);
   detelPic[i].setText("刪除");
   detelPic[i].setId(i);
   detelPic[i].setOnClickListener(dp); // 動作
   row.addView(detelPic[i], 1);

   t1.addView(row);
  }

 }

 private OnClickListener dp = new OnClickListener() {
  public void onClick(View v) {

   id = v.getId();
   // 刪除照片
   File file = new File("/storage/emulated/0/takePic/" + dataName[id]
     + ".jpg");
   file.delete();

   
   setTable();//重整
  }
 };

}

take_a_photo_activity.xml //拍照layout


    
  
    
 
    

    

    


photo_list.xml //照相列表 layout


    

        
        
    


檔案下載:
https://github.com/terryyamg/AndroidCamera
參考來源:
1.http://cw1057.blogspot.tw/2011/12/android-camera_09.html
2.http://stackoverflow.com/questions/8058122/where-to-put-autofocus-in-the-class-android-camera
3.http://stackoverflow.com/questions/5486529/delete-file-from-internal-storage
4.http://stackoverflow.com/questions/10660598/android-camera-preview-orientation-in-portrait-mode 
(2015-09-11 update)
5. http://rincliu.com/blog/2013/11/18/camera/
6.http://bingtian.iteye.com/blog/642128

2014年12月8日 星期一

Android NFC tag writer 寫入 訊息

NFC感應TAG,將訊息寫入TAG中
1.AndroidManifest.xml
加入權限
與最低版本
android:minsdkversion="17" android:targetsdkversion="17"
2.activity_main.xml



    

        

        
    

    

        

        
    

    


3.MainActivity.java
import java.io.IOException;
import nl.paulus.nfctagwriter.R;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.Ndef;
import android.nfc.tech.NdefFormatable;
import android.os.Bundle;
import android.os.Parcelable;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

/**
 * Activity to write NFC tags with own mimetype and ID Based on the excellent
 * tutorial by Jesse Chen
 * http://www.jessechen.net/blog/how-to-nfc-on-the-android-platform/
 */
public class MainActivity extends Activity {

 boolean mWriteMode = false;
 private NfcAdapter mNfcAdapter;
 private PendingIntent mNfcPendingIntent;

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

  ((Button) findViewById(R.id.button))
    .setOnClickListener(new OnClickListener() {

     @Override
     public void onClick(View v) {
      mNfcAdapter = NfcAdapter
        .getDefaultAdapter(MainActivity.this);
      mNfcPendingIntent = PendingIntent.getActivity(
        MainActivity.this,
        0,
        new Intent(MainActivity.this,
          MainActivity.class)
          .addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP),
        0);
      //開啟寫入
      enableTagWriteMode();

      new AlertDialog.Builder(MainActivity.this)
        .setTitle("感應tag寫入")
        .setOnCancelListener(
          new DialogInterface.OnCancelListener() {
           @Override
           public void onCancel(
             DialogInterface dialog) {
            //關閉寫入
            disableTagWriteMode();
           }

          }).create().show();
     }
    });
 }

 private void enableTagWriteMode() {
  mWriteMode = true;
  IntentFilter tagDetected = new IntentFilter(
    NfcAdapter.ACTION_TAG_DISCOVERED);
  IntentFilter[] mWriteTagFilters = new IntentFilter[] { tagDetected };
  mNfcAdapter.enableForegroundDispatch(this, mNfcPendingIntent,
    mWriteTagFilters, null);
 }

 private void disableTagWriteMode() {
  mWriteMode = false;
  mNfcAdapter.disableForegroundDispatch(this);
 }

 @SuppressLint("NewApi")
 @Override
 protected void onNewIntent(Intent intent) {
  // Tag writing mode
  if (mWriteMode
    && NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())) {
   Tag detectedTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
   NdefRecord record = NdefRecord.createMime( //需要Android 4.1(API Level 16)
     ((TextView) findViewById(R.id.mime)).getText().toString(),
     ((TextView) findViewById(R.id.value)).getText().toString()
       .getBytes());
   NdefMessage message = new NdefMessage(new NdefRecord[] { record });
   if (writeTag(message, detectedTag)) {
    Toast.makeText(this, "成功寫入!",
      Toast.LENGTH_LONG).show();
   }
  }
  
  //讀取寫入訊息 看是否有寫入
  
        try {
         Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
      NdefMessage[] msgs = new NdefMessage[rawMsgs.length];
      for (int i = 0; i < rawMsgs.length; i++) {
                msgs[i] = (NdefMessage) rawMsgs[i];
            }

            NdefMessage msg = msgs[0];
         String msgstring = new String(msg.getRecords()[0].getPayload(), "UTF-8");
         Toast.makeText(getApplicationContext(), msgstring, Toast.LENGTH_LONG).show();
   
        } catch (Exception e) {
            e.printStackTrace();
        }
 }

 /* 檢查訊息 */
 public boolean writeTag(NdefMessage message, Tag tag) {
  int size = message.toByteArray().length;
  try {
   Ndef ndef = Ndef.get(tag);
   if (ndef != null) {
    ndef.connect();
    if (!ndef.isWritable()) {
     Toast.makeText(getApplicationContext(),
       "Error: tag not writable", Toast.LENGTH_SHORT)
       .show();
     return false;
    }
    if (ndef.getMaxSize() < size) {
     Toast.makeText(getApplicationContext(),
       "Error: tag too small", Toast.LENGTH_SHORT).show();
     return false;
    }
    ndef.writeNdefMessage(message);
    return true;
   } else {
    NdefFormatable format = NdefFormatable.get(tag);
    if (format != null) {
     try {
      format.connect();
      format.format(message);
      return true;
     } catch (IOException e) {
      return false;
     }
    } else {
     return false;
    }
   }
  } catch (Exception e) {
   return false;
  }
 }
} 
參考來源:
https://github.com/balloob/Android-NFC-Tag-Writer 
http://stackoverflow.com/questions/7917567/strange-character-on-android-ndef-record-payload 

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