My Calendar

顯示具有 Android 標籤的文章。 顯示所有文章
顯示具有 Android 標籤的文章。 顯示所有文章

2016年8月2日 星期二

Uri.fromFile中文亂碼

Uri.fromFile 中文亂碼

最近在開發 APP 的時候發現有某部分拍照後有確認和取消按鈕的手機會讓整個 APP 崩潰。花了一些時間最後找到兇手原來就是 Uri.fromFile已知 ASUS_T00P 會有這個問題。

URl使用中文去訪問是沒有問題的,因为android在內部進行了轉碼。 但是從URL獲取文件名的時候,因为android已經轉過碼,所以得到的就是亂碼了。如果一定需要中文路徑或是中文檔案名稱,可以用到android提供的方法Uri.decode()獲取正確的中文路徑或是直接使用Uri.parse()


 String imageRef= "/mnt/sdcard/測試.jpg";;
 File f = new File(imageRef);
 Uri uri = Uri.fromFile(f); //會造成檔案亂碼
 Uri uri =  Uri.parse("file://"+imageRef.getPath()); // 使用Uri.parse()
 Uri uri =  Uri.parse(Uri.decode(path)); // 使用Uri.decode() 轉碼

2014年7月26日 星期六

Android-建立選單(Menu)

Android-建立選單(Menu)

建立選單有兩種方法:
  1. 透過XML定義選單
  2. 透過程式碼定義選單

不管是第一種或第二種方法都要用onCreateOptionMenu建立選單。

透過XML定義選單

選單的xml描述檔在 res -> menu 當中,本篇的選單xml檔案名稱為main.xml(任何名稱都可以)在xml檔案裡定義我們想要的選單內容。以下是一個範例。

main.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context="com.example.bmi.MainActivity" >

<item
     android:id="@+id/action_settings"
     android:orderInCategory="100"
     android:title="@string/action_settings"
     android:showAsAction="never"/>

</menu>


menu標籤在加入item標籤,就可以定義每個選項與顯示的內容。
  • android:id = 指定選單項目的識別代號
  • android:title = 指定選項的名字。
  • android:orderInCategory = 指定選單間的排列順序,數字小的優先。若沒有指定這個屬性,則按照你定義item標籤的順序顯示。
  • android:showAsAction = 定義選單項目在ActionBar上的顯示方式。詳細資訊到Menu Resources看看。
將選單定義完成過後,要將定義好的選單加到Android應用程式上要用到onCreateOptionMenugetMenuInfalter.inflate().
@Override
 public boolean onCreateOptionsMenu(Menu menu) {
  getMenuInflater().inflate(R.menu.main, menu);
  return true;
 }

透過程式碼定義選單

除了可以透過XML定義選單,也可以透過程式碼來定義選單。新增一個選項要用到menu.add()


menu.add(groupId, itemId, order, title)
  • groupId = 指定選項屬於哪一個組別
  • itemId = 指定每一個選項一個唯一值,如果沒有指定就用Menu.NONE
  • order = 排列順序
  • title = 顯示選項的名字

 
@Override 
public boolean onCreateOptionsMenu(Menu menu) {
  menu.add(0,Menu.FIRST,100,R.string.about)
  return true;
 }

處理選單項目的功能
當選單設定好過後,這時候要處理每個選單項目的功能就需要加入onOptionsItemSelected函式。
 
@Override
public boolean onOptionsItemSelected(MenuItem item){
  // TODO Auto-generated method stub
  switch(item.getItemId()) {
     case R.id.action_about:
       openOptionsDialog();
       break;
     case R.id.action_close:
       finish();
       break;
   }
    return super.onOptionsItemSelected(item);
}

onOptionsItemSelected這個函式可以處理所有選項項目。函式中傳入一個MenuItem型別的item參數程式中的super.onOptionsItesSelected(item)表示要先執行已定義在Activity類別中原本的onOptionsItemSelected函式內容,後面才執行我們為此函式新定義的動作。

接著要在程式中對每個選項作處理 :
 
 switch(item.getItemId()) {
   case R.id.action_about:
       openOptionsDialog();
       break;
   case R.id.action_close:
       finish();
       break;
}
我們可以使用item.getItemId()函式,來取得在熒幕上選取的選單項目所對應的識別符號。然後在『switch』中,根據從item.getItemId()所取得的識別符號判斷程式應該運行的流程。R.id.action_aboutR.id.action_close是XML檔中定義的識別符號。 

2014年6月15日 星期日

Android 程式開發(四)

Android 程式開發(四)

在 Android程式開發 (三) 中已經將BMI程式所需要的UI Components都已經建立好。接下來將開始BMI的程式設計。以下是BMI完整的程式。

package com.example.bmi;

import java.text.DecimalFormat;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends Activity {

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  initViews();
  setListener();  
 }
 
 private Button button_calc;
 private EditText num_height;
 private EditText num_weight;
 private TextView show_result;
 private TextView show_suggest;
 
 private void initViews(){
  button_calc = (Button)findViewById(R.id.submit); 
  num_height = (EditText)findViewById(R.id.height);
  num_weight = (EditText)findViewById(R.id.weight);
  show_result  = (TextView)findViewById(R.id.result);
  show_suggest  = (TextView)findViewById(R.id.suggest);
 }
 
 private void setListener(){
  button_calc.setOnClickListener(calcBMI);
 }

 
 private OnClickListener calcBMI = new OnClickListener(){
  public void onClick(View v){
     
    DecimalFormat nf = new DecimalFormat("0.00");
    double height = Double.parseDouble(num_height.getText().toString())/100;
    double weight = Double.parseDouble(num_weight.getText().toString());
    double BMI = weight/ (height*height);
     
    //Present result
    show_result.setText(getText(R.string.bmi_result)+nf.format(BMI));
       
    //Give advice 
    if(BMI > 25){
      show_suggest.setText(R.string.advice_heavy);
     } else if (BMI < 20){
      show_suggest.setText(R.string.advice_light);
     } else {
      show_suggest.setText(R.string.advice_average);
     }
  }
 };
 
 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
  // Inflate the menu; this adds items to the action bar if it is present.
  getMenuInflater().inflate(R.menu.main, menu);
  return true;
 }
}


第15-16行
@Override
protected void onCreate(Bundle savedInstanceState) {
}
『onCreate』是這個方法的名稱,同時傳入一個Bundle類別的參數savedInstanceState。目前只需要知道savedInstanceState只是處理記憶體相關的事情就可以。因為我們的『MainActivity』類別繼承了Activity類別,所以『MainActivity』也要實作『onCreate』方法。事實『onCreate』方法是每個Activity類別在初始化時都會呼叫的方法。第15行中有『@』開頭的語句,那是裝飾子(decorator)的語句,『@Override』的作用是告訴程式我們要覆載『onCreate』這個方法。這時候當程式執行的時,將不再使用Activity類別裡的『onCreate』方法,而是使用『MainActivity』中自行實作的行為。接下來看看『onCreate』方法中的程式內容。

第17行
super.onCreate(savedInstanceState);
『super』是關鍵字,表示『MainActivity』的父類別(Activity)。程式的意思是呼叫Activity中的『onCreate』方法。Activity類別初始化的時候都會呼叫『onCreate』的方法。原本繼承『Activity』類別的『onCreate』方法,因為『@Override』的原因內容被重寫。因此想要將『Activity』類別的『onCreate』方法保留並加入我們的內容,就要使用『super』語句。

第18行
setContentView(R.layout.activity_main);
要將我們所定義好的畫面顯示在Activity當中要用『setContentView』,而在上一章節所定義好的UI components在activity_main.xml檔案中,只要透過『setContentView』參數設定為『R.layout.activity_main』引用XML文件描述檔就能將UI 顯示在Activity中。

第24-36行
private void initViews(){
  button_calc = (Button)findViewById(R.id.submit); 
     ...
 }
這段程式主要的功用是宣告Android介面上全部的UI components。透過Activity類別中內建的『findViewById』方法,可以根據識別代號從資源檔中取得對應的UI components實體。這邊以『R.id.submit』按鈕元件為例。我們可以在前面加上『Button』來強制將這個UI components 實體轉型為Button類別的實體。

『R.id.submit』對應到XML描述檔的資源。
  <Button android:id="@+id/submit"
  />
第39行
button_calc.setOnClickListener(calcBMI);
這句是包含『Button』類別中『setOnClickListener』方法。方法中傳入一個名叫『calcBMI』的函式。在Android系統的UI互動方式是採用事件驅動方式。也就是當使用者按下『button_calc』按鈕的時候,Android系統會去觸發『setOnClickListener』方法中所指定的函式『calcBMI』。

 private OnClickListener calcBMI = new OnClickListener(){
  public void onClick(View v){
    ....
   }
};
當使用者按下按鈕時,就會觸發『OnClickListener』類型的事件函式。此範例中的所有邏輯運算都放在這函式中。

BMI值運算,BMI的公式是(體重/身高(m)*身高(m))
double height = Double.parseDouble(num_height.getText().toString())/100;
double weight = Double.parseDouble(num_weight.getText().toString());
double BMI = weight/ (height*height);

透過『TextView』類別中的『setText』方法將結果輸出到手機畫面。
show_result.setText(getText(R.string.bmi_result)+nf.format(BMI));

顯示建議
if(BMI > 25){
   show_suggest.setText(R.string.advice_heavy);
} else if (BMI < 20){
   show_suggest.setText(R.string.advice_light);
} else {
   show_suggest.setText(R.string.advice_average);
}

2014年5月19日 星期一

Android 程式開發(三)

           Android 程式開發(三)

上一篇 Android程式開發(二)介紹了Android的UI Components。接下來將會以開發一個BMI程式為例子進行講解。在開始寫BMI程式之前,應該先設計interface。

介面設計

我們從Form Widgets當中選擇兩個TextView,兩個Large Text和一個Button。再來從Text Fields當中選擇兩個 Number (Decimal)。然後將這些UI Components擺放在自己喜歡的地方。TextView是用來顯示文字,Large Text是用來顯示結果,Button是用來計算BMI,Number(Decimal) 則是讓使用者輸入。


然後點擊第一個Edit Text按右鍵,選擇Edit ID,會彈出一個對話框讓我們輸入識別符號,我們在對話框中輸入 『height』當作這個這個UI Component的識別符號。



除了使用 Graphical Layout的方法設定ID,當然也可以使用XML檔進行編輯。現在我們將切換到 『activity_main.xml』將會看到以下的片段。

<TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="16dp"
        android:text="身高 (cm)" />

『android:text』是用來顯示文字,而『android:id』和給UI Components的識別符號,每一個介面元件都要有一個ID,主要的用處是為了讓程式可以找到相關的UI Components。以下是完整的activity_main.xml的描述

  <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.bmi.MainActivity$PlaceholderFragment" />

<EditText
        android:id="@+id/weight"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/textView1"
        android:layout_centerHorizontal="true"
        android:ems="10"
        android:inputType="numberDecimal" >
    </EditText>

    <Button
        android:id="@+id/submit"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/weight"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="26dp"
        android:text="計算 BMI 值" />

    <TextView
        android:id="@+id/suggest"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/result"
        android:layout_below="@+id/result"
        android:layout_marginTop="14dp"
        android:textAppearance="?android:attr/textAppearanceLarge" />

    <TextView
        android:id="@+id/result"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/submit"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="19dp"
        android:textAppearance="?android:attr/textAppearanceLarge" />

    <EditText
        android:id="@+id/height"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/textView2"
        android:layout_centerHorizontal="true"
        android:ems="10"
        android:inputType="numberDecimal" />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="16dp"
        android:text="身高 (cm)" />

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignRight="@+id/textView2"
        android:layout_below="@+id/height"
        android:text="體重 (kg)" />

</RelativeLayout>

將字串抽離XML介面描述檔

為了更好的維護介面,我們可以將『activity_main.xml』檔中的字串抽離。我們可以在 『res』->『values』->『string.xml』中定義我們所需要的字串如下。

    <string name="app_name">BMI</string>
    <string name="hello_world">Hello world!</string>
    <string name="bmi_height">身高 (cm)</string>
    <string name="bmi_weight">體重 (kg)</string>
    <string name="bmi_btn">計算  BMI 值</string>
    <string name="bmi_result">你的BMI值是 </string>
    <!-- advise -->
    <string name="advice_light">你該多吃點</string>
    <string name="advice_average">體型很棒</string>
    <string name="advice_heavy">你該節食</string>
    <!-- other -->
    <string name="action_settings">Settings</string>

定義完成後,要使用所定義的文字我們要使用"@string/"。可以在『Graphical Layout』中選擇『身高(cm)』然後按F2後輸入 @string/bmi_height 。有沒有注意畫面的感嘆號已經消失了。其他在介面所顯示的文字採用一樣的方法進行更換。

2014年4月8日 星期二

Android 程式開發(二)

Android 程式開發(二)


上一篇Android程式開發(一)介紹開發Android程式的工具和前置工作,接下來將討論Android的介面元件 (UI Components)。

在開發Android程式之前,一定要先弄清楚Android有提供那些UI components讓我們使用才能更好的開發Android程式。

Android UI Components

Android提供非常豐富和多樣化的UI components,開啟專案中的『res/layout/activity_main.xml』可以看到預覽畫面和包含Hello World的字串。在左下角有兩個標籤『Graphical Layout』和『activity_main.xml』。在『Graphical Layout』我們可以直接將UI components以drag and drop(拖、拉)的方式進行設定,而 『activity_main.xml』是採用XML檔案描述手機畫面,可以透過修改XML檔進而設計手機畫面。



UI components 根據GraphicalLayout上的分類,共有以下幾種

  • Form Widgets
  • Text Fields
  • Layouts
  • Composite
  • Images and Media
  • Time and Date
  • Transitions
  • Advanced
Android Form UI Components:

名稱 作用
TextView 顯示文字
Button 按鈕
Spinner 下拉選單
CheckBox 勾選鈕

Android Layout Components:


名稱 作用
Linear Layout 線性版面
Relative Layout 相對版面
FrameLayout 框架版面
TableLayout 表格版面

Android DatePicker Components:

名稱 作用
TimePicker 選取時間
DatePicker 選取日期
CalendarView 日曆檢視
AnalogClock 類比時鐘

更詳細的UI components到官網觀看Android UI Components

我們從預覽換面看到『Hello World!』,現在要把它改成『Hello, Android Program』。剛才提到有『Graphical Layout』和『activity_main.xml』描述手機畫面。透過『Graphical Layout』修改,只要點擊畫面中的『Hello World!』然後按 "F2" 就能直接修改文字。透過『activity_main.xml』我們看到如下的XML檔案:
        
<TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" ?>
我們只需要將『android:text="@string/hello_world"』改成 『android:text="Hello,Android Program"』就能將文字內容改變了。

Android 程式開發(一)

Android 程式開發(一)

Android 是什麼?
Android 簡單來說就是一個手持式設備(主要是手機)的作業系統平台。

安裝 Android 開發工具
Android的安裝流程可以分為以下兩個步驟 :
  1. 下載並安裝Java
  2. 到Android官網下載Eclipse (已經整合了Android 的套件) 或 Android Studio.(我是採用Eclipse)

Android程式執行前置工作
執行Android程式有兩種方法:
  1. 在Eclipse當中建立一個Android的虛擬機器
  2. 有一台Android 平台的手機 (廢話....)
     建立一個Android的虛擬機器
  1. 在Eclipse上方點選Android Virtual Device Manager                                                                                                  
  2. 點選過後會彈出一個表格然後點選New,接下來輸入虛擬器的名稱,你要的設備,CPU,Memory等等

  3. 設定完成後,就可以執行Android程式了。
     P.S. 個人而言不建議這種做法,因為每次執行虛擬機器的時候都需要等很久,當需要debug
     時真的很浪費時間尤其只有小錯誤的時候(其實是我沒耐心)。所以說既然要寫Android程式
     那不如買一台Android手機吧

     有一台Android手機
     如果你有一台Android手機那就太好了,不管在執行Android程式或者debug的時候都會很方  
     便。
     1. 首先要開啟手機的開發人員選項,然後對USB偵錯模式打勾。(Android 4.2 以上的使用者            官方因為安全因素將開發人員選項隱藏。開啟方法是設定->關於手機->不斷點選"軟體版
         本", 這樣就能開啟開發人員選項了)

     2.當你執行程式的時候會出現以下的圖,然後選擇 "Choose a running Android device" 就能將
        你所寫的程式在手機執行。

    
  
接下來將會討論關於Android手機的介面元件(User Interface Components)