2015年4月28日 星期二

Android Load Image From Camera Or Gallery 讀取照片從相機或圖片庫

利用相機拍照或從已經存在的圖片庫,讀取照片並紀錄,將其顯示在app上。
1.AndroidManifest.xml加入讀取與寫入權限
 
 
2./res/layout/activity_main.xml


    

        
    

    

        
        
    


3.MainActivity.java
package tw.android;

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

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.provider.MediaStore.MediaColumns;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;

public class MainActivity extends Activity {

 private Button btnSelect;
 private ImageView ivImage;

 private int REQUEST_CAMERA = 0, SELECT_FILE = 1;
 private String selectedImagePath; // 圖片檔案位置

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  btnSelect = (Button) findViewById(R.id.btnSelectPhoto);
  ivImage = (ImageView) findViewById(R.id.ivImage);

  // 取出最後圖片檔案位置
  try {
   SharedPreferences preferencesGet = getApplicationContext()
     .getSharedPreferences("image",
       android.content.Context.MODE_PRIVATE);
   selectedImagePath = preferencesGet.getString("selectedImagePath",
     ""); // 圖片檔案位置,預設為空

   Log.i("selectedImagePath", selectedImagePath + "");

  } catch (Exception e) {
  }

  /* 選擇照片 */
  btnSelect.setOnClickListener(new OnClickListener() {

   public void onClick(View v) {
    selectImage();
   }
  });

  setImage();
 }

 /* 設定圖片 */
 private void setImage() {
  BitmapFactory.Options options = new BitmapFactory.Options();
  options.inJustDecodeBounds = false; // 不顯示照片
  BitmapFactory.decodeFile(selectedImagePath, options);
  final int REQUIRED_SIZE = 200;
  int scale = 1;
  /* 圖片縮小2倍 */
  while (options.outWidth / scale / 2 >= REQUIRED_SIZE
    && options.outHeight / scale / 2 >= REQUIRED_SIZE) {
   scale *= 2;
  }
  options.inSampleSize = scale;
  options.inJustDecodeBounds = false; // 顯示照片
  Bitmap bm = BitmapFactory.decodeFile(selectedImagePath, options);
  Log.i("selectedImagePath", selectedImagePath + "");
  ivImage.setImageBitmap(bm);// 將圖片顯示
 }

 private void selectImage() {
  final String item1, item2, item3;
  item1 = "拍一張照";
  item2 = "從圖庫選取";
  item3 = "取消";

  final CharSequence[] items = { item1, item2, item3 };

  AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
  builder.setTitle("新增照片視窗");
  builder.setItems(items, new DialogInterface.OnClickListener() {
   public void onClick(DialogInterface dialog, int item) {
    switch (item) {
    case 0: // 拍一張照
     Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
     startActivityForResult(intent, REQUEST_CAMERA);
     break;
    case 1: // 從圖庫選取
     Intent intent1 = new Intent(
       Intent.ACTION_PICK,
       android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
     intent1.setType("image/*");
     startActivityForResult(
       Intent.createChooser(intent1, "選擇開啟圖庫"),
       SELECT_FILE);
     break;
    default: // 取消
     dialog.dismiss(); // 關閉對畫框
     break;
    }

   }
  });
  builder.show();
 }

 /* 啟動選擇方式 */
 @Override
 public void onActivityResult(int requestCode, int resultCode, Intent data) {
  super.onActivityResult(requestCode, resultCode, data);

  if (resultCode == Activity.RESULT_OK) {
   if (requestCode == SELECT_FILE) // 從圖庫開啟
    onSelectFromGalleryResult(data);
   else if (requestCode == REQUEST_CAMERA) // 拍照
    onCaptureImageResult(data);
  }
 }

 /* 拍照 */
 private void onCaptureImageResult(Intent data) {
  Bitmap thumbnail = (Bitmap) data.getExtras().get("data");
  ByteArrayOutputStream bytes = new ByteArrayOutputStream();
  thumbnail.compress(Bitmap.CompressFormat.JPEG, 90, bytes);
  File destination = new File(Environment.getExternalStorageDirectory(),
    System.currentTimeMillis() + ".jpg"); // 輸出檔案名稱
  selectedImagePath = destination + ""; // 輸出檔案位置
  FileOutputStream fo;
  try {
   destination.createNewFile(); // 建立檔案
   fo = new FileOutputStream(destination); // 輸出
   fo.write(bytes.toByteArray());
   fo.close();
  } catch (FileNotFoundException e) {
   e.printStackTrace();
  } catch (IOException e) {
   e.printStackTrace();
  }

  ivImage.setImageBitmap(thumbnail); // 將圖片顯示
 }

 @SuppressWarnings("deprecation")
 private void onSelectFromGalleryResult(Intent data) {
  Uri selectedImageUri = data.getData();
  String[] projection = { MediaColumns.DATA };
  Cursor cursor = managedQuery(selectedImageUri, projection, null, null,
    null);
  int column_index = cursor.getColumnIndexOrThrow(MediaColumns.DATA);
  cursor.moveToFirst();

  selectedImagePath = cursor.getString(column_index); // 選擇的照片位置

  setImage(); // 設定圖片
 }

 /* 結束時 */
 @Override
 protected void onDestroy() {
  super.onDestroy();
  /* 紀錄圖片檔案位置 */
  SharedPreferences preferencesSave = getApplicationContext()
    .getSharedPreferences("image",
      android.content.Context.MODE_PRIVATE);
  SharedPreferences.Editor editor = preferencesSave.edit();
  editor.putString("selectedImagePath", selectedImagePath); // 紀錄最後圖片位置
  editor.commit();

  Log.i("onDestroy", "onDestroy");
 }

}



檔案下載:
https://github.com/terryyamg/loadImageFromGalleryTest
參考來源:
http://www.theappguruz.com/blog/android-take-photo-camera-gallery-code-sample/

2015年4月27日 星期一

Android Set Volume Switch SeekBar 設定 音量 大小 開關

app中設定音樂開關與大小相關設定,不影響原手機音樂大小設定的方法。
1.AndroidManifest.xml版本設定為
android:minSdkVersion="14"
switch元件需要版本14以上
2./res/layout/activity_main.xml



    
    

    
    

    
    

    
    

    
    

    
    

    
    

    
    

    
    

    
    

    
    

    
    

    
    


2.MainActivity.java
package tw.android;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.media.AudioManager;
import android.os.Bundle;
import android.util.Log;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.Switch;
import android.widget.TextView;

public class MainActivity extends Activity {
 private Switch switchVolume; // 開關

 private SeekBar mediaVlmSeekBar = null; // 音樂、影片、遊戲及其他媒體

 private SeekBar ringerVlmSeekBar = null; // 鈴聲

 private SeekBar alarmVlmSeekBar = null; // 鬧鐘

 private SeekBar notifyVlmSeekBar = null; // 通知

 private AudioManager audioManager = null;

 private TextView tv1, tv2, tv3, tv4;

 private boolean setSwitch;
 private int originalMedia, originalRinger, originalAlarm, originalNotify,
   setMedia, setRinger, setAlarm, setNotify;

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

  /* 權限 */
  this.setVolumeControlStream(AudioManager.STREAM_MUSIC);
  this.setVolumeControlStream(AudioManager.STREAM_RING);
  this.setVolumeControlStream(AudioManager.STREAM_ALARM);
  this.setVolumeControlStream(AudioManager.STREAM_NOTIFICATION);

  setContentView(R.layout.activity_main);

  initControls();
 }

 @SuppressLint("InlinedApi")
 private void initControls() {
  // Return the handle to a system-level service - 'AUDIO'.
  audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
  /* 手機原設定音量大小 */
  originalMedia = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
  originalRinger = audioManager.getStreamVolume(AudioManager.STREAM_RING);
  originalAlarm = audioManager.getStreamVolume(AudioManager.STREAM_ALARM);
  originalNotify = audioManager
    .getStreamVolume(AudioManager.STREAM_NOTIFICATION);

  // 取出最後設定音量大小
  try {
   SharedPreferences preferencesGet = getApplicationContext()
     .getSharedPreferences("vol",
       android.content.Context.MODE_PRIVATE);
   setSwitch = preferencesGet.getBoolean("setSwitch", false);// 預設開關為關閉
   setMedia = preferencesGet.getInt("setMedia", originalMedia); // 預設音量大小
   setRinger = preferencesGet.getInt("setRinger", originalRinger);
   setAlarm = preferencesGet.getInt("setAlarm", originalAlarm);
   setNotify = preferencesGet.getInt("setNotify", originalNotify);

   Log.i("setSwitch", setSwitch + "");
   Log.i("setMedia", setMedia + "");
   Log.i("setRinger", setRinger + "");
   Log.i("setAlarm", setAlarm + "");
   Log.i("setNotify", setNotify + "");
  } catch (Exception e) {
  }

  /* 開關 */
  switchVolume = (Switch) findViewById(R.id.switchVolume);
  switchVolume.setChecked(setSwitch); // 預設開關為關閉

  /* 音樂、影片、遊戲及其他媒體 */
  mediaVlmSeekBar = (SeekBar) findViewById(R.id.seekBar1);
  tv1 = (TextView) findViewById(R.id.tv1);
  mediaVlmSeekBar.setMax(audioManager
    .getStreamMaxVolume(AudioManager.STREAM_MUSIC)); // 最大值

  /* 鈴聲 */
  ringerVlmSeekBar = (SeekBar) findViewById(R.id.seekBar2);
  tv2 = (TextView) findViewById(R.id.tv2);
  ringerVlmSeekBar.setMax(audioManager
    .getStreamMaxVolume(AudioManager.STREAM_RING));

  /* 鬧鐘 */
  alarmVlmSeekBar = (SeekBar) findViewById(R.id.seekBar3);
  tv3 = (TextView) findViewById(R.id.tv3);
  alarmVlmSeekBar.setMax(audioManager
    .getStreamMaxVolume(AudioManager.STREAM_ALARM));

  /* 通知 */
  notifyVlmSeekBar = (SeekBar) findViewById(R.id.seekBar4);
  tv4 = (TextView) findViewById(R.id.tv4);
  notifyVlmSeekBar.setMax(audioManager
    .getStreamMaxVolume(AudioManager.STREAM_NOTIFICATION));

  /* 設定音量大小 */
  mediaVlmSeekBar.setProgress(setMedia);
  ringerVlmSeekBar.setProgress(setRinger);
  alarmVlmSeekBar.setProgress(setAlarm);
  notifyVlmSeekBar.setProgress(setNotify);

  /* 開關動作 */
  if (setSwitch) {
   tv1.setText(audioManager
     .getStreamMaxVolume(AudioManager.STREAM_MUSIC) + "");// 顯示大小
  } else {
   tv1.setText("0");// 顯示大小
  }

  switchVolume.setOnCheckedChangeListener(new OnCheckedChangeListener() {

   public void onCheckedChanged(CompoundButton buttonView,
     boolean isChecked) {

    if (isChecked) { // 開啟
     mediaVlmSeekBar.setProgress(audioManager
       .getStreamMaxVolume(AudioManager.STREAM_MUSIC)); // 設到最大
     setMedia = audioManager
       .getStreamMaxVolume(AudioManager.STREAM_MUSIC);
     setSwitch = true;
    } else { // 關閉
     mediaVlmSeekBar.setProgress(0); // 設到最小
     setMedia = 0;
     setSwitch = false;
    }

   }
  });

  try {
   /* 音樂、影片、遊戲及其他媒體 */
   mediaVlmSeekBar
     .setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
      // seekbar停止時動作
      public void onStopTrackingTouch(SeekBar arg0) {
      }

      // seekbar開始前時動作
      public void onStartTrackingTouch(SeekBar arg0) {
      }

      // seekbar改變時動作
      public void onProgressChanged(SeekBar arg0,
        int progress, boolean arg2) {
       tv1.setText(progress + "");// 顯示大小
       audioManager.setStreamVolume(
         AudioManager.STREAM_MUSIC, progress, 0);
       setMedia = progress; // 修改預設值為選定大小
      }
     });

   /* 鈴聲 */
   ringerVlmSeekBar
     .setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
      public void onStopTrackingTouch(SeekBar arg0) {
      }

      public void onStartTrackingTouch(SeekBar arg0) {
      }

      public void onProgressChanged(SeekBar arg0,
        int progress, boolean arg2) {
       tv2.setText(progress + "");// 顯示大小
       audioManager.setStreamVolume(
         AudioManager.STREAM_RING, progress, 0);
       setRinger = progress; // 修改預設值為選定大小
      }
     });

   /* 鬧鐘 */
   alarmVlmSeekBar
     .setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
      public void onStopTrackingTouch(SeekBar arg0) {
      }

      public void onStartTrackingTouch(SeekBar arg0) {
      }

      public void onProgressChanged(SeekBar arg0,
        int progress, boolean arg2) {
       tv3.setText(progress + "");// 顯示大小
       audioManager.setStreamVolume(
         AudioManager.STREAM_ALARM, progress, 0);
       setAlarm = progress; // 修改預設值為選定大小
      }
     });

   /* 通知 */
   notifyVlmSeekBar
     .setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
      public void onStopTrackingTouch(SeekBar arg0) {
      }

      public void onStartTrackingTouch(SeekBar arg0) {
      }

      public void onProgressChanged(SeekBar arg0,
        int progress, boolean arg2) {
       tv4.setText(progress + "");// 顯示大小
       audioManager.setStreamVolume(
         AudioManager.STREAM_NOTIFICATION, progress,
         0);
       setNotify = progress; // 修改預設值為選定大小
      }
     });
  } catch (Exception e) {
   e.printStackTrace();
  }
 }

 /* 結束時 */
 @Override
 protected void onDestroy() {
  super.onDestroy();
  /* 紀錄設定音量大小 */
  SharedPreferences preferencesSave = getApplicationContext()
    .getSharedPreferences("vol",
      android.content.Context.MODE_PRIVATE);
  SharedPreferences.Editor editor = preferencesSave.edit();
  editor.putBoolean("setSwitch", setSwitch);
  editor.putInt("setMedia", setMedia);
  editor.putInt("setRinger", setRinger);
  editor.putInt("setAlarm", setAlarm);
  editor.putInt("setNotify", setNotify);
  editor.commit();
  /* 還原手機原設定音量大小 */
  audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, originalMedia,
    0);
  audioManager.setStreamVolume(AudioManager.STREAM_RING, originalRinger,
    0);
  audioManager.setStreamVolume(AudioManager.STREAM_ALARM, originalAlarm,
    0);
  audioManager.setStreamVolume(AudioManager.STREAM_NOTIFICATION,
    originalNotify, 0);
  Log.i("onDestroy", "onDestroy");
 }

}

檔案下載:
https://github.com/terryyamg/seekBarVolumeTest
參考連結:
http://programmerguru.com/android-tutorial/android-seekbar-example/
http://www.mysamplecode.com/2013/04/android-switch-button-example.html

2015年4月21日 星期二

Android Load Image From Url 讀取網址照片

從網址上讀取圖片,仿ptt app讀圖片功能
1.AndroidManifest.xml加入網路權限
    
    

2./res/layout/activity_main.xml


    

    

    
    


3.MainActivity.java
package tw.android;

import java.io.InputStream;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;

public class MainActivity extends Activity {

 private Button btUrl, btLoad;
 private String url;

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

  btUrl = (Button) findViewById(R.id.btUrl);
  btLoad = (Button) findViewById(R.id.btLoad);

  /* 顯示url */

  url = "http://i.imgur.com/WPydEEx.jpg"; // 圖片網址
  btUrl.setText(url); // 顯示網址
  btUrl.setOnClickListener(new Button.OnClickListener() {
   public void onClick(View v) {
    Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri
      .parse(url));
    startActivity(browserIntent); // 使用網頁開啟
   }
  });

  /* 下載圖片 */
  btLoad.setOnClickListener(new Button.OnClickListener() {
   public void onClick(View v) {
    btLoad.setVisibility(View.GONE); // 隱藏按鈕
    new DownloadImageTask((ImageView) findViewById(R.id.ivLoad))
      .execute(url); // 載入圖片

   }
  });

 }

 /* AsyncTask執行下載任務 */
 @SuppressLint("NewApi")
 private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
  ImageView bmImage;

  public DownloadImageTask(ImageView bmImage) {
   this.bmImage = bmImage;
  }

  protected Bitmap doInBackground(String... urls) {
   String urldisplay = urls[0];
   Bitmap mIcon11 = null;
   try {
    InputStream in = new java.net.URL(urldisplay).openStream(); // 從網址上下載
    mIcon11 = BitmapFactory.decodeStream(in);
   } catch (Exception e) {
    Log.e("Error", e.getMessage());
    e.printStackTrace();
   }
   return mIcon11;
  }

  protected void onPostExecute(Bitmap result) {
   bmImage.setImageBitmap(result); // 下載完成後載入結果
  }
 }
}


參考網址:
http://stackoverflow.com/questions/5776851/load-image-from-url

2015年4月20日 星期一

Android Zxing QRcode Scanner QRcode掃描

將掃一維二維條碼功能zxing加入自己的app
前置步驟
Step1.下載zxing https://github.com/zxing/zxing/archive/master.zip

Step2. File -> import android這個資料夾


Step3. 去下載的資料夾 android-core 最裡層的CameraConfigurationUtils.java檔案


複製貼到剛剛import下的CaptureActivity\src\com\google\zxing\client\android\camera下。


Step4. 下載core-3.2.0.jar http://mvnrepository.com/artifact/com.google.zxing/core/3.2.0
在CaptureActivity資料夾下建立libs,將core-3.2.0.jar放入。

Step5. 在 CaptureActivity專案點右鍵 -> Properties->點選Android->勾選Android 4.4.2


點選 Java Compiler ->Compiler選擇 compliance level: 1.7


Step6. 點選上方功能列Project -> Clean ->勾選CaptureActivity,
然後回頭去把Android的Is Library打勾


Step7. 打勾後有些檔案會出現錯誤,打開這些檔案,在switch上用滑鼠點一下,按下鍵盤
Ctrl+1,點選Convert'switch' to 'if-else',每個有錯誤的檔案接照此方法。


---------------------------------------已上完成前置動作---------------------------------------

建立新專案
1.在專案點右鍵 -> Properties->點選Android->點選Add->加入CaptureActivity


2.AndroidManifest.xml


    
    

    
    

    
        
            
                
                

                
                
            
        
        
        
            
                
                

                
                
            
            
                
                

                
                
            
        
    


3./res/layout/activity_main.xml


    
    

    

    


4.MainActivity.java
package tw.android;

import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;

public class MainActivity extends Activity {
 
 static final String ACTION_SCAN = "com.google.zxing.client.android.SCAN";

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

 //掃描一維條碼
 public void scanBar(View v) {
  try {
   Intent intent = new Intent(ACTION_SCAN);
   intent.putExtra("SCAN_MODE", "PRODUCT_MODE"); //一維條碼模式
   startActivityForResult(intent, 0);
  } catch (ActivityNotFoundException anfe) {
   
  }
 }
 
 //掃描QRcode
 public void scanQR(View v) {
  try {
   Intent intent = new Intent(ACTION_SCAN);
   intent.putExtra("SCAN_MODE", "QR_CODE_MODE"); //QR code模式
   startActivityForResult(intent, 0);
  } catch (ActivityNotFoundException anfe) {
  
  }
 }

 //傳回結果
 public void onActivityResult(int requestCode, int resultCode, Intent intent) {
  if (requestCode == 0) {
   if (resultCode == RESULT_OK) {
    //get the extras that are returned from the intent
    String contents = intent.getStringExtra("SCAN_RESULT"); //掃描結果
    String format = intent.getStringExtra("SCAN_RESULT_FORMAT");//掃描格式
    Toast toast = Toast.makeText(this, "內容:" + contents + " 格式:" + format, Toast.LENGTH_LONG);
    toast.show();
   }
  }
 }
}


檔案下載:
https://github.com/terryyamg/scannerTest
參考來源:
1.https://github.com/zxing/zxing
2.http://www.androidaz.com/development/zxing-qr-reader-direct-integration
3.http://examples.javacodegeeks.com/android/android-barcode-and-qr-scanner-example/
4.http://mvnrepository.com/artifact/com.google.zxing/core/3.2.0
5.http://stackoverflow.com/questions/11226941/error-in-switch-cases-of-zxing-project-in-android
6.http://stackoverflow.com/questions/24818566/build-library-zxing-for-android-project

2015年4月15日 星期三

Android Parsing XML 解析XML

從網路上的XML檔,取得資訊,並根據項目裡的元素(ex:<item>)取得資訊
1.準備一個xml檔,放置網路上,輸入資訊如網址內容
http://terryyamg.3eeweb.com/ea_103052/drink.xml
2./res/layout/main.xml


    
    


3./res/layout/list_item.xml --自訂ListView的layout


    

        

        
        
        

        
        
        

        

            

            
            
            

            
            
        
    


4.XMLParser.java --解析頁
package com.androidhive.xmlparsing;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import android.util.Log;

public class XMLParser {

 // constructor
 public XMLParser() {

 }

 /**
  * Getting XML from URL making HTTP request
  * @param url string
  * */
 public String getXmlFromUrl(String url) {
  String xml = null;

  try {
   // defaultHttpClient
   DefaultHttpClient httpClient = new DefaultHttpClient();
   HttpPost httpPost = new HttpPost(url);

   HttpResponse httpResponse = httpClient.execute(httpPost);
   HttpEntity httpEntity = httpResponse.getEntity();
   /*處理編碼問題*/
   InputStream inputStream = httpEntity.getContent();
            
            BufferedReader bufReader = new BufferedReader(new InputStreamReader(inputStream, "utf-8"), 8);
            Log.i("bufReader", bufReader+"");
            StringBuilder builder = new StringBuilder();
            String line = null;
            while((line = bufReader.readLine()) != null) {
                builder.append(line + "\n");
            }
            inputStream.close();
           xml = builder.toString();

//   xml = EntityUtils.toString(httpEntity);
   Log.i("xml", xml+"");
   
  } catch (UnsupportedEncodingException e) {
   e.printStackTrace();
  } catch (ClientProtocolException e) {
   e.printStackTrace();
  } catch (IOException e) {
   e.printStackTrace();
  }
  // return XML
  return xml;
 }
 
 /**
  * Getting XML DOM element
  * @param XML string
  * */
 public Document getDomElement(String xml){
  Document doc = null;
  DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
  try {

   DocumentBuilder db = dbf.newDocumentBuilder();

   InputSource is = new InputSource();
          is.setCharacterStream(new StringReader(xml));
          doc = db.parse(is);
   } catch (ParserConfigurationException e) {
    Log.e("Error: ", e.getMessage());
    return null;
   } catch (SAXException e) {
    Log.e("Error: ", e.getMessage());
             return null;
   } catch (IOException e) {
    Log.e("Error: ", e.getMessage());
    return null;
   }

         return doc;
 }
 
 /** Getting node value
   * @param elem element
   */
  public final String getElementValue( Node elem ) {
      Node child;
      if( elem != null){
          if (elem.hasChildNodes()){
              for( child = elem.getFirstChild(); child != null; child = child.getNextSibling() ){
                  if( child.getNodeType() == Node.TEXT_NODE  ){
                      return child.getNodeValue();
                  }
              }
          }
      }
      return "";
  }
  
  /**
   * Getting node value
   * @param Element node
   * @param key string
   * */
  public String getValue(Element item, String str) {  
   NodeList n = item.getElementsByTagName(str);  
   return this.getElementValue(n.item(0));
  }
}
5.AndroidXMLParsingActivity.java --主頁
package com.androidhive.xmlparsing;

import java.util.ArrayList;
import java.util.HashMap;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import android.app.ListActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import android.widget.Toast;

public class AndroidXMLParsingActivity extends ListActivity {

 static final String URL = "http://terryyamg.3eeweb.com/ea_103052/drink.xml"; // 資料網址
 // XML node keys
 static final String KEY_ITEM = "item"; // 網址上的<item> node
 static final String KEY_ID = "id"; // 網址上的<id> node
 static final String KEY_NAME = "name"; // 網址上的<name> node
 static final String KEY_COST = "cost"; // 網址上的<cost> node
 static final String KEY_DESC = "description"; // 網址上的<description> node

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

  ArrayList<HashMap<String, String>> menuItems = new ArrayList<HashMap<String, String>>();

  XMLParser parser = new XMLParser();
  String xml = parser.getXmlFromUrl(URL); // 從網路上drink.xml取得資訊

  Document doc = parser.getDomElement(xml); // 從xml取得DOM元素

  NodeList nl = doc.getElementsByTagName(KEY_ITEM); // 取得<item>裡的資訊

  /* 迴圈取得幾筆(nl.getLength())資料並對應放至map */
  for (int i = 0; i < nl.getLength(); i++) {

   HashMap<String, String> map = new HashMap<String, String>(); // 建立HashMap

   Element e = (Element) nl.item(i);

   /* 對應值 key => value */
   map.put(KEY_ID, parser.getValue(e, KEY_ID));
   map.put(KEY_NAME, parser.getValue(e, KEY_NAME));
   map.put(KEY_COST, "NT." + parser.getValue(e, KEY_COST));
   map.put(KEY_DESC, parser.getValue(e, KEY_DESC));

   Log.i("map", map + "");

   menuItems.add(map); // map加入到menuItems
  }

  /* menuItems加入到ListView */
  ListAdapter adapter = new SimpleAdapter(this, menuItems,
    R.layout.list_item, // 對應自訂的layout
    new String[] { KEY_NAME, KEY_DESC, KEY_COST }, new int[] {
      R.id.name, R.id.desciption, R.id.cost });

  setListAdapter(adapter);

  /* 選中ListView項目 */
  ListView lv = getListView();

  lv.setOnItemClickListener(new OnItemClickListener() {

   @Override
   public void onItemClick(AdapterView<?> parent, View view,
     int position, long id) {
    /* 取得選中的項目值 */
    String name = ((TextView) view.findViewById(R.id.name))
      .getText().toString();
    String cost = ((TextView) view.findViewById(R.id.cost))
      .getText().toString();
    String description = ((TextView) view
      .findViewById(R.id.desciption)).getText().toString();

    Toast.makeText(view.getContext(),
      "您點選的是" + name + "\n總共" + cost + "\n注意:" + description,
      Toast.LENGTH_LONG).show();

   }
  });
 }
}

檔案下載:
https://github.com/terryyamg/AndroidXMLParsing
參考來源:
http://www.androidhive.info/2011/11/android-xml-parsing-tutorial/

2015年4月14日 星期二

Android Battery Information 電池資訊

電池相關功能
1./res/layout/main.xml


    

    
    

    
    


2.Main.java
package tw.android;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.drawable.LevelListDrawable;
import android.os.BatteryManager;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

public class Main extends Activity {
 private Button btBattery;
 private TextView tvBatteryInfo;
 private ImageView ivBattery;
 
 private String healthState,acOrUSB,batteryState;
 
 /** Called when the activity is first created. */
 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);

  btBattery = (Button) findViewById(R.id.btBattery);
  tvBatteryInfo = (TextView) findViewById(R.id.tvBatteryInfo);
  ivBattery = (ImageView) findViewById(R.id.ivBattery);
  
  btBattery.setOnClickListener(new Button.OnClickListener() {
   public void onClick(View v) {
    runInfo();
    
   }
  });
  
  
 }
 
 public void runInfo(){
  /*電池訊息*/
  this.registerReceiver(this.mBatInfoReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
 }
 
 private BroadcastReceiver mBatInfoReceiver = new BroadcastReceiver(){
     @SuppressWarnings("deprecation")
  @Override
     public void onReceive(Context ctxt, Intent intent) {
      int  health= intent.getIntExtra(BatteryManager.EXTRA_HEALTH,0); //健康狀態
   int  icon_small= intent.getIntExtra(BatteryManager.EXTRA_ICON_SMALL,0); //電池i-con圖
   int  level= intent.getIntExtra(BatteryManager.EXTRA_LEVEL,0); //目前電量
   int  plugged= intent.getIntExtra(BatteryManager.EXTRA_PLUGGED,0); //電流來源
   boolean  present= intent.getExtras().getBoolean(BatteryManager.EXTRA_PRESENT); //電池存在否
   int  scale= intent.getIntExtra(BatteryManager.EXTRA_SCALE,0); //電量最大值
   int  status= intent.getIntExtra(BatteryManager.EXTRA_STATUS,0); //充電狀態
   String  technology= intent.getExtras().getString(BatteryManager.EXTRA_TECHNOLOGY); //電池技術
   int  temperature= intent.getIntExtra(BatteryManager.EXTRA_TEMPERATURE,0); //目前溫度
   int  voltage= intent.getIntExtra(BatteryManager.EXTRA_VOLTAGE,0); //目前電壓
   
   /*判斷健康狀態*/
   switch (health) {  
            case BatteryManager.BATTERY_HEALTH_COLD:  
             healthState = "COLD";
                break;  
            case BatteryManager.BATTERY_HEALTH_DEAD:  
             healthState = "DEAD";
                break;  
            case BatteryManager.BATTERY_HEALTH_GOOD:  
             healthState = "GOOD";
                break;  
            case BatteryManager.BATTERY_HEALTH_OVERHEAT:  
             healthState = "OVERHEAT";
                break;  
            case BatteryManager.BATTERY_HEALTH_OVER_VOLTAGE:  
             healthState = "OVER_VOLTAGE";
                break;  
            case BatteryManager.BATTERY_HEALTH_UNKNOWN:  
             healthState = "UNKNOWN";
                break;  
            case BatteryManager.BATTERY_HEALTH_UNSPECIFIED_FAILURE:  
             healthState = "UNSPECIFIED_FAILURE"; 
                break;  
            default:  
                break;  
            }  
   
   /*電池i-con圖*/
   LevelListDrawable batteryLevel = (LevelListDrawable) getResources().getDrawable(icon_small);
   batteryLevel.setLevel(level);
         ivBattery.setBackgroundDrawable(batteryLevel);
   
   /*判斷電流來源*/
   switch (plugged) {  
            case BatteryManager.BATTERY_PLUGGED_AC:  
             acOrUSB = "使用AC";
                break;  
            case BatteryManager.BATTERY_PLUGGED_USB:  
             acOrUSB = "使用USB";
                break;  
            default:  
                break;  
            }  

   /*判斷充電狀態來源*/
    switch (status) {  
             case BatteryManager.BATTERY_STATUS_CHARGING:  
              batteryState = "充電中";
                 break;  
             case BatteryManager.BATTERY_STATUS_DISCHARGING:  
              batteryState = "取消充電";
                 break;  
             case BatteryManager.BATTERY_STATUS_FULL:  
              batteryState = "電量已滿";
                 break;  
             case BatteryManager.BATTERY_STATUS_NOT_CHARGING:  
              batteryState = "未充電";
                 break;  
             case BatteryManager.BATTERY_STATUS_UNKNOWN:  
              batteryState = "未知";
                 break;  
             default:  
                 break;  
             }  
   
    tvBatteryInfo.setText("健康狀態: "+healthState+"\n"+
      "目前電量: "+level+"% \n"+
      "電流來源: "+acOrUSB+"\n"+
      "電池存在: "+present+"\n"+
      "電量最大值: "+scale+"%\n"+
      "充電狀態: "+batteryState+"\n"+
      "電池技術: "+technology+"\n"+
      "目前溫度: "+temperature+"度\n"+
      "目前電壓: "+voltage+"\n");
     }
   };
   
   @Override
  protected void onDestroy() {
   super.onDestroy();
   //結束後要移除,否則會出現 Activity xxx has leaked IntentReceiver
   unregisterReceiver(mBatInfoReceiver);
  }
}

檔案下載:
https://github.com/terryyamg/JudgeBatteryTest
 參考來源:
http://mobiledevtuts.com/android/android-sdk-get-device-battery-information/
http://stackoverflow.com/questions/4891598/android-access-system-drawables
http://stackoverflow.com/questions/9781769/activity-has-leaked-intentreceiver

2015年4月13日 星期一

Android DragSortListView 拖動 自訂 排序

實作像facebook Messenger的貼圖自訂排序


1.下載檔案https://github.com/terryyamg/DragSortListViewTest
如果要看所有demo,請前往https://github.com/bauerca/drag-sort-listview下載

這裡舉demo裡有刪除的例子-簡化版
匯入library

File -> improt Existing Android Code Into Workspace -> Next

Browse...選擇下載的library -> 打勾Copy projects into workspace-> Finish


建立專案->在專案點右鍵-> Properties-> 點選Android ->Add

選擇library ->OK

出現綠色打勾,點選OK完成匯入

2./res/values/string.xml


    DragSortListViewTest

    
        Orioles
        Blue Jays
        Red Sox
        Yankees
        Tigers
        Indians
    


3./res/values/ids.xml

    
    

4./res/values/main.xml --主畫面(注意xmlns:dslv="http://schemas.android.com/apk/res/tw.android的package名稱要與自己的app相同)



5./res/values/list_item_checkable.xml --項目選項(注意tw.android.CheckableLinearLayout的package名稱要與自己的app相同)


    
    

    
    

    
    


6./res/drawable加入兩張圖片delete_x.pngdrag.9.png

7.Main.java
package tw.android;

import java.util.ArrayList;
import java.util.Arrays;

import android.app.ListActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.ArrayAdapter;

import com.mobeta.android.dslv.DragSortListView;
import com.mobeta.android.dslv.DragSortListView.RemoveListener;

public class Main extends ListActivity {
 private ArrayAdapter<String> adapter;

 /*拖拉選項*/
 private DragSortListView.DropListener onDrop = new DragSortListView.DropListener() {
  public void drop(int from, int to) {
   Log.i("from", from+"");
   Log.i("to", to+"");
   if (from != to) { //選項有移動位置
    DragSortListView list = getListView();
    String item = adapter.getItem(from);
    adapter.remove(item); //移除初始A的位置
    adapter.insert(item, to); //將A加入到B的位置
    list.moveCheckState(from, to);
   }
  }
 };

 /*移除選項*/
 private RemoveListener onRemove = new DragSortListView.RemoveListener() {
  public void remove(int which) {
   Log.i("which", which+"");
   DragSortListView list = getListView();
   String item = adapter.getItem(which);
   adapter.remove(item); //移除選中位置
   list.removeCheckState(which);
  }
 };

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

  /*建立選單*/
  String[] array = getResources().getStringArray(R.array.mlb_team); //在res/valuse/string.xml 建立選單
  ArrayList<String> arrayList = new ArrayList<String>(
    Arrays.asList(array));

  adapter = new ArrayAdapter<String>(this, R.layout.list_item_checkable, //選單layout樣式
    R.id.text, arrayList);

  setListAdapter(adapter);

  DragSortListView list = getListView();
  list.setDropListener(onDrop);
  list.setRemoveListener(onRemove);
 }

 @Override
 public DragSortListView getListView() {
  return (DragSortListView) super.getListView();
 }

}
8.CheckableLinearLayout.java
package tw.android;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.Checkable;
import android.widget.LinearLayout;

public class CheckableLinearLayout extends LinearLayout implements Checkable {

    private static final int CHECKABLE_CHILD_INDEX = 1;
    private Checkable child;

    public CheckableLinearLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        child = (Checkable) getChildAt(CHECKABLE_CHILD_INDEX);
    }

    public boolean isChecked() {
        return child.isChecked(); 
    }

    public void setChecked(boolean checked) {
        child.setChecked(checked);
    }

    public void toggle() {
        child.toggle();
    }
    
}
移除

檔案下載:
https://github.com/terryyamg/DragSortListViewTest
參考來源:
https://github.com/bauerca/drag-sort-listview

2015年4月10日 星期五

Android DatePicker Hide Year Month Day 日期選項 隱藏 年 月 日

隱藏原生的DatePicker的年或月
1./res/layout/main.xml


    

        

            
            

            
            

            
            

            
            

            
            

            
            
        
    


2.Main.java
package tw.android;

import java.lang.reflect.Field;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.DatePicker;

public class Main extends Activity {
 private DatePicker datePicker1, datePicker2;

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

  datePicker1 = (DatePicker) findViewById(R.id.datePicker1);
  datePicker2 = (DatePicker) findViewById(R.id.datePicker2);

  try {
   /* 隱藏年 */
   Field f1[] = datePicker1.getClass().getDeclaredFields(); // 建立datePicker1
   for (Field field : f1) {
    Log.i("f1's all field", field.getName() + ""); // log出f1的所有元素
    if (field.getName().equals("mYearSpinner")) { // 取得的元素等於mYearSpinner
     field.setAccessible(true);
     Object yearPicker = new Object();
     yearPicker = field.get(datePicker1);
     ((View) yearPicker).setVisibility(View.GONE); // 隱藏年
    }

   }
   /* 隱藏年、月 */
   Field f2[] = datePicker2.getClass().getDeclaredFields(); // 建立datePicker2
   for (Field field : f2) {
    Log.i("f2's all field", field.getName() + ""); // log出f2的所有元素
    if (field.getName().equals("mYearSpinner")) { // 取得的元素等於mYearSpinner
     field.setAccessible(true);
     Object yearPicker = new Object();
     yearPicker = field.get(datePicker2);
     ((View) yearPicker).setVisibility(View.GONE); // 隱藏年
    }

    if (field.getName().equals("mMonthSpinner")) { // 取得的元素等於mMonthSpinner
     field.setAccessible(true);
     Object monthPicker = new Object();
     monthPicker = field.get(datePicker2);
     ((View) monthPicker).setVisibility(View.GONE); // 隱藏月
    }

   }
  } catch (Exception e) {
   Log.d("ERROR", e.getMessage());
  }
 }
}


參考來源:
http://stackoverflow.com/questions/10401915/hide-year-field-in-android-datepicker

2015年4月9日 星期四

Android CheckBox Text Up Left Right Bottom Location 核取方塊 文字位置

要改變checkbox的text位置需自訂圖片與選擇器
1.在/res/drawable/加入圖片checked.pngunchecked.png 


2./res/drawable/bottom.xml

    
    
        

3./res/layout/main.xml
android:button="@android:color/transparent" ----- 隱藏原核取方塊
android:drawableTop="@drawable/bottom" ----- 加入選擇器bottom.xml,文字在下方
android:drawableLeft ----- 文字在右方
android:drawableRight ----- 文字在左方
android:drawableBottom ----- 文字在上方


    

        
        
    

    

        
        
    

    

        
        
    

    

        
        
    


4.Main.java
package tw.android;

import android.app.Activity;
import android.os.Bundle;

public class Main extends Activity {

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

 }
 

}


參考來源:
http://stackoverflow.com/questions/27030629/android-how-to-align-the-checkbox-text-in-the-bottom
http://stackoverflow.com/questions/16063135/removing-the-box-from-the-checkbox-in-android

2015年4月2日 星期四

Android Compass Sensor 指南針 感應器

基本指南針感應器應用,需在實機上應用,如果手機無感應器,則LogCat會出現
 sensor or listener is null
1.加入圖片



2./res/layout/main.xml


    
    

    
    


3.Main.java
package tw.android;

import android.app.Activity;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.view.animation.Animation;
import android.view.animation.RotateAnimation;
import android.widget.ImageView;
import android.widget.TextView;

public class Main extends Activity implements SensorEventListener {

 private ImageView image;
 // 初始角度
 private float currentDegree = 0f;
 // 感應器管理
 private SensorManager mSensorManager;

 private TextView tvHeading;

 float[] mGravity;
 float[] mGeomagnetic;
 float Rotation[] = new float[9];
 float[] degree = new float[3];

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

  image = (ImageView) findViewById(R.id.imageViewCompass);
  tvHeading = (TextView) findViewById(R.id.tvHeading);
  mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
 }

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

  // 註冊感應監聽器

  Sensor accelerometer = mSensorManager
    .getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
  Sensor magnetometer = mSensorManager
    .getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);

  mSensorManager.registerListener(this, accelerometer,
    SensorManager.SENSOR_DELAY_GAME);
  mSensorManager.registerListener(this, magnetometer,
    SensorManager.SENSOR_DELAY_GAME);
 }

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

  // 停止感應監聽器
  mSensorManager.unregisterListener(this);
 }

 public void onSensorChanged(SensorEvent event) {

  if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
   mGravity = event.values;
  }
  if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
   mGeomagnetic = event.values;
  }
  if (mGravity != null && mGeomagnetic != null) {

   SensorManager.getRotationMatrix(Rotation, null, mGravity,
     mGeomagnetic);
   SensorManager.getOrientation(Rotation, degree);

   degree[0] = (float) Math.toDegrees(degree[0]);


   tvHeading.setText("Heading: " + (int) degree[0] + " degrees");

   // currentDegree-初始角度,-degree逆時針旋轉結束角度
   RotateAnimation ra = new RotateAnimation(currentDegree, -degree[0],
     Animation.RELATIVE_TO_SELF, 0.5f, // x座標
     Animation.RELATIVE_TO_SELF, 0.5f); // y座標

   // 轉動時間
   ra.setDuration(210);

   // 預設狀態結束後的動作設定
   ra.setFillAfter(true);

   // 將動作放入圖片
   image.startAnimation(ra);
   currentDegree = -degree[0];
  }
 }

 /* 改變經確度 */
 public void onAccuracyChanged(Sensor sensor, int accuracy) {
  // not in use
 }
}


檔案下載:
https://github.com/terryyamg/compassTest
參考來源:
http://www.javacodegeeks.com/2013/09/android-compass-code-example.html
http://www.codingforandroid.com/2011/01/using-orientation-sensors-simple.html