2016年6月3日 星期五

Detect if TextVIew is ellipsized

Code snippet
//Hide/Show More buttion
final TextView detail   = (TextView) findViewById(R.id.detail);
final TextView more     = (TextView) findViewById(R.id.more);
ViewTreeObserver vto = detail.getViewTreeObserver();
vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
        @Override
        public boolean onPreDraw() {
                ViewTreeObserver observer = detail.getViewTreeObserver();
                observer.removeOnPreDrawListener(this);
                String text         = detail.getText().toString();
                String layoutText   = detail.getLayout().getText().toString();
                more.setVisibility((!text.equals(layoutText)) ? View.VISIBLE:View.INVISIBLE);
                return true;
        }
});

2016年5月26日 星期四

Recyclerview inside ScrollView not scrolling smoothly

Method 1:

Reference:

http://stackoverflow.com/questions/33143485/recyclerview-inside-scrollview-not-scrolling-smoothly

Illustration:

RecyclerView view = (RecyclerView) findViewById(R.id.myrecycler);
view .setNestedScrollingEnabled(false);

Drawback:

OutOfMemory when there are many bitmap in the RecyclerView


Method 2:

Wrap all the component into the RecyclerView

Error: ArrayAdapter requires the resource ID to be a TextView

Reference:

http://stackoverflow.com/questions/9280965/arrayadapter-requires-the-resource-id-to-be-a-textview-xml-problems

Illustration:

Layout xml裡只能包含一個 TextView,不能將 TextView包在其他的 layout裡,例如:LinearLayou

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    ......
/>

2016年5月6日 星期五

String Resources: Formatting and Styling

References:

http://developer.android.com/intl/zh-tw/guide/topics/resources/string-resource.html#FormattingAndStyling


Example:

<string name="welcome_messages">Hello, %1$s! You have %2$d new messages.</string>

Resources res = getResources();
String text = String.format(res.getString(R.string.welcome_messages), username, mailCount);

TextView 省略文字的用法

Reference:

http://blog.csdn.net/sonicliji/article/details/8523746

illustration:

1.android:ellipsize=”start”—–省略號顯示在開頭
Ex: ......start
2.android:ellipsize=”end”——省略號顯示在結尾
Ex: end.......
3.android:ellipsize=”middle”—-省略號顯示在中間
4.android:ellipsize=”marquee”–以跑馬燈的方式顯示(動畫橫向移動)

2016年4月27日 星期三

Android Studio build error: illegal character: '\ufeff'

References:

http://nobodycare.me/2014/11/07/android-studiode-common-questions/
http://www.codegur.net/36027875/character-set-issue-utf-8
http://lifelongprogrammer.blogspot.tw/2014/05/powershell-and-java-stumble-by-utf8-bom.html

Scenario:

Import android project from Eclipse to Android Studio.

Error message:

illegal character: '\ufeff'


Root cause:

The invisible prefix is \ufeff. U+FEFF is byte order mark (BOM).
But java uses utf8 without bom to read file.

Solution:

Opened the document in notepad and changed the encoding to UTF-8 to save it.

2016年4月19日 星期二

Install Android device driver

References:
http://j796160836.pixnet.net/blog/post/29610725

Step:
1. 到 Android SDK Manager裡安裝 Google USB Driver
2. 進入裝置管理員
3. 找到 Android device,右鍵選擇“更新驅動程式”
4. 瀏覽電腦上的驅動程式軟體
5. 讓我從電腦上的裝置驅動程式清單中挑選
6. 從磁碟安裝
7. 選擇  <你裝的android SDK的路徑>\extras\google\usb_driver\android_winusb
例如:
C:\Users\HueiJheYu\AppData\Local\Android\sdk\extras\google\usb_driver\android_winusb
8. Android ADB Interface

2016年4月7日 星期四

Android UriMatcher.addURI中的 /# 和 /* 解释

Reference:
http://bbs.isgphone.com/archiver/tid-6755.html

說明:
* may be used as a wild card for any text, and # may be used as a wild card for numbers
*: 任何字元
#: 任何數字

The difference between getMeasuredHeight() and getHeight()

Reference:
http://blog.csdn.net/xujainxing/article/details/8985063

說明:
getMeasuredHeight() 是 View實際的大小
getHeight() 是 View 在 Screen內的大小
如果 View超出 Screen的邊界時,getMeasuredHeight() = getHeight() + View超出 Screen的大小

2016年3月24日 星期四

Difference between setRepeating and setInexactRepeating of AlarmManager

Reference:

http://stackoverflow.com/questions/21232984/difference-between-setrepeating-and-setinexactrepeating-of-alarmmanager


Example:

alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
                AlarmManager.INTERVAL_FIFTEEN_MINUTES, alarmIntent);
alarmMgr.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
                AlarmManager.INTERVAL_DAY, alarmIntent);

There are two differences between these calls. The simpler one is that the intent will be sent every fifteen minutes on the first call, and every day on the second call (as you can see in the third parameter). The more complicated difference is the function call itself: setRepeating will schedule the first alarm for exactly every fifteen minutes; setInexactRepeating will schedule the second alarm for approximately every 24 hours, meaning it might deviate from that interval - with the advantage of consuming less power.

Illustration:

setRepeating(int type, long triggerAtMillis, long intervalMillis, PendingIntent operation)
setInexactRepeating(int type, long triggerAtMillis, long intervalMillis, PendingIntent operation)

setRepeating在第一次啟動 alarm後,會每隔 intervalMillis啟動一次alarm
setInexactRepeating則是第一次啟動 alarm後,會每隔大約 intervalMillis啟動一次alarm,目的是為了省電,啟動時間相近的 alarm會同時啟動

2016年3月15日 星期二

Get ringtone list from android settings

References:

http://stackoverflow.com/questions/2724871/how-to-bring-up-list-of-available-notification-sounds-on-android

Code snippet:

private static final int RINGTONE_REQUEST_CODE = 5;
public void requestProfileRingtone(){
 
    Intent ringtoneListIntent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER);
                    ringtoneListIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE,     RingtoneManager.TYPE_RINGTONE);
    ringtoneListIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_TITLE, "Select Tone");
    ringtoneListIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, (Uri) null);
    startActivityForResult(ringtoneListIntent, RINGTONE_REQUEST_CODE);
}



@Override
    protected void onActivityResult(final int requestCode, final int resultCode, final Intent intent){
        if (resultCode == Activity.RESULT_OK && requestCode == RINGTONE_REQUEST_CODE){
            Uri uri = intent.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI);

            if (uri != null){
                Toast.makeText(this, "chosenRingtone: " + uri.toString(), toast.LENGTH_SHORT).show();
                Log.d(TAG, "chosenRingtone: " + uri.toString());
            } else{
                Toast.makeText(this, "chosenRingtone is null", Toast.LENGTH_SHORT).show();
                Log.d(TAG, "chosenRingtone is null");
            }
        }
    }

2016年3月7日 星期一

Send android broadcast by adb

Reference:

http://blog.csdn.net/yelangjueqi/article/details/43231425

Command:

adb shell am broadcast:

[-a <ACTION>]
[-d <DATA_URI>]
[-t <MIME_TYPE>]
[-c <CATEGORY> [-c <CATEGORY>] ...]
[-e|--es <EXTRA_KEY> <EXTRA_STRING_VALUE> ...]
[--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE> ...]
[-e|--ei <EXTRA_KEY> <EXTRA_INT_VALUE> ...]
[-n <COMPONENT>]
[-f <FLAGS>] [<URI>]

Example:
adb shell am broadcast -a com.android.test --es test_string "this is test string" --ei test_int 100 --ez test_boolean true

2016年3月6日 星期日

How to animate a TextView using TextSwitcher

Reference:
http://www.learn-android-easily.com/2013/06/android-textswitcher.html
http://www.cnblogs.com/over140/archive/2010/10/22/1857991.html
http://never-say-never.iteye.com/blog/976886


Code snippet:

public class MainActivity implements ViewSwitcher.ViewFactory{
    private TextSwitcher mTextSwitcher;
    private Button mButton;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ........
        mTextSwitcher = (TextSwitcher) findViewById(R.id.text_switcher);
        mTextSwitcher.setFactory(this);

       // Declare the in and out animations and initialize them
       Animation in = AnimationUtils.loadAnimation(this,android.R.anim.slide_in_left);
       Animation out = AnimationUtils.loadAnimation(this,android.R.anim.slide_out_right);
                     
       // set the animation type of textSwitcher
       mSwitcher.setInAnimation(in);
       mSwitcher.setOutAnimation(out);

        mButton = (Button) findViewById(R.id.button);
        mButton.setOnClickListener(new View.OnClickListener() {

            public void onClick(View v) {
                // TODO Auto-generated method stub
                mSwitcher.setText(myTextString);
            }
        });
    }

    // 重寫 ViewSwitcher.ViewFactory makeView()方法,返回一個 ViewTextSwitcher 交換時 使用  
    @Override 
    public View makeView() {  
        TextView textView = new TextView(this);  
        textView.setTextSize(36);
        textView.setColor(Color.White);
        textView.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL);
        return textView;  
    }
}

IllegalArgumentException: View not attached to window manager

Reference:

http://stackoverflow.com/questions/22924825/view-not-attached-to-window-manager-crash
http://www.2cto.com/kf/201202/119310.html

Scenario:

UI thread產生另一個 thread(Ex: AsyncTask)來顯示一個 Dialog,當 thread任務完成了再 dismiss dialog,如果在此期間 Activity因為某種原因被殺掉且又重新啟動了,那麼當  Dismiss的時候, WindowManager檢查發現  Dialog所屬的  Activity已經不存在了,就會跳出這個 Exception

Code snippet:

@Override
protected void onDestroy() {
    dismissProgressDialog();
    super.onDestroy();
}

protected void onPostExecute(String file_url)
{
    if (YourActivity.this.isDestroyed()) { // or call isFinishing() if min sdk version < 17
        return;
    }
    dismissProgressDialog();
    something(note);
}

private void dismissProgressDialog() {
    if (mDialog != null && mDialog.isShowing()) {
        mDialog.dismiss();
    }
}


2016年1月25日 星期一

Close Google Map toolbar

Reference:
https://developers.google.com/maps/documentation/android-api/controls#toolbar

Code sinppet:
mMap.getUiSettings().setMapToolbarEnabled(false);

2016年1月11日 星期一

[Exception] couldn't find class 'com.google.android.gms.measurement.internal.zzz'

References:

http://stackoverflow.com/questions/33196015/error-on-some-devices-couldnt-find-class-com-google-android-gms-measurement

Error log:

01-12 14:45:58.910    4347-4347/? E/dalvikvm﹕ Could not find class 'com.google.android.gms.measurement.internal.zzx', referenced from method com.google.android.gms.measurement.internal.zzt.zzaU

    java.lang.VerifyError: com/google/android/gms/measurement/internal/zzt
            at com.google.android.gms.measurement.AppMeasurementContentProvider.onCreate(Unknown Source)
            at android.content.ContentProvider.attachInfo(ContentProvider.java:1591)
            at android.content.ContentProvider.attachInfo(ContentProvider.java:1562)
            at android.app.ActivityThread.installProvider(ActivityThread.java:4897)
            at android.app.ActivityThread.installContentProviders(ActivityThread.java:4487)
            at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4427)
            at android.app.ActivityThread.access$1500(ActivityThread.java:143)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1302)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:136)
            at android.app.ActivityThread.main(ActivityThread.java:5124)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:797)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:613)
            at dalvik.system.NativeStart.main(Native Method)

Code snippet:

MyApplication.java
public class MyApplication extends Application {

    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        MultiDex.install(this);
    }
}

AndroidManifest.xml
<application
        android:name=".MyApplication"
        android:allowBackup="true"
        android:icon="@mipmap/xxxxxx"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >

Solution:

This happens because of multi-dexing. When your code is so big that it can't be compiled with a single dex file, we use multidexing. But after that it wouldn't run on all phones

2016年1月10日 星期日

Get application directory

Reference:

http://stackoverflow.com/questions/5527764/get-application-directory

Code snippet:

PackageManager m = getPackageManager();
String s = getPackageName();
try {
    PackageInfo p = m.getPackageInfo(s, 0);
    s = p.applicationInfo.dataDir;
} catch (PackageManager.NameNotFoundException e) {
    Log.w("yourtag", "Error Package name not found ", e);
}

2016年1月8日 星期五

Open Google Play Store for your application

Reference:

http://stackoverflow.com/questions/11753000/how-to-open-the-google-play-store-directly-from-my-android-application

Code snippet:

String appPackageName = "Your app package name";
try {
    startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + appPackageName)));
} catch (android.content.ActivityNotFoundException anfe) {
    startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" + appPackageName)));
}