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

Android Parcel occurs 'Unmarshalling unknown type code'

Paracel一直以來都用得很順,即使是下列這種複雜的資料結構都OK
A class implements Parcelable {
    private B dataB;
    private ArrayList myList1;
    private ArrayList myList2;

    // 其他省略...

    // region Parcelable
    private A(Parcel parcel) {
        try {
            dataB= parcel.readParcelable(B.class.getClassLoader());
            myList1= parcel.readArrayList(String.class.getClassLoader());
            myList2= parcel.readArrayList(C.class.getClassLoader());
        } catch (Exception e) {
            Log.e("parcelable error", "A class:" + e.toString());
        }
    }

    public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
        public A createFromParcel(Parcel parcel) {
            return new A(parcel);
        }

        public A[] newArray(int size) {
            return new A[size];
        }
    };

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel parcel, int i) {
        parcel.writeParcelable(dataB, i);
        parcel.writeList(myList1);
        parcel.writeList(myList2);
    }
    // endregion
}

B class implements Parcelable {
    private String id;
    private String name;
    // 其他省略...
}

C class implements Parcelable {
    private String gender;
    private String age;
    // 其他省略...
}

但最近用一樣的寫法,在A class中實作Parcel的時候,write部分沒問題read部分卻crash並出現錯誤java.lang.RuntimeException: Parcel android.os.Parcel@ffd1087: Unmarshalling unknown type code 7667825 at offset 1152

檢查了三款自訂的Parcel Class A、B、C都有確實實作相關methods,後來看到此篇文章Parcel Unmarshalling unknown type code提到資料的讀寫要按照相同順序,回頭檢查欄位高達四十個的B class才發現順序正確,但是write部分寫了三十六個欄位,read部分卻讀取了三十七個欄位,也因此影響了Parcel A的讀取部分@@

特此紀錄一下,在使用Parcel時要特別注意資料的讀寫順序與個數!!! 


Android設定圓角

如題
如果Button沒有要做到按下去有不同效果,懶得特地製作drawable xml給button吃,
那可以考慮如下做法,直接寫程式透過GradientDrawable達成

// 設定按鈕drawable

GradientDrawable shape =  new GradientDrawable();

shape.setCornerRadius(18);
  //圓角
shape.setColor(Color.parseColor("#FF7419"));  //顏色

Button sellButton = this.getActivity().findViewById(R.id.myButton);
sellButton.setBackground(shape);

Encoding and Decoding Objects

無論Android或Objective-C都會有自訂Data Model的應用

把object instance存放於記憶體是最常見的方式,二者的作法如下
Android:制定欄位 & getter/setter
Objective-C:制定欄位

但在下列場景一定要序列化
Android:二個頁面間傳值(例如activityA跳轉至activityB的時候要傳遞一個自訂data)
Objective-C:自訂data儲存於NSDefault

序列化方式
Android:implements Parcelable
Objective-C:implements NSCoding

參考資料
Archiving Objective-C Objects with NSCoding
Encoding and Decoding Objects

gradle錯誤 造成Android Studio無法安裝apk至device

如題,通常停止gradle即可。但是Android Studio沒有提供GUI協助我們做這件事 @"@

來下command吧

STEP 1 開啟命令視窗
在Windows作業系統請開啟cmd
在MAC作業系統開啟Terminal

STEP 2 前往專案root path

STEP 3 輸入終止指令
在Windows作業系統請輸入
gradlew --stop

在MAC作業系統請輸入
./gradlew --stop

收工...

參考資料

back to previous event

Objective-C(5.0+)
- (void)willMoveToParentViewController:(UIViewController *)parent;

Android
onBackPressed();

如果要在預設的back傳值或觸發其他事件,可override上述event

How to use Android Volley

Volley其實老在Google I/O 2013就被介紹了
但我問遍google,無論是自己包裝或使用第三方已封裝好的jar都是舊版做法,以下提供最新作法

環境&工具:Android Studio 1.1.0、jcenter


1. Download volley 
使用git command從google下載volley專案(請記得安裝Git)
前往Git的位置
cd C:\Program Files (x86)\Git\cmd
執行下載指令
git clone https://android.googlesource.com/platform/frameworks/volley


2. Make volley.aar
是的,你沒看錯,是.aar (Android Archive Library) !!!當然你要堅持用jar也是可以ˋ(′~‵")ˊ

目前,Android Studio似乎還無法直接做aar,我是隨意新增一個android專案,再把前一步驟下載回來的volley匯入並compile即可得到aar file~
假設專案根目錄在D:\AndroidStudioProject\MyApplication
aar產出位置就會是D:\AndroidStudioProject\MyApplication\volley\build\outputs\aar


3. Add volley.aar to your project
在"app"增加aar資料夾,複製步驟2製作的aar至此(就像以前用Eclipse複製jar到lib資料夾那樣)
此時,"app"底下的build.gradle檔案會自動替你補上相依性描述
dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:21.0.3'
    compile(name: 'volley', ext: 'aar')
}
或是透過Project Structure來看


接著修改root directory下的build.gradle,加入粉紅色highlight處(因為剛剛把檔案放在aar這個自訂資料夾)
allprojects {
    repositories {
        jcenter()
        flatDir {
            dirs 'aar' //代表有個資料夾名稱叫做aar
        }
    }
}


4. Have fun to use volley
ya~開始在app專案使用
例如
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.Volley;

public class MainActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        RequestQueue mQueue = Volley.newRequestQueue(this);
    }

    //略...
}

進階用法請參考

跟第3點有關的參考資訊

因環境與工具的相異浪費了一些時間@@  希望這篇能幫助近期有需要的人

[Note]ViewPager & ViewPagerAdapter & ViewPageStateAdapter

-ViewPager

  • allows u to flip left & right to show data
  • often conjunction with fragment, which is convenience to manage lifecycle of page
  • there are two standard adapter  'ViewPageAdapter' & 'ViewPageStateAdapter' implemented using fragment, which cover the most common use cases

-ViewPageAdapter
  • this adapter is best for use when there are static fragments to be paged through, such as a set of tabs


-ViewPageStateAdapter

  • this adapter is best for use when there are a large number of pages, working like the listview

The logging tag can be at most 23 characters

Android Studio最近升級後會在logging tag的地方報錯
    『The logging tag can be at most 23 characters, ....
        Log tags are only allowed to be at most 23 characters long.』
解決方式不是改tag長度,就是把Error關掉或降低層級

從功能選單「Analyze→Inspect Code」開啟如下視窗,並點選紅色框起處

承上,開啟如下視窗後在搜尋框輸入log
會看到Too Long Log Tags,可以選擇關閉或是把右側的Security層級降低


參考資料
The logging tag can be at most 23 characters

Gradle DSL method not found: 'android()'

使用Android Studio新增空白專案,乾淨的專案竟然有Gradle DSL method not found: 'android()'問題而無法正常編譯

仔細查看Error Message發現android在build.gradle無法被辨識,原來是Android Studio產生root build.gradle時多加入下圖框起處

只要把上圖紅框內容刪除即可,要記得對android sdk的描述必須寫在專案內的build.gradle而非最上層的root build.gradle

[轉載]improving Gradle build performance

如題,由Eclipse跳到Android  Studio也幾個月了,光是速度跟穩定性就很讓人滿意!
但是Gradle有時候會Sync很久=_=
找到一篇實用文章分享improving Gradle build performance

我依照第二點做了調整,就有明顯的改善
調整步驟如下
●前往準備新增設定檔的資料夾
   Linux:/home/< username>/.gradle/
   Mac:/Users/< username>/.gradle/
   Windows:C:\Users\< username>\.gradle
●新增gradle.properties檔案至上述位置
●在gradle.properties加入內容
   org.gradle.daemon=true

android ListView load more data

手機小小的,不可能ListView第一次長出來就呈現所有data
無論是要透過下拉刷新,或是其他操作模式去取得更多資料,都要該要能做到原始資料保持在ListView上,新資料往後append的效果。作法如下

ListView mListView;
MyAdapter mAdapter ;

第一次用
mListView.setAdapter(mAdapter);

第二次~第N次要append新資料
mAdapter.addAll(新資料);
mAdapter.notifyDataSetChanged();

絕對不要這樣寫
((MyAdapter) mListView.getAdapter()).addAll(新資料);
((MyAdapter)mListView.getAdapter()).notifyDataSetChanged();
因為(MyAdapter) mListView.getAdapter()取出來的並不是mAdapter,似乎是ListView的HeaderViewListAdapter
錯誤大概會是下列這類訊息
java.lang.ClassCastException: android.widget.HeaderViewListAdapter cannot be cast to MyAdapter


在app中開啟外部app

筆記一下開外部app的寫法

private void startOthersApp(String packagename) {
Intent i = new Intent(Intent.ACTION_MAIN);
PackageManager manager = getPackageManager();
try {
i = manager.getLaunchIntentForPackage(packagename);

if (i == null)
throw new PackageManager.NameNotFoundException();
else {
i.addCategory(Intent.CATEGORY_LAUNCHER);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
}
} catch (PackageManager.NameNotFoundException e) {
}
}

android emulator "Unfortunately, launcher has stopped."

從API 18(Android 4.3)開始我的模擬器就呈現跑不動的狀態,跑些自己寫的簡單demo還可,反倒是點個應用程式清單去看所有App就掛了,連launcher都掛掉還以為是bug哩XD

其實是VM heap給不夠,可能Android 4.3之後heap吃重程度大吧?!
調大就好,如下圖

參考網址
http://ktatsiu.wordpress.com/2013/10/15/fixing-android-emulator-unfortunately-launcher-has-stopped/

另外,關於stack vs. heap的解釋
http://antrash.pixnet.net/blog/post/70456505-stack-vs-heap%EF%BC%9A%E5%9F%B7%E8%A1%8C%E6%99%82%E6%9C%9F%E5%84%B2%E5%AD%98%E5%85%A9%E5%A4%A7%E8%A6%81%E8%A7%92

Eclipse升級Android至API19報錯java.nio.BufferOverflowException

在Eclipse穩定使用API 17一陣子,最近開始升級至API 18、19,還包含了Android SDK Build-tools
沒想到本來運行正常的project現在都報錯,錯誤大致上不脫以下這些
Unable to execute dex: java.nio.BufferOverflowException. 
Check the Eclipse log for stack trace. 
Conversion to Dalvik format failed: Unable to execute dex: java.nio.BufferOverflowException. Check the Eclipse log for stack trace.

解決辦法
uninstall Android SDK Build-tools(版本19)
install Android SDK Build-tools(版本18.1.1)

Remove CAB(Contextual Action Bar) Done Button

廢話不多說,相信App內有使用ActionBar或是ListView有實作MultiChoiceMode的都看過下圖
左上角會出現 勾勾、完成、Done之類的字樣,可能會讓user困惑


如果要改text~目前辦不到XD  只能先透過res\values\styles.xml去隱藏
作法如下圖紅框處

emulator is not showing up in DDMS devices list

開發app的VM和同事共用一台,大多數是記憶體不夠,模擬器起不來
結果今天只有我登入VM使用,模擬器還是怪怪的~卡在黑畫面,DDMS的Devices清單也抓不到,只能手動作了,紀錄一下方便以後查用

●先關閉adb
adb kill-server 

●再開啟adb
adb start-server

下adb指令
DDMS的Console資訊

Android之GCMRegistrar拋錯:retry receiver class not set yet

最近要透過GCM作推播,Server推我想先暫時寫死~直接指定訊息到我的emulator,因此要先取得該emulator的Registration Id

無論是取得Sender Id或App裡的Mainfest.xml設定...等,都按照官方作法。
無奈一值拋錯internal error: retry receiver class not set yet
(PS:該錯誤可藉由LogCat的 by Log Tag為"GCMRegistrar,快速找到)

後來找到一篇篇幅雖短卻很有用的文章,解決了我的問題
參考文章:Android GCM, Retry Receiver Class Not Set Yet
文章主要是說~~這是gcm.jar的bug,Google方面雖已解決,但還沒release為正式版本讓user直接安裝,所以要使用較新的gcm.jar要自己去下載

1.開啟下列網址,點右側的"gcm.jar"連結

2.點擊右下角的""View raw file"",下載最新的gcm.jar

3.把下載回來的gcm.jar放到你的App專案下的libs

4.重Build一次,錯誤retry receiver class not set yet不再出現,也成功取得emulator的RegistrationId

Calling RESTful web service on Android by AsyncTask

在Google搜尋"REST" & "Android"的介接方式不外乎是下面這篇文章的做法

Article : Android and REST
Link : http://www.majidkhosravi.com/android-rest/

不知為何照做都沒錯,實際運行時就是接不到RESTful web service(以下簡稱REST)。無奈問了同事也是類似的方式,頂多加了延遲的秒數,讓Android的執行緒可以等待REST  response而不會timeout,後來才發現是Android 3以上就不支援Android and REST作法,正確且符合Android多執行緒宗旨的做法應該是改用AnsyncTask

那又為什麼同事的可以,我的Android Application Project卻不行呢?!
因為我手癢把android:minSdkVersion調到超高,而同事的minSdkVersion向下支援到2.3所以可以運行無誤(菸)

以下來說明AnsyncTask如何實作

●  在\AndroidManifest.xml加權限
< uses-permission android:name="android.permission.INTERNET">

●  src按右鍵→New→Class
替Class取個名稱(Name),Package則選擇當下Project對應的Package Name


●  選擇Superclass
在前一畫面的Superclass點選Browser..按鈕,開啟Superclass Selection視窗

●  搜尋AsyncTask
在Choose Type的input textbox輸入AsyncTask,選擇android.jar提供的AsyncTask

●  產生Rest.java檔案
可以從檔案中觀察此class已經繼承AsyncTask(extends AsyncTask)

●  實作產生Rest.java檔案
定義Params、Progress、Result的型別,定義如下
Params:呼叫這支class時傳入的值
Progress:這支class運作時的進度
Result:class運作後產生的資料

Rest.java我希望設計成User傳入一個String類型的URL,回傳HttpEntity類型的資料,至於描述執行進度的Progress則不需要回傳任何值。
所以這三個重要的參數是這樣設計的
Params:String類型的URL
Progress:不需要執行進度
Result:HttpEntity類型的資料
所以最後的樣子是AsyncTask< String, Void, HttpEntity> 

利用Eclipse提供的quick fixes快速實作介面

將介接REST的程式碼撰寫於quick fixes產生的doInBackground

●  在Activity呼叫
最後這樣呼叫就好


Source not found ─ android.jar has no source attachement

此錯誤並非只發生於Android,當我們引入外部JAR來使用時,如果沒有指定好JAR的存放路徑,就會有Source not found ─ XXX.jar has no source attachement的錯誤資訊。


而這種錯誤通常發生在以下二種情況
●  Debug
●  觀看api的source code

這個錯誤不解決不會影響專案的建立,只是開發上很難去理解錯誤發生在哪,也無法深入理解你使用的外部JAR到底是怎麼運作的。

解決辦法如下
方法1:直接從出現錯誤的頁面去改
●  點選Attach Source...按鈕,出現Source Attachement Configuration

●  點選External Folder...按鈕,瀏覽至你使用的android.jar相對版本
例如使用version 4.2的SDK,那就要指向C:\Program Files (x86)\Android\android-sdk\sources\android-17

●  按下OK,大功告成!

方法2:修改外部JAR的Properties
●  對android.jar按右鍵選擇「Properties」


●  點選External Folder...按鈕,瀏覽至你使用的android.jar相對版本
例如使用version 4.2的SDK,那就要指向C:\Program Files (x86)\Android\android-sdk\sources\android-17


●  按下Apply,再按OK,大功告成!