[Android] App 應用程式開發指南

Intro


Quick Start

  1. 建立第一個 Android 應用程式 - Android Developers

  2. 建構並執行應用程式 - Android Developers
    若有建立 Android Emulator 則可以直接在 Android Studio 的 Running Devices 列表找到,實體手機則可以透過 USB 或 Wi-Fi 連結裝置以加入列表。

    使用連結的 Device 執行 Run 後該 Device 就會安裝 apk 並開啟執行

  3. Build app for release
    Build 出來的 apk 預設檔案目錄:app/build/outputs/apk/


WebView

Quick Start

快速在 onCreate 時就搭建好 WebView:

  1. Add a WebView in onCreate()
    包含在 AndroidManifest.xml 加入 INTERNET permission

  2. Handle page navigation
    Override shouldOverrideUrlLoading() 讓 WebView 可以支援 URL 的開啟方式。WebView.context.startActivity(Intent) 用來支援 Intent 開啟 URL,可同時處理 App scheme launch 以及 HTTP URL 外開預設瀏覽器。

    onCreate - MainActivity.kt:

    class MainActivity : ComponentActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            ...
            val myWebView = WebView(this)
            myWebView.webViewClient = MyWebViewClient()
            myWebView.settings.javaScriptEnabled = true
            setContentView(myWebView)
            myWebView.loadUrl("https://webview.page")
        }
    }

    Override WebView client - {custom}/{MyWebViewClient}.kt:

    class MyWebViewClient : WebViewClient() {
        override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
            if (Uri.parse(url).host == "www.webview-site.com") {
                // This is the loading web site, so do not override; let my WebView load the page
                return false
            }
            // Otherwise, launch another Activity that handles URLs including App scheme URL
            Intent(Intent.ACTION_VIEW, Uri.parse(url)).apply {
                view.context.startActivity(this)
            }
            return true
        }
    }

Deep Link

AndroidManifest.xml 中,透過新增 <intent-filter> 來定義 App 支援的 URL Scheme:

<activity
    android:name=".MainActivity"
    android:label="@string/app_name">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
    <intent-filter android:label="URL Scheme Setting">
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <!-- Accepts URIs that begin with "example://gizmos” -->
        <data android:scheme="example" android:host="gizmos" />
    </intent-filter>
</activity>

Deep Link 也可以使用 https:// 協議,但因未經過官方驗證,當多個 App 都能處理該網域時,系統仍會彈出「開啟工具(app)」選擇選單。


App Link (Verified Links)

當你希望使用標準的 https 網址開啟 App,且不希望系統彈出「選擇開啟 App」的選單時,應使用 App Link。這是 Deep Link 的進階版,增加了「自動驗證」機制。

  1. Manifest 設定
    intent-filter 中加入 android:autoVerify="true",並指定你的官方網域
<intent-filter android:autoVerify="true"> <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />

    <data android:scheme="https" android:host="[www.yourdomain.com](https://www.yourdomain.com)" />
    <data android:scheme="http" />
</intent-filter>
  1. 銜接要點:伺服器驗證
    與 Custom Scheme (Deep link) 不同,App Link 必須在你的 Web Server 放置驗證檔案,證明該網域與 App 的關聯性:

App Scheme 轉導「覆蓋/取代」問題總結

當 A App 透過 myapp:// 呼叫 B App,若發現 B 直接蓋在 A 的視窗內(多工界面只剩一個 app 視窗),通常是 Task Stack(任務棧) 管理不當。


🛠️ 解決方案:誰該負責?

要避免「覆蓋」現象,只要其中一方做好設定即可:

1. 呼叫者 (Caller App) 的責任

在發送 Intent 時,強制要求系統開啟新任務。

  • 作法:加入 FLAG_ACTIVITY_NEW_TASK
  • 原理:告訴系統「把這個 URL 送到它目標去開」。
  • 範例
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

2. 目標 App (Target App) 的責任

在自己的設定檔中,聲明自己永遠要獨立開啟。

  • 作法:在 AndroidManifest.xml 設定 android:launchMode
  • 推薦值singleTasksingleInstance
  • 原理:不論誰呼叫我,我都會強行建立/回到自己的 Task Stack。
  • Sample
    <activity
    android:name=".MainActivity"
    android:label="@string/app_name"
    android:launchMode="singleTask">  
    <intent-filter> ...

📊 行為矩陣 (Priority Matrix)

呼叫者 (帶 Flag) 目標 App (LaunchMode) 結果 說明
NEW_TASK 任意 (如 standard) 正常 呼叫者強制要求獨立。
NEW_TASK singleTask 正常 目標 App 自行要求獨立。
NEW_TASK (standard) 覆蓋 雙方都沒堅持,系統會疊在一起。

💡 為什麼 Chrome 轉導 app 皆不會發生覆蓋?

因為 Chrome 內建已處理好 Flag。當你在 Chrome 點擊連結時,它發出的 Intent 預設就帶有「NEW_TASK」的指令,所以不會發生 Chrome 被目標 App 取代的情況。


References

Leave a Reply

Your email address will not be published. Required fields are marked *