發表文章

目前顯示的是 2019的文章

透過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;

Kotlin - Convert Unix Timestamp to Date 時間戳記的轉換

What is a Unix Timestamp 參考連結 直接進入程式碼的部分: object TimeUtil { @JvmStatic fun StampToDate(time: Long, locale: Locale): String { // 進來的time以秒為單位,Date輸入為毫秒為單位,要注意 val simpleDateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", locale) return simpleDateFormat.format(Date(time)) } @JvmStatic fun DateToStamp(date: String, locale: Locale): Long { val simpleDateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", locale) /// 輸出為毫秒為單位 return simpleDateFormat.parse(date).time } } 使用: println(TimeUtil.StampToDate(1560839160000, Locale.TAIWAN)) println(TimeUtil.DateToStamp("2019-06-18 14:26:00", Locale.TAIWAN)) 以台灣為例,GMT+8  Date 格式是 "yyyy-MM-dd HH:mm:ss" 假如 台灣 Date = "2020-10-21 18:00:00" 轉換成時間戳是  1603274400 同時間 在 GMT +0 時區的地方 Date =  "2020-10-21 10:00:00" 轉換成時間戳也是  1603274400

Android - 使用 adb 安装apk

adb就是Android debug bridge的簡寫,用來和模擬器或實機互動的工具,可以參考 官方文件 。 adb在 \sdk\platform-tools 目錄底下,直接點選是無法正常使用的,一定要透過 命令提示字元 。 啟動 命令提示字元 的方法: windowsKey + R,然後輸入cmd.exe。 或是找到命令提示字元的捷徑點開。 啟動後,會看到目前的目錄,請將目錄改到\sdk\platform-tools,方法是輸入cd <path>。 確定目錄在\sdk\platform-tools下面後,輸入adb shell,adb就會 啟動 。 通常我們是要使用adb去安裝apk檔案到手機內。先將手機設定好,開啟debug偵錯,然後透過adb來確認有無連接上手機,輸入: adb devices 。若有連接上的話,會看到手機的序號,是一串字碼,反之,則什麼都沒有。 安裝apk 的方法是, 先把apk檔案放到\sdk\platform-tools下, 或是把目錄改到apk檔案所在的目錄。 然後輸入 adb install name.apk ,就會安裝,安裝完會顯示success。 若是要重新安裝,不須解除安裝,僅需輸入adb install  -r  name.apk。多一個-r。 原文連結如下:http://wisdomskyduan.blogspot.com/2014/10/android-adbapkusb.html

Godot 使用Android module 踩坑步驟,一踩就上手

圖片
範例影片: https://www.youtube.com/watch?v=rbr3a7xh4dk 參考網址: https://docs.godotengine.org/en/3.1/development/compiling/compiling_for_android.html 作業系統:Mac OSX 由於我需要修改 godot 對輸出 Android 平台的設置,需要修改Android manifest 並且使用Android Class(Content provider) 去達到 多個應用程式共用資料,需要使用 godot GitHub 上的 Godot IDE source 。 Step 1. 打開Terminal,git clone https://github.com/godotengine/godot.git Step 2.  cd godot/ Step 3. 這時候你可以先在godot/ 資料夾內,這邊使用scons自動構建工具去安裝平台的套件套件,輸入scons看看,如果找不到,需要上網搜尋如何安裝scons。 Step 4. 安裝好scons後,輸入scons看看有幾個平台,如果沒有Android,你要先把SDK、NDK路徑先設定好, 這篇 給你參考。 *** 注意這邊我為什麼用ndk-r15c(第一坑)呢,因為我遇到 這個問題 *** 順邊貼上我自己的設定 Step 5. 設定完成後發現輸入scons 有多一個Android平台跑出來,此時輸入 scons platform = android Step 6. 安裝完成後, cd godot/bin/ chmod +x godot.osx.tools.64 ./godot.osx.tools.64 即可開啟Godot IDE Step 7. 接下來要 Building the export templates Step 8. 接下來  Installing the templates 設定debug release apk Step 9. Setting it up in Godot ,設定Adb Jarsigner Debug keystore,

Android FirebaseInstanceIdService is deprecated 已棄用

最近開啟專案發現 FirebaseInstanceIdService onTokenRefresh() 方法已棄用了。 查詢一下 官方文件 發現將此方法改用 FirebaseMessagingService onNewToken  取代 這意味著無需使用 FirebaseInstanceIdService 服務來獲取FCM令牌。您可以安全地刪除   FirebaseInstanceIdService 服務 範例代碼: public class MyFirebaseMessagingService extends FirebaseMessagingService { @Override public void onNewToken(String s) { super.onNewToken(s); Log.e("NEW_TOKEN",s); } @Override public void onMessageReceived(RemoteMessage remoteMessage) { super.onMessageReceived(remoteMessage); } } 希望你能在這裡得到解決方案。

Android get file extension 取得文件的副檔名

筆記用途 // 取得文件的副檔名 private String getFileExtension(Uri uri) { ContentResolver contentResolver = getContentResolver(); MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton(); return mimeTypeMap.getExtensionFromMimeType(contentResolver.getType(uri)); } Done.

Android ContentProvider 實現多個應用程式共享資料

圖片
這篇文章探討的是如何在 單個 應用程式或者 多個 應用程式間做出 安全的共享資料 功能,此篇會運用到  ContentProvider + SQLite , ContentProvider為應用間的數據交互提供了一個安全的環境。它準許你把自己的應用數據根據需求開放給其它應用進行 新增(insert)、刪除(delete)、修改(update)、查詢(query) ,而不用擔心直接開放數據庫權限而帶來的安全問題。

Android FirebaseUI for Cloud Firestore - FirestoreRecyclerAdapter

根據上一篇 FireStore 文章的延伸, 今天這篇打算分享  FirestoreRecyclerAdapter , FirestoreRecyclerAdapter  是  FirebaseUI-Android  的其中一個部分的工具,在學習 firestore 發現這個東西非常好用 ,順便自己做個筆記用途,如有錯誤的地方,敬請留言告知。

Android 8.0 Oreo 通知頻道Notification channels

圖片
這是在我們針對API 26(Oreo)的應用中更新我們的FCM內容的快速提示。 我不得不更新當前的應用程序(將targetSdkVersion更改為26)以支持Android Oreo(8.0)。一切都很好(在以前的版本中),但在 Oreo,這不是快樂的情況。通知未按預期工作:當設備收到推送通知時,應用程序崩潰。這是logcat中的例外: Fatal Exception: java.lang.RuntimeException: Unable to start receiver com.google.firebase.iid.FirebaseInstanceIdInternalReceiver: java.lang.IllegalStateException: Not allowed to start service Intent { act=com.google.firebase.INSTANCE_ID_EVENT pkg=PACKAGE cmp=COMPONENT }: app is in background uid UidRecord{c5e5e69 u0a325 RCVR bg:+1m25s411ms idle procs:1 seq(0,0,0)} at android.app.ActivityThread.handleReceiver(ActivityThread.java:3397) at android.app.ActivityThread.-wrap18(Unknown Source) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1780) at android.os.Handler.dispatchMessage(Handler.java:105) at android.os.Looper.loop(Looper.java:164) at android.app.ActivityThread.main(ActivityThread.java:6938) at java.lang.reflect.Method.invoke(Method.java) at com.android.internal.os.Zygote$MethodAndAr

Android Cloud Firestore - Real-time database

圖片
Cloud Firestore 是一個靈活,可擴展的數據庫,用於從 Firebase 和 Google Cloud Platform 進行移動,Web和服務器開發。與 Firebase 實時數據庫一樣,它可以通過 實時監聽器 使您的數據在客戶端應用程序之間 保持同步 ,並為移動和Web提供 離線支持 ,因此您可以構建響應式應用程序,無論網絡延遲或 Internet 連接如何,都能正常運行。 Cloud Firestore 還提供與其他 Firebase 和 Google Cloud Platform 產品的無縫集成,包括雲功能。

RecyclerView 使用ItemTouchHelper實現滑動刪除、拖移改變順序效果

圖片
前置作業創建RecyclerView、Adapter我這邊就不贅述了 直接進入主題 我們會使用到 ItemTouchHelper工具類別 官方解釋:這是一個實用工具類,用於添加滑動以關閉和拖放支持到RecyclerView。 這是一個支持RecyclerView滑動刪除和拖拽的實用工具類 如何使用: SimpleCallback建立時,需要指定想要支援的拖拉(move)與swipe的方向,在此範例我們讓他可以上下拖拉跟左右swipe(或用START、END,則可支援右到左方向的排列), 而主要需要實作的函式有分別對應到拖拉與swipe的 onMove 與 onSwipe 。 private void setUpRecyclerView() { adapter = new ContactAdapter(options); recyclerView.setLayoutManager(new LinearLayoutManager(this)); recyclerView.setAdapter(adapter); // 實現拖移、左右滑動刪除的效果 new ItemTouchHelper(new ItemTouchHelper.SimpleCallback( ItemTouchHelper.UP | ItemTouchHelper.DOWN, ItemTouchHelper.RIGHT | ItemTouchHelper.LEFT) { @Override public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder viewHolder1) { // 上下拖移callback return false; } @Override

Android 更改Toolbar actionBar button icon

很多的Android應用左上角都有返回按鈕 在默認的情況下ADT會默認給一個返回圖標 而作為開發需求很多都要求定制一個新的圖標 在Android的網站上發現了2種可以更改的方法

在設置了android:parentActivityName後,點擊子Activity返回鍵,父Activity總會調用OnDestroy()的解決方案

一個Activity在manifet裡聲明了 android:parentActivityName ;這時候通過Activity左上角的返回按鈕點擊返回,啟動聲明的父Activity,總會先調用父Activity的OnDestroy方法,具體如下面所說: <activity android:name=".NewContactActivity" android:parentActivityName=".MainActivity"/>

Android firebase notification message type

圖片
這篇講述自己在開發時遇到的問題,使用方法網路上很多,這邊就不再贅述。 直接進入問題點 問題描述: FirebaseMessagingService 的 onMessageReceived 裡面收到推播時,設定大圖示彩色 icon ,還有一個顯示小 icon ,需求是 icon 設定為 大圖示彩色 icon  。