發表文章

透過Postman測試Android接收推播訊息

圖片
前言 推播問題多,透過Postman能快速自我驗證,釐清問題 測試步驟 首先請安裝Postman。Postman: a Google chrome extension. Postman設定 Request Type: POST URL: https://android.googleapis.com/gcm/send Header   Authorization :  key=your key  //Google API KEY   Content-Type :  application/json Body JSON (raw) : 請照自己的發送格式 {   "to":"token",   "data": {     "message" : "Test測試"   } } 確認回應訊息,當success的值大於0,表示成功發送幾個

AndroidX 和 Android Support 相容問題

圖片
Run App時發生的問題: Manifest merger failed : Attribute application@appComponentFactory value=(android.support.v4.app.CoreComponentFactory) from [com.android.support:support-compat:28.0.0] AndroidManifest.xml:22:18-91 is also present at [androidx.core:core:1.0.0] AndroidManifest.xml:22:18-86 value=(androidx.core.app.CoreComponentFactory). Suggestion: add 'tools:replace="android:appComponentFactory"' to <application> element at AndroidManifest.xml:36:5-364:19 to override. Sol: project目錄按下右鍵 -> Refactor -> Migrate to AndroidX Android Studio會幫你先壓一個zip,避免壞掉

Android Navigation 學習筆記

圖片
為什麼要用Navigation? 當你專案中的頁面越來越多,Fragment和Activity之間的跳轉越來越繁雜,是不是搞得你一團亂呢?你是否羨慕Xcode中能將頁面跳轉視覺化的Storyboard呢? Xcode Storyboard 好在Google終於提供了Navigation套件來幫我們處理這些問題,讓我們一起來試玩看看吧。 Android Navigation Graph 環境設定 如果你的Android Studio版本是3.2的話,必須到Setting將Navigation Editor打開,3.3以上版本無需此動作 enable Navigation Editor dependencies 首先設定module層的build.gradle,我的Demo會用androidx的版本示範 androidx version dependencies { implementation "androidx.navigation:navigation-fragment:2.0.0" implementation "androidx.navigation:navigation-ui:2.0.0" } 新建三個Fragment class MainPage1Fragment : Fragment() { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { return inflater.inflate(R.layout.fragment_main_page1, container, false) } } class MainPage2Fragment : Fragment() { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,

Kotlin - dagger 2

Dependencies Project build.gradle buildscript { ext.dagger_version = '2.5' } App build.gradle apply plugin: 'kotlin-kapt' dependencies { implementation "com.google.dagger:dagger:$dagger_version" kapt "com.google.dagger:dagger-compiler:$dagger_version" } 下面我們直接來看一個範例: 我這邊使用四個Model,分別為Model A B C D ModelA 裡面包含了 B跟C ModelC 裡面包含了 D 先看ModelA: class ModelA @Inject constructor(val context: Context, var modelB: ModelB, var modelC: ModelC){ var somethingData: String = "modelA haha " fun print() { Log.d("ModelA", somethingData + modelB.somethingData + modelC.somethingData) } } 傳入的context,實際上沒用到只是純粹練習  print()  會印出ModelA的data,data會將ABC的data加起來 ModelB: class ModelB @Inject constructor(){ var somethingData: String = "modelB haha " } ModelC: class ModelC @Inject constructor(modelD: ModelD){ var somethingData: String = "modelC haha " + modelD.somethingData

Kotlin - 實現Android中的Parcelable

圖片
使用 Parcelable 的最基本用例是當我們需要將模型從一個活動傳遞到另一個活動時。當傳遞原始類型時,很簡單,但是當我們想要傳遞自己的對象時,我們需要對它們做一些事情: class ActivityA : Activity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val intent = Intent(this, ActivityB::class.java) val person = Person("name", 32, "email@email.com", 1234) intent.putExtra("A_STRING", "some string") intent.putExtra("A_NUMBER", 1234) intent.putExtra("AN_OBJECT", person) // compilation error startActivity(intent) } } 如果我們認為我們使用的 Person 對象與上一篇文章相同,則會在第11行收到編譯錯誤,因為我們無法照原樣傳遞 Person 模型。 我們的模型不符合以上任何條件,因此我們需要對此做些事情,我們有一些選擇: Implement Serializable: 希望您不再這樣做,儘管它有效且易於實施,但由於它基於反射,因此性能相當差。 Json String representation : 您也可以這樣做,並將模型作為String傳遞。同樣,這也非常簡單,特別是如果您已經Gson在項目中使用了類似功能,但又不是最佳選擇。 Implement Parcelable: 這顯然是正確的答案。根據官方文檔,這是推薦的方式。它也適用於   marshalling/unmarshallingJava 對象,例如序列化,但性能更高。 因此,Parcelable是最好

Android Coroutine Recipes

圖片
本文的原始碼可以在 YangQiRen/coroutine-recipes 中找到 基於Coroutine v1.0.0版本 引入依賴 implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.0.0' implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.0' 如何啟動協程(Coroutine) 在 kotlinx.coroutines 庫中,您可以使用 launch 或 async 函數來啟動新的協程。 從概念上講, async 就像 launch 。它啟動一個單獨的協程,這是一個輕量級線程,可與所有其他協程同時工作。區別在於, launch 返回一個 Job 且不攜帶任何結果值,而 async 返回一個 Deferred 輕量無阻塞的未來,表示希望稍後提供結果。您可以使用 .await() 延期的值來獲得其最終結果,但是 Deferred 它也是一個 Job ,因此可以根據需要取消它。 ***重點*** 如果裡面的代碼 launch 以異常終止,然後將其視為未捕獲線程中的異常會使Android應用程序崩潰。內部未捕獲的異常 async 代碼存儲在結果中 Deferred 並且不會在其他任何地方交付,除非經過處理,否則它將被靜默丟棄。 協程調度員(Coroutine Dispatcher) 在Android中,我們通常使用兩個調度程序: uiDispatcher將執行分派到Android主UI線程(用於父協程)。 bgDispatcher在後台線程中分派執行(用於子協程)。 //將執行分派到Android主線程中 val uiDispatcher:CoroutineDispatcher = Dispatchers.Main //將共享線程池表示為協程分派器 val bgDispatcher:CoroutineDispatcher = Dispatchers.I0 在下面的例子中,我們將使用 CommonPool 用於 bgContext 這限制並行運行為值64個線程或核的數量

Android Room資料庫的使用

前言 Google終於釋出了一個和SQLite相關的庫了。之前一直都是在SQLite、XUtils、greenDao、Realm這些資料庫之間來回折騰。現在終於有一個更“正統”資料庫了。 Room是什麼? 2017 年 5 月,Google I/O ’17 發佈了 Room,至此 persistence 歸於一統 — Room。Room 具有良好的擴充性及彈性,對於多個 Table 間的複合查詢也相當的容易,簡單的標示即可產生Database、Table,對於SQL 語法頭疼的人乃一大福音。 使用Room 1、在app/build.gradle中新增以下依賴 implementation 'android.arch.persistence.room:runtime:1.1.1' annotationProcessor 'android.arch.persistence.room:compiler:1.1.1' 2、建立JavaBean @Entity public class User { @PrimaryKey(autoGenerate = true) // 主鍵是否自動增加,預設為false @ColumnInfo(name = "id") private int id; private String name; private int age; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age;