新終極密碼

聚會團康小遊戲,打賭抽籤好工具

One Piece 海賊王

我是要成為海賊王的男人!

Wreck-It Ralph 無敵破壞王

「變好無望,壞也無妨,我只想做我自己」 感動推薦給曾經迷失方向的人們

Spartacus 斯巴達克斯

羅馬時代,身為一名競技場角鬥士的榮耀與卑微。熱血推薦!

Puffy 帕妃

大貫亞美 & 吉村由美

2013年7月27日 星期六

[DIY] Android APP 新終極密碼 New Ultimate Password



心裡盤旋著「這一生至少要上架一個 APP 吧?」於是就開始動手了。但上傳個沒營養的 APP 著實也沒多大意義,甚至讓人心疼那 $25 美元的 Google 入場卷。於是把之前寫的 Windows 版終極密碼,改寫至 Android 上;至於為什麼名稱要多一個「新」字呢?因為我的神奇表弟傲獅卡集思廣益貢獻了一個獨特的遊戲模式「爾虞我詐」,這是 Google Play 架上類似終極密碼的遊戲所沒有的。

2013 年 6 月中開始動工,2013/07/06 在生日前一天上架,似乎別具意義。感謝眾家好友 Lomeoh、傲獅卡、艾芙拉的協助測試以及寶貴的建議,還有美國兄弟 DrT 和 Francis 的英文版校對,感謝各位!


新終極密碼 New Ultimate Password

[雜耍] 貴妃最愛~ 荔枝~ 種子盆栽

荔枝盆栽非常好種,而且奇妙的基因讓荔枝苗呈現完美的對稱方式生長:首先主幹會分岔,分岔的兩枝會再個別對稱地開啟兩片葉子。

更令人驚奇的是,在幼苗時期 (葉子尚未轉綠),由於被吹襲導致幾片葉子受傷枯萎,用剪刀剪去枯萎的葉子後,那一株竟然在分岔的交會點另外長出一個分枝,而分枝也是依循著基因的安排,相互對稱地敞開葉子,大自然的生命力真是令人讚嘆!

2013/06/05 泡水第一天




2013/06/10 泡水第五天




2013/06/10 種植第一天





2013/06/13 種植第四天




2013/06/14 種植第五天




2013/06/15 種植第六天




2013/06/16 種植第七天




2013/06/17 種植第八天




2013/06/18 種植第九天




2013/06/19 種植第十天




2013/06/20 種植第十一天




2013/06/21 種植第十二天




2013/06/22 種植第十三天




2013/06/23 種植第十四天




2013/07/01 種植三週




2013/07/04 新芽冒出

這株就是在幼苗受傷,而被我減掉兩枝分岔的可憐蟲,但堅強的生命力讓她在分岔處,又額外冒出了褐色的新芽,而且新芽一樣依照「荔枝公式」分岔再分岔,開出新葉。令人激賞!

[隨筆] Diablo III 全成就達成

2013/03/25 全成就達成

Diablo III 這個從學生時期讓大家等待了 10 年的續作,只讓我撐了 10 個月就 Quit 了 (更多好友撐不到半年啊 Orz...)。現實中同期加入的好友,也從盛況 10 幾位同時上線團戰,到最後只剩下 1、2 位陪我繼續堅持著。當好友名單一大片空白,卻還能繼續堅持的,那真的是對遊戲充滿了愛與熱情呀。Lomeoh 與 Yab,感謝你們啦!

之後為了解成就,加了許多志同道合的網友,大家一同分享「獨特蒐藏」這個難解的成就,可遇不可求的獨特怪消耗了許多成就狂的精力啊!itisjoe 在整個解成就過程裡是我的最佳夥伴,我們合作一起逛地圖互相幫忙解怪,itisjoe 還發現了一個能讓獨特怪出現機率變高的遊戲開房秘技,真是太強了 XD

解成就初期還缺很多隻獨特怪時,版上隨時有網友分享,這時靠的是推文的速度才搶得到車票,因此持續關注 Diablo 版面的新文章是初期重要的工作。

中期,版上分享的獨特怪自己大多已經解過了,這時要靠初期積極和網友搏感情的人脈 (玩個遊戲也能體會人脈的重要!?),就是所謂的「內線」,志同道合的網友找到特殊獨特怪時,都會先私訊詢問內線們有沒有需要,尚有空位才會上版面發車票。

到了後期,剩下 5 隻以內的獨特怪,這時真的是看天意了,這時網友們能找到的獨特怪幾乎都是自己已經找過的。於是我到 Blizzard 官網論壇發文徵求獨特怪,老外的確蠻多 Geek,其中一隻獨特怪還是新加坡的賞金獵人給的。徵求賞金獵人過程中,因為時差,有好幾次都是我不在線上時北美的老外丟過來的尋獲訊息,每次上線看到留言都讓人扼腕啊!

最後一隻難找的獨特怪「魔嬰布拉格」,是網友 threesmall 幫忙找到的,整個過程一路艱辛,達成後相當有感觸呀!最後就用這段紀錄影片紀念這個只讓我玩 10 個月的 10 年期待大作,Diablo III。


2013年7月23日 星期二

[Android] 使用 Drawable 時發生 Memory Leak 問題

參考自小鰻的 Android 學習筆記。

開發過程中使用到 setBackgroundDrawable 函式來設定 Activity 的背景,從初期到現在偶發性會出現 memory leak 的問題。初期解法僅嘗試降低圖像的解析度,雖然立即有改善記憶體不足的問題,但卻不是治本的方法,以下筆記解決的根本之道。

使用 Drawable 發生 memory leak 的兩種情況:

1、Activity 載入時立即 exception。
解法:降低圖像解析度。

2、Activity 切換過程 (包括螢幕轉向) 發生 exception。
解法:在有呼叫 setBackgroundDrawable 的 Activity 覆寫 onDestroy(),將 Drawable 的 callback 設為 null。

原因在文初的連結說明得很詳細,主要就是呼叫 setBackgroundDrawable 時,程序內部將會偷偷建立 callback 連結至物件內容,因為有 callback 關係,導致此 Activity 在系統 memory 不足時無法被回收。

以下為程式節錄。
RelativeLayout background;

@Override
protected void onCreate(Bundle savedInstanceState) {
    background = (RelativeLayout)findViewById(R.id.layout_begin);
    background.setBackgroundDrawable(getResources().getDrawable(R.drawable.begin_16x9));
}

@Override
public void onDestroy() {
    background.setBackgroundDrawable(null);
    super.onDestroy();
}


另外也可以使用 getNativeHeapSize() 來即時監控目前的 heap memory 使用情況。
Log.i(TAG, "userdMemory: " + Debug.getNativeHeapSize() / 1048576);

2013年6月20日 星期四

[Android] 按下 PositiveButton 時,如何控制 AlertDialog 關閉與否

一般來說,AlertDialog 內建三種按鈕方法,分別為 setPositiveButton, setNegativeButton, setNeutralButton,設計者可以根據不同的按鈕,實做個別的 onClickListener 來處理按鈕行為。但這三個按鈕按下後一致的結果就是:關閉 AlertDialog。這對於需要在按下按鈕進行一些資料判斷,若資料不符則不允許關掉 AlertDialog 的設計上,是一大麻煩。好在搜尋到網路上武林高手提供的解法,筆記於下。
   View view = View.inflate(this, R.layout.activity_indicate, null);
   final EditText edittextIndicate = (EditText)view.findViewById(R.id.edittext_indicate);
   
   AlertDialog.Builder alertDialog = new AlertDialog.Builder(this);
   alertDialog.setTitle("指定密碼");
   alertDialog.setMessage("輸入指定密碼");
   alertDialog.setCancelable(false);
   alertDialog.setView(view);
   alertDialog.setPositiveButton("OK", null); // 真正覆寫內容重新定義於下
   alertDialog.setNegativeButton("Cancel", null);
   
   final AlertDialog alert = alertDialog.create();
   alert.show(); // 取代原本的 alertDialog.show(); 必須在 button 存取之前呼叫
   Button button = alert.getButton(AlertDialog.BUTTON_POSITIVE);
   button.setOnClickListener(new View.OnClickListener() {
    
    @Override
    public void onClick(View v) {
     if(!"".equals(edittextIndicate.getText().toString().trim())) {
      finalNumber = Integer.valueOf(edittextIndicate.getText().toString().trim());
     
      alert.dismiss();
     }
    }
   });


首先是標準的 AlertDialog 定義內容,需注意此行,省略了 setPositiveButton 第二個參數 onClickListener 的實做,真正的實做定義於下方。
alertDialog.setPositiveButton("OK", null); // 真正覆寫內容重新定義於下


新建一個 AlertDialog alert,因為原本的 AlertDialog.Builder alertDialog 並沒有 dismiss() 方法。因此程式最後將會利用 alert.dismiss() 來關閉畫面。另外,也需要靠 alert.getButton() 方法取得 PositiveButton 的按鈕控制,這也是 AlertDialog.Builder 沒有提供的方法。特別注意的是,如同註解所示,alert.show() 必須在下一行 button 的存取前呼叫,否則會有 exception 出現。
   final AlertDialog alert = alertDialog.create();
   alert.show(); // 取代原本的 alertDialog.show(); 必須在 button 存取之前呼叫


定義一個 Button,並使用 alert.getButton(AlertDialog.BUTTON_POSITIVE) 取得控制。接著就是正常的 button.setOnClickListener 的定義了。在 onClick 的實做中,可以任意進行資料判斷,如果有需要關閉畫面,呼叫 alert.dismiss() 即可。
   Button button = alert.getButton(AlertDialog.BUTTON_POSITIVE);
   button.setOnClickListener(new View.OnClickListener() {
    
    @Override
    public void onClick(View v) {
     if(!"".equals(edittextIndicate.getText().toString().trim())) {
      finalNumber = Integer.valueOf(edittextIndicate.getText().toString().trim());
     
      alert.dismiss();
     }
    }
   });

[Android] 如何正確取得 AlertDialog 元件的 findViewById

一般正規的 Android layout 中,如需控制元件,首先需執行 findViewById 取得元件的控制入口,例如
  Spinner spinner = (Spinner)view.findViewById(R.id.spinner_player);
  EditText edittextPlayer = (EditText)view.findViewById(R.id.editText_player);

若元件所屬的 layout 被設定到 AlertDialog 之中呢?如果還是使用上述的呼叫方式,雖然 Eclipse 不會報錯,但執行時一旦操作元件,將會遇到 "null pointer" 的 exception。
需改寫成以下方式,第 2、3 行的元件必須使用第 1 行定義的 view 來呼叫 findViewById。
  View view = View.inflate(this, R.layout.activity_player, null);
  Spinner spinner = (Spinner)view.findViewById(R.id.spinner_player);
  EditText edittextPlayer = (EditText)view.findViewById(R.id.editText_player);
  
  AlertDialog.Builder alertDialog = new AlertDialog.Builder(this);
  alertDialog.setTitle("Player Setting");
  alertDialog.setMessage("Set the number of players");
  alertDialog.setCancelable(false); // 避免點選畫面其他地方而關閉 AlertDialog
  alertDialog.setView(view);
  alertDialog.setPositiveButton("OK", null);
  alertDialog.setNegativeButton("Cancel", null);
  alertDialog.show();