2014年4月13日 星期日

[Tips] 如何設定 VMWare Workstation 配置多網卡



前些日子因為需要在 Ubuntu 雙網卡的環境下開發新功能, 而我的 Ubuntu 是跑在 VMWare workstation 10 上, 為了能讓Ubuntu 看見我筆電上的無線網卡和乙太網卡, 所以第一個要處理的問題就是怎麼在 VMWare 上新增虛擬網卡?






1. 首先在主畫面左上角的 "Edit" 選擇 "Virtual Network Editor" 選項.



2. 進入編輯畫面後選擇 "Add Network" 新增 VMnet 虛擬網卡, 此處我新增了VMnet2 而將他使用 "Bridged" 的方式連接到我筆電的乙太網路卡為綠框標示處 ( Intel(R) 82579LM Gigabit Network Connection ), 而原本的 VMnet0 也使用 "Bridged"的方式連接至無線網卡為紅框處( Intel(R) Centrino(R) Advanced-N 6205 ).

再確認生效後 VMWare 需要花點時間進行網路配置, 而有關於VMWare 所提供的三種虛擬網卡的類別分別為: Bridged , Host-only, NAT 關於這三種的差別和說明在這不再贅述, 可以參考:  VMware 的 Bridged, Host-only 和 NAT 網路型態.




3. 請確認 VW Image 為 "Power Off" 再對它進行設定.




4. 點擊 "Network Adapter" 選擇 Custom : VMnet2 作為網路連線的類型, 此虛擬網卡設定為 Bridged 到我乙太網路卡, 接下來我們再新增加入一個虛擬網卡, 按下左下角的 "Add".





5. 選擇 "Network Adapter".





6. 這裡會要求我們對新增的虛擬網卡選擇類型, 在這邊我們選擇先前設定好的 VMnet0 它將會 Bridged 到我的無線網卡.





7. 在硬體清單出現了剛才設定的新虛擬網卡.




8. 進入Ubuntu後發現系統已自動偵測到兩張網卡, 綠框即為連接至WAN端的eth



而在Ubuntu 裡對雙網卡的網路調適, 像是對WAN端 eth 選擇使用DHCP or 固定IP, rourting table的設定也是一門課題, 有機會再詳述.

[NBA] NBA 2k14 Official Roster Patchs (2014.04.11)






NBA 2K14 Official Roster Patchs



Latest Update: 2014.04.11

Install:
Start > Run > Type : %appdata%, then find 2K Sports\NBA 2K14\Saves , overwrite all the files.
for XP users: C:\Documents and Settings\[your user name]\Application Data\2K Sports\NBA 2K14\Saves
for Vista or Win 7 users: C:\Users\[your user name]\AppData\Roaming\2K Sports\NBA 2K14\Saves

Then go to NBA 2K14 and load it
Download Links:

2012年10月3日 星期三

[Android] 如何使用 PreferenceActivity 及宣告Preference.xml (How to use PreferenceActivity and define Preference.xml)





        如果你想在app 中加入Setting 的功能讓使用者可以修改app 的功能和行為, 甚至將Setting value同步到 System Setting , Preference APIs 是一個不錯的選擇, 它的UI呈現方式就像 ListView 一樣, 而每個在ListView 中的subView 都可以宣告一個Key 為的是可以在SharedPreference 中存取資料, 如此一來Preference API 就會自動的幫我們儲存每個subView資料的變化, 讓我們省了不少功夫。


首先第一步要做的就是定義 XML, 將Setting 中會出現的各種Preference object 使用階層式的方式在XML 中定義清楚, 我們在 res/xml 中產生一個 XML 檔案preference.xml 如下:




在XML 檔案中 root element 必定為 PreferenceScreen, 代表著一個全新的Setting 畫面並且在其中加入我們所需要的Preference objects, 通常我們只會用到一個XML 檔案, 因為如果有需要新的Setting 畫面需求, 可以在root PreferenceScreen 中加入另一個PreferenceScreen 形成巢狀Setting。





我們使用Eclipse editor 的 Structure mode來編輯preference.xml, 這樣對於preference.xml 階層式的架構就非常清楚了, 所有的 Preference objects 都在root Preference中, 另外還加入了一個Second PreferenceScreen, 當使用者點選時會跳出一個新的Setting 畫面, 無需create 一個額外activity。

接下來介紹幾個常用的 attribute:





android:key
最重要的屬性, 必須是一個唯一的Key供SharedPreference 儲存setting value使用, 之後在PreferenceActivity 中我們也是靠Key 來識別不同的Preference object。
android:title
Preference object 出現在Setting 畫面中的名稱。
android:defaultValue
  SharedPreference 中儲存的初始值

android:summary
  Preference object 出現在Setting 畫面中的說明文字, 以較小的字出現在title 下方。



接下來先附上完整的 preference.xml, 再來針對每個Preference object 作介紹




    
        
    
        
        
    
    
        
    
    
        
        
          




EditTextPreference : 當使用者選擇時會跳出Dialog, 而關於這個Dialog 的屬性可以使用 Editor 事先編輯, 特別的是EditText 能宣告的屬性, EditTextPreference 也能拿來使用, 所以在這邊宣告了 inputType 屬性為只能輸入Decimal number, 另外我們將使用者輸入的數字顯示在summay 中, 不過這邊需要在PreferenceActivity 中加入此功能, 這部分稍後會提到。




ListPreference : 顯示一組有著Radio button 的List, 要使List 能呈現內容的話, 要事先為List import Entry array和Entry value array, 我們可以在 /res/value 中宣告 string array 再使用Editor 引入即可, array 內容如下:


    PreferenceActivity
    Hello world!
    Settings
    MainActivity
         
        First item    
        Second item    
        Third item    
     
        
        0    
        1    
        2    
     


Entry 宣告了要顯示在List 中的內容, Entry value 對應為每個 Entry 內容所代表的value
另外值得一提的是因為選擇ListPrefence時會跳出Dialog 所以如果在Editor 中再宣告Dialog Message 屬性時就會導致顯示內容錯誤, 另外Dialog 只會出現Negative Button !





RingtonePreference : 讓使用者選擇手機上的鈴聲, 將被選擇鈴聲的URI 以string 格式儲存在SharedPreference 中, showSilent 屬性表示列表中是否包含靜音的選項, ringtoneType 用來限制列表中顯示的鈴聲類型。


PreferenceCategory : 單純的將Prefence object 分類而已, 在針對不同的Category 內加入Preference object, 可以看到畫面上的"第一個分類", "第二個分類"....均是。


Preference : 更單純, 通常只是被用來當作"說明"功能而已。



稍微簡介了用到的Preference Objects 之後, 開始來看PreferenceActivity.java 程式主要在處理每個Preference object 初始的Summary 設定, 和註冊value change 的事件。



package com.example.preferenceactivity;


import android.os.Bundle;
import android.preference.EditTextPreference;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.PreferenceScreen;
import android.preference.RingtonePreference;
import android.view.Menu;


public class MainActivity extends PreferenceActivity implements OnPreferenceChangeListener
{
 
 EditTextPreference editTextPreference, secondEditTextPreference;
 ListPreference listPreference;
 RingtonePreference ringtonePreference;
 
 
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.preference); // 記得替換掉預設的 setContentView(R.layout.activity_main) 
    
        editTextPreference = (EditTextPreference) findPreference("EditTextP");
  editTextPreference.setOnPreferenceChangeListener(this);
  //替Preference註冊value改變事件, 因為我們要動態的更新Summary content
  
  editTextPreference.setSummary("EditTextPreference Value:" +editTextPreference.getText());
  
  listPreference = (ListPreference) findPreference("ListP");
  listPreference.setOnPreferenceChangeListener(this);
  listPreference.setSummary("ListPreference Value:"+ listPreference.getEntry());
  
  ringtonePreference = (RingtonePreference) findPreference("RingtoneP");
  ringtonePreference.setOnPreferenceChangeListener(this);
  
  //---In the second Screen
  
  secondEditTextPreference = (EditTextPreference) findPreference("SPCEditTextP");
  secondEditTextPreference.setOnPreferenceChangeListener(this);
  secondEditTextPreference.setSummary("EditTextPreference Value:" +secondEditTextPreference.getText());  
  
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu)
    {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }       

 @Override
 public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,
   Preference preference)
 {
  // TODO Auto-generated method stub
  return super.onPreferenceTreeClick(preferenceScreen, preference);
 }

 public boolean onPreferenceChange(Preference preference, Object newValue)
 {
  // TODO Auto-generated method stub  
   
  if(preference.getKey().equals("EditTextP")) //根據不同的key來辨別不同的Preference
   preference.setSummary("EditTextPreference Value:" +newValue);
  else if(preference.getKey().equals("ListP"))
   preference.setSummary("ListPreference Value:" +((ListPreference) preference).getEntries()[Integer.parseInt(newValue.toString())]);
      //從Entry中對應顯示使用者選擇的item value
  else if(preference.getKey().equals("RingtoneP"))
   preference.setSummary("RingtonePreference Value:" +newValue);
  else if(preference.getKey().equals("SPCEditTextP"))
   preference.setSummary("EditTextPreference Value:" +newValue);
  
  return true; 
 }
}


最後當我們成功儲存了每個Preference objects value 後, 該透過甚麼方法取得呢? 

網路上建議的作法:

SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);

return value preferences 為 context 所使用的preference file, 接下來就可以對 preferences 進行數值的存取了。


相關文章:



2012年9月29日 星期六

[Android] 使用 TextSwitcher 切換ListView的內容 (How to use TextSwitcher change ListView content)



    
    透過TextSwitcher 的切換來改變ListView 的內容, 並且在切換的同時加入Animation 動畫. 然後使用Typeface將TextView的字體改變, 意即使用custom Font. 而為了要使用custom Font需將字體檔 wt021.ttf 事先匯入 assert/font folder, 到時候再透過 Typeface.createFromAsset(getAssets(), "fonts/wt021.ttf") 取用, 特別注意要加上副檔名 .ttf



首先來看 MainActivity的部分,



package com.example.textswitcher;

import android.os.Bundle;
import android.app.Activity;
import android.graphics.Color;
import android.graphics.Typeface;
import android.view.Gravity;
import android.view.Menu;
import android.view.View;
import android.view.animation.AnimationUtils;
import android.widget.ListView;
import android.widget.TextSwitcher;
import android.widget.TextView;
import android.widget.ViewSwitcher.ViewFactory;

public class MainActivity extends Activity
{

    TextSwitcher TSwitcher;
    static int textIndex = 0;
    
    String[] TSwitcherContent;
    ListView LView;
    TextArrayAdapter LAdapter;
    
    Typeface font;
    
 
 @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        font = Typeface.createFromAsset(getAssets(), "fonts/wt021.ttf");
        //從 assert folder 中取用我們匯入的自訂字體 wt021.ttf  
        
        iniTexTSwitcher();
        iniListView();
    }
    
 private void iniTexTSwitcher()
    {
  // TODO Auto-generated method stub
     
  TSwitcher = (TextSwitcher) findViewById(R.id.textSwitcher);
  
  //透過 setFactory method 產生兩個 Views給 TextSwitcher切換
     TSwitcher.setFactory(new ViewFactory(){
      
      //實作makeView() method 產生 View供TextSwitcher作切換 
      public View makeView()
      {       
       TextView tv =new TextView(MainActivity.this);
       tv.setTypeface(font); // 使用自訂的字體
       tv.setTextSize(40);
       tv.setTextColor(Color.GREEN);       
       tv.setGravity(Gravity.CENTER);           
       return tv;
      }
     });
     
     TSwitcherContent = getResources().getStringArray(R.array.textSwitcherContent);
     //將事先定義在 /res/value 的string array 取出使用
     
     TSwitcher.setText(TSwitcherContent[textIndex]);      
     
     //替 TextSwitcher註冊 onClickListener
     TSwitcher.setOnClickListener(new View.OnClickListener()
     {
      public void onClick(View v)
      {       
       textIndex++;
       
       if (textIndex >= TSwitcherContent.length) textIndex = 0;
         
       TSwitcher.setText(TSwitcherContent[textIndex]);       
       
       LAdapter.notifyDataSetChanged();
       //告知Adapter的data 已經改變了, 所以我們手動的呼叫 notifyDataSetChanged() method
       
       LView.startAnimation(AnimationUtils.loadAnimation(getApplicationContext(), android.R.anim.fade_in));
       //當TextSwitcher切換時, 讓ListView有淡入的效果
      }
     });      
      
     TSwitcher.setInAnimation(AnimationUtils.loadAnimation(getApplicationContext(), android.R.anim.slide_in_left));       
     // TextSwitcher切換時也使用動畫效果
 }

 private void iniListView()
    {
  // TODO Auto-generated method stub  
  
  LView = (ListView) findViewById(R.id.listView);
  
  LAdapter = new TextArrayAdapter(MainActivity.this, android.R.layout.simple_list_item_1, TSwitcherContent, font);
  //宣告使用custom TextArrayAdapter that extends ArrayAdapter
  //android.R.layout.simple_list_item_1, 為android system resource layout 只能顯示single line, 所以本身即為一個TextView  
  
  LView.setAdapter(LAdapter);  
 }

 
 @Override
    public boolean onCreateOptionsMenu(Menu menu)
    {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }
}


接著來談一下TextSwitcher吧, TextSwitcher的父類別為 ViewSwitcher, 所以具有和ViewSwitcher共同的性質, ViewSwitcher 透過 setFactory(new ViewFactory()) 產生兩個child views給ViewSwitcher作切換, ViewSwitcher 只能夠有兩個 child views, 並且一次只能顯示一個, 另外 ViewSwitcher 有兩個子類別, 一為TextSwitcher 另一個為 ImageSwitcher, 差別在於TextSwitcher 所包含的 child views 只能為 TextView type的 view, ImageSwitcher 只能擁有 ImageView type的 child view



處理完畢 MainActivity.java 的內容之後我們來看 ListView, 首先ListView 和 data 之間必須有Adapter作為配接, 在這邊我們使用custom Adapter that extends ArrayAdapter, 我已經將這個custom adapter 取名為 TextArrayAdapter, 並且獨立一個.java 如下


package com.example.textswitcher;

import android.app.Activity;
import android.content.Context;
import android.graphics.Typeface;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;

public class TextArrayAdapter extends ArrayAdapter
{

 Activity mainActivity;
 Typeface itemFont;
 
 public TextArrayAdapter(Context context, int textViewResourceId, String[] objects, Typeface font)
 {
  super(context, textViewResourceId, objects);
  // TODO Auto-generated constructor stub
  
  mainActivity = (Activity) context;
  //特別取得 MainActivity
  
  itemFont = font;
 }

 @Override
 public View getView(int position, View convertView, ViewGroup parent)
 {
  // TODO Auto-generated method stub
  
  View rowview = convertView;
        if (rowview == null) {
                LayoutInflater inflater = mainActivity.getLayoutInflater();
                rowview = inflater.inflate(android.R.layout.simple_list_item_1, parent, false);
                //為了要把xml所描述的Layout轉變為View , 也就是我們要的rowview
                //所以必須使用LayoutInflater來轉化 , 而要取得LayoutInflater的Instance方式還包括
                //LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                //接著再使用inflate (int resource, ViewGroup root, boolean attachToRoot)
                //傳回我們要的rowview
        }
        
        TextView item = (TextView) rowview;
        
        item.setTypeface(itemFont);
        item.setGravity(Gravity.CENTER);
        
        //根據當前的 textIndex 來決定ListView該呈現的內容
        switch(MainActivity.textIndex)
        {
         case 0:
          item.setText("First");
         break;
         
         case 1:
          item.setText("Second");
         break;
         
         case 2:
          item.setText("Third");
         break;
         
         case 3:
          item.setText("Fouth");
         break;        
        }
  
  return rowview;
 } 

}



最後是簡單的 activity_main.xml


    
    

    

    






2012年9月27日 星期四

[雜談] Hello, I`m Back !



    

         看了上一篇文章的發文日期在四月份, 發覺荒廢了很久已經快半年沒發新文章了, 這段時間都在寫C 和忙別的雜事, 最近因為工作的關係又重新回到久違的行動平台了, 接到主管交付開發Android app, iOS app的任務, 按慣例要將開發 app學到的新心得整理放上來, 所以之後也會有對於開發iOS心得的相關文章, 讓自己以後可以快速的找查相關資料也方便檢視所學, 最後希望這些心得對app開發者們有幫助, 加快自己進入這個領域和縮短開發app的時間。




Google Analytics