From 81ab643d2bf17b7ac5c70efa6f33e0737969cf85 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Fri, 4 Aug 2017 12:24:18 -0500 Subject: [PATCH] ProfileList: Convert to a fragment This is required for a future two-fragment tablet layout, and simplifies the code a bit since the profile detail (view/edit) will be implemented as fragments anyway. Signed-off-by: Jason A. Donenfeld --- app/src/main/AndroidManifest.xml | 2 +- ...ListActivity.java => ProfileActivity.java} | 57 ++++++++------ .../android/ProfileListFragment.java | 76 +++++++++++++++++++ .../android/ServiceConnectionListener.java | 11 +++ app/src/main/res/layout/profile_activity.xml | 6 ++ ...activity.xml => profile_list_fragment.xml} | 0 .../res/menu/{profile_list.xml => main.xml} | 0 7 files changed, 127 insertions(+), 25 deletions(-) rename app/src/main/java/com/wireguard/android/{ProfileListActivity.java => ProfileActivity.java} (61%) create mode 100644 app/src/main/java/com/wireguard/android/ProfileListFragment.java create mode 100644 app/src/main/java/com/wireguard/android/ServiceConnectionListener.java create mode 100644 app/src/main/res/layout/profile_activity.xml rename app/src/main/res/layout/{profile_list_activity.xml => profile_list_fragment.xml} (100%) rename app/src/main/res/menu/{profile_list.xml => main.xml} (100%) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2c02aa9..e585fe1 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -12,7 +12,7 @@ android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@android:style/Theme.Material.Light.DarkActionBar"> - + diff --git a/app/src/main/java/com/wireguard/android/ProfileListActivity.java b/app/src/main/java/com/wireguard/android/ProfileActivity.java similarity index 61% rename from app/src/main/java/com/wireguard/android/ProfileListActivity.java rename to app/src/main/java/com/wireguard/android/ProfileActivity.java index 6114cf1..5daaf54 100644 --- a/app/src/main/java/com/wireguard/android/ProfileListActivity.java +++ b/app/src/main/java/com/wireguard/android/ProfileActivity.java @@ -5,49 +5,45 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; -import android.databinding.DataBindingUtil; import android.os.Bundle; import android.os.IBinder; import android.view.Menu; import android.view.MenuItem; -import android.view.View; -import android.widget.AdapterView; -import android.widget.ListView; -import com.wireguard.android.databinding.ProfileListActivityBinding; import com.wireguard.config.Profile; -public class ProfileListActivity extends Activity { +import java.util.ArrayList; +import java.util.List; + +/** + * Activity that allows creating/viewing/editing/deleting WireGuard profiles. + */ + +public class ProfileActivity extends Activity { private final ServiceConnection connection = new ProfileServiceConnection(); - private ProfileListActivityBinding binding; + private final List listeners = new ArrayList<>(); private ProfileServiceInterface service; + public void addServiceConnectionListener(ServiceConnectionListener listener) { + listeners.add(listener); + } + + public ProfileServiceInterface getService() { + return service; + } + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - binding = DataBindingUtil.setContentView(this, R.layout.profile_list_activity); + setContentView(R.layout.profile_activity); // Ensure the long-running service is started. This only needs to happen once. Intent intent = new Intent(this, ProfileService.class); startService(intent); - - ListView listView = findViewById(R.id.profile_list); - listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { - @Override - public void onItemClick(AdapterView parent, View view, int position, long id) { - Profile profile = (Profile) parent.getItemAtPosition(position); - if (profile == null || service == null) - return; - if (profile.getIsConnected()) - service.disconnectProfile(profile); - else - service.connectProfile(profile); - } - }); } @Override public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.profile_list, menu); + getMenuInflater().inflate(R.menu.main, menu); return true; } @@ -55,6 +51,10 @@ public class ProfileListActivity extends Activity { } + public void onProfileSelected(Profile profile) { + + } + @Override public void onStart() { super.onStart(); @@ -67,20 +67,29 @@ public class ProfileListActivity extends Activity { super.onStop(); if (service != null) { unbindService(connection); + for (ServiceConnectionListener listener : listeners) + listener.onServiceDisconnected(); service = null; } } + public void removeServiceConnectionListener(ServiceConnectionListener listener) { + listeners.remove(listener); + } + private class ProfileServiceConnection implements ServiceConnection { @Override public void onServiceConnected(ComponentName component, IBinder binder) { service = (ProfileServiceInterface) binder; - binding.setProfiles(service.getProfiles()); + for (ServiceConnectionListener listener : listeners) + listener.onServiceConnected(service); } @Override public void onServiceDisconnected(ComponentName component) { // This function is only called when the service crashes or goes away unexpectedly. + for (ServiceConnectionListener listener : listeners) + listener.onServiceDisconnected(); service = null; } } diff --git a/app/src/main/java/com/wireguard/android/ProfileListFragment.java b/app/src/main/java/com/wireguard/android/ProfileListFragment.java new file mode 100644 index 0000000..1dfa9b7 --- /dev/null +++ b/app/src/main/java/com/wireguard/android/ProfileListFragment.java @@ -0,0 +1,76 @@ +package com.wireguard.android; + +import android.app.Fragment; +import android.content.Context; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ListView; + +import com.wireguard.android.databinding.ProfileListFragmentBinding; +import com.wireguard.config.Profile; + +/** + * Fragment containing the list of available WireGuard profiles. Must be part of a ProfileActivity. + */ + +public class ProfileListFragment extends Fragment implements ServiceConnectionListener { + private ProfileActivity activity; + private ProfileListFragmentBinding binding; + private ProfileServiceInterface service; + + @Override + public void onAttach(Context context) { + super.onAttach(context); + activity = (ProfileActivity) context; + activity.addServiceConnectionListener(this); + service = activity.getService(); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) { + binding = ProfileListFragmentBinding.inflate(inflater, parent, false); + final ListView listView = (ListView) binding.getRoot(); + listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + final Profile profile = (Profile) parent.getItemAtPosition(position); + ((ProfileActivity) getActivity()).onProfileSelected(profile); + } + }); + listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { + @Override + public boolean onItemLongClick(AdapterView parent, View view, int position, + long id) { + final Profile profile = (Profile) parent.getItemAtPosition(position); + if (profile == null || service == null) + return false; + if (profile.getIsConnected()) + service.disconnectProfile(profile); + else + service.connectProfile(profile); + return true; + } + }); + return binding.getRoot(); + } + + @Override + public void onDetach() { + super.onDetach(); + activity.removeServiceConnectionListener(this); + } + + @Override + public void onServiceConnected(ProfileServiceInterface service) { + this.service = service; + binding.setProfiles(service.getProfiles()); + } + + @Override + public void onServiceDisconnected() { + service = null; + } +} diff --git a/app/src/main/java/com/wireguard/android/ServiceConnectionListener.java b/app/src/main/java/com/wireguard/android/ServiceConnectionListener.java new file mode 100644 index 0000000..5f3c8d0 --- /dev/null +++ b/app/src/main/java/com/wireguard/android/ServiceConnectionListener.java @@ -0,0 +1,11 @@ +package com.wireguard.android; + +/** + * Interface for fragments that need notification about connection changes to the ProfileService. + */ + +interface ServiceConnectionListener { + void onServiceConnected(ProfileServiceInterface service); + + void onServiceDisconnected(); +} diff --git a/app/src/main/res/layout/profile_activity.xml b/app/src/main/res/layout/profile_activity.xml new file mode 100644 index 0000000..e408985 --- /dev/null +++ b/app/src/main/res/layout/profile_activity.xml @@ -0,0 +1,6 @@ + + diff --git a/app/src/main/res/layout/profile_list_activity.xml b/app/src/main/res/layout/profile_list_fragment.xml similarity index 100% rename from app/src/main/res/layout/profile_list_activity.xml rename to app/src/main/res/layout/profile_list_fragment.xml diff --git a/app/src/main/res/menu/profile_list.xml b/app/src/main/res/menu/main.xml similarity index 100% rename from app/src/main/res/menu/profile_list.xml rename to app/src/main/res/menu/main.xml