From: Keith Packard Date: Sat, 16 Oct 2021 22:48:22 +0000 (-0700) Subject: altosdroid: Fix tab updates on Android 11 after rotate X-Git-Tag: 1.9.10.4~67^2^2~1 X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=commitdiff_plain;h=a1b7357aa5bca6afb588b0bfb5cfe72c4d0255ef altosdroid: Fix tab updates on Android 11 after rotate Android 11 appears to have "optimized" application rotation by regenerating fragments automatically. This means the tab fragments aren't getting created by TabsAdapter.getItem, so that code didn't know about them, which caused it to not know which tab was active so all of the application state wasn't getting updated in the tabs after rotation. Fix this by telling TabsAdapter about fragments that are already created -- altosdroid hears about them in the registerTab hook. Signed-off-by: Keith Packard --- diff --git a/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosDebug.java b/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosDebug.java index 469ec50a..b2bfeb21 100644 --- a/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosDebug.java +++ b/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosDebug.java @@ -56,11 +56,14 @@ public class AltosDebug { Log.e(TAG, String.format(format, arguments)); } + static void trace(String format, Object ... arguments) { + error(format, arguments); + for (StackTraceElement el : Thread.currentThread().getStackTrace()) + Log.e(TAG, "\t" + el.toString() + "\n"); + } + static void check_ui(String format, Object ... arguments) { - if (Looper.myLooper() == Looper.getMainLooper()) { - Log.e(TAG, String.format("ON UI THREAD " + format, arguments)); - for (StackTraceElement el : Thread.currentThread().getStackTrace()) - Log.e(TAG, "\t" + el.toString() + "\n"); - } + if (Looper.myLooper() == Looper.getMainLooper()) + trace("ON UI THREAD " + format, arguments); } } diff --git a/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosDroid.java b/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosDroid.java index 1fcb0a47..05a023ac 100644 --- a/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosDroid.java +++ b/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosDroid.java @@ -199,15 +199,16 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener, } }; - private ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { + AltosDebug.debug("onServiceConnected\n"); mService = new Messenger(service); try { Message msg = Message.obtain(null, TelemetryService.MSG_REGISTER_CLIENT); msg.replyTo = mMessenger; mService.send(msg); } catch (RemoteException e) { + AltosDebug.debug("attempt to register telemetry service client failed\n"); // In this case the service has crashed before we could even do anything with it } if (pending_usb_device != null) { @@ -220,17 +221,20 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener, } public void onServiceDisconnected(ComponentName className) { + AltosDebug.debug("onServiceDisconnected\n"); // This is called when the connection with the service has been unexpectedly disconnected - process crashed. mService = null; } }; void doBindService() { + AltosDebug.debug("doBindService\n"); bindService(new Intent(this, TelemetryService.class), mConnection, Context.BIND_AUTO_CREATE); mIsBound = true; } void doUnbindService() { + AltosDebug.debug("doUnbindService\n"); if (mIsBound) { // If we have received the service, and hence registered with it, then now is the time to unregister. if (mService != null) { @@ -248,6 +252,13 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener, } } + public AltosDroidTab findTab(String name) { + for (AltosDroidTab mTab : mTabs) + if (name.equals(mTab.tab_name())) + return mTab; + return null; + } + public void registerTab(AltosDroidTab mTab) { mTabs.add(mTab); } @@ -441,6 +452,12 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener, void update_ui(TelemetryState telem_state, AltosState state, boolean quiet) { + AltosDebug.debug("update_ui telem %b state %b quiet %b saved_state %b\n", + telem_state != null, + state != null, + quiet, + saved_state != null); + this.state = state; int prev_state = AltosLib.ao_flight_invalid; @@ -530,8 +547,11 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener, saved_state = new SavedState(state); } - for (AltosDroidTab mTab : mTabs) + for (AltosDroidTab mTab : mTabs) { + AltosDebug.debug("mTab %s current %s\n", + mTab, mTabsAdapter.currentItem()); mTab.update_ui(telem_state, state, from_receiver, location, mTab == mTabsAdapter.currentItem()); + } if (mAltosVoice != null && mTabsAdapter.currentItem() != null) mAltosVoice.tell(telem_state, state, from_receiver, location, (AltosDroidTab) mTabsAdapter.currentItem(), quiet); @@ -594,13 +614,13 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener, @Override public void onCreate(Bundle savedInstanceState) { + AltosDebug.init(this); + AltosDebug.debug("+++ ON CREATE +++"); + // Initialise preferences AltosDroidPreferences.init(this); setTheme(themes[AltosDroidPreferences.font_size()]); super.onCreate(savedInstanceState); - AltosDebug.init(this); - AltosDebug.debug("+++ ON CREATE +++"); - fm = getSupportFragmentManager(); @@ -616,10 +636,10 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener, mTabsAdapter = new TabsAdapter(this, mTabHost, mViewPager); - mTabsAdapter.addTab(mTabHost.newTabSpec(tab_pad_name).setIndicator(create_tab_view("Pad")), TabPad.class, null); - mTabsAdapter.addTab(mTabHost.newTabSpec(tab_flight_name).setIndicator(create_tab_view("Flight")), TabFlight.class, null); - mTabsAdapter.addTab(mTabHost.newTabSpec(tab_recover_name).setIndicator(create_tab_view("Recover")), TabRecover.class, null); - mTabsAdapter.addTab(mTabHost.newTabSpec(tab_map_name).setIndicator(create_tab_view("Map")), TabMap.class, null); + mTabsAdapter.addTab(mTabHost.newTabSpec(tab_pad_name).setIndicator(create_tab_view("Pad")), TabPad.class, null, findTab(tab_pad_name)); + mTabsAdapter.addTab(mTabHost.newTabSpec(tab_flight_name).setIndicator(create_tab_view("Flight")), TabFlight.class, null, findTab(tab_flight_name)); + mTabsAdapter.addTab(mTabHost.newTabSpec(tab_recover_name).setIndicator(create_tab_view("Recover")), TabRecover.class, null, findTab(tab_recover_name)); + mTabsAdapter.addTab(mTabHost.newTabSpec(tab_map_name).setIndicator(create_tab_view("Map")), TabMap.class, null, findTab(tab_map_name)); // Display the Version mVersion = (TextView) findViewById(R.id.version); @@ -740,11 +760,11 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener, @Override public void onNewIntent(Intent intent) { super.onNewIntent(intent); - AltosDebug.debug("onNewIntent"); + AltosDebug.debug("+ ON NEW INTENT +"); noticeIntent(intent); } - private void enable_location_updates() { + private void enable_location_updates(boolean do_update) { // Listen for GPS and Network position updates LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE); @@ -765,7 +785,8 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener, AltosDebug.debug("Failed to get GPS updates\n"); } - update_ui(telemetry_state, state, true); + if (do_update) + update_ui(telemetry_state, state, true); } static final int MY_PERMISSION_REQUEST = 1001; @@ -789,7 +810,7 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener, if (grantResults[i] == PackageManager.PERMISSION_GRANTED) { if (permissions[i].equals(Manifest.permission.ACCESS_FINE_LOCATION)) { have_location_permission = true; - enable_location_updates(); + enable_location_updates(true); if (map_online != null) map_online.position_permission(); } @@ -803,9 +824,10 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener, @Override public void onResume() { - super.onResume(); AltosDebug.debug("+ ON RESUME +"); + super.onResume(); + if (!asked_permission) { asked_permission = true; if (ActivityCompat.checkSelfPermission(this, @@ -833,13 +855,15 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener, } } if (have_location_permission) - enable_location_updates(); + enable_location_updates(false); } @Override public void onPause() { - super.onPause(); AltosDebug.debug("- ON PAUSE -"); + + super.onPause(); + // Stop listening for location updates if (have_location_permission) ((LocationManager) getSystemService(Context.LOCATION_SERVICE)).removeUpdates(this); @@ -847,15 +871,19 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener, @Override public void onStop() { - super.onStop(); AltosDebug.debug("-- ON STOP --"); + + super.onStop(); } @Override public void onDestroy() { - super.onDestroy(); AltosDebug.debug("--- ON DESTROY ---"); + super.onDestroy(); + + saved_state = null; + doUnbindService(); if (mAltosVoice != null) { mAltosVoice.stop(); diff --git a/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosDroidTab.java b/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosDroidTab.java index e6923c37..f79c88e6 100644 --- a/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosDroidTab.java +++ b/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosDroidTab.java @@ -68,6 +68,7 @@ public abstract class AltosDroidTab extends Fragment implements AltosUnitsListen @Override public void onAttach(Context context) { + AltosDebug.debug("tab onAttach %s %s\n", tab_name(), this); super.onAttach(context); altos_droid = (AltosDroid) context; altos_droid.registerTab(this); @@ -75,6 +76,7 @@ public abstract class AltosDroidTab extends Fragment implements AltosUnitsListen @Override public void onDetach() { + AltosDebug.debug("tab onDetach %s %s\n", tab_name(), this); super.onDetach(); altos_droid.unregisterTab(this); altos_droid = null; @@ -83,13 +85,14 @@ public abstract class AltosDroidTab extends Fragment implements AltosUnitsListen @Override public void onResume() { super.onResume(); - AltosDebug.debug("onResume tab %s\n", tab_name()); + AltosDebug.debug("onResume tab %s %s\n", tab_name(), this); set_visible(true); } public void update_ui(TelemetryState telem_state, AltosState state, AltosGreatCircle from_receiver, Location receiver, boolean is_current) { + AltosDebug.debug("update_ui %s is_current %b\n", tab_name(), is_current); last_telem_state = telem_state; last_state = state; last_from_receiver = from_receiver; diff --git a/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/TabPad.java b/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/TabPad.java index 4a8b3f86..fd997612 100644 --- a/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/TabPad.java +++ b/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/TabPad.java @@ -67,6 +67,7 @@ public class TabPad extends AltosDroidTab { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + AltosDebug.debug("TabPad onCreateView\n"); View v = inflater.inflate(R.layout.tab_pad, container, false); battery_voltage_view = (TextView) v.findViewById(R.id.battery_voltage_value); battery_lights = new GoNoGoLights((ImageView) v.findViewById(R.id.battery_redled), @@ -157,12 +158,15 @@ public class TabPad extends AltosDroidTab { receiver_latitude_view = (TextView) v.findViewById(R.id.receiver_lat_value); receiver_longitude_view = (TextView) v.findViewById(R.id.receiver_lon_value); receiver_altitude_view = (TextView) v.findViewById(R.id.receiver_alt_value); - return v; + + AltosDebug.debug("TabPad onCreateView done battery_voltage_view %s\n", battery_voltage_view); + return v; } public String tab_name() { return AltosDroid.tab_pad_name; } public void show(TelemetryState telem_state, AltosState state, AltosGreatCircle from_receiver, Location receiver) { + AltosDebug.debug("pad show state %b bvv %s\n", state != null, battery_voltage_view); if (state != null) { battery_voltage_view.setText(AltosDroid.number("%1.2f V", state.battery_voltage)); battery_lights.set(state.battery_voltage >= AltosLib.ao_battery_good, state.battery_voltage == AltosLib.MISSING); @@ -244,8 +248,11 @@ public class TabPad extends AltosDroidTab { double altitude = AltosLib.MISSING; if (receiver.hasAltitude()) altitude = receiver.getAltitude(); - receiver_latitude_view.setText(AltosDroid.pos(receiver.getLatitude(), "N", "S")); - receiver_longitude_view.setText(AltosDroid.pos(receiver.getLongitude(), "E", "W")); + String lat_text = AltosDroid.pos(receiver.getLatitude(), "N", "S"); + String lon_text = AltosDroid.pos(receiver.getLongitude(), "E", "W"); + AltosDebug.debug("lat %s lon %s\n", lat_text, lon_text); + receiver_latitude_view.setText(lat_text); + receiver_longitude_view.setText(lon_text); set_value(receiver_altitude_view, AltosConvert.height, 1, altitude); } } diff --git a/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/TabsAdapter.java b/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/TabsAdapter.java index 23d365b4..0878c011 100644 --- a/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/TabsAdapter.java +++ b/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/TabsAdapter.java @@ -54,10 +54,11 @@ public class TabsAdapter extends FragmentPagerAdapter private final Bundle args; private Fragment fragment; - TabInfo(String _tag, Class _class, Bundle _args) { + TabInfo(String _tag, Class _class, Bundle _args, Fragment _fragment) { tag = _tag; clss = _class; args = _args; + fragment = _fragment; } } @@ -86,11 +87,11 @@ public class TabsAdapter extends FragmentPagerAdapter mViewPager.addOnPageChangeListener(this); } - public void addTab(TabHost.TabSpec tabSpec, Class clss, Bundle args) { + public void addTab(TabHost.TabSpec tabSpec, Class clss, Bundle args, Fragment fragment) { tabSpec.setContent(new DummyTabFactory(mContext)); String tag = tabSpec.getTag(); - TabInfo info = new TabInfo(tag, clss, args); + TabInfo info = new TabInfo(tag, clss, args, fragment); mTabs.add(info); mTabHost.addTab(tabSpec); notifyDataSetChanged(); @@ -105,7 +106,8 @@ public class TabsAdapter extends FragmentPagerAdapter public Fragment getItem(int position) { TabInfo info = mTabs.get(position); AltosDebug.debug("TabsAdapter.getItem(%d)", position); - info.fragment = Fragment.instantiate(mContext, info.clss.getName(), info.args); + if (info.fragment == null) + info.fragment = Fragment.instantiate(mContext, info.clss.getName(), info.args); return info.fragment; } @@ -121,15 +123,19 @@ public class TabsAdapter extends FragmentPagerAdapter AltosDroidTab cur_frag = (AltosDroidTab) mTabs.get(position).fragment; + AltosDebug.debug("TabsAdapter.onTabChanged(%s) = %d cur %s prev %s", tabId, position, cur_frag, prev_frag); + if (prev_frag != cur_frag) { if (prev_frag != null) { prev_frag.set_visible(false); } } - if (cur_frag != null) { + + /* This happens when the tab is selected before any of them + * have been created, like during rotation + */ + if (cur_frag != null) cur_frag.set_visible(true); - } - AltosDebug.debug("TabsAdapter.onTabChanged(%s) = %d", tabId, position); mViewPager.setCurrentItem(position); }