ProfileService: Create it and move profile loading
The long-running service is needed for keeping track of which profiles are enabled, for showing notifications, and for the tile service to use. Since it has to know which profiles exist anyway, moving the main ObservableList there avoids some code duplication. It ensures the list is only loaded once, so it cannot get out of sync. It also makes the ProfileList activity load faster, because it doesn't have to wait for file I/O; and it provides a canonical place for storing the Profile objects so they are accessible everywhere, instead of having to look them up by name. This does present some challenges with leaking activities, because all listeners must be removed from the profiles list (and its contents) when an activity is stopped. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
package com.wireguard.android;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Intent;
|
||||
import android.databinding.ObservableArrayList;
|
||||
import android.databinding.ObservableList;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import android.util.Log;
|
||||
|
||||
import com.wireguard.config.Profile;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Service that handles profile state coordination and all background processing for the app.
|
||||
*/
|
||||
|
||||
public class ProfileService extends Service {
|
||||
private static final String TAG = "ProfileService";
|
||||
|
||||
private final IBinder binder = new ProfileServiceBinder();
|
||||
private final ObservableList<Profile> profiles = new ObservableArrayList<>();
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return binder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
new ProfileLoader().execute(getFilesDir().listFiles());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
return START_STICKY;
|
||||
}
|
||||
|
||||
private class ProfileLoader extends AsyncTask<File, Void, List<Profile>> {
|
||||
@Override
|
||||
protected List<Profile> doInBackground(File... files) {
|
||||
final List<Profile> loadedProfiles = new LinkedList<>();
|
||||
for (File file : files) {
|
||||
final String fileName = file.getName();
|
||||
final String profileName = fileName.substring(0, fileName.length() - 5);
|
||||
final Profile profile = new Profile(profileName);
|
||||
try {
|
||||
profile.parseFrom(openFileInput(fileName));
|
||||
loadedProfiles.add(profile);
|
||||
} catch (IOException e) {
|
||||
Log.w(TAG, "Failed to load profile from " + fileName, e);
|
||||
}
|
||||
if (isCancelled())
|
||||
break;
|
||||
}
|
||||
return loadedProfiles;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(List<Profile> loadedProfiles) {
|
||||
profiles.addAll(loadedProfiles);
|
||||
}
|
||||
}
|
||||
|
||||
private class ProfileServiceBinder extends Binder implements ProfileServiceInterface {
|
||||
public ObservableList<Profile> getProfiles() {
|
||||
return profiles;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user