2015年3月20日 星期五

Android file upload 檔案 上傳

將檔案上傳置後端server與php溝通
1.加入權限AndroidManifest.xml
<uses-sdk
        android:minSdkVersion="11"
        android:targetSdkVersion="21" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

2.加入三個檔案放在lib資料夾下
httpclient-4.3.6.jar
httpcore-4.3.3.jar
httpmime-4.3.6.jar

3./res/layout/main.xml



    
    

    
    

    


4.建立檔案AndroidMultiPartEntity.java
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;

import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntity;

@SuppressWarnings("deprecation")
public class AndroidMultiPartEntity extends MultipartEntity

{

 private final ProgressListener listener;

 public AndroidMultiPartEntity(final ProgressListener listener) {
  super();
  this.listener = listener;
 }

 public AndroidMultiPartEntity(final HttpMultipartMode mode,
   final ProgressListener listener) {
  super(mode);
  this.listener = listener;
 }

 public AndroidMultiPartEntity(HttpMultipartMode mode, final String boundary,
   final Charset charset, final ProgressListener listener) {
  super(mode, boundary, charset);
  this.listener = listener;
 }

 @Override
 public void writeTo(final OutputStream outstream) throws IOException {
  super.writeTo(new CountingOutputStream(outstream, this.listener));
 }

 public static interface ProgressListener {
  void transferred(long num);
 }

 public static class CountingOutputStream extends FilterOutputStream {

  private final ProgressListener listener;
  private long transferred;

  public CountingOutputStream(final OutputStream out,
    final ProgressListener listener) {
   super(out);
   this.listener = listener;
   this.transferred = 0;
  }

  public void write(byte[] b, int off, int len) throws IOException {
   out.write(b, off, len);
   this.transferred += len;
   this.listener.transferred(this.transferred);
  }

  public void write(int b) throws IOException {
   out.write(b);
   this.transferred++;
   this.listener.transferred(this.transferred);
  }
 }
}

5.主檔Main.java
import java.io.File;
import java.io.IOException;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;

import tw.android.AndroidMultiPartEntity.ProgressListener;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;

public class Main extends Activity {

 private ProgressBar progressBar;
 private String FILE_UPLOAD_URL,filePath = null;
 private TextView txtPercentage;
 private Button btnUpload;
 long totalSize = 0;
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);

  txtPercentage = (TextView) findViewById(R.id.txtPercentage);
  btnUpload = (Button) findViewById(R.id.btnUpload);
  progressBar = (ProgressBar) findViewById(R.id.progressBar);

  /*上傳server網址*/
  FILE_UPLOAD_URL= "http://xxxxx.3eeweb.com/AndroidFileUpload/fileUpload.php";
  
  String folder="life"; //資料夾名稱
  String fileName="IMG_20150226_161243.jpg"; //要上傳的手機裡的檔案-檔案名稱
  
  filePath = "/storage/sdcard0/"+folder+"/"+fileName; // 檔案路徑位置
  
  /*上傳按鈕*/
  btnUpload.setOnClickListener(new View.OnClickListener() {

   public void onClick(View v) {
    // 上傳至後端sever
    new UploadFileToServer().execute();
   }
  });

 }

 /* 上傳至後端sever */
 private class UploadFileToServer extends AsyncTask {
  /* 背景執行前的顯示動作 */
  @Override
  protected void onPreExecute() {
   // 設定進度條初始為0
   progressBar.setProgress(0);
   super.onPreExecute();
  }

  /* 背景執行中的顯示動作 */
  @Override
  protected void onProgressUpdate(Integer... progress) {
   // 顯示進度條
   progressBar.setVisibility(View.VISIBLE);

   // 更新進度療
   progressBar.setProgress(progress[0]);

   // 更新顯示文字百分比
   txtPercentage.setText(String.valueOf(progress[0]) + "%");
  }

  /* 背景執行的工作 */
  @Override
  protected String doInBackground(Void... params) {
   return uploadFile();
  }

  @SuppressWarnings("deprecation")
  private String uploadFile() {
   String responseString = null;

   HttpClient httpclient = new DefaultHttpClient();
   HttpPost httppost = new HttpPost(FILE_UPLOAD_URL);

   try {
    AndroidMultiPartEntity entity = new AndroidMultiPartEntity(
      new ProgressListener() {

       public void transferred(long num) {
        publishProgress((int) ((num / (float) totalSize) * 100));
       }
      });

    File sourceFile = new File(filePath);

    
    // Adding file data to http body
    entity.addPart("image", new FileBody(sourceFile));
    /* 攜帶參數(非必要) */
    // Extra parameters if you want to pass to server
//    entity.addPart("website",
//      new StringBody("www.androidhive.info"));
//    entity.addPart("email", new StringBody("abc@gmail.com"));

    totalSize = entity.getContentLength();
    httppost.setEntity(entity);

    // Making server call
    HttpResponse response = httpclient.execute(httppost);
    HttpEntity r_entity = response.getEntity();

    int statusCode = response.getStatusLine().getStatusCode();
    if (statusCode == 200) {
     // Server response
     responseString = EntityUtils.toString(r_entity);
    } else {
     responseString = "Error occurred! Http Status Code: "
       + statusCode;
    }

   } catch (ClientProtocolException e) {
    responseString = e.toString();
   } catch (IOException e) {
    responseString = e.toString();
   }

   return responseString;

  }

  /* 背景執行完成後的顯示動作 */
  @Override
  protected void onPostExecute(String result) {
   Log.e("END", "Response from server: " + result);

   /* 完成後alert顯示訊息 */
   showAlert(result);

   super.onPostExecute(result);
  }

 }

 /* 完成後alert顯示訊息 */
 private void showAlert(String message) {
  AlertDialog.Builder builder = new AlertDialog.Builder(this);
  builder.setMessage(message).setTitle("Response from Servers")
    .setCancelable(false)
    .setPositiveButton("OK", new DialogInterface.OnClickListener() {
     public void onClick(DialogInterface dialog, int id) {
      // do nothing
     }
    });
  AlertDialog alert = builder.create();
  alert.show();
 }

}
6.後端php接收檔案/AndroidFileUpload/fileUpload.php
檔案會上傳至/AndroidFileUpload/uploads/
echo $_FILES['image']['name'] . '< br/>';


//ini_set('upload_max_filesize', '10M');
//ini_set('post_max_size', '10M');
//ini_set('max_input_time', 300);
//ini_set('max_execution_time', 300);


$target_path = "uploads/";

$target_path = $target_path . basename($_FILES['image']['name']);

try {
    //throw exception if can't move the file
    if (!move_uploaded_file($_FILES['image']['tmp_name'], $target_path)) {
        throw new Exception('Could not move file');
    }

    echo "The file " . basename($_FILES['image']['name']) .
    " has been uploaded";
} catch (Exception $e) {
    die('File did not upload: ' . $e->getMessage());
}




檔案下載:
app:https://github.com/terryyamg/uploadTest
php:https://drive.google.com/file/d/0BxoUMTbigRuCZnVyM3VTV2o2NVU/view?usp=sharing

推薦後端網頁:http://cpanel.2freehosting.com/

參考來源:http://www.androidhive.info/2014/12/android-uploading-camera-image-video-to-server-with-progress-bar/

2015年3月18日 星期三

Android password SHA1 密碼 編碼

登入密碼使用SHA1編碼
1.MainActivity.java

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

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

public class MainActivity extends Activity{
 
 private String password="123456";
 
 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  Log.i("Original:::",password+"");
  try {
   Log.i("SHA1:::::::",SHA1(password)+"");
  } catch (NoSuchAlgorithmException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (UnsupportedEncodingException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }
 
 /* SHA1 */
 public String SHA1(String text) throws NoSuchAlgorithmException, UnsupportedEncodingException {
  MessageDigest md = MessageDigest.getInstance("SHA-1");
  md.update(text.getBytes("iso-8859-1"), 0, text.length());
  byte[] sha1hash = md.digest();
  return convertToHex(sha1hash);
 }
 
 private String convertToHex(byte[] data) {
  StringBuilder buf = new StringBuilder();
  for (byte b : data) {
   int halfbyte = (b >>> 4) & 0x0F;
   int two_halfs = 0;
   do {
    buf.append((0 <= halfbyte) && (halfbyte <= 9) ? (char) ('0' + halfbyte) : (char) ('a' + (halfbyte - 10)));
    halfbyte = b & 0x0F;
   } while (two_halfs++ < 1);
  }
  return buf.toString();
 }
}
Log訊息:

參考來源:http://stackoverflow.com/questions/5980658/how-to-sha1-hash-a-string-in-android

2015年3月12日 星期四

Android TabHost Customize 頁籤 客製化 自製化

TabHost自行製作
1.主要layout檔/res/layout/main.xml



    

        
        

        

            

                
                
            

            

                
                
            

            

                
                
            
        
    


2.Main.java
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TabHost;
import android.widget.TabHost.TabContentFactory;
import android.widget.TabHost.TabSpec;
import android.widget.TextView;

public class Main extends Activity {
 private TabHost mTabHost;
 
 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);
  
  mTabHost = (TabHost) findViewById(android.R.id.tabhost);
  mTabHost.setup();
  
  LinearLayout tv1 = (LinearLayout) findViewById(R.id.tab1); //頁籤1內容
  LinearLayout tv2 = (LinearLayout) findViewById(R.id.tab2); //頁籤2內容
  LinearLayout tv3 = (LinearLayout) findViewById(R.id.tab3); //頁籤3內容
  
     setupTab(tv1, "Tab 1",1); //頁籤 (內容,標籤,圖id)
     setupTab(tv2, "Tab 2",1);
     setupTab(tv3, "Tab 3",1);
     
     mTabHost.setCurrentTab(2); //點選頁籤3
     mTabHost.setCurrentTab(1); //點選頁籤2
     mTabHost.setCurrentTab(0); //點選頁籤1
 }
 
 private void setupTab(final View view, final String tag,final Integer iconId) {
     View tabview = createTabView(mTabHost.getContext(), tag, iconId); //設定頁籤
     TabSpec setContent = mTabHost.newTabSpec(tag).setIndicator(tabview).setContent(new TabContentFactory() {
         public View createTabContent(String tag) {
             return view;
         }
     });
     mTabHost.addTab(setContent);
 }

 @SuppressLint("InflateParams")
 private static View createTabView(final Context context, final String text,final Integer iconId) {
     View view = LayoutInflater.from(context).inflate(R.layout.tabs_bg, null);
     ImageView iv = (ImageView) view.findViewById(R.id.icon); //顯示icon圖示
     TextView tv = (TextView) view.findViewById(R.id.tabsText); //顯示文字
        iv.setImageResource(iconId); //設定圖示
     tv.setText(text); //設定文字
     return view;
 }
}
3.layout頁籤背景 /res/layout/tabs_bg.xml


    
    

    
    


4.drawable背景檔-選擇器 /res/drawable/tab_bg_selector.xml


    
    
    
    
    
    
    
    


5.drawable背景檔-選中色彩 /res/drawable/tab_bg_selected.xml


    


6.drawable背景檔-沒選中色彩 /res/drawable/tab_bg_unselected.xml


    


7.drawable圖示檔-選擇器 /res/drawable/tab_icon_selector.xml
sport1,sport2為圖檔


    
    
    
    


8.drawable文字檔-選擇器 /res/drawable/tab_text_selector.xml


    
    
    
    


效果如圖


檔案位址:https://github.com/terryyamg/tabhost_customize
參考來源:http://stackoverflow.com/questions/17897351/how-to-customize-android-tabs-or-background-change

2015年2月25日 星期三

Android db file copy backup 資料庫 檔案 複製 備份

備份資料庫或檔案到其他位置,加入下列程式碼

try {
         File sd = Environment.getExternalStorageDirectory(); //複製到哪裡
         File data = Environment.getDataDirectory(); //原始位置

         if (sd.canWrite()) {
             String currentDBPath = "//data//com.httc.pipeline//xxx.db"; //原始位置檔名
             String backupDBPath = "xxx.db"; //複製位置檔名
             File currentDB = new File(data, currentDBPath);
             File backupDB = new File(sd, backupDBPath);
             Log.i("currentDB", currentDB+"");
             Log.i("backupDB", backupDB+"");
             if (currentDB.exists()) { //原始檔案存在
                 FileChannel src = new FileInputStream(currentDB).getChannel();
                 FileChannel dst = new FileOutputStream(backupDB).getChannel();
                 dst.transferFrom(src, 0, src.size()); //開始複製
                 Log.i("dst", dst+"");
                 src.close();
                 dst.close();
             }
         }
     } catch (Exception e) {
       Log.i("eDB", e+"");
     }
參考來源: http://stackoverflow.com/questions/1995320/how-to-backup-database-file-to-sdcard-on-android

2015年2月12日 星期四

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/