今天要介紹的是地圖功能,這個功能提供了離線地圖和線上地圖兩種功能。離線地圖功能允許使用者下載地圖資料,並在沒有網路連接的情況下使用,這對於在偏遠地區或網路信號較弱的地方使用地圖非常有用。而線上地圖功能允許使用者即時連接到網路,使用地圖服務提供商的資源和功能,來找尋到附近的資源或醫療設施等,來獲取進一步的幫助。



   <androidx.constraintlayout.widget.ConstraintLayout 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"
    tools:context=".ui.map.MapsActivity"
    android:background="@color/theme">
    <androidx.appcompat.widget.Toolbar
        android:id="@+id/offline_map_toolbar"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        app:layout_constraintBottom_toTopOf="@+id/offline_map_guideline1"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/offline_map_guideline1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.06" />
    <FrameLayout
        android:id="@+id/map_frameLayout"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintBottom_toTopOf="@+id/linearLayout8"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/offline_map_toolbar">
    </FrameLayout>
    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.93" />
    <LinearLayout
        android:id="@+id/linearLayout8"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:orientation="horizontal"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@+id/guideline2">
        <Button
            android:id="@+id/online_map_button"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_margin="5dp"
            android:layout_weight="1"
            android:background="@drawable/custom_button"
            android:fontFamily="@font/fonts"
            android:textSize="16sp"
            android:textStyle="bold"
            android:text="地圖"/>
        <Button
            android:id="@+id/offline_map_button"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_margin="5dp"
            android:layout_weight="1"
            android:textColor="@color/black"
            android:background="@drawable/custom_button"
            android:fontFamily="@font/fonts"
            android:textSize="16sp"
            android:text="離線地圖"
            android:textStyle="bold"/>
    </LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
private void offlineMapClicked(View view) {
file = new File(Environment.getExternalStorageDirectory().getPath()+"/Download", "taiwan.mbtiles");
    // 檢查離線地圖文件是否存在
    if (!file.exists()) {
        // 如果文件不存在,顯示警告對話框,提示用戶下載地圖
        AlertDialog.Builder dialog = new AlertDialog.Builder(this);
        dialog.setPositiveButton("下載", downloadClicked) // 定義「下載」按鈕的點擊操作
              .setNegativeButton("取消", cancelClicked) // 定義「取消」按鈕的點擊操作
              .setMessage("請先下載離線地圖!!") // 設置對話框消息
              .show(); // 顯示警告對話框
    } else {
        // 如果離線地圖文件存在
        if (offlineMapFragment == null) {
            // 如果離線地圖片段尚未初始化,則初始化它
            offlineMapFragment = new OfflineMapFragment(this);
        }
        // 將離線地圖片段替換到指定的佈局容器中
        getSupportFragmentManager().beginTransaction().replace(R.id.map_frameLayout, offlineMapFragment).commit();
    }
}
private DialogInterface.OnClickListener downloadClicked = new DialogInterface.OnClickListener() {
    @Override
    public void onClick(DialogInterface dialog, int which) {
        // 定義要下載的地圖文件的 URI
        Uri uri = Uri.parse("https://data.moi.gov.tw/MoiOD/System/DownloadFile.aspx?DATA=4BE02238-E336-4F91-91F3-869FBA4CF4DB");
        // 獲取下載管理器(DownloadManager)
        DownloadManager downloadManager = (DownloadManager) MapsActivity.this.getSystemService(DOWNLOAD_SERVICE);
        // 創建下載請求(DownloadManager.Request)
        DownloadManager.Request request = new DownloadManager.Request(uri);
        // 設定下載請求的一些屬性
        request.setAllowedOverRoaming(true); // 允許在漫遊時下載
        request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); // 顯示下載通知
        request.setTitle("TaiwanMapDownload"); // 設定通知標題
        request.setDestinationUri(Uri.fromFile(file)); // 設定下載文件的保存位置
        // 將下載請求加入到下載隊列並獲取下載任務的 ID
        long download_id = downloadManager.enqueue(request);
        // 創建用於查詢下載狀態的查詢對象(DownloadManager.Query)
        DownloadManager.Query query = new DownloadManager.Query();
        query.setFilterById(download_id);
        // 創建下載完成時的廣播接收器,以便在下載完成後執行相應的操作
        IntentFilter filter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
        DownloadCompleteReceiver receiver = new DownloadCompleteReceiver();
        receiver.getIdAndFile(download_id, file); // 傳遞下載 ID 和文件
        registerReceiver(receiver, filter); // 註冊廣播接收器
        // 創建一個線程用於監視下載進度
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                boolean downloading = true;
                while (downloading) {
                    // 創建新的查詢對象以查詢下載狀態
                    DownloadManager.Query query = new DownloadManager.Query();
                    query.setFilterById(download_id);
                    Cursor cursor = downloadManager.query(query);
                    if (cursor != null && cursor.moveToFirst()) {
                        int downloadedBytesIndex = cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR);
                        int totalBytesIndex = cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES);
                        // 獲取已下載和總大小的字節數
                        long downloadedBytes = cursor.getLong(downloadedBytesIndex);
                        long totalBytes = cursor.getLong(totalBytesIndex);
                        // 計算下載進度
                        int progress = (int) ((downloadedBytes * 100) / totalBytes);
                        // 在 UI 線程上更新進度按鈕的文本和禁用按鈕
                        activity.runOnUiThread(() -> {
                            offline_map_button.setText(progress + "%");
                            offline_map_button.setEnabled(false);
                        });
                        int statusIndex = cursor.getColumnIndex(DownloadManager.COLUMN_STATUS);
                        int status = cursor.getInt(statusIndex);
                        // 如果下載成功,設置標誌以結束循環
                        if (status == DownloadManager.STATUS_SUCCESSFUL) {
                            downloading = false;
                        }
                    } else {
                        downloading = false;
                        // 在 UI 線程上啟用按鈕
                        activity.runOnUiThread(() -> {
                            offline_map_button.setEnabled(true);
                        });
                    }
                    if (cursor != null) {
                        cursor.close();
                    }
                    try {
                        // 每隔一秒更新進度
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                // 下載完成後,恢復按鈕的文本
                activity.runOnUiThread(() -> {
                    offline_map_button.setText("離線地圖");
                });
            }
        });
        thread.start(); // 開始監視下載進度的線程
    }
};
這就是今天介紹的部分,明天會繼續介紹地圖的使用~!!!