My app has the following characteristics.
When in landscape mode, split the screen in half and show a couple of Fragments ("LocFragment" and "MapFragment").
When in portrait mode, show 2 Tabs in ActionBar. A Fragment covers the whole screen, and switch between the Fragments with Tab selection.
Targeting 4.x+, so I'm not concerned about Support Library or ActionBarSherlock.
If the phone is in the landscape mode when the app starts, everything works fine. But the app crashes when 1) the phone is in the portrait mode, 2) app starts, and 3) the phone turned to the landscape mode.
layour/activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="#+id/FragmentContainer"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
layout-land/activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:name="org.solamour.eq.LocFragment"
android:id="#+id/EarthquakeListFragment"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent" />
<fragment
android:name="org.solamour.eq.MapFragment"
android:id="#+id/EarthquakeMapFragment"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent" />
public class MainActivity extends Activity {
TabListener<LocFragment> locTabListener;
TabListener<MapFragment> mapTabListener;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ActionBar actionBar = getActionBar();
View fragmentContainer = findViewById(R.id.FragmentContainer);
boolean bLandscape = fragmentContainer == null;
if (!bLandscape) {
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
actionBar.setDisplayShowTitleEnabled(false);
Tab listTab = actionBar.newTab();
locTabListener = new TabListener<LocFragment>
(this, R.id.FragmentContainer,
LocFragment.class);
listTab.setText("List")
.setContentDescription("List of locations")
.setTabListener(locTabListener);
actionBar.addTab(listTab);
Tab mapTab = actionBar.newTab();
mapTabListener = new TabListener<MapFragment>
(this, R.id.FragmentContainer,
MapFragment.class);
mapTab.setText("Map")
.setContentDescription("Map of interests")
.setTabListener(mapTabListener);
actionBar.addTab(mapTab);
}
}
#Override
public void onSaveInstanceState(Bundle outState) {
View fragmentContainer = findViewById(R.id.FragmentContainer);
boolean bLandscape = fragmentContainer == null;
if (!bLandscape) {
FragmentTransaction ft =
getFragmentManager().beginTransaction();
if (mapTabListener.fragment != null) {
ft.detach(mapTabListener.fragment);
}
if (locTabListener.fragment != null) {
ft.detach(locTabListener.fragment);
}
ft.commit();
}
super.onSaveInstanceState(outState);
}
#Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
View fragmentContainer = findViewById(R.id.FragmentContainer);
boolean bLandscape = fragmentContainer == null;
if (!bLandscape) {
locTabListener.fragment =getFragmentManager().
findFragmentByTag(LocFragment.class.getName());
mapTabListener.fragment = getFragmentManager().
findFragmentByTag(MapFragment.class.getName());
}
}
public static class TabListener<T extends Fragment>
implements ActionBar.TabListener {
private Fragment fragment;
private Activity activity;
private Class<T> fragmentClass;
private int fragmentContainer;
public TabListener(Activity activity,
int fragmentContainer, Class<T> fragmentClass) {
this.activity = activity;
this.fragmentContainer = fragmentContainer;
this.fragmentClass = fragmentClass;
}
public void onTabSelected(Tab tab, FragmentTransaction ft) {
if (fragment == null) {
String fragmentName = fragmentClass.getName();
fragment = Fragment.instantiate(activity, fragmentName);
ft.add(fragmentContainer, fragment, fragmentName);
} else {
ft.attach(fragment);
}
}
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
if (fragment != null) {
ft.detach(fragment);
}
}
public void onTabReselected(Tab tab, FragmentTransaction ft) {
if (fragment != null)
ft.attach(fragment);
}
}
}
Speaking of crash, Eclipse simply says "Unable to start activity ComponentInfo{...}: android.view.InflateException: Binary XML file line #7: Error inflating class fragment". It must be somewhere in "setContentView(R.layout.activity_main)", but I'm not sure how to set up the source to follow inside the code. I'd appreciate any suggestions. Thank you.
__
sol
The error is in the line 7 in the landscape layout:
fragment
android:name="org.solamour.eq.LocFragment"
Maybe the path to the class is wrong or Maybe the LocFragment had an error and when you show it you get a crash.
Related
I have a problem finding places with AutocompleteSupportFragment because it doesn't show me any results and I get an error.
I already put the new code that is used since they ask me for a Google console key and it still doesn't work.
This is my code
I don't have the password restricted, I don't know if that's the problem.
The Places API is enabled
Thank you.
MainActivity.java
public class MainActivity extends AppCompatActivity {
PlacesClient placesClient;
List<Place.Field> placesFields= Arrays.asList(Place.Field.ID,Place.Field.NAME,Place.Field.ADDRESS);
AutocompleteSupportFragment places_fragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initPlaces();
setUpPlacesAutocomplete();
}
private void initPlaces() {
Places.initialize(this,getString(R.string.places_api_key));
placesClient=Places.createClient(this);
}
private void setUpPlacesAutocomplete() {
places_fragment =(AutocompleteSupportFragment)getSupportFragmentManager()
.findFragmentById(R.id.places_autocompletar);
places_fragment.setPlaceFields(placesFields);
places_fragment.setOnPlaceSelectedListener(new PlaceSelectionListener() {
#Override
public void onPlaceSelected(#NonNull Place place) {
Toast.makeText(MainActivity.this, ""+place.getName(), Toast.LENGTH_SHORT).show();
}
#Override
public void onError(#NonNull Status status) {
Toast.makeText(MainActivity.this, ""+status.getStatusMessage(), Toast.LENGTH_SHORT).show();
}
});
}
}
activity_main.xml
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<fragment
android:id="#+id/places_autocompletar"
android:name="com.google.android.libraries.places.widget.AutocompleteSupportFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</fragment>
</LinearLayout>
In the part of the key I have it in application restrictions in the option of NONE
Please try with below code
private static final int AUTOCOMPLETE_REQUEST_CODE = 101;
/*-- initializing Places API --**/
if (!Places.isInitialized()) {
Places.initialize(getActivity(), getActivity().getResources().getString(R.string.google_map_key));
}
/*-- function to open address search activity --**/
public void createAutoCompleteIntent() {
if (getActivity() != null) {
List<Place.Field> fields = Arrays.asList(Place.Field.ID, Place.Field.NAME, Place.Field.LAT_LNG, Place.Field.ADDRESS);
Intent intent = new Autocomplete.IntentBuilder(
AutocompleteActivityMode.FULLSCREEN, fields)
.build(getActivity());
startActivityForResult(intent, AUTOCOMPLETE_REQUEST_CODE);
}
}
/*-- Result of Auto complete google address search --**/
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == AUTOCOMPLETE_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
Place place = Autocomplete.getPlaceFromIntent(data);
if (place.getLatLng() != null) {
// reverse geoCoding to get Street Address, city,state and postal code
Geocoder geocoder = new Geocoder(getActivity(), Locale.getDefault());
try {
System.out.println("------addressList-----" + place.getAddress() + " " + place.getName());
List<Address> addressList = geocoder.getFromLocation(
place.getLatLng().latitude, place.getLatLng().longitude, 1);
System.out.println("------addressList-----" + addressList);
if (addressList != null && addressList.size() > 0) {
Address address = addressList.get(0);
System.out.println("------address-----" + address);
addressEd.setText(address.getAddressLine(0));
String featureName = "";
if (address.getFeatureName()!=null){
featureName = address.getFeatureName();
}
String throughFare = "";
if (address.getThoroughfare()!=null){
throughFare = address.getThoroughfare();
}
String streetAddress = featureName + " " + throughFare;
streetAddressEd.setText(streetAddress);
cityEd.setText(address.getLocality());
stateEd.setText(address.getAdminArea());
postCodeEd.setText(address.getPostalCode());
countryEd.setText(address.getCountryName());
}
} catch (IOException e) {
Log.e(TAG, "Unable connect to Geocoder", e);
}
}
} else if (resultCode == AutocompleteActivity.RESULT_ERROR) {
Status status = Autocomplete.getStatusFromIntent(data);
if (getActivity() != null) {
Util.showMessageBar(getActivity(), status.getStatusMessage());
}
} else if (resultCode == RESULT_CANCELED) {
// The user canceled the operation.
}
}
}
I'm writing an app that has two kinds of displays:
1. "phone mode" on normal sized displays, show one fragment at a time (search fragment, map fragment, etc). Here the fragments load with no particular problem.
2."Tablet mode" on larger displays, shows two fragments side by side - one is the same as "phone mode", the second is a permenant display of the map fragment. When trying to load the app on a tablet emulator it throws an exception:
FATAL EXCEPTION: main
Process: il.co.sredizemnomorie.myapiplaces, PID: 7808
java.lang.RuntimeException: Unable to start activity ComponentInfo{il.co.sredizemnomorie.myapiplaces/il.co.sredizemnomorie.myapiplaces.MainActivity}: java.lang.NullPointerException
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2195)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245)
at android.app.ActivityThread.access$800(ActivityThread.java:135)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5017)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at maps.f.g.a(Unknown Source)
at maps.ag.g$a.<init>(Unknown Source)
at maps.ag.g.a(Unknown Source)
at maps.ag.R.<init>(Unknown Source)
at maps.ag.t.a(Unknown Source)
at uz.onTransact(:com.google.android.gms.DynamiteModulesB:167)
at android.os.Binder.transact(Binder.java:361)
at com.google.android.gms.maps.internal.IGoogleMapDelegate$zza$zza.addMarker(Unknown Source)
at com.google.android.gms.maps.GoogleMap.addMarker(Unknown Source)
at il.co.sredizemnomorie.myapiplaces.FragmentWithMap.setUpMap(FragmentWithMap.java:165)
at il.co.sredizemnomorie.myapiplaces.FragmentWithMap.setUpMapIfNeeded(FragmentWithMap.java:141)
at il.co.sredizemnomorie.myapiplaces.FragmentWithMap.onCreateView(FragmentWithMap.java:72)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:1974)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1252)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:742)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1617)
at android.support.v4.app.FragmentController.execPendingActions(FragmentController.java:339)
at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:602)
at il.co.sredizemnomorie.myapiplaces.MainActivity.onStart(MainActivity.java:270)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1171)
at android.app.Activity.performStart(Activity.java:5241)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2168)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245)
at android.app.ActivityThread.access$800(ActivityThread.java:135)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5017)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
at dalvik.system.NativeStart.main(Native Method)
Here's the code:
MainActivity.java
public class MainActivity extends ActionBarActivity implements FragmentWithDetails.OnFragmentInteractionListener, FragmentWithMap.OnFragmentInteractionListener,
FragmentWithDetails.ListFragmentListener, TextView.OnEditorActionListener, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener,
SettingsFragment.OnFragmentInteractionListener {
private static final String TAG = "PlaceFounder";
public static final String TAG_FAVORITES = "frag_favorites";
private static final String TAG_MAP = "map";
private static final String TAG_DETAILS = "details";
protected GoogleApiClient mGoogleApiClient;
protected Location mLastLocation;
private Bundle currentLocationBundle = new Bundle();
FragmentTransaction fragmentTransaction;
private android.support.v4.app.FragmentManager fragmentManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
buildGoogleApiClient();
fragmentManager = getSupportFragmentManager();
FragmentWithDetails fragmentDetails;
if (isSingleFragment()) {
if (savedInstanceState == null) {
fragmentDetails = FragmentWithDetails.newInstance();
fragmentDetails.setArguments(currentLocationBundle);
fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.fragmnet_container, fragmentDetails, TAG_DETAILS);
fragmentTransaction.commit();
}
}//end if we at small screen
else {
if (savedInstanceState == null) {
fragmentDetails = FragmentWithDetails.newInstance();
FragmentWithMap fragmentWithMap = FragmentWithMap.newInstance(null);
fragmentDetails.setArguments(currentLocationBundle);
fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.fragmnet_container_details, fragmentDetails, TAG_DETAILS);
fragmentTransaction.add(R.id.fragmnet_container_map, fragmentWithMap, TAG_MAP);
fragmentTransaction.commit();
}
}//end if big screen
}
// Show favorites fragment
private void showFavorites() {
currentLocationBundle.putInt("isShowFav", 1);
FragmentWithDetails fragmentFavorites = (FragmentWithDetails) fragmentManager.findFragmentByTag(TAG_FAVORITES);
if (fragmentFavorites == null) {
fragmentFavorites = FragmentWithDetails.newInstance();
fragmentFavorites.setArguments(currentLocationBundle);
}
fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fragmnet_container, fragmentFavorites, TAG_FAVORITES);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.show(fragmentFavorites);
handleLargeLayout();
fragmentTransaction.commit();
}
//Hide details and map only on large screen
//On small screen we reuse the same container
private void handleLargeLayout() {
if (!isSingleFragment()) {
fragmentTransaction.hide(getDetailsFragment());
fragmentTransaction.hide(getMapFragment());
}
}
private FragmentWithMap getMapFragment() {
return (FragmentWithMap) fragmentManager.findFragmentByTag(TAG_MAP);
}
private FragmentWithDetails getDetailsFragment() {
return (FragmentWithDetails) fragmentManager.findFragmentByTag(TAG_DETAILS);
}
private FragmentWithDetails getFavoritesFragment() {
return (FragmentWithDetails) fragmentManager.findFragmentByTag(TAG_FAVORITES);
}
// Show settings fragment
private void showSettings() {
SettingsFragment settingsFragment = SettingsFragment.newInstance();
fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fragmnet_container, settingsFragment, "frag_settings");
fragmentTransaction.addToBackStack(null);
fragmentTransaction.show(settingsFragment);
handleLargeLayout();
fragmentTransaction.commit();
}
// Display current location on map
private void getCurrentLocation() {
String currentLat = null;
String currentLong = null;
if (mLastLocation != null) {
currentLat = String.valueOf(mLastLocation.getLatitude());
currentLong = String.valueOf(mLastLocation.getLongitude());
if (getMapFragment() != null) {
getMapFragment().setPlace(new Place(0, "Current location", "", (float) mLastLocation.getLatitude(), (float) mLastLocation.getLongitude()));
}
}
currentLocationBundle.putString("currentLat", currentLat);
currentLocationBundle.putString("currentLong", currentLong);
}
//Builds a GoogleApiClient.
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_settings:
showSettings();
return true;
case R.id.action_favorites:
showFavorites();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
protected boolean isSingleFragment() {
return findViewById(R.id.layout_single_fragment) != null;
}
#Override
public void onFragmentInteraction(Uri uri) {
}
#Override
public void onPlaceSelected(long placeId) {
fragmentManager = getSupportFragmentManager();
Place place = getPlace(placeId);
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
if (isSingleFragment()) {
FragmentWithMap fragmentWithMap = FragmentWithMap.newInstance(place);
fragmentTransaction.replace(R.id.fragmnet_container, fragmentWithMap, TAG_MAP).addToBackStack(null);
} else {
if (getMapFragment() == null) {
android.support.v4.app.Fragment fragmentWithMap = FragmentWithMap.newInstance(place);
fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.fragmnet_container_map, fragmentWithMap, TAG_MAP);
fragmentTransaction.show(fragmentWithMap);
fragmentTransaction.show(getDetailsFragment());
} else {
FragmentWithMap fragmentWithMap = getMapFragment();
fragmentTransaction.show(fragmentWithMap);
fragmentTransaction.show(getDetailsFragment());
if (getFavoritesFragment() != null) {
fragmentTransaction.hide(getFavoritesFragment());
}
fragmentWithMap.showPlace(place);
}
}
fragmentTransaction.commit();
}
private Place getPlace(long placeId) {
Cursor cursor = null;
Place place = null;
try {
cursor = getContentResolver().query(PlacesContract.Places.CONTENT_URI, null, "_id=" + placeId, null, "name DESC");
cursor.moveToNext();
place = new Place(cursor.getInt(0), cursor.getString(1), cursor.getString(2), cursor.getFloat(3), cursor.getFloat(4));
} finally {
if (cursor != null && !cursor.isClosed()) {
cursor.close();
}
}
return place;
}
#Override
public void onBackPressed() {
if (isSingleFragment() && getMapFragment() != null) {
fragmentManager.popBackStack(null,
FragmentManager.POP_BACK_STACK_INCLUSIVE);
} else if (fragmentManager.findFragmentByTag("frag_favorites") != null) {
fragmentManager.popBackStack(null,
FragmentManager.POP_BACK_STACK_INCLUSIVE);
} else if (fragmentManager.findFragmentByTag("frag_settings") != null) {
fragmentManager.popBackStack(null,
FragmentManager.POP_BACK_STACK_INCLUSIVE);
} else {
super.onBackPressed();
}
}
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
return true;
}
#Override
protected void onStart() {
super.onStart();
mGoogleApiClient.connect();
//start google analytics
EasyTracker.getInstance(this).activityStart(this); // Add this method.
}
#Override
protected void onStop() {
super.onStop();
if (mGoogleApiClient.isConnected()) {
mGoogleApiClient.disconnect();
}
//stop google analytics
EasyTracker.getInstance(this).activityStop(this); // Add this method.
}
/**
* Runs when a GoogleApiClient object successfully connects.
*/
#Override
public void onConnected(Bundle connectionHint) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (mLastLocation == null) {
Toast.makeText(this, "Location not found", Toast.LENGTH_LONG).show();
}
getCurrentLocation();
}
#Override
public void onConnectionFailed(ConnectionResult result) {
toast("No Google Service");
Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = " + result.getErrorCode());
}
private void toast(String message) {
Toast.makeText(this, message,
Toast.LENGTH_LONG).show();
}
#Override
public void onConnectionSuspended(int cause) {
// The connection to Google Play services was lost for some reason
Log.i(TAG, "Connection suspended");
mGoogleApiClient.connect();
}
}
the map fragment:
FragmentWithMap.java
public class FragmentWithMap extends android.support.v4.app.Fragment {
private OnFragmentInteractionListener mListener;
private static final double LAT = 32.084;
private static final double LON = 34.8878;
Place place;
private GoogleMap mMap;
private View view;
private Marker marker;
int userIcon = FragmentWithDetails.userIcon;
public static FragmentWithMap newInstance(Place place) {
Bundle args = new Bundle();
if (place != null) {
args.putInt("id", place.getId());
args.putString("name", place.getName());
args.putString("address", place.getAddress());
args.putFloat("lat", place.getLat());
args.putFloat("lng", place.getLng());
}
FragmentWithMap fragment = new FragmentWithMap();
fragment.setArguments(args);
return fragment;
}
public FragmentWithMap() {
//empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null && getArguments().getString("name") != null) {
place = new Place(getArguments().getInt("id"), getArguments().getString("name"),
getArguments().getString("address"), getArguments().getFloat("lat"),
getArguments().getFloat("lng"));
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if (view == null) {
view = inflater.inflate(R.layout.fragment_fragment_with_map, container, false);
}
setUpMapIfNeeded();
return view;
}
#Override
public void onDestroyView() {
super.onDestroyView();
android.support.v4.app.Fragment f = getFragmentManager()
.findFragmentById(R.id.fragmnet_container_map);
if (f != null) {
try {
getFragmentManager().beginTransaction().remove(f).commit();
} catch (IllegalStateException ise) {
Log.d("FragmentWithMap", "Already closed");
}
}
ViewGroup parentViewGroup = (ViewGroup) view.getParent();
if (parentViewGroup != null) {
parentViewGroup.removeAllViews();
}
}
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mListener = (OnFragmentInteractionListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnFragmentInteractionListener");
}
}
#Override
public void onDetach() {
super.onDetach();
mListener = null;
}
public void showPlace(Place place) {
setPlace(place);
setUpMap();
}
public void setPlace(Place place) {
this.place = place;
}
public interface OnFragmentInteractionListener {
public void onFragmentInteraction(Uri uri);
}
private void setUpMapIfNeeded() {
// Do a null check
if (mMap == null) {
// Try to obtain the map from the SupportMapFragment.
Fragment mmm = getChildFragmentManager().findFragmentById(R.id.fragment_map2);
mMap = ((SupportMapFragment) mmm).getMap();
// Check if we were successful
if (mMap != null) {
setUpMap();
}
}
}
private void setUpMap() {
double lat = LAT;
double lng = LON;
String name = "You are here";
if (place != null) {
lat = place.getLat();
lng = place.getLng();
name = place.getName();
}
if (marker != null) {
marker.remove();
}
LatLng position = new LatLng(lat, lng);
MarkerOptions markerOptions = new MarkerOptions().
position(position).
title(name).
icon(BitmapDescriptorFactory.fromResource(userIcon)).
snippet("Your last recorded location");
marker = mMap.addMarker(markerOptions);
if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
mMap.setMyLocationEnabled(true);
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(position, 15);
mMap.animateCamera(cameraUpdate);
}
}
The XMLs:
activity_main.xml
"phone mode":
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/layout_single_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/darker_gray"
android:paddingBottom="16dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="16dp"
tools:context=".MainActivity">
<FrameLayout
android:id="#+id/fragmnet_container"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"></FrameLayout>
and "tablet mode"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/layout_two_fragments"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/darker_gray"
android:paddingBottom="16dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="16dp"
tools:context=".MainActivity"
>
<FrameLayout
android:id="#+id/fragmnet_container"
android:layout_width="wrap_content"
android:layout_height="match_parent"></FrameLayout>
<FrameLayout
android:id="#+id/fragmnet_container_details"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1.31"></FrameLayout>
<FrameLayout
android:id="#+id/fragmnet_container_map"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"></FrameLayout>
I'd greatly appreciate any help you might offer...
Update:
The crashpoint is at the end of the mapfragment in the at the marker = mMap.addMarker(markerOptions); line. I guess I must not be handling the markers correctly... Still not clear why it works fine in single fragment mode, and not dual fragments.
You are trying to access UI elements in the onCreate() but , onCreate() is too early to call getView() and it will return null. Postpone the code that needs to touch the fragment's view hierarchy to onCreateView() or later in the fragment lifecycle. Since in fragment views can be created in onCreateView() method.
Try to include onActivityCreated() which calls when the fragment's activity has been created and this fragment view hierarchy instantiated.
Update: solved
The problem ended up being with the userIcon (which represents the cosmetic type of marker shown on the map). When the app first load, it for some reason returned 0 instead of null. Since it's merely a cosmetic feature I simply removed, and that solved the problem. Not the prettiest solution but it's the one I got, since time constraint prevent me from dedicated more time to this when more critical parts of the app still need tending; I hope it helps. I hope a more experienced programmer will likely be familiar enough with the marker system to offer alternative solutions/workarounds for those who wish to include custom markers.
I have developed an app that can play videos from gallery and then save the played video back into a folder in gallery. The app is working fine as I can select and play videos from gallery and then save it. When the "Save Video' button is clicked, 'Video saved!' message pops and the saved video are found in gallery. The issue now is I cant play the video, it says 'Sorry, this video cannot be played'. Im unable to identify where it went wrong. My codings are as follow:
AndroidVideoPlayer.java:
public class AndroidVideoPlayer extends Activity {
/**
* Called when the activity is first created.
*/
Button button, button2;
VideoView videoView;
private static final int PICK_FROM_GALLERY = 1;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_android_video_player);
button = (Button) findViewById(R.id.button);
button2 = (Button) findViewById(R.id.savevideo);
videoView = (VideoView) findViewById(R.id.videoview);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent = new Intent();
intent.setType("video/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Complete action using"), PICK_FROM_GALLERY);
}
});
button2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
savequesimage();
// Toast.makeText(getActivity(), "Sample Answer Saved", Toast.LENGTH_LONG).show();
}
});
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode != RESULT_OK) return;
if (requestCode == PICK_FROM_GALLERY) {
Uri mVideoURI = data.getData();
videoView.setVideoURI(mVideoURI);
videoView.start();
}
}
protected boolean savequesimage() {
boolean success = false;
View content = videoView;
content.invalidate();
// make the directory
String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/SavedVideo/";
File dir = new File(path);
if(!dir.exists())
dir.mkdirs();;
// create unique identifier
Random generator = new Random();
int n = 100;
n = generator.nextInt(n);
// create file name
String videoName = "Video_" + n + ".mp4";
File fileVideo = new File(dir.getAbsolutePath(), videoName);
try {
fileVideo.createNewFile();
success = true;
} catch (IOException e) {
e.printStackTrace();
}
if (success) {
Toast.makeText(getApplicationContext(), "Video saved!",
Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getApplicationContext(),
"Error during video saving", Toast.LENGTH_LONG).show();
}
return true;
}
}
activity_android_video_player.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<Button
android:id="#+id/button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="- PLAY Video -"
/>
<Button
android:id="#+id/savevideo"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="- Save Video -"
/>
<VideoView
android:id="#+id/videoview"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.mainapp.videoview" >
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".AndroidVideoPlayer"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Can anyone help me to resolve this issue? Any help/suggestion would be really helpful. Thank you.
Firstly, add permission READ_EXTERNAL_STORAGE & WRITE_EXTERNAL_STORAGE to AndroidManifest.xml like this:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
With Android Level >=23 you need ask permission in code:
// With Android Level >= 23 you need ask permission.
if (android.os.Build.VERSION.SDK_INT >= 23) {
// Check if we have write & read permission
int writePermission = this.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);
int readPermission = this.checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE);
if (writePermission != PackageManager.PERMISSION_GRANTED ||
readPermission != PackageManager.PERMISSION_GRANTED) {
// If don't have permission so prompt the user.
this.requestPermissions(
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE},
REQUEST_PERMISSION
);
}
}
See more here.
I'm developing an app with a left navigation drawer and every secion of the navigation drawer loads a different fragment containing a RecyclerView list with JSON data from a server. The JSON data is get via Volley but sometimes the async task takes a while and the RecyclerView shows up empty. I want to implement a SwypeRefreshLayout on the fragments so they can be reloaded when the user drags down the view.
I have 2 problems:
1) The animation with the little spinning ball just shows up for a second and then disappears
2) After I do the swype down, all other fragments from the navigation drawer sections show this exact same fragment that was refreshed and not their own anymore.
How can I get it fixed, showing the reload animation properly and triggering the fragment reload on each section independently?
Here's the XML code of the fragment:
<android.support.v4.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/instancesSRL">
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin">
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/instancesCV"
android:layout_gravity="center"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
app:cardBackgroundColor="#color/accent"
android:elevation="100dp"
android:layout_marginBottom="1dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/instancesSection"
android:textColor="#android:color/white"
android:textSize="#dimen/abc_text_size_large_material"
android:textAlignment="center"
android:id="#+id/instancesTV"
android:gravity="center_horizontal"
android:paddingBottom="5dp"
android:paddingTop="5dp"
android:textStyle="bold" />
<LinearLayout
android:layout_width="44dp"
android:layout_height="#dimen/abc_action_button_min_height_material"
android:background="#color/window_bg"
android:layout_alignEnd="#id/instancesTV">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/endpoint_icon"
android:src="#drawable/ic_stars_white_48dp"
android:layout_gravity="center_vertical"
android:padding="5dp"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
</LinearLayout>
</RelativeLayout>
</android.support.v7.widget.CardView>
<android.support.v7.widget.RecyclerView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/instancesRV"
android:layout_below="#+id/instancesCV"
android:clickable="true"
android:scrollbars="vertical"
/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/imageView"
android:src="#drawable/openstack_logo"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentBottom="false"
android:layout_alignParentRight="true"
android:layout_alignWithParentIfMissing="false"
android:alpha="0.1"/>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageButton
android:id="#+id/add_buttonInstances"
android:layout_width="#dimen/diameter"
android:layout_height="#dimen/diameter"
android:tint="#android:color/white"
android:layout_gravity="end|bottom"
android:layout_marginBottom="#dimen/add_button_margin"
android:layout_marginEnd="#dimen/card_height"
android:src="#android:drawable/ic_input_add"
android:clickable="true"
android:stateListAnimator="#drawable/button_elevation"
android:background="#drawable/fab_selector"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"/>
</FrameLayout>
</RelativeLayout>
</android.support.v4.widget.SwipeRefreshLayout>
And here's the fragment code:
public class InstancesFragment extends Fragment {
/**
* The fragment argument representing the section number for this
* fragment.
*/
private static final String ARG_SECTION_NUMBER = "section_number";
private OnFragmentInteractionListener mListener;
/**
* Returns a new instance of this fragment for the given section
* number.
*/
public static InstancesFragment newInstance(int sectionNumber) {
InstancesFragment fragment = new InstancesFragment();
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, sectionNumber);
fragment.setArguments(args);
return fragment;
}
public InstancesFragment() {
}
public ArrayList<HashMap<String, String>> jsonList;
public RecyclerView recyclerView;
public SwipeRefreshLayout refreshLayout;
private Handler handler = new Handler();
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Bundle extras = getArguments();
Serializable parsedList = extras.getSerializable("NovaParsed");
jsonList = (ArrayList<HashMap<String, String>>)parsedList;
View rootView = inflater.inflate(R.layout.fragment_instances, container, false);
refreshLayout = (SwipeRefreshLayout)rootView.findViewById(R.id.instancesSRL);
recyclerView = (RecyclerView)rootView.findViewById(R.id.instancesRV);
return rootView;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
layoutManager.supportsPredictiveItemAnimations();
recyclerView.setLayoutManager(layoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setClickable(true);
recyclerView.setHasFixedSize(true);
recyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL_LIST));
NovaAdapter novaAdapter = new NovaAdapter(getActivity(),jsonList);
if (novaAdapter.getItemCount() != 0) {
recyclerView.setAdapter(novaAdapter);
}
refreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
Fragment instancesFragment = getFragmentManager().findFragmentById(R.id.container);
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.remove(instancesFragment);
fragmentTransaction.commit();
refreshLayout.measure(20, 20);
refreshLayout.setRefreshing(true);
}
});
refreshLayout.setColorSchemeColors(Color.RED, Color.GRAY);
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
((Stackerz) activity).onSectionAttached(
getArguments().getInt(ARG_SECTION_NUMBER));
//try {
// mListener = (OnFragmentInteractionListener) activity;
//} catch (ClassCastException e) {
// throw new ClassCastException(activity.toString()
// + " must implement OnFragmentInteractionListener");
//}
}
/**
* This interface must be implemented by activities that contain this
* fragment to allow an interaction in this fragment to be communicated
* to the activity and potentially other fragments contained in that
* activity.
* <p>
* See the Android Training lesson <a href=
* "http://developer.android.com/training/basics/fragments/communicating.html"
* >Communicating with Other Fragments</a> for more information.
*/
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
public void onFragmentInteraction(Uri uri);
}
}
And this is how I call every fragment from the MainActivity using the Navigation Drawer:
#Override
public void onNavigationDrawerItemSelected(int position) {
// update the main content by replacing fragments
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.container, PlaceholderFragment.newInstance(position))
.commit();
switch (position) {
case 0:
extras = authBundle();
OverviewFragment overviewFragment = new OverviewFragment();
overviewFragment.setArguments(extras);
fragmentManager.beginTransaction().add(R.id.container, OverviewFragment.newInstance(position)).commit();
fragmentManager.beginTransaction().replace(R.id.container,overviewFragment).commit();
break;
case 1:
novaExtras = novaBundle();
InstancesFragment instancesFragment = new InstancesFragment();
instancesFragment.setArguments(novaExtras);
fragmentManager.beginTransaction().add(R.id.container, InstancesFragment.newInstance(position)).commit();
fragmentManager.beginTransaction().replace(R.id.container, instancesFragment).commit();
break;
case 2:
flavorsExtras = flavorsBundle();
FlavorsFragment flavorsFragment = new FlavorsFragment();
flavorsFragment.setArguments(flavorsExtras);
fragmentManager.beginTransaction().add(R.id.container, FlavorsFragment.newInstance(position)).commit();
fragmentManager.beginTransaction().replace(R.id.container, flavorsFragment).commit();
break;
case 3:
glanceExtras = glanceBundle();
ImagesFragment imagesFragment = new ImagesFragment();
imagesFragment.setArguments(glanceExtras);
fragmentManager.beginTransaction().add(R.id.container, ImagesFragment.newInstance(position)).commit();
fragmentManager.beginTransaction().replace(R.id.container, imagesFragment).commit();
break;
case 4:
networksExtras = networksBundle();
NetworksFragment networksFragment = new NetworksFragment();
networksFragment.setArguments(networksExtras);
fragmentManager.beginTransaction().add(R.id.container, NetworksFragment.newInstance(position)).commit();
fragmentManager.beginTransaction().replace(R.id.container, networksFragment).commit();
break;
case 5:
subnetsExtras = subnetsBundle();
SubnetsFragment subnetsFragment = new SubnetsFragment();
subnetsFragment.setArguments(subnetsExtras);
fragmentManager.beginTransaction().add(R.id.container, SubnetsFragment.newInstance(position)).commit();
fragmentManager.beginTransaction().replace(R.id.container, subnetsFragment).commit();
break;
case 6:
routersExtras = routersBundle();
RoutersFragment routersFragment = new RoutersFragment();
routersFragment.setArguments(routersExtras);
fragmentManager.beginTransaction().add(R.id.container, RoutersFragment.newInstance(position)).commit();
fragmentManager.beginTransaction().replace(R.id.container, routersFragment).commit();
break;
case 7:
securityExtras = securityBundle();
SecurityFragment securityFragment = new SecurityFragment();
securityFragment.setArguments(securityExtras);
fragmentManager.beginTransaction().add(R.id.container, SecurityFragment.newInstance(position)).commit();
fragmentManager.beginTransaction().replace(R.id.container, securityFragment).commit();
break;
default:
fragmentManager.beginTransaction().replace(R.id.container, PlaceholderFragment.newInstance(position)).commit();
break;
}
}
I'm trying to use the fileplugin and json serializer to do this.
I have the following DcsSetup class, in the core project.
For now I'm working with droid. I can't seem to save the file. The json serialize is ok. The WriteFile seems ok, but next time I try to read the file using TryReadTextFile it fails.
I can't find the file on the device, so I think the WriteFile stuff is wrong.
What is the correct way to save and read my Settings class on Android?
public class DcsSetup
{
public class Settings
{
//Server
public string Server;
public int Port;
public int Device;
public string EncodingFromClient;
public string EncodingToClient;
public int FontCorrectionPixelsWidth; //Pixels to add or subtract i Y dimension to get the right font size
public int FontCorrectionPixelsHeight; //Pixels to add or subtract i Y dimension to get the right font size
public float XPct;//Pct to add to vertical placement of textBox and Buttons.
public float YPct;//Pct to add to horisontal placement of textBox and Buttons.
public float SizePct;//Pct to add to horisontal size of textBox and Buttons.
public bool FullScreen;
public bool DontSleep;
//Diverse
public bool AutoSendEnter;
}
public Settings Setting;
public DcsSetup()
{
var setupFound=true;
var fileService = Mvx.Resolve<IMvxFileStore>();
var jsonConvert = Mvx.Resolve<IMvxJsonConverter>();
var path = fileService.PathCombine("Setting", "Settings.txt");
Setting = new Settings();
try {
string settingFile;
if (fileService.TryReadTextFile(path, out settingFile)){
Setting = jsonConvert.DeserializeObject<Settings>(settingFile);
} else{
setupFound = false;
}
}
catch(Exception e) {
AppTrace.Error("Failed to read settings: {0}", e.Message);
setupFound=false;
}
if(setupFound==false){
Setting.Server = "192.168.1.100";
Setting.Port = 1650;
Setting.Device = 1;
Setting.EncodingFromClient = "CP1252";
Setting.EncodingToClient = "CP1252";
Setting.FontCorrectionPixelsWidth = 0;
Setting.FontCorrectionPixelsHeight = 0;
Setting.XPct = 97.0f;
Setting.YPct = 100.0f;
Setting.SizePct = 98.0f;
Setting.FullScreen = false;
Setting.DontSleep = true;
Setting.AutoSendEnter = true;
try {
//json
var json = jsonConvert.SerializeObject(Setting);
fileService.EnsureFolderExists("Setting");
fileService.WriteFile(path, json);
}
catch (Exception e) {
AppTrace.Error("Failed to save settings: {0}", e.Message);
}
}
}
}
}
I just created a project in VS2012 using the 3.1.1-beta2 packages for MvvmCross
I then added the File and Json plugin packages
I changed the core FirstViewModel to:
public class FirstViewModel
: MvxViewModel
{
private readonly IMvxFileStore _fileStore;
private readonly IMvxJsonConverter _jsonConverter;
private readonly string _filePath;
public class ToStore
{
public string Foo { get; set; }
}
public ICommand SaveCommand
{
get
{
return new MvxCommand(() =>
{
var toStore = new ToStore() {Foo = Hello};
var json = _jsonConverter.SerializeObject(toStore);
_fileStore.WriteFile(_filePath, json);
});
}
}
public ICommand LoadCommand
{
get
{
return new MvxCommand(() =>
{
string txt;
if (_fileStore.TryReadTextFile(_filePath, out txt))
{
Mvx.Trace("Loaded {0}", txt);
var stored = _jsonConverter.DeserializeObject<ToStore>(txt);
Hello = stored.Foo;
}
});
}
}
private string _hello = "Hello MvvmCross";
public FirstViewModel(IMvxFileStore fileStore, IMvxJsonConverter jsonConverter)
{
_fileStore = fileStore;
_jsonConverter = jsonConverter;
_filePath = _fileStore.PathCombine("SubDir", "MyFile.txt");
_fileStore.EnsureFolderExists("SubDir");
}
public string Hello
{
get { return _hello; }
set { _hello = value; RaisePropertyChanged(() => Hello); }
}
}
I called this from a test Android UI:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="40dp"
local:MvxBind="Text Hello"
/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="40dp"
local:MvxBind="Text Hello"
/>
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="40dp"
android:text="Load"
local:MvxBind="Click LoadCommand"
/>
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="40dp"
android:text="Save"
local:MvxBind="Click SaveCommand"
/>
</LinearLayout>
This seemed to work OK - it saved and loaded the JSON fine within and between test runs.
Based on this, my only guess is whether you are redeploying the app between runs - if you do this and you don't have MonoDroid's Preserve application data/cache on device between deploys checked, then you won't see the settings preserved.