From d91fbe7b0efe0d844ba82cd6b3dbd2d0caee58d3 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Thu, 16 May 2019 14:07:00 +0200 Subject: [PATCH] rework swap startup putting SwapService first SwapService is the thing that needs to be always running, and the last thing killed. So it should start first, and stop last. So now, the user clicking the button starts SwapService, which starts SwapWorkflowActivity. This also eliminatings the "Loading" screen in favor of just showing the StartSwapView with various inline progress indicators. --- .../fdroid/fdroid/localrepo/SwapService.java | 29 +++++++-- .../org/fdroid/fdroid/localrepo/SwapView.java | 2 +- .../fdroid/views/main/NearbyViewBinder.java | 4 +- .../views/swap/SwapWorkflowActivity.java | 64 +++---------------- .../full/res/layout/swap_initial_loading.xml | 29 --------- app/src/main/res/values/strings.xml | 1 + 6 files changed, 36 insertions(+), 93 deletions(-) delete mode 100644 app/src/full/res/layout/swap_initial_loading.xml diff --git a/app/src/full/java/org/fdroid/fdroid/localrepo/SwapService.java b/app/src/full/java/org/fdroid/fdroid/localrepo/SwapService.java index df5a9f397..78a7b7f3d 100644 --- a/app/src/full/java/org/fdroid/fdroid/localrepo/SwapService.java +++ b/app/src/full/java/org/fdroid/fdroid/localrepo/SwapService.java @@ -14,6 +14,7 @@ import android.content.SharedPreferences; import android.net.Uri; import android.net.wifi.WifiManager; import android.os.AsyncTask; +import android.os.Build; import android.os.IBinder; import android.support.annotation.NonNull; import android.support.annotation.Nullable; @@ -72,10 +73,20 @@ public class SwapService extends Service { @NonNull private final Set appsToSwap = new HashSet<>(); + private static LocalBroadcastManager localBroadcastManager; private static SharedPreferences swapPreferences; private static BluetoothAdapter bluetoothAdapter; private static WifiManager wifiManager; + public static void start(Context context) { + Intent intent = new Intent(context, SwapService.class); + if (Build.VERSION.SDK_INT < 26) { + context.startService(intent); + } else { + context.startForegroundService(intent); + } + } + public static void stop(Context context) { Intent intent = new Intent(context, SwapService.class); context.stopService(intent); @@ -413,12 +424,8 @@ public class SwapService extends Service { public void onCreate() { super.onCreate(); - - Utils.debugLog(TAG, "Creating swap service."); startForeground(NOTIFICATION, createNotification()); - - deleteAllSwapRepos(); - + localBroadcastManager = LocalBroadcastManager.getInstance(this); swapPreferences = getSharedPreferences(SHARED_PREFERENCES, Context.MODE_PRIVATE); bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); @@ -455,9 +462,16 @@ public class SwapService extends Service { } } + /** + * This is for setting things up for when the {@code SwapService} was + * started by the user clicking on the initial start button. The things + * that must be run always on start-up go in {@link #onCreate()}. + */ @Override public int onStartCommand(Intent intent, int flags, int startId) { - return START_STICKY; + deleteAllSwapRepos(); + startActivity(new Intent(this, SwapWorkflowActivity.class)); + return START_NOT_STICKY; } @Override @@ -525,7 +539,6 @@ public class SwapService extends Service { } private void initTimer() { - // TODO replace by Android scheduler if (timer != null) { Utils.debugLog(TAG, "Cancelling existing timeout timer so timeout can be reset."); timer.cancel(); @@ -537,6 +550,8 @@ public class SwapService extends Service { @Override public void run() { Utils.debugLog(TAG, "Disabling swap because " + TIMEOUT + "ms passed."); + String msg = getString(R.string.swap_toast_closing_nearby_after_timeout); + Utils.showToastFromService(SwapService.this, msg, android.widget.Toast.LENGTH_LONG); stop(SwapService.this); } }, TIMEOUT); diff --git a/app/src/full/java/org/fdroid/fdroid/localrepo/SwapView.java b/app/src/full/java/org/fdroid/fdroid/localrepo/SwapView.java index 9404ad14f..668827827 100644 --- a/app/src/full/java/org/fdroid/fdroid/localrepo/SwapView.java +++ b/app/src/full/java/org/fdroid/fdroid/localrepo/SwapView.java @@ -21,7 +21,7 @@ public class SwapView extends RelativeLayout { public final int toolbarColor; public final String toolbarTitle; - private int layoutResId; + private int layoutResId = -1; protected String currentFilterString; diff --git a/app/src/full/java/org/fdroid/fdroid/views/main/NearbyViewBinder.java b/app/src/full/java/org/fdroid/fdroid/views/main/NearbyViewBinder.java index 26b3f56b2..96e33b552 100644 --- a/app/src/full/java/org/fdroid/fdroid/views/main/NearbyViewBinder.java +++ b/app/src/full/java/org/fdroid/fdroid/views/main/NearbyViewBinder.java @@ -18,8 +18,8 @@ import android.widget.TextView; import android.widget.Toast; import org.fdroid.fdroid.R; import org.fdroid.fdroid.localrepo.SDCardScannerService; +import org.fdroid.fdroid.localrepo.SwapService; import org.fdroid.fdroid.localrepo.TreeUriScannerIntentService; -import org.fdroid.fdroid.views.swap.SwapWorkflowActivity; import java.io.File; @@ -75,7 +75,7 @@ class NearbyViewBinder { ActivityCompat.requestPermissions(activity, new String[]{coarseLocation}, MainActivity.REQUEST_LOCATION_PERMISSIONS); } else { - activity.startActivity(new Intent(activity, SwapWorkflowActivity.class)); + SwapService.start(activity); } } }); diff --git a/app/src/full/java/org/fdroid/fdroid/views/swap/SwapWorkflowActivity.java b/app/src/full/java/org/fdroid/fdroid/views/swap/SwapWorkflowActivity.java index 74dc5792e..373477115 100644 --- a/app/src/full/java/org/fdroid/fdroid/views/swap/SwapWorkflowActivity.java +++ b/app/src/full/java/org/fdroid/fdroid/views/swap/SwapWorkflowActivity.java @@ -102,7 +102,6 @@ public class SwapWorkflowActivity extends AppCompatActivity { private ViewGroup container; - private static final int CONNECT_TO_SWAP = 1; private static final int REQUEST_BLUETOOTH_ENABLE_FOR_SWAP = 2; private static final int REQUEST_BLUETOOTH_DISCOVERABLE = 3; private static final int REQUEST_BLUETOOTH_ENABLE_FOR_SEND = 4; @@ -134,17 +133,14 @@ public class SwapWorkflowActivity extends AppCompatActivity { private final ServiceConnection serviceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName className, IBinder binder) { - Utils.debugLog(TAG, "Swap service connected. Will hold onto it so we can talk to it regularly."); service = ((SwapService.Binder) binder).getService(); showRelevantView(); } - // TODO: What causes this? Do we need to stop swapping explicitly when this is invoked? @Override public void onServiceDisconnected(ComponentName className) { - Utils.debugLog(TAG, "Swap service disconnected"); + finish(); service = null; - // TODO: What to do about the UI in this instance? } }; @@ -153,10 +149,6 @@ public class SwapWorkflowActivity extends AppCompatActivity { @NonNull public SwapService getService() { - if (service == null) { - // *Slightly* more informative than a null-pointer error that would otherwise happen. - throw new IllegalStateException("Trying to access swap service before it was initialized."); - } return service; } @@ -178,9 +170,6 @@ public class SwapWorkflowActivity extends AppCompatActivity { case R.layout.swap_connecting: nextStep = R.layout.swap_select_apps; break; - case R.layout.swap_initial_loading: - nextStep = R.layout.swap_join_wifi; - break; case R.layout.swap_join_wifi: nextStep = STEP_INTRO; break; @@ -215,12 +204,12 @@ public class SwapWorkflowActivity extends AppCompatActivity { ((FDroidApp) getApplication()).setSecureWindow(this); super.onCreate(savedInstanceState); - // The server should not be doing anything or occupying any (noticeable) resources - // until we actually ask it to enable swapping. Therefore, we will start it nice and - // early so we don't have to wait until it is connected later. - Intent service = new Intent(this, SwapService.class); - if (bindService(service, serviceConnection, Context.BIND_AUTO_CREATE)) { - startService(service); + currentView = new SwapView(this); // dummy placeholder to avoid NullPointerExceptions; + + if (!bindService(new Intent(this, SwapService.class), serviceConnection, + BIND_ABOVE_CLIENT | BIND_IMPORTANT)) { + Toast.makeText(this, "ERROR: cannot bind to SwapService!", Toast.LENGTH_LONG).show(); + finish(); } setContentView(R.layout.swap_activity); @@ -357,7 +346,6 @@ public class SwapWorkflowActivity extends AppCompatActivity { new IntentFilter(UpdateService.LOCAL_ACTION_STATUS)); checkIncomingIntent(); - showRelevantView(); } @Override @@ -446,15 +434,6 @@ public class SwapWorkflowActivity extends AppCompatActivity { } private void showRelevantView() { - showRelevantView(false); - } - - private void showRelevantView(boolean forceReload) { - - if (service == null) { - inflateSwapView(R.layout.swap_initial_loading); - return; - } if (confirmSwapConfig != null) { inflateSwapView(R.layout.swap_confirm_receive); @@ -463,12 +442,6 @@ public class SwapWorkflowActivity extends AppCompatActivity { return; } - if (!forceReload - && (container.getVisibility() == View.GONE || currentView != null && currentView.getLayoutResId() == currentSwapViewLayoutRes)) { - // Already showing the correct step, so don't bother changing anything. - return; - } - switch (currentSwapViewLayoutRes) { case STEP_INTRO: showIntro(); @@ -491,20 +464,12 @@ public class SwapWorkflowActivity extends AppCompatActivity { return service; } - public SwapView inflateSwapView(@LayoutRes int viewRes) { + public void inflateSwapView(@LayoutRes int viewRes) { container.removeAllViews(); View view = ((LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE)).inflate(viewRes, container, false); currentView = (SwapView) view; currentView.setLayoutResId(viewRes); - - // Don't actually set the step to STEP_INITIAL_LOADING, as we are going to use this view - // purely as a placeholder for _whatever view is meant to be shown_. - if (currentView.getLayoutResId() != R.layout.swap_initial_loading) { - if (service == null) { - throw new IllegalStateException("We are not in the STEP_INITIAL_LOADING state, but the service is not ready."); - } - currentSwapViewLayoutRes = currentView.getLayoutResId(); - } + currentSwapViewLayoutRes = viewRes; toolbar.setBackgroundColor(currentView.getToolbarColour()); toolbar.setTitle(currentView.getToolbarTitle()); @@ -534,8 +499,6 @@ public class SwapWorkflowActivity extends AppCompatActivity { setUpConnectingView(); break; } - - return currentView; } private void onToolbarCancel() { @@ -734,8 +697,6 @@ public class SwapWorkflowActivity extends AppCompatActivity { Toast.makeText(this, R.string.swap_qr_isnt_for_swap, Toast.LENGTH_SHORT).show(); } } - } else if (requestCode == CONNECT_TO_SWAP && resultCode == Activity.RESULT_OK) { - finish(); } else if (requestCode == REQUEST_WRITE_SETTINGS_PERMISSION) { if (Build.VERSION.SDK_INT >= 23 && Settings.System.canWrite(this)) { setupWifiAP(); @@ -809,11 +770,6 @@ public class SwapWorkflowActivity extends AppCompatActivity { intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, discoverableTimeout); startActivityForResult(intent, REQUEST_BLUETOOTH_DISCOVERABLE); } - - if (service == null) { - throw new IllegalStateException("Can't start Bluetooth swap because service is null for some strange reason."); - } - service.getBluetoothSwap().startInBackground(); // TODO replace with Intent to SwapService } @@ -897,7 +853,7 @@ public class SwapWorkflowActivity extends AppCompatActivity { case Installer.ACTION_INSTALL_COMPLETE: localBroadcastManager.unregisterReceiver(this); - showRelevantView(true); + showRelevantView(); break; case Installer.ACTION_INSTALL_INTERRUPTED: localBroadcastManager.unregisterReceiver(this); diff --git a/app/src/full/res/layout/swap_initial_loading.xml b/app/src/full/res/layout/swap_initial_loading.xml deleted file mode 100644 index 502420b66..000000000 --- a/app/src/full/res/layout/swap_initial_loading.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2ded2d573..40ee0ee11 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -517,6 +517,7 @@ This often occurs with apps installed via Google Play or other sources, if they Invalid URL for swapping: %1$s Wi-Fi Hotspot enabled Could not enable Wi-Fi Hotspot! + Nearby closed since it was idle. needs access to Do you want to install an update