Permalink
Browse files

Mondo implementation of workaround for known Google Maps APIv2 OpenGL…

… crash.

https://code.google.com/p/gmaps-api-issues/issues/detail?id=5100#c34
No more than 1 map may be in the Resumed state at any time.
Implement and rewrite various fragment lifecycle events in MapHostingFragment and PageSlidingTabStripFragment to painstakingly uphold this invariant.
Include MapFragmentCounter to help debug this.
Force portrait mode on MainActivity to reduce incidences of configuration changes, which the app doesn't usually survive due to this crash.
Temporarily disable auto-zoom on start until implementation of the new Location Client introduced in GPS 6.5.87.
This solution is robust for now - rare crashes have been seen when coming back from long-term pauses (when the activity has been destroyed by the system and is being restored.) Keeping an eye on that for now.
  • Loading branch information...
aphexcx committed Jan 12, 2015
1 parent bddf2e8 commit 70bdc7a0db1708ab931a81f107b248298a1cfc39
@@ -6,7 +6,7 @@ buildscript {

dependencies {
classpath 'me.tatarka:gradle-retrolambda:2.4.0'
classpath 'io.fabric.tools:gradle:1.+'
classpath 'io.fabric.tools:gradle:1.14.4'
}
}
apply plugin: 'com.android.application'
@@ -40,16 +40,17 @@ android {

buildTypes {
release {
runProguard false
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
}

dependencies {
compile 'com.android.support:support-v4:21.0.0'
compile 'com.android.support:support-v4:21.0.3'
compile 'com.android.support:support-v13:20.0.0'
compile 'com.google.android.gms:play-services:6.1.11'
compile 'com.google.android.gms:play-services:6.5.87'
// compile 'com.google.android.gms:play-services-maps:6.5.87'

// compile 'com.astuetz:pagerslidingtabstrip:1.0.1'

@@ -61,6 +61,7 @@
<activity
android:name=".activities.MainActivity"
android:label="@string/app_name"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustPan"></activity>

<activity
@@ -4,6 +4,7 @@
import android.app.AlertDialog;
import android.app.FragmentTransaction;
import android.content.Intent;
import android.content.IntentSender;
import android.content.res.Configuration;
import android.location.Address;
import android.os.Bundle;
@@ -20,6 +21,8 @@
import android.widget.ArrayAdapter;
import android.widget.ListView;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.parse.GetCallback;
import com.parse.ParseException;
import com.parse.ParseQuery;
@@ -44,21 +47,15 @@
public class MainActivity extends Activity implements
RequestPickupFragment.PickUpDetailInteractionListener,
PickupRequestsFragment.PickupRequestDetailInteractionListener,
PickupRequestDetailFragment.PickupRequestConfirmedListener {
PickupRequestDetailFragment.PickupRequestConfirmedListener,
GoogleApiClient.OnConnectionFailedListener {
private static final int POSITION_DONATE = 0;
private static final int POSITION_VOLUNTEER = 1;
private static final int POSITION_PROFILE = 2;
private static final int POSITION_SIGN_OUT = 3;
// implements NavigationDrawerFragment.NavigationDrawerCallbacks {

/**
* Fragment managing the behaviors, interactions and presentation of the navigation drawer.
*/
// private NavigationDrawerFragment mNavigationDrawerFragment;
private final static int CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000;

/**
* Used to store the last screen title. For use in { #restoreActionBar()}.
*/
DrawerLayout mDrawerLayout;
ListView mDrawerList;
ActionBarDrawerToggle mDrawerToggle;
@@ -71,6 +68,7 @@
private PickupRequestDetailFragment pickupRequestDetailFragment;
private AlertDialog acceptPendingDialog;
private Intent mIntent;
private GoogleApiClient mGoogleApiClient;

@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -88,9 +86,11 @@ protected void onCreate(Bundle savedInstanceState) {
initializeFragments();
// mCurrentFragment = null;
mSelectedItem = 0;
selectItem(mSelectedItem);
// selectItem(mSelectedItem);
}


// GoogleApiClientManager.build(this);
//TODO: Open Navigation drawer on first launch to hint user that navigation drawer exists, per google UX design spec

}
@@ -105,7 +105,7 @@ public void onSaveInstanceState(Bundle outState) {
public void onRestoreInstanceState(Bundle inState) {
super.onRestoreInstanceState(inState);
mSelectedItem = inState.getInt("mSelectedItem");
selectItem(mSelectedItem);
// selectItem(mSelectedItem);
}

@Override
@@ -115,8 +115,13 @@ protected void onResume() {
//if the user resumed the app by entering through a Volunteer push notif, show dashboard
boolean isPushNotif = handlePushNotifResume();

if (!isPushNotif) {
if (isPushNotif) {
selectItem(POSITION_VOLUNTEER);
} else {
checkForPendingRequests();
selectItem(mSelectedItem);


}
}

@@ -139,7 +144,7 @@ private boolean handlePushNotifResume() {
mIntent.removeExtra("com.parse.Data");

//try setting us to the Volunteer fragment
selectItem(POSITION_VOLUNTEER);
// selectItem(POSITION_VOLUNTEER);
//move to dashboard duey
// VolunteerFragment volunteerFragment = (VolunteerFragment) getFragmentManager().findFragmentByTag("vol");
//0 means dashboard
@@ -328,9 +333,11 @@ private void selectItem(int position) {
switch (position) {
case POSITION_DONATE: //Donate
if (volunteerFragment != null) {
// volunteerFragment.onPause();
ft.hide(volunteerFragment);
}
if (profileFragment != null) {
// profileFragment.onPause();
ft.hide(profileFragment);
}

@@ -442,6 +449,30 @@ public void onPickupConfirmed(PickupRequest pickupRequest) {
}
}

@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
/* Google Play services can resolve some errors it detects. If the error
* has a resolution, try sending an Intent to start a Google Play
* services activity that can resolve error.
*/
if (connectionResult.hasResolution()) {
try {
// Start an Activity that tries to resolve the error
connectionResult.startResolutionForResult(this,
CONNECTION_FAILURE_RESOLUTION_REQUEST);
/* Thrown if Google Play services canceled the original
* PendingIntent */
} catch (IntentSender.SendIntentException e) {
// Log the error
e.printStackTrace();
}
} else {
// Toast.makeText(getActivity(),
// "Sorry. Location services not available to you", Toast.LENGTH_LONG).show();
}

}

// The click listener for ListView in the navigation drawer
private class DrawerItemClickListener implements
ListView.OnItemClickListener {
@@ -452,5 +483,4 @@ public void onItemClick(AdapterView<?> parent, View view, int position,
}
}


}
@@ -17,20 +17,17 @@

import java.lang.reflect.Field;

public class PageSlidingTabStripFragment extends Fragment {
public class PageSlidingTabStripFragment extends Fragment implements ViewPager.OnPageChangeListener {

public final String TAG = this.getClass().getSimpleName();
private ViewPager mViewPager;
private MyPagerAdapter mAdapter;
private int currentPosition = 0;

protected String[] getTitles() {
return new String[] {"Categories", "Home", "Top Paid", "Top Free"};
}

//this doesnt make sense, why not just instnatiate the fragment, why newinstance
// public static PageSlidingTabStripFragment newInstance() {
// return new PageSlidingTabStripFragment();
// }

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -49,15 +46,12 @@ public void onViewCreated(View view, Bundle savedInstanceState) {
PagerSlidingTabStrip tabStrip = (PagerSlidingTabStrip) view
.findViewById(R.id.tabs);
mViewPager = (ViewPager) view.findViewById(R.id.pager);
final MyPagerAdapter adapter = new MyPagerAdapter(getChildFragmentManager(), getTitles());
// viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
//
// });
mViewPager.setAdapter(adapter);
mAdapter = new MyPagerAdapter(getChildFragmentManager(), getTitles());
mViewPager.setAdapter(mAdapter);

// Determines how many pages can be offscreen before the viewpager starts destroying fragments it's hosting.
// http://stackoverflow.com/questions/11852604/why-is-my-fragment-oncreate-being-called-extensively-whenever-i-page-through-my
mViewPager.setOffscreenPageLimit(adapter.getCount() - 1);
mViewPager.setOffscreenPageLimit(mAdapter.getCount() - 1);

tabStrip.setShouldExpand(true);
tabStrip.setTabPaddingLeftRight(10); //10 is the magic number?
@@ -69,42 +63,94 @@ public void onViewCreated(View view, Bundle savedInstanceState) {
tabStrip.setTextColor(getResources().getColorStateList(R.color.tab_text));
tabStrip.setBackgroundColor(Color.argb(0xFF, 0xdd, 0xe8, 0xed));
tabStrip.setBackgroundResource(R.drawable.ab_background_textured_onewarmcoat);
tabStrip.setOnPageChangeListener(this);

tabStrip.setViewPager(mViewPager);
tabStrip.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
int currentPosition = 0;

@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}

@Override
public void onPageSelected(int newPosition) {
try {
ViewPagerChangeListener fragmentToHide = (ViewPagerChangeListener) adapter.getItem(currentPosition);
fragmentToHide.onViewPagerHide();
} catch (ClassCastException e) {
Log.i(getClass().getSimpleName(), "Fragment at position " + String.valueOf(currentPosition) + " doesn't implement ViewPagerChangeListener.");
}

try {
ViewPagerChangeListener fragmentToShow = (ViewPagerChangeListener) adapter.getItem(newPosition);
fragmentToShow.onViewPagerShow();
} catch (ClassCastException e) {
Log.i(getClass().getSimpleName(), "Fragment at position " + String.valueOf(newPosition) + " doesn't implement ViewPagerChangeListener.");
}

currentPosition = newPosition;
}

@Override
public void onPageScrollStateChanged(int state) {
}
});
}
}

@Override
public void onHiddenChanged(boolean hidden) {
// When we get hidden or shown by the Main Activity navigation, pause and resume accordingly.
super.onHiddenChanged(hidden);

if (hidden) {
onPause();
} else {
onResume();
}
}

// PageChangeListeners:
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}

@Override
public void onPageSelected(int newPosition) {
callOnViewPagerHide(currentPosition);
pauseFragment(currentPosition);

callOnViewPagerShow(newPosition);
resumeFragment(newPosition);

currentPosition = newPosition;
}

@Override
public void onPageScrollStateChanged(int state) {
}


@Override
public void onPause() {
Log.e(getClass().getSimpleName(), "OnPause.");
super.onPause();

callOnViewPagerHide(mViewPager.getCurrentItem());
pauseFragment(mViewPager.getCurrentItem());
}

@Override
public void onResume() {
Log.e(getClass().getSimpleName(), "OnResume.");
super.onResume();

callOnViewPagerShow(mViewPager.getCurrentItem());
resumeFragment(mViewPager.getCurrentItem());
}

private void pauseFragment(int pos) {
Fragment currentPositionFragment = mAdapter.getItem(pos);
if (currentPositionFragment != null) {
currentPositionFragment.onPause();
}
}

public void setCurrentItem(int index) {
mViewPager.setCurrentItem(index);
private void resumeFragment(int pos) {
Fragment newPositionFragment = mAdapter.getItem(pos);
if (newPositionFragment != null) {
newPositionFragment.onResume();
}
}

private void callOnViewPagerHide(int i) {
Log.e(getClass().getSimpleName(), "CallOnViewPagerHide(" + String.valueOf(i) + ")");
try {
ViewPagerChangeListener fragmentToShow = (ViewPagerChangeListener) mAdapter.getItem(i);
fragmentToShow.onViewPagerHide();
} catch (ClassCastException e) {
Log.i(getClass().getSimpleName(), "Fragment at position " + String.valueOf(i) + " doesn't implement ViewPagerChangeListener.");
}
}

private void callOnViewPagerShow(int i) {
Log.e(getClass().getSimpleName(), "CallOnViewPagerShow(" + String.valueOf(i) + ")");
try {
ViewPagerChangeListener fragmentToShow = (ViewPagerChangeListener) mAdapter.getItem(i);
fragmentToShow.onViewPagerShow();
} catch (ClassCastException e) {
Log.i(getClass().getSimpleName(), "Fragment at position " + String.valueOf(i) + " doesn't implement ViewPagerChangeListener.");
}
}

protected Fragment getFragmentForPosition(int position) {
@@ -156,4 +202,5 @@ public Fragment getItem(int position) {
}

}

}
Oops, something went wrong.

0 comments on commit 70bdc7a

Please sign in to comment.