首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

Android 背景服務監聽 WiFi 狀態自動下載/刪除視頻實作架構

     編輯:程式設計疑難解答

需求場景

App 掛載背景服務,監聽 WiFi 連線廣播,連線成功後自動下載 3 支視頻,播放完畢自動刪除。

核心架構

┌─────────────────────────────────────┐
│           Foreground Service        │  ← 保持存活、顯示通知
├─────────────────────────────────────┤
│  BroadcastReceiver (WiFi 狀態)       │  ← CONNECTIVITY_CHANGE / WIFI_STATE_CHANGED
├─────────────────────────────────────┤
│  DownloadManager / WorkManager       │  ← 可靠下載、支援斷點續傳
├─────────────────────────────────────┤
│  MediaPlayer / ExoPlayer             │  ← 播放完成回調
├─────────────────────────────────────┤
│  File 清理邏輯                       │  ← 播放完成刪除快取
└─────────────────────────────────────┘

關鍵實作步驟

1. Manifest 權限與組件宣告

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

<service android:name=".VideoDownloadService"
    android:foregroundServiceType="dataSync" />

<receiver android:name=".WifiStateReceiver" android:exported="true">
    <intent-filter>
        <action android:name="android.net.wifi.STATE_CHANGE" />
        <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
    </intent-filter>
</receiver>

2. WiFi 狀態接收器

public class WifiStateReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action) ||
            ConnectivityManager.CONNECTIVITY_ACTION.equals(action)) {
            
            ConnectivityManager cm = (ConnectivityManager) 
                context.getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo wifi = cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
            
            if (wifi != null && wifi.isConnected()) {
                // 啟動前台服務開始下載
                Intent serviceIntent = new Intent(context, VideoDownloadService.class);
                ContextCompat.startForegroundService(context, serviceIntent);
            }
        }
    }
}

3. 前台下載服務 (使用 WorkManager 更現代)

public class VideoDownloadService extends Service {
    private static final String[] VIDEO_URLS = {
        "https://example.com/video1.mp4",
        "https://example.com/video2.mp4", 
        "https://example.com/video3.mp4"
    };
    
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // 建立前台通知
        Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
            .setContentTitle("視頻預載中")
            .setContentText("正在下載 3 支視頻...")
            .setSmallIcon(R.drawable.ic_download)
            .setProgress(3, 0, false)
            .build();
        startForeground(1, notification);
        
        // 使用 WorkManager 可靠下載
        downloadVideos();
        return START_NOT_STICKY;
    }
    
    private void downloadVideos() {
        for (int i = 0; i < VIDEO_URLS.length; i++) {
            final int index = i;
            WorkRequest request = new OneTimeWorkRequest.Builder(VideoDownloadWorker.class)
                .setInputData(new Data.Builder()
                    .putString("url", VIDEO_URLS[i])
                    .putInt("index", i)
                    .build())
                .build();
            WorkManager.getInstance(this).enqueue(request);
        }
    }
}

4. Worker 執行下載與播放後清理

public class VideoDownloadWorker extends Worker {
    @NonNull
    @Override
    public Result doWork() {
        String url = getInputData().getString("url");
        int index = getInputData().getInt("index", 0);
        
        File dest = new File(getApplicationContext().getCacheDir(), "video_" + index + ".mp4");
        try (InputStream in = new URL(url).openStream();
             FileOutputStream out = new FileOutputStream(dest)) {
            byte[] buffer = new byte[8192];
            int len;
            while ((len = in.read(buffer)) > 0) out.write(buffer, 0, len);
        } catch (IOException e) {
            return Result.retry();
        }
        
        // 更新通知進度
        // ...
        return Result.success();
    }
}

5. 播放完成刪除

// 播放器完成監聽
player.setOnCompletionListener(mp -> {
    File videoFile = new File(getCacheDir(), "video_" + currentIndex + ".mp4");
    if (videoFile.exists()) videoFile.delete();
});

Android 版本適配要點

版本關鍵變更應對
Android 8.0+背景執行限制Foreground Service + Notification Channel
Android 10+Scoped Storage使用 getCacheDir() 或 MediaStore
Android 12+精確鬧鐘/前台服務類型宣告 foregroundServiceType="dataSync"

替代方案:WorkManager 純方案 (無 Service)

// 直接用 WorkManager 監聽網路約束
Constraints constraints = new Constraints.Builder()
    .setRequiredNetworkType(NetworkType.UNMETERED) // WiFi
    .build();

PeriodicWorkRequest work = new PeriodicWorkRequest.Builder(
    VideoSyncWorker.class, 15, TimeUnit.MINUTES)
    .setConstraints(constraints)
    .build();
WorkManager.getInstance(context).enqueueUniquePeriodicWork(
    "video_sync", ExistingPeriodicWorkPolicy.KEEP, work);
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved