show code block

2017年8月20日 星期日

雜感 — 見自己、見天地、見眾生




前幾天看了一代宗師, 如然想起裡面的一句台詞

見自己、見天地、見眾生。

見自己 — 累積自己的實力

見天地 — 覺得實力夠了,出外闖

見眾生 — 覺得自己的實力夠了,而且有本事在外打滾,讓我把自身的本領往下傳吧!

讓我有很大的啟發,有人問我你不是才剛學android嗎?為什麼要寫blog,不怕塗害眾生嗎?(誤

這就是那年代和我們這年代的差距了,古代知識含量少,認真苦讀絕對有本事做到十年寒窗變大師。

在我們這資訊爆炸的年代,你不有點知識焦慮都會覺得自己技不如人,見自己這步驟就變得有所不同,我所做的是我們這代人學習最重要的技巧,叫縫合

看過、認同、點頭、得到的結果就是略過。

快速地學習一門技巧的方式就是看過、走過、和做過。

此時我看了使用方式、寫了blog、寫了demo,印象深刻,這東西以後就是我的了!這就是縫合。

但在見自己的同時,我也同步的見了天地和見了眾生

這代人怎麼學習最快呢? 答案是和牛人學習最快。

當你看了我的文章,妳可以輕易地指出我的錯誤。這是我的進步。

相同的也會看他人的文章,並且實作他們的demo方式,順道指出他們的錯誤,這是我們的一起進步。

見自己、見天地、見眾生的區分就好像沒那麼大了。

讓我們一起見自己、見天地、見眾生吧。



浪人劍客

Android元件 — Service 服務

前言:

這是拿來做大量運算和下載的地方。
並且不阻塞你前台的線程。
可以用來做異步download
通常更新app或是網路下載都可以寫在這邊,就算Line或是微信突然跳出來,點到離開app,也不用擔心下載被中斷導致出錯。

此篇參考:
http://givemepass.blogspot.tw/2015/11/bindservice.html
http://www.cnblogs.com/yejiurui/p/3429451.html
http://xnfood.com.tw/android/


程式碼:

https://developer.android.com/guide/components/services.html?hl=zh-tw
這裡已經有中文版的android介紹。
稍微區分一下startService 和 bindService有什麼區別。

bindService 的生命週期是和activity綁在一起的。
你呼叫他之後,只要呼叫他的activity被消滅後,他也會隨之關閉。
這邊有一個Service和activity溝通的橋樑 ServiceConnection

startService 是支持後台運行的,你首次運行startService的那一剎那,只要不手動關閉(或是記憶體不足被系統砍掉),就會一直運行下去。
適合長時間監控手機的app,像是小米手環之類的。




先從startService開始吧

先寫一個自己的Service 並且extands Service
我命名為 CountService.java這邊寫一個計時Thread到開啟Service內讓他倒數。
等等看Log就可以知道他到底有無在運作。
然後寫一個boolean來控制是否進入倒數處,如果onDestory這個Service,可以完美的停止倒數。

public class CountService extends Service {
    boolean threadDisable;
    int count;

    public IBinder onBind(Intent intent) {
        return null;
    }


    public void onCreate() {
        super.onCreate();
        new Thread(new Runnable() {
            public void run() {
                while (!threadDisable) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {

                    }
                    count++;
                    Log.v("CountService", "Count is = " + count);
                }
            }
        }).start();
    }

    public void onDestroy() {
        this.threadDisable = true;
        super.onDestroy();
    }

    public int getConunt() {
        return count;
    }

    class ServiceBinder extends Binder {
        public CountService getService() {
            return CountService.this;
        }
    }
}

 
然後在AndroidManifest.xml內註冊自己的Service


開始使用它吧!

我們來拉個activity_main.xml的畫面
activity_main.xml
<LinearLayout 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"
    tools:context=".MainActivity" 
    android:orientation="vertical"    
    >

 <Button
 android:id="@+id/startServerButton"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:text="開啟Service"
 />
<Button
 android:id="@+id/sutdownServerButton"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:text="關閉Service"
 />
<Button
 android:id="@+id/startBindServerButton"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:text="開啟bindService activity"
 />

</LinearLayout>
 

然後在MainActivity.java內調用Service
public class MainActivity extends Activity {

    private static final String TAG = MainActivity.class.getSimpleName();

    Button startServiceButton;// 開啟startService
    Button shutDownServiceButton;// 關閉
    Button startBindServiceButton;// 開啟bindService

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initView();
        initListener();
    }


    public void initView() {
        startServiceButton = (Button) findViewById(R.id.startServerButton);
        startBindServiceButton = (Button) findViewById(R.id.startBindServerButton);
        shutDownServiceButton = (Button) findViewById(R.id.sutdownServerButton);
    }

    public void initListener() {
        startServiceButton.setOnClickListener(startService);
        shutDownServiceButton.setOnClickListener(shutdownService);
        startBindServiceButton.setOnClickListener(startBinderService);
    }


    public Button.OnClickListener startService = new Button.OnClickListener() {
        public void onClick(View view) {

            Intent intent = new Intent(MainActivity.this,
                    CountService.class);
            startService(intent);
            Log.v(TAG, "start Service");
        }
    };


    public Button.OnClickListener shutdownService = new Button.OnClickListener() {
        public void onClick(View view) {
            Intent intent = new Intent(MainActivity.this,
                    CountService.class);
            stopService(intent);
            Log.v(TAG, "shutDown serveice");
        }
    };


    public Button.OnClickListener startBinderService = new Button.OnClickListener() {
        public void onClick(View view) {
          
            Log.v(TAG, "還未實作");
        }
    };
}
 
此時你按下『開啟Service』的按鈕應該就可以開始動作了。
這時候你可以看一下Log

開始startService囉!!

之後先來測試一下當我把app直接滑到後,Service是否存活。

你把app關閉後,可以看到Log還是繼續在倒數的。

如果你想關閉,就在打開app按下『關閉Service』按鈕就行了。




然後我們來實作一下bindService

為了方便測試,我們另外創了一個Activity,讓bindService和那個Activity作綁定

bindService和startService最大的差異就是多了一個ServiceConnection做綁定。
這邊一進入activity就開始運作,一離開activity就停止。
 必須調用它。
bind_activity.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="啟動bindService" />
</LinearLayout>
 
bindTestActivity.java
public class bindTestActivity extends Activity {

    CountService countService;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.bind_activity);


        Intent intent = new Intent(bindTestActivity.this, CountService.class);
        /** 開啟Service */
        bindService(intent, conn, Context.BIND_AUTO_CREATE);

    }


    //BindService和activity 的溝通方式
    private ServiceConnection conn = new ServiceConnection() {
        public void onServiceConnected(ComponentName name, IBinder service) {
            // TODO Auto-generated method stub
            countService = ((CountService.ServiceBinder) service).getService();

        }

        public void onServiceDisconnected(ComponentName name) {
            // TODO Auto-generated method stub
            countService = null;
        }

    };

    protected void onDestroy() {
        super.onDestroy();
        this.unbindService(conn);
        Log.v("BindService", "離開activity時,關掉BindService");
    }
}
 


這時候可以試試看效果囉。
打開app點擊『開啟bindService activity』看Log就可以看到在計數。
離開activity就會停止計數。





Demo:
https://drive.google.com/open?id=0Byk75IYx-dKXeUZJWno1Qks1X0E



2017年8月16日 星期三

Java基礎 — 猛虎出柙雙劍合璧版

前言:

Android寫久了,你會發現雖然自己在用java寫Android,但是會Android不代表會Java。

所以我找了猛虎出柙雙劍合璧版來拜讀。

還沒買,網路上的電子書有試讀版的,大改只給你試讀187頁。

我還沒買正式版,看完試讀版後整理一些我之前忽略的Java基礎。

https://play.google.com/store/books/details?id=EElBCgAAQBAJ

上面是連結,有興趣可以看看他的試讀版內容。




 正文開始:


1、&和&&差別

同樣都是 AND 但差別在哪呢?
用一個陣列和if判斷式做簡單說明
ArrayList<String> arrayTest = null;

if(ArrayTest != null && ArrayTest.size() == 1){
}
if(ArrayTest != null & ArrayTest.size() == 1){
}

做個很簡單的判斷,其實公用一樣,差別就在於&如果第一個為false,他還是會往下一個做判斷。
&&如果第一個是false,就直接離開if判斷式了
把上面的例子開程式去跑,if判斷式使用&會崩潰,因為根本是null判斷不了。
&&很順利地跑完判斷式。


2、for迴圈的命名斷點
label_name:

label_outLoop:
for (int i = 0; i < 10; i++) {
    label_InnerLoop:
    for (int j = 0; j < 7; j++) {
        if (j == 5)
            break label_outLoop;
    }
}
 
可做到goto的效果

3、for-each的用法
假設你有個陣列內有很多String,這時候我們可以使用for-each把它全部列出來
for-each

ArrayList<String> TestList = new ArrayList<>();
TestList.add("hello1");
TestList.add("hello2");
TestList.add("hello3");
TestList.add("hello4");
for (String string : TestList) {
    System.out.println(string);
}

 
for(要顯示的單體string : 要顯示的陣列)

此時看Log就會很漂亮的全部顯示出來。

4、方法內變數int...用法
我們要先了解方法超載overloading這件事情
有時候我們會需要使用到同個名稱,但方法參數有變。
ex:
public void calc(int a){...}
public void calc(int a, int b){...}
 
如果要寫很多這種的就很累人。
所以可以用int...的方式代表很多參數,這時候就可以取用這些參數做事。
如下例子:

public int newCalc(int... c) {
   int sum = 0;
   for (int i : c) {
       sum += i;
   }
   return sum;
}

 
這就變成一個加法計算的方法。
System.out.println("加總:”+newCalc(5,5,10,8)); //加總:28

5、繼承的一些技巧

class Animal {
    public void move() {
        System.out.println("animal move...");
    }
}

class Cat extends Animal {
    @Override
    public void move() {
        System.out.println("cat小貓跳動!!!");
    }

    public void skill() {
        System.out.println("cat小貓亂抓!!!");
    }
}

class Bird extends Animal {
    public void move() {
        System.out.println("鳥拳跳動!!!");
    }
}

class Tiger extends Cat {
    public void skill() {
        System.out.println("狩獵!!!");
    }
}
 
看看圖片有助於幫助了解這邊在幹嘛
這時候

Tiger tiger = new Tiger(); //這行我們稱做用Tiger的觀點來看Tiger
Cat tiger=new Tiger();//用貓科動物的觀點來看Tiger
Animal tiger=new Tiger();//用動物的觀點來看Tiger

Animal tiger = new Tiger();
((Bird) tiger).move();

 
編譯是可以過的,但是會Crash
利用Bird的觀點來操作new Tiger();的實體基本上是不合邏輯的,但卻可以過關,因為Bird和Tiger都同為Animal的子類別。
此時可以使用instanceof來做判斷

if(tiger instanceof Bird){
((Bird) tiger).move();
}else{
Log.d(“checkpoint”,"根本不是Bird!!");
}
 



後記


然後....

就沒有然後了。

如果我有買這本書在做分享。

2017年8月14日 星期一

Android元件 (圖像視圖元件)— 幾個常被忽略的東西editText、ToggleButton 影藏顯示密碼轉換、RadioGroup、ImageView ContentDescription作用

實作:

1、editText可以設定你要叫出來的軟鍵盤功能為何
<EditText
        android:id="@+id/edit_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="hint"
        android:inputType="phone" />
 

其中inputType為控制方法
這裡有幾個好用的值

phone 只能輸入號碼
date 只能輸入數字和斜線/
textPassword  提供文字輸入鍵盤,並影藏內容
textCapSentences  讓句子的第一個單字以大寫開頭
textAutoCorrect  自動改正輸入的文字


2、ToggleButton 我用順便用來影藏和顯示editText的顯示和影藏密碼
  toggle_btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (toggle_btn.isChecked()) {
                    editText.setTransformationMethod(HideReturnsTransformationMethod.getInstance());//顯示密碼
                } else {
                    editText.setTransformationMethod(PasswordTransformationMethod.getInstance());//影藏
                }
            }
        });
 


3、RadioGroup使用
在被呼叫的時候如果沒做選擇
 int id = radioGroup.getCheckedRadioButtonId();
                if (id == -1) {
                    Toast.makeText(MainActivity.this, "您未做任何選擇。", Toast.LENGTH_SHORT).show();
                } else {
                    RadioButton radiobutton = (RadioButton) findViewById(id);
                    Toast.makeText(MainActivity.this, "你選擇了:" + radiobutton.getText().toString(), Toast.LENGTH_SHORT).show();
                }
 



4、ImageView中的ContentDescription
來源:http://www.cnblogs.com/baiyan1/archive/2012/11/27/2790094.html

在写Android的XML布局文件时,在ImageView或ImageButton中经常会碰到一个提示:
Missing contentDescription attribute on image.

这个属性是做什么的呢?

其实这个属性是方便一些生理功能有缺陷的人使用应用程序的。比如我们有一个ImageView里面放置一张颜色复杂的图片,可能一些色弱色盲的人,分不清这张图片中画的是什么东西。如果用户安装了辅助浏览工具比如TalkBack,TalkBack就会大声朗读出用户目前正在浏览的内容。TextView控件TalkBack可以直接读出里面的内容,但是ImageView TalkBack就只能去读contentDescription的值,告诉用户这个图片到底是什么。

原文在Android官网:


5、一行TextView內塞太多東西的省略文字
在xml中:
android:ellipsize="end"     省略號在結尾
android:ellipsize="start"   省略號在開頭
android:ellipsize="middle"   省略號在中間
android:ellipsize="marquee"  跑馬燈
最後TextView顯示行數的限制:
android:singleline="true"或者android:lines="1"



全部程式碼:


MainActivity畫面佈局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.hello.kaiser.ui.MainActivity">

    <EditText
        android:id="@+id/edit_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="hint"
        android:inputType="" />

    <ToggleButton
        android:id="@+id/toggle_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="10dp"
        android:layout_marginTop="10dp"
        android:onClick="onToggleClicked"
        android:textOff="測試隱藏狀態"
        android:textOn="測試開啟狀態" />

    <Switch
        android:id="@+id/switch_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="10dp" />

    <CheckBox
        android:id="@+id/checkbox_one"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="CheckBoxClick" />

    <CheckBox
        android:id="@+id/checkbox_two"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="CheckBoxClick" />

    <RadioGroup
        android:id="@+id/radio_group"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:orientation="vertical">

        <RadioButton
            android:id="@+id/radio_one"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="groupButton"
            android:text="MILK" />

        <RadioButton
            android:id="@+id/radio_two"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="groupButton"
            android:text="COFFEE" />
    </RadioGroup>

    <Button
        android:text="最後選擇確認"
        android:id="@+id/checkRadioButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />


    <ImageView
        android:id="@+id/image_view"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_marginTop="10dp"
        android:contentDescription="This is android logo"
        android:src="@drawable/android_photo" />
</LinearLayout>

 


MainActivity.java
public class MainActivity extends AppCompatActivity {

    private EditText editText;
    private ToggleButton toggle_btn;
    private Switch switch_btn;
    private RadioGroup radioGroup;
    private ImageView imageview;
    private Button button;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        setInit();
        setView();
        setListener();
    }

    private void setInit() {
        editText = (EditText) findViewById(R.id.edit_text);
        toggle_btn = (ToggleButton) findViewById(R.id.toggle_btn);
        switch_btn = (Switch) findViewById(R.id.switch_btn);
        radioGroup = (RadioGroup) findViewById(R.id.radio_group);
        imageview = (ImageView) findViewById(R.id.image_view);
        button = (Button) findViewById(R.id.checkRadioButton);
    }

    private void setView() {
        toggle_btn.setChecked(false);//設定一開始是關閉狀態
        int image = R.drawable.android_photo;
        String description = "This is logo";
        imageview.setImageResource(image);
        imageview.setContentDescription(description);

    }

    private void setListener() {
        toggle_btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (toggle_btn.isChecked()) {
                    editText.setTransformationMethod(HideReturnsTransformationMethod.getInstance());//顯示密碼
                } else {
                    editText.setTransformationMethod(PasswordTransformationMethod.getInstance());//影藏
                }
            }
        });
        switch_btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (switch_btn.isChecked()) {
                    Toast.makeText(MainActivity.this, "開啟", Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(MainActivity.this, "關閉", Toast.LENGTH_SHORT).show();
                }
            }
        });
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                int id = radioGroup.getCheckedRadioButtonId();
                if (id == -1) {
                    Toast.makeText(MainActivity.this, "您未做任何選擇。", Toast.LENGTH_SHORT).show();
                } else {
                    RadioButton radiobutton = (RadioButton) findViewById(id);
                    Toast.makeText(MainActivity.this, "你選擇了:" + radiobutton.getText().toString(), Toast.LENGTH_SHORT).show();
                }
            }
        });
    }

    public void CheckBoxClick(View view) {
        boolean checked = ((CheckBox) view).isChecked();
        switch (view.getId()) {
            case R.id.checkbox_one:
                if (checked)
                    Toast.makeText(this, "選擇牛奶", Toast.LENGTH_SHORT).show();
                else
                    Toast.makeText(this, "unCheck牛奶", Toast.LENGTH_SHORT).show();
                break;
            case R.id.checkbox_two:
                if (checked)
                    Toast.makeText(this, "選擇咖啡", Toast.LENGTH_SHORT).show();
                else
                    Toast.makeText(this, "unCheck coffee", Toast.LENGTH_SHORT).show();
                break;
            default:
                break;
        }
    }

    public void groupButton(View view) {
        int id = radioGroup.getCheckedRadioButtonId();
        switch (id) {
            case R.id.radio_one:
                Toast.makeText(this, "選milk", Toast.LENGTH_SHORT).show();
                break;
            case R.id.radio_two:
                Toast.makeText(this, "選coffee", Toast.LENGTH_SHORT).show();
                break;

        }
    }


}

 




就不提供Demo了,就如同上面一樣,複製貼上就可看到demo

2017年8月13日 星期日

Android元件 — Notification簡易使用

做個紀錄 有空補齊

https://developer.android.com/reference/android/app/Notification.html

public void showNotification(String title, String message) {
        Intent notifyIntent = new Intent(this, MainActivity.class);
        notifyIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);

        PendingIntent pendingIntent = PendingIntent.getActivities(this, 0,
                new Intent[]{notifyIntent}, PendingIntent.FLAG_UPDATE_CURRENT);

        Notification notification = new Notification.Builder(this)
                .setSmallIcon(android.R.drawable.ic_dialog_info)
                .setContentTitle(title)
                .setContentText(message)
                .setAutoCancel(true)
                .setContentIntent(pendingIntent)
                .build();
        notification.defaults |= Notification.DEFAULT_SOUND;
        NotificationManager notificationManager =
                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        notificationManager.notify(1, notification);
    }
 

簡易使用。

開個button 點擊後,notification通知就出來了。

可以設定在alarmManager做配合使用

比如定點定時,做出推播效果提醒使用者。






協程(coroutine) - 協程為什麼要學它?

 Coroutine 協程 再強調一次 協程就是由kotlin官方所提供的線程api //Thread Thread { }.start() //Executor val execu...