show code block

2017年10月18日 星期三

Android工具(Mocky、json-generator)— Json檔案的生成、自製

前言:

我一個手賤不小心把文章內文給清除了....

這邊再次做個紀錄

不詳細了,直接附上網址

Mocky(生成工具)
https://www.mocky.io/

jsoneditoronline(編輯工具)
http://jsoneditoronline.org/

json-generator(生成工具)
https://www.json-generator.com/

個人偏愛Mocky 比較simple

2017年10月17日 星期二

Android方法(BuildType、Flavors、variants) — 簡易使用Flavors不同開發環境

前言:


如果你們公司需要不同的開發環境來做App測試,可以試試看這個。
flavors and buildType

這個的效果是什麼呢?

可以讓你把測試環境給分開


有什麼特別的嗎?

當然有特別,這三個App其實是同一個。
那為什麼要設成三個呢?
可以拿來當切換環境用,一個開發團隊內通常會有測試區lab和正式區。
 
如果在做檢查的時候,正式區和測試區切來切去非常的不方便。
你的程式大概會長這樣


每次切換都要重新選擇註解,再build一次。
中間等待的時間就白白浪費了,所以可以使用flavors來同時build起不同的開發環境。

這邊指讓你最簡易程度上的完成實作。
當然還有其他的玩法,詳情請見其他地方 or flavors and buildType



重點程式碼:

再gradle內

 

 defaultConfig {
       ...
        resValue "string", "app_label", "default_name"
        buildConfigField "String", "initAPI", "defult_value"
    }

productFlavors {
        dev {
            applicationId "com.example.branchOne"
            versionName "MyApp_dev"
            resValue "string","app_name","DEV_APP"
            buildConfigField "String", "initAPI", "\"https://www.google.com.tw/\""
        }
        RC {
            applicationId "com.example.branchTwo"
            versionName "MyApp_RC"
            resValue "string", "app_name", "RC_APP"
            buildConfigField "String", "initAPI", "\"開發環境一\""
        }
        PUB {
            applicationId "com.example.branchThree"
            versionName "My App"
            resValue "string","app_name","PUB_APP"
            buildConfigField "String", "initAPI", "\"正式版\""
        }
    }
 

上面的initAPI參數都應該是你們自己的api網址,在引號內的\"不能少

介紹一下裡面在幹嘛的
applicationId 每個app要獨立出來都必須有自己的androidId,如果androidId一樣系統會判定你為同一個APP

resValue 這是指會在下圖的地方看到dev pub rc 你設定的文字都會跑到這裡



再來是
buildConfig 看下圖,她會出現在和resValue很近的地方



再buildConfig內,程式碼會自動生成
public final class BuildConfig {
  public static final boolean DEBUG = Boolean.parseBoolean("true");
  public static final String APPLICATION_ID = "com.example.branchTwo";
  public static final String BUILD_TYPE = "debug";
  public static final String FLAVOR = "RC";
  public static final int VERSION_CODE = 1;
  public static final String VERSION_NAME = "MyApp_RC";
  // Fields from product flavor: RC
  public static final String initAPI = "開發環境一";
}

 

你會發現它自動生成了 initAPI,此時開發環境一就會是一串網址。

如何使用initAPI呢?
在要call這串網址的地方BuildConfig.initAPI就行了。
因為我們有在gradle > defaultConfig內設定初始值
如果你在productFlavors內沒有設定buildConfigField "String", "initAPI", "正式版"
會自動幫妳生成defult_value這個string




使用方式:


把畫面帶到android studio的左下角 有一個build Variants 在這裡切換你想要build的版本就行了。
當然他有分bugrelease版本
release版本有牽扯到 發布問題的key
單純demo就不說了。

然後如果你在程式內有寫DB,會需要做額外設定。

詳情請見
https://stackoverflow.com/questions/14368867/permission-denial-opening-provider

如果我有用到的話再做討論XD

有問題歡迎提出。

2017年10月6日 星期五

Android元件(ActivityLifecycleCallbacks) — 逾時登出製作 (二)

前言:

伊隆·馬斯克 space x 的創辦人,曾經說過把事情簡化的重要性。

像是把一件不可能的事情,中間的步驟不斷分解簡化。
就像他提出的第一性原理
就是讓我們把目光從那些別人做的事上挪開,不管做什麼選擇,都以最根本的那個原則為參照點,不斷用那個參照點為自己糾偏。

 上一次做逾時登出也是用這方法,把每一個想得到的情況都包含進去,在不斷簡化。

但在簡化的過程,其實也可以抬頭看一下有沒有其他平行更好的方法。

剛剛我發現了一個更快的方式,一個方法就概括監控所有Activity的方法
 ActivityLifecycleCallbacks
 https://developer.android.com/reference/android/app/Application.ActivityLifecycleCallbacks.html

 ActivityLifecycleCallbacks

他能瞬間監控所有的activity,也能在其中做一些變化,像是ToolBar
關於ToolBar我是參考
http://www.jianshu.com/p/75a5c24174b2

這篇讓你實現每個頁面實現toolbar的方式。

有興趣可以連過去看看,這邊只講逾時登出。



 重點程式碼:

Application內 可以直接使用ActivityLifecycleCallbacks
public class MyApplicationTwo extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
            @Override
            public void onActivityCreated(Activity activity, Bundle bundle) {
                
            }

            @Override
            public void onActivityStarted(Activity activity) {

            }

            @Override
            public void onActivityResumed(Activity activity) {

            }

            @Override
            public void onActivityPaused(Activity activity) {

            }

            @Override
            public void onActivityStopped(Activity activity) {

            }

            @Override
            public void onActivitySaveInstanceState(Activity activity, Bundle bundle) {

            }

            @Override
            public void onActivityDestroyed(Activity activity) {

            }
        });
    }
}

 

上述就和Activity的生命週期幾乎一模一樣,在每個方法內打上Log。

設置兩三個Activity就可以做測試了!

在逾時登出的案子裡,我們還原一下裡面的CustomApplication這個方法
http://nikeru8.blogspot.tw/2017/09/android.html

把整個App關於逾時登出的部分全部砍掉,包含情境A情境B


這裡一行就完成ActivityLifecycleCallbacks
public class CustomApplication extends Application {

    private static final String TAG = "CustomApplication";
    private static long PAUSE_TIME = 0;//暫停的時間點
    private static long RESTART_TIME = 0;//喚醒的時間點

    @Override
    public void onCreate() {
        super.onCreate();
        registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
            @Override
            public void onActivityCreated(Activity activity, Bundle bundle) {
                Log.d(TAG, "onActivityCreated");
            }

            @Override
            public void onActivityStarted(Activity activity) {
                Log.d(TAG, "onActivityStarted");
            }

            @Override
            public void onActivityResumed(Activity activity) {
                Log.d(TAG, "onActivityResumed");
                if (PAUSE_TIME != 0) {
                    RESTART_TIME = System.currentTimeMillis();
                    long totalTime = RESTART_TIME - PAUSE_TIME;
                    Log.d("checkpoint", "checkpoint PAUSE_TIME = " + PAUSE_TIME);
                    Log.d("checkpoint", "checkpoint RESTART_TIME = " + RESTART_TIME);
                    Log.d("checkpoint", "checkpoint = " + totalTime);
                }

            }

            @Override
            public void onActivityPaused(Activity activity) {
                Log.d(TAG, "onActivityPaused");
            }

            @Override
            public void onActivityStopped(Activity activity) {
                Log.d(TAG, "onActivityStopped");
            }

            @Override
            public void onActivitySaveInstanceState(Activity activity, Bundle bundle) {
                Log.d(TAG, "onActivitySaveInstanceState");
            }

            @Override
            public void onActivityDestroyed(Activity activity) {
                Log.d(TAG, "onActivityDestroyed");
            }
        });
    }
}

 
這就和Activity的生命週期一模一樣。
我在喚醒activity的Resume部分,寫了方法。

假如停止時間點有值,喚醒時,拿PAUSE_TIME(暫停的時間點)比較一下 RESTART_TIME (喚醒的時間點)
long 每一千個單位 等於 一秒。
相減下來如果1204,就等於app暫停了1.204



好啦,試試看自己的App能不能有逾時登出的效果吧!
以下是我的Log
checkpoint 就是相扣的單位 2934
所以是2.934


2017年10月5日 星期四

Android錯誤解決 — backend:compileEndpointsSrcJava

前言:
早上遇到了一個奇怪的錯誤。
以前都好好的專案突然build不起來了!

看了一下Log







Error:(302, 5) error: method does not override or implement a method from a supertype
Error:(304, 29) error: cannot find symbol method setBatchPath(String)

Error:(474, 5) error: method does not override or implement a method from a supertype
Error:(476, 29) error: cannot find symbol method setBatchPath(String)

Error:Execution failed for task ':backend:compileEndpointsSrcJava'.
> Compilation failed; see the compiler error output for details.



實在不知道什麼情況。

就拿關鍵字下去搜索。

重點訊息還非常之少!!!!

我轉頭就直接開stackoverflow直接搜索

可以判斷如果不是我程式碼有問題,這就是一個史無前例的新bug

 Google App Engine endpoints

就是這出問題啦!


解決方式:


在backend project內增加這串

appengine {
    endpoints {
        googleClientVersion = '1.23.0'
    }
}
 

問題就解決了

https://stackoverflow.com/questions/46554771/cannot-find-symbol-method-setbatchpathstring-in-the-generated-source-from-ge

突然有種從0到1真的很困難的感觸。


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

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