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