I'm new to android programming. I want to create a custom progress dialog with some textview and button and showing the progress with two progressBar and updating them while sending the files from Asynctask, Also I want it works with minimum API 10. google doc recommend me to use DialogFragment and i do not have any idea how to update the progress bars and textviews that are in that custom layout of my fragmentDialog, when I try to reference a textview or progress bar it throw null exeption
Here is my code
public static class FireMissilesDialogFragment extends DialogFragment {
public FireMissilesDialogFragment(){
}
public static FireMissilesDialogFragment newInstance(String title) {
FireMissilesDialogFragment frag = new FireMissilesDialogFragment();
Bundle args = new Bundle();
args.putString("title", title);
frag.setArguments(args);
return frag;
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// Use the Builder class for convenient dialog construction
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// Get the layout inflater
LayoutInflater inflater = this.getActivity().getLayoutInflater();
// Inflate and set the layout for the dialog
// Pass null as the parent view because its going in the dialog layout
View view = inflater.inflate(R.layout.custom_progress, null);
ProgressBar pbCurrent = (ProgressBar) view.findViewById(R.id.current);
builder.setView(view);
builder.setMessage("Fire Missiles")
.setPositiveButton("Fire", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// FIRE ZE MISSILES!
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// User cancelled the dialog
}
});
// Create the AlertDialog object and return it
return builder.create();
}
}
I got a nullExeption here in my main activity when try to reference a view
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button frag = (Button) findViewById(R.id.frag);
frag.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FireMissilesDialogFragment fragment = FireMissilesDialogFragment.newInstance("hi") ;
fragment.getActivity().findViewById(R.id.current);// nullExeption here
// downloadAsync as = new downloadAsync();
// as.execute();
}
});
I didn't see much question and example about that, did I go all the way wrong and should pick another way to achieve my point??!!
Edit :
I'm trying to create something like this
thanks in advance
I can not do a full explanation but I can leave an example and then hopefully you can figure out a way to incorporate the things you need.
The DialogFragment with an AsyncTask and a Progress bar:
public class LoadHydrantsToMapTaskFragment extends DialogFragment {
public static final String TAG = LoadHydrantsToMapTaskFragment.class
.getSimpleName();
public interface LoadHydrantsToMapTaskCallback {
void onPreExecute(int maxProgress);
void onProgressUpdate(int progress);
void onCancelled();
void onPostExecute();
}
private LoadHydrantsToMapTask mTask;
// private ProgressBar mProgressBar;
private List<HydrantHolder> mHydrants;
private GoogleMap map;
public static LoadHydrantsToMapTaskFragment newInstance(
List<HydrantHolder> hydrants, GoogleMap map) {
LoadHydrantsToMapTaskFragment taskFragment = new LoadHydrantsToMapTaskFragment();
taskFragment.mHydrants = hydrants;
taskFragment.map = map;
return taskFragment;
}
#Override public void onAttach(Activity activity) {
super.onAttach(activity);
}
#Override public View onCreateView(LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.dialog_progress_task, container);
mProgressBar = (ProgressBar) view.findViewById(R.id.progressBar);
mProgressBar.setProgress(0);
mProgressBar.setMax(mHydrants.size());
getDialog().setTitle(getActivity().getString(R.string.adding_hydrants));
// This dialog can't be canceled by pressing the back key.
getDialog().setCancelable(false);
getDialog().setCanceledOnTouchOutside(false);
return view;
}
/**
* This method will only be called once when the retained Fragment is first
* created.
*/
#Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStyle(SherlockDialogFragment.STYLE_NORMAL, R.style.TuriosDialog);
// Retain this fragment across configuration changes.
setRetainInstance(true);
mTask = new LoadHydrantsToMapTask(mHydrants);
mTask.setCallback(new LoadHydrantsToMapTaskCallback() {
#Override public void onPreExecute(int maxProgress) {
}
#Override public void onProgressUpdate(int progress) {
mProgressBar.setProgress(progress);
}
#Override public void onPostExecute() {
if (isResumed())
dismiss();
mTask = null;
}
#Override public void onCancelled() {
if (isResumed())
dismiss();
mTask = null;
}
});
mTask.execute();
}
#Override public void onResume() {
super.onResume();
// This is a little hacky, but we will see if the task has finished
// while we weren't
// in this activity, and then we can dismiss ourselves.
if (mTask == null)
dismiss();
}
#Override public void onDetach() {
super.onDetach();
}
// This is to work around what is apparently a bug. If you don't have it
// here the dialog will be dismissed on rotation, so tell it not to dismiss.
#Override public void onDestroyView() {
if (getDialog() != null && getRetainInstance())
getDialog().setDismissMessage(null);
super.onDestroyView();
}
// Also when we are dismissed we need to cancel the task.
#Override public void onDismiss(DialogInterface dialog) {
super.onDismiss(dialog);
// If true, the thread is interrupted immediately, which may do bad
// things.
// If false, it guarantees a result is never returned (onPostExecute()
// isn't called)
// but you have to repeatedly call isCancelled() in your
// doInBackground()
// function to check if it should exit. For some tasks that might not be
// feasible.
if (mTask != null)
mTask.cancel(false);
}
private class LoadHydrantsToMapTask extends
AsyncTask<Void, Integer, List<MarkerOptions>> {
// Before running code in separate thread
List<HydrantHolder> mHydrants;
LoadHydrantsToMapTaskCallback mLoadHydrantsToMapTaskCallback;
public LoadHydrantsToMapTask(List<HydrantHolder> hydrants) {
this.mHydrants = hydrants;
}
public void setCallback(
LoadHydrantsToMapTaskCallback loadHydrantsToMapTaskCallback) {
this.mLoadHydrantsToMapTaskCallback = loadHydrantsToMapTaskCallback;
}
#Override protected void onPreExecute() {
if (mLoadHydrantsToMapTaskCallback != null) {
mLoadHydrantsToMapTaskCallback.onPreExecute(mHydrants.size());
}
}
// The code to be executed in a background thread.
#Override protected List<MarkerOptions> doInBackground(Void... arg) {
List<MarkerOptions> markers = new ArrayList<MarkerOptions>();
for (HydrantHolder hydrant : mHydrants) {
final String hydrant_type = hydrant.getHydrantType();
final String hydrant_icon_path = hydrant.getIconPath();
double latitude = hydrant.getLatitude();
double longitude = hydrant.getLongitude();
final LatLng position = new LatLng(latitude, longitude);
final String address = hydrant.getAddress();
final String addressNumber = hydrant.getAddressNumber();
final String addressremark = hydrant.getAddressRemark();
final String remark = hydrant.getRemark();
// Log.d(TAG, hydrant.toString());
BitmapDescriptor icon = BitmapDescriptorFactory
.defaultMarker(BitmapDescriptorFactory.HUE_RED);
if (!hydrant_icon_path.isEmpty()) {
File iconfile = new File(hydrant_icon_path);
if (iconfile.exists()) {
BitmapDescriptor loaded_icon = BitmapDescriptorFactory
.fromPath(hydrant_icon_path);
if (loaded_icon != null) {
icon = loaded_icon;
} else {
Log.e(TAG, "loaded_icon was null");
}
} else {
Log.e(TAG, "iconfile did not exist: "
+ hydrant_icon_path);
}
} else {
Log.e(TAG, "iconpath was empty on hydrant type: "
+ hydrant_type);
}
StringBuffer snippet = new StringBuffer();
if (!address.isEmpty())
snippet.append("\n" + address + " " + addressNumber);
if (addressremark.isEmpty())
snippet.append("\n" + addressremark);
if (!remark.isEmpty())
snippet.append("\n" + remark);
markers.add(new MarkerOptions().position(position)
.title(hydrant_type).snippet(snippet.toString())
.icon(icon));
publishProgress(markers.size());
}
return markers;
}
// Update the progress
#Override protected void onProgressUpdate(Integer... values) {
if (mLoadHydrantsToMapTaskCallback != null) {
mLoadHydrantsToMapTaskCallback.onProgressUpdate(values[0]);
}
}
#Override protected void onCancelled() {
if (mLoadHydrantsToMapTaskCallback != null) {
mLoadHydrantsToMapTaskCallback.onCancelled();
}
}
// after executing the code in the thread
#Override protected void onPostExecute(List<MarkerOptions> markers) {
for (MarkerOptions marker : markers) {
if (marker != null && map != null)
map.addMarker(marker);
}
if (mLoadHydrantsToMapTaskCallback != null) {
mLoadHydrantsToMapTaskCallback.onPostExecute();
}
}
}
}
My dialog_progress_task layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" >
<ProgressBar
android:id="#+id/progressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="100"
android:maxHeight="10dip"
android:minHeight="10dip"
android:progress="0"
android:progressDrawable="#drawable/progress_orange" />
</LinearLayout>
And finally the code I use to add it:
#Override public void loadHydrantsToMap(List<HydrantHolder> hydrants,
GoogleMap map) {
LoadHydrantsToMapTaskFragment loadHydrantsFragment;
if (fm != null) {
FragmentTransaction ft = fm.beginTransaction();
loadHydrantsFragment = (LoadHydrantsToMapTaskFragment) fm
.findFragmentByTag(LoadHydrantsToMapTaskFragment.TAG);
if (loadHydrantsFragment != null) {
Log.i("Attatching LoadHydrantsToMapTaskFragment");
ft.attach(loadHydrantsFragment);
} else {
loadHydrantsFragment = LoadHydrantsToMapTaskFragment
.newInstance(hydrants, map);
Log.i("Adding new LoadHydrantsToMapTaskFragment");
ft.add(loadHydrantsFragment, LoadHydrantsToMapTaskFragment.TAG);
}
ft.commit();
}
}
Related
I am trying to launch the NavigationLauncher.startNavigation, from another activity but am unable to do so. I have a button in the second activity which I want to use to start the navigation.
Any suggestions are welcome. Thanks
Here is my code:
/*
fabstart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
boolean simulateRoute = false;
NavigationLauncherOptions options = NavigationLauncherOptions.builder()
.directionsRoute(route)
.shouldSimulateRoute(simulateRoute)
.build();
// Call this method with Context from within an Activity
NavigationLauncher.startNavigation(MainActivity.this, options);
}
});
*/
fabstart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this, Before_Go.class);
startActivity(intent);
// Here is where I want to go to a new activity, inside this activity have a button to
// launch the "NavigationLauncher.startNavigation"
}
});
NavigationLauncher.startnavigation() opens a new activity that handles the navigation. Therefore it does not matter from where it is called. However, wherever it is called from, the NavigationLauncher must be defined, and the options object that is passed as the second parameter has to contain the directionsRoute object.
Can you please share code of the activity from which you call it, as well as how you initialize and define the options object?
thanks for your response to my question. I am new to stakoverflow, so i hope i get this additional posting of code right.
MainActivity
public class MainActivity extends AppCompatActivity implements OnMapReadyCallback, PermissionsListener,
MapboxMap.OnMapLongClickListener, OnRouteSelectionChangeListener {
private static final int REQUEST_CODE_AUTOCOMPLETE = 1;
private static final int ONE_HUNDRED_MILLISECONDS = 100;
//private static final String DROPPED_MARKER_LAYER_ID = "DROPPED_MARKER_LAYER_ID";
//Mapbox
private MapView mapView;
private MapboxMap mapboxMap;
private LocationComponent locationComponent;
private PermissionsManager permissionsManager;
private LocationEngine locationEngine;
private long DEFAULT_INTERVAL_IN_MILLISECONDS = 1000L;
private long DEFAULT_MAX_WAIT_TIME = DEFAULT_INTERVAL_IN_MILLISECONDS * 5;
private final MainActivityLocationCallback callback = new MainActivityLocationCallback(this);
private NavigationMapRoute mapRoute;
private DirectionsRoute route;
private String symbolIconId = "symbolIconId";
private String geojsonSourceLayerId = "geojsonSourceLayerId";
private StyleCycle styleCycle = new StyleCycle();
CarmenFeature selectedCarmenFeature;
CarmenFeature feature;
Layer layer;
private static final String TAG = "DirectionsActivity";
// variables
private FloatingActionButton fablocation;
private FloatingActionButton fabstart;
private FloatingActionButton fabRemoveRoute;
private FloatingActionButton fabStyles;
private TextView search;
private TextView kmDisplay;
private TextView timeDisplay;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Mapbox.getInstance(this, getString(R.string.access_token));
setContentView(R.layout.activity_main);
mapView = findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
mapView.getMapAsync(this);
search=findViewById(R.id.search);
kmDisplay = findViewById(R.id.kmDisplay);
timeDisplay = findViewById(R.id.timeDisplay);
fablocation=findViewById(R.id.fabLocation);
fabstart=findViewById(R.id.fabStart);
fabRemoveRoute=findViewById(R.id.fabRemoveRoute);
fabStyles=findViewById(R.id.fabStyles);
fablocation.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Location lastKnownLocation = mapboxMap.getLocationComponent().getLastKnownLocation();
// Move map camera back to current device location
mapboxMap.animateCamera(CameraUpdateFactory.newCameraPosition(
new CameraPosition.Builder()
.target(new LatLng(lastKnownLocation.getLatitude(), lastKnownLocation.getLongitude()))
.zoom(15)
.build()), 3000);
}
});
}
#Override
public boolean onMapLongClick(#NonNull LatLng point) {
vibrate();
Point destinationPoint = Point.fromLngLat(point.getLongitude(), point.getLatitude());
Point originPoint = Point.fromLngLat(locationComponent.getLastKnownLocation().getLongitude(),
locationComponent.getLastKnownLocation().getLatitude());
GeoJsonSource source = mapboxMap.getStyle().getSourceAs("destination-source-id");
if (source != null) {
source.setGeoJson(Feature.fromGeometry(destinationPoint));
} else {
// Use the map camera target's coordinates to make a reverse geocoding search
reverseGeocode(Point.fromLngLat(point.getLongitude(), point.getLatitude()));
}
getRoute(originPoint, destinationPoint);
if(destinationPoint !=originPoint) {
fabRemoveRoute.setOnClickListener(new View.OnClickListener() {
#SuppressLint("RestrictedApi")
#Override
public void onClick(View view) {
removeRouteAndMarkers();
fabstart.setVisibility(View.INVISIBLE);
fabRemoveRoute.setVisibility(View.INVISIBLE);
//fablocation.setVisibility(View.INVISIBLE);
kmDisplay.setText("");
timeDisplay.setText("");
search.setText(String.format(getString(R.string.hint_where_to)));
Location lastKnownLocation = mapboxMap.getLocationComponent().getLastKnownLocation();
// Move map camera back to current device location
mapboxMap.animateCamera(CameraUpdateFactory.newCameraPosition(
new CameraPosition.Builder()
.target(new LatLng(lastKnownLocation.getLatitude(), lastKnownLocation.getLongitude()))
.zoom(15)
.build()), 3000);
}
});
}
//imageView.setEnabled(true);
//imageView.setBackgroundResource(R.color.mapboxBlue);
return true;
}
private void getRoute(Point origin, Point destination) {
NavigationRoute.builder(this)
.accessToken(Mapbox.getAccessToken())
.origin(origin)
.destination(destination)
.voiceUnits(DirectionsCriteria.METRIC)
.alternatives(true)
.build()
.getRoute(new Callback<DirectionsResponse>() {
#SuppressLint("RestrictedApi")
#Override
public void onResponse(Call<DirectionsResponse> call, Response<DirectionsResponse> response) {
// You can get the generic HTTP info about the response
if (response.isSuccessful()
&& response.body() != null
&& !response.body().routes().isEmpty()) {
List<DirectionsRoute> routes = response.body().routes();
mapRoute.addRoutes(routes);
//routeLoading.setVisibility(View.INVISIBLE);
fabRemoveRoute.setVisibility(View.VISIBLE);
fablocation.setVisibility(View.VISIBLE);
fabstart.setVisibility(View.VISIBLE);
route = response.body().routes().get(0);
routeCalcs();
}
// Once you have the route zoom the camera out to show the route within the bounds of the device
mapboxMap.easeCamera(CameraUpdateFactory.newLatLngBounds(
new LatLngBounds.Builder()
.include(new LatLng(origin.latitude(), origin.longitude()))
.include(new LatLng(destination.latitude(), destination.longitude()))
.build(), 150), 4000);
}
#Override
public void onFailure(Call<DirectionsResponse> call, Throwable throwable) {
Log.e(TAG, "Error: " + throwable.getMessage());
}
});
}
private void removeRouteAndMarkers() {
mapRoute.removeRoute();
toggleLayer();
}
#Override
public void onNewPrimaryRouteSelected(DirectionsRoute directionsRoute) {
route = directionsRoute;
routeCalcs();
}
private void routeCalcs(){
// rounds the kilometer to zero decimals
kmDisplay.setText((int) Math.ceil(route.distance()/1000) + " km");
//Log.d(TAG1,(int) Math.ceil(currentRoute.distance()/1000) + " km");
// This converts to output of duration() in seconds to minutes and hours format
int minutes = (int) (route.duration() / 60);
long hour = TimeUnit.MINUTES.toHours(minutes);
long remainMinute = minutes - TimeUnit.HOURS.toMinutes(hour);
if (hour >= 1) {
timeDisplay.setText(String.format(getString(R.string.hours_textview),hour)
+ String.format(getString(R.string.minutes_textview),remainMinute));
} else {
timeDisplay.setText(String.format(getString(R.string.minutes_textview), remainMinute));
}
}
private void reverseGeocode(Point point) {
if (selectedCarmenFeature == null) {
try {
MapboxGeocoding client = MapboxGeocoding.builder()
.accessToken(getString(R.string.access_token))
.query(Point.fromLngLat(point.longitude(), point.latitude()))
.geocodingTypes(GeocodingCriteria.TYPE_ADDRESS)
.build();
client.enqueueCall(new Callback<GeocodingResponse>() {
#Override
public void onResponse(Call<GeocodingResponse> call, Response<GeocodingResponse> response) {
if (response.body() != null) {
List<CarmenFeature> results = response.body().features();
if (results.size() > 0) {
feature = results.get(0);
// If the geocoder returns a result, we take the first in the list and show a Toast with the place name.
mapboxMap.getStyle(new Style.OnStyleLoaded() {
#Override
public void onStyleLoaded(#NonNull Style style) {
if (style.getLayer("SYMBOL_LAYER_ID") != null) {
search.setText(feature.placeName());
}
}
});
} else {
Toast.makeText(MainActivity.this,
getString(R.string.location_picker_dropped_marker_snippet_no_results), Toast.LENGTH_SHORT).show();
}
}
}
#Override
public void onFailure(Call<GeocodingResponse> call, Throwable throwable) {
Timber.e("Geocoding Failure: %s", throwable.getMessage());
}
});
} catch (ServicesException servicesException) {
Timber.e("Error geocoding: %s", servicesException.toString());
servicesException.printStackTrace();
}
}
}
#Override
public void onMapReady(#NonNull MapboxMap mapboxMap) {
this.mapboxMap = mapboxMap;
mapboxMap.setStyle(Style.MAPBOX_STREETS, new Style.OnStyleLoaded() {
#Override
public void onStyleLoaded(#NonNull Style style){
mapRoute = new NavigationMapRoute(null, mapView, mapboxMap);
mapRoute.setOnRouteSelectionChangeListener(MainActivity.this::onNewPrimaryRouteSelected);
mapboxMap.addOnMapLongClickListener(MainActivity.this);
initializeLocationComponent(style);
// Add the symbol layer icon to map for future use
style.addImage(symbolIconId, BitmapFactory.decodeResource(
MainActivity.this.getResources(), R.drawable.mapbox_marker_icon_default));
// Create an empty GeoJSON source using the empty feature collection
setUpSource(style);
// Set up a new symbol layer for displaying the searched location's feature coordinates
setupLayer(style);
fabStyles.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (mapboxMap != null) {
mapboxMap.setStyle(styleCycle.getNextStyle());
}
}
});
initSearchFab();
}
});
// This is the code in the docs, but this launches the turn by turn navigation inside this activity
// and this is not what I need
/* fabstart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
boolean simulateRoute = false;
NavigationLauncherOptions options = NavigationLauncherOptions.builder()
.directionsRoute(route)
.shouldSimulateRoute(simulateRoute)
.build();
// Call this method with Context from within an Activity
NavigationLauncher.startNavigation(MainActivity.this, options);
}
});*/
fabstart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this, Before_Go.class);
startActivity(intent);
// Here is where I want to go to a new activity, inside this activity have a button to
// launch the "NavigationLauncher.startNavigation"
}
});
}
private static class StyleCycle {
private static final String[] STYLES = new String[] {
Style.MAPBOX_STREETS,
Style.OUTDOORS,
Style.LIGHT,
Style.DARK,
//Style.SATELLITE_STREETS,
Style.TRAFFIC_DAY,
Style.TRAFFIC_NIGHT
};
private int index;
private String getNextStyle() {
index++;
if (index == STYLES.length) {
index = 0;
}
return getStyle();
}
private String getStyle() {
return STYLES[index];
}
}
private void initSearchFab() {
findViewById(R.id.search).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new PlaceAutocomplete.IntentBuilder()
.accessToken(Mapbox.getAccessToken())
.placeOptions(PlaceOptions.builder()
.backgroundColor(Color.parseColor("#EEEEEE"))
.limit(10)
//.addInjectedFeature(home)
//.addInjectedFeature(work)
.build(PlaceOptions.MODE_CARDS))
.build(MainActivity.this);
startActivityForResult(intent, REQUEST_CODE_AUTOCOMPLETE);
}
});
}
#SuppressWarnings( {"MissingPermission"})
private void initializeLocationComponent(#NonNull Style loadedMapStyle) {
// Check if permissions are enabled and if not request
if (PermissionsManager.areLocationPermissionsGranted(this)) {
locationComponent = mapboxMap.getLocationComponent();
// Set the LocationComponent activation options
LocationComponentActivationOptions locationComponentActivationOptions =
LocationComponentActivationOptions.builder(this, loadedMapStyle)
.useDefaultLocationEngine(false)
.build();
// Activate with the LocationComponentActivationOptions object
locationComponent.activateLocationComponent(locationComponentActivationOptions);
locationComponent.setLocationComponentEnabled(true);
locationComponent.setRenderMode(RenderMode.NORMAL);
locationComponent.setCameraMode(CameraMode.TRACKING);
//locationComponent.zoomWhileTracking(10d);
initLocationEngine();
} else {
permissionsManager = new PermissionsManager(this);
permissionsManager.requestLocationPermissions(this);
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK && requestCode == REQUEST_CODE_AUTOCOMPLETE) {
// Retrieve selected location's CarmenFeature
selectedCarmenFeature = PlaceAutocomplete.getPlace(data);
search.setText(selectedCarmenFeature.placeName());
// Create a new FeatureCollection and add a new Feature to it using selectedCarmenFeature above.
// Then retrieve and update the source designated for showing a selected location's symbol layer icon
if (mapboxMap != null) {
Style style = mapboxMap.getStyle();
if (style != null) {
GeoJsonSource source = style.getSourceAs(geojsonSourceLayerId);
if (source != null) {
source.setGeoJson(FeatureCollection.fromFeatures(
new Feature[] {Feature.fromJson(selectedCarmenFeature.toJson())}));
}
// Move map camera to the selected location
mapboxMap.animateCamera(CameraUpdateFactory.newCameraPosition(
new CameraPosition.Builder()
.target(new LatLng(((Point) selectedCarmenFeature.geometry()).latitude(),
((Point) selectedCarmenFeature.geometry()).longitude()))
.zoom(14)
.build()), 4000);
}
}
}
}
#SuppressLint("MissingPermission")
private void vibrate() {
Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
if (vibrator == null) {
return;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
vibrator.vibrate(VibrationEffect.createOneShot(ONE_HUNDRED_MILLISECONDS, VibrationEffect.DEFAULT_AMPLITUDE));
} else {
vibrator.vibrate(ONE_HUNDRED_MILLISECONDS);
}
}
/**
* Set up the LocationEngine and the parameters for querying the device's location
*/
#SuppressLint("MissingPermission")
private void initLocationEngine() {
locationEngine = LocationEngineProvider.getBestLocationEngine(this);
LocationEngineRequest request = new LocationEngineRequest.Builder(DEFAULT_INTERVAL_IN_MILLISECONDS)
.setPriority(LocationEngineRequest.PRIORITY_HIGH_ACCURACY)
.setMaxWaitTime(DEFAULT_MAX_WAIT_TIME).build();
locationEngine.requestLocationUpdates(request, callback, getMainLooper());
locationEngine.getLastLocation(callback);
}
#Override
public void onExplanationNeeded(List<String> permissionsToExplain) {
Toast.makeText(this, R.string.user_location_permission_explanation, Toast.LENGTH_LONG).show();
}
#Override
public void onPermissionResult(boolean granted) {
if (granted) {
if (mapboxMap.getStyle() != null) {
initializeLocationComponent(mapboxMap.getStyle());
}
} else {
Toast.makeText(this, R.string.user_location_permission_not_granted, Toast.LENGTH_LONG).show();
finish();
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
permissionsManager.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
private static class MainActivityLocationCallback
implements LocationEngineCallback<LocationEngineResult> {
private final WeakReference<MainActivity> activityWeakReference;
MainActivityLocationCallback(MainActivity activity) {
this.activityWeakReference = new WeakReference<>(activity);
}
#Override
public void onSuccess(LocationEngineResult result) {
MainActivity activity = activityWeakReference.get();
if (activity != null) {
Location location = result.getLastLocation();
if (location == null) {
return;
}
if (activity.mapboxMap != null && result.getLastLocation() != null) {
activity.mapboxMap.getLocationComponent().forceLocationUpdate(result.getLastLocation());
}
}
}
#Override
public void onFailure(#NonNull Exception exception) {
Timber.d(exception.getLocalizedMessage());
MainActivity activity = activityWeakReference.get();
if (activity != null) {
Toast.makeText(activity, exception.getLocalizedMessage(),
Toast.LENGTH_SHORT).show();
}
}
}
/**
* Adds the GeoJSON source to the map
*/
private void setUpSource(#NonNull Style loadedMapStyle) {
loadedMapStyle.addSource(new GeoJsonSource(geojsonSourceLayerId));
}
/**
* Setup a layer with maki icons, eg. west coast city.
*/
private void setupLayer(#NonNull Style loadedMapStyle) {
loadedMapStyle.addLayer(new SymbolLayer("SYMBOL_LAYER_ID", geojsonSourceLayerId).withProperties(
iconImage(symbolIconId),
iconOffset(new Float[] {0f, -8f})
));
}
// This method will remove the destination icon
private void toggleLayer() {
mapboxMap.getStyle(new Style.OnStyleLoaded() {
#Override
public void onStyleLoaded(#NonNull Style style) {
layer = style.getLayer("SYMBOL_LAYER_ID");
if (layer != null) {
if (VISIBLE.equals(layer.getVisibility().getValue())) {
layer.setProperties(visibility(NONE));
} else {
layer.setProperties(visibility(VISIBLE));
}
}
}
});
}
// Add the mapView lifecycle to the activity's lifecycle methods
#Override
public void onResume() {
super.onResume();
mapView.onResume();
}
#Override
protected void onStart() {
super.onStart();
mapView.onStart();
if (mapRoute != null) {
mapRoute.onStart();
}
}
#Override
protected void onStop() {
super.onStop();
mapView.onStop();
if (mapRoute != null) {
mapRoute.onStop();
}
}
#Override
public void onPause() {
super.onPause();
mapView.onPause();
}
#Override
public void onLowMemory() {
super.onLowMemory();
mapView.onLowMemory();
}
#Override
protected void onDestroy() {
super.onDestroy();
mapView.onDestroy();
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mapView.onSaveInstanceState(outState);
}
}
Before_Go - this is the activity where i want to click the button and launch the navigationlauncher
public class Before_Go extends AppCompatActivity {
Button btnGo;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_before__go);
btnGo=findViewById(R.id.btnGo);
btnGo.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent btnGo = new Intent(Before_Go.this, Go.class);
startActivity(btnGo);
}
});
}
}
GoActivity, this is where the navigation launcher needs to launch after the button click in the Before_Go activity
public class Go extends AppCompatActivity implements OnNavigationReadyCallback,
NavigationListener {
private NavigationView navigationView;
private DirectionsRoute route;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
setTheme(R.style.Theme_AppCompat_NoActionBar);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_go);
navigationView = findViewById(R.id.navigationViewB);
navigationView.onCreate(savedInstanceState);
}
/*fabstart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
boolean simulateRoute = false;
NavigationLauncherOptions options = NavigationLauncherOptions.builder()
.directionsRoute(route)
.shouldSimulateRoute(simulateRoute)
.build();
// Call this method with Context from within an Activity
NavigationLauncher.startNavigation(MainActivity.this, options);
}
});*/
#Override
public void onNavigationReady(boolean isRunning) {
MapboxNavigationOptions.Builder navigationOptions = MapboxNavigationOptions.builder();
NavigationViewOptions.Builder options = NavigationViewOptions.builder();
options.navigationListener(this);
extractRoute(options);
extractConfiguration(options);
options.navigationOptions(navigationOptions.build());
//options.navigationOptions(new MapboxNavigationOptions.Builder().build());
launchNavigationWithRoute();
//navigationView.startNavigation(options.build());
navigationView.initialize(this);
/*MapboxNavigationOptions.Builder navigationOptions = MapboxNavigationOptions.builder();
NavigationViewOptions.Builder options = NavigationViewOptions.builder();
options.navigationListener(this);
extractRoute(options);
options.navigationOptions(navigationOptions.build());
//navigationView = NavigationLauncher.startNavigation(options.build());
navigationView.startNavigation(options.build());
initialize();*/
}
#Override
public void onCancelNavigation() {
// Navigation canceled, finish the activity
showCustomCancel();
finishNavigation();
}
#Override
public void onNavigationFinished() {
}
#Override
public void onNavigationRunning() {
}
private void launchNavigationWithRoute() {
if (route != null) {
NavigationLauncher.startNavigation(this, route);
}
}
private void extractRoute(NavigationViewOptions.Builder options) {
route = NavigationLauncher.extractRoute(this);
options.directionsRoute(route);
}
private void extractConfiguration(NavigationViewOptions.Builder options) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
options.shouldSimulateRoute(preferences.getBoolean(NavigationConstants.NAVIGATION_VIEW_SIMULATE_ROUTE, false));
}
private void finishNavigation() {
NavigationLauncher.cleanUpPreferences(this);
finish();
}
private void showCustomCancel(){
ViewGroup viewGroup = findViewById(android.R.id.content);
View dialogView2 = LayoutInflater.from(this).inflate(R.layout.my_dialog_logout, viewGroup, false);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setView(dialogView2);
AlertDialog alertDialog2 = builder.create();
Button buttonNo = dialogView2.findViewById(R.id.buttonNo);
Button buttonYes = dialogView2.findViewById(R.id.buttonYes);
buttonYes.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (alertDialog2 != null && alertDialog2.isShowing()) {
alertDialog2.dismiss();
}
Intent intentCancelTrip_Yes = new Intent(getApplicationContext(),MainActivity.class);
startActivity(intentCancelTrip_Yes);
finish();
navigationView.stopNavigation();
}
});
buttonNo.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (alertDialog2 != null && alertDialog2.isShowing()) {
alertDialog2.dismiss();
}
navigationView.onResume();
}
});
alertDialog2.show();
}
/* private void initialize() {
Parcelable position = getIntent().getParcelableExtra(NavigationConstants.NAVIGATION_VIEW_INITIAL_MAP_POSITION);
if (position != null) {
navigationView.initialize(this, (CameraPosition) position);
} else {
navigationView.initialize(this);
}
}*/
#Override
public void onStart() {
super.onStart();
navigationView.onStart();
}
#Override
public void onResume() {
super.onResume();
navigationView.onResume();
}
#Override
public void onLowMemory() {
super.onLowMemory();
navigationView.onLowMemory();
}
#Override
public void onBackPressed() {
// If the navigation view didn't need to do anything, call super
if (!navigationView.onBackPressed()) {
super.onBackPressed();
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
navigationView.onSaveInstanceState(outState);
super.onSaveInstanceState(outState);
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
navigationView.onRestoreInstanceState(savedInstanceState);
}
#Override
public void onPause() {
super.onPause();
navigationView.onPause();
}
#Override
public void onStop() {
super.onStop();
navigationView.onStop();
}
#Override
protected void onDestroy() {
super.onDestroy();
navigationView.onDestroy();
}
}
NavigationLauncher class i am using to try initiate the navigation inside the Go activity
public class NavigationLauncher {
public static void startNavigation(Activity activity, DirectionsRoute route) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity);
SharedPreferences.Editor editor = preferences.edit();
editor.putString(NavigationConstants.NAVIGATION_VIEW_ROUTE_KEY, new Gson().toJson(route));
//editor.putString(NavigationConstants.NAVIGATION_VIEW_AWS_POOL_ID, awsPoolId);
//editor.putBoolean(NavigationConstants.NAVIGATION_VIEW_SIMULATE_ROUTE, simulateRoute);
editor.apply();
Intent navigationActivity = new Intent(activity, Go.class);
activity.startActivity(navigationActivity);
}
/* public static void startNavigation(Activity activity, NavigationLauncherOptions options){
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity);
SharedPreferences.Editor editor = preferences.edit();
storeDirectionsRouteValue(options, editor);
storeConfiguration(options, editor);
editor.apply();
Intent navigationActivity = new Intent(activity, Go.class);
storeInitialMapPosition(options, navigationActivity);
activity.startActivity(navigationActivity);
}*/
private static void storeConfiguration(NavigationLauncherOptions options, SharedPreferences.Editor editor) {
editor.putBoolean(NavigationConstants.NAVIGATION_VIEW_SIMULATE_ROUTE, options.shouldSimulateRoute());
}
private static void storeDirectionsRouteValue(NavigationLauncherOptions options, SharedPreferences.Editor editor) {
editor.putString(NavigationConstants.NAVIGATION_VIEW_ROUTE_KEY, options.directionsRoute().toJson());
/*if (options.directionsRoute() != null) {
storeDirectionsRouteValue(options, editor);
}
else {
throw new RuntimeException("A valid DirectionsRoute or origin and "
+ "destination must be provided in NavigationViewOptions");
}*/
}
static DirectionsRoute extractRoute(Context context) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
String directionsRouteJson = preferences.getString(NavigationConstants.NAVIGATION_VIEW_ROUTE_KEY, "");
return DirectionsRoute.fromJson(directionsRouteJson);
}
static void cleanUpPreferences(Context context) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = preferences.edit();
editor
.remove(NavigationConstants.NAVIGATION_VIEW_ROUTE_KEY)
.remove(NavigationConstants.NAVIGATION_VIEW_SIMULATE_ROUTE)
.apply();
}
private static void storeInitialMapPosition(NavigationLauncherOptions options, Intent navigationActivity) {
if (options.initialMapCameraPosition() != null) {
navigationActivity.putExtra(
NavigationConstants.NAVIGATION_VIEW_INITIAL_MAP_POSITION, options.initialMapCameraPosition()
);
}
}
}
I assume that the application crashes once the activity "Go.java" is launched.
The problem appears to be that you are not instantiating the Mapbox object in this activity. You are doing it correclty in your "mainactivity.java" however you are missing it in "go.java". Make sure to have the line Mapbox.getInstance(this, getString(R.string.access_token)); also in your "go.java" activity before calling setContentView()
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Mapbox.getInstance(this, getString(R.string.access_token));
setContentView(R.layout.activity_main);
I am trying to implement callback between AsyncTask and Fragment but cannot find correct info how to do it. The issue is that all callback implementations are between activity and asynctask but I need between fragment and asynctask. Could someone give me small working example how to implement it without activity.
My action structure: Fragment call DialogFragment -> choose something and send server request to async task -> async task process everything and update view and some variables. My main problem is that I call prepareData() only once in onCreate and when I walk between other fragment and returns come back I see old data. That is to say there is not enough to update only view in onPost of asynctask. It will be good to have callback which will update the whole variables.
public class TermsAndConditionsFragment extends SherlockFragment implements OnClickListener, OnTouchListener, OnItemClickListener, onTaskListener {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
fm = getSherlockActivity().getSupportFragmentManager();
prepareData();
}
public void prepareData() {
termsAndConditionsM = new TermsAndConditionsManager(getSherlockActivity());
termsAndConditions = termsAndConditionsM.getTermsAndConditions();
if (termsAndConditions != null) {
int totalPayments = Integer.valueOf(termsAndConditions.get(ServerAPI.NO_OF_PAYMENTS));
if (totalPayments > 0) {
paymentsData = termsAndConditionsM.getpayments();
if (paymentsData != null) {
payments = new ArrayList<Payment>();
for (int i = 1; i <= totalPayments; i++) {
paymentValues = new Payment();
paymentValues.setPaymentID(Integer.valueOf(paymentsData.get(ServerAPI.PAYMENT_NO + "_" + i)));
paymentValues.setPaymentDate(paymentsData.get(ServerAPI.PAYMENT_DATE + "_" + i));
paymentValues.setPaymentTotalAmount(paymentsData.get(ServerAPI.PAYMENT_TOTAL + "_" + i));
payments.add(paymentValues);
}
}
}
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootView = init(inflater, container);
if (payments != null || termsAndConditions != null)
updateTermsAndConditionsView();
return rootView;
}
private View init(LayoutInflater inflater, ViewGroup container) {
rootView = inflater.inflate(R.layout.fragment_terms_and_conditions, container, false);
...
return rootView;
}
public void updateTermsAndConditionsView() {
etHowMuch.setText("£" + termsAndConditions.get(ServerAPI.AMOUNT_OF_CREDIT));
etForHowLong.setText(Helpers.ConvertDays2Date(Integer.valueOf(termsAndConditions.get(ServerAPI.TERM_OF_AGREEMENT_IN_DAYS))));
PaymentAdapter adapter = new PaymentAdapter(getSherlockActivity(), R.layout.custom_loan_item, payments);
lvPayments.setAdapter(adapter);
tvNoOfPayments.setText(termsAndConditions.get(ServerAPI.NO_OF_PAYMENTS));
tvFirstPayment.setText(termsAndConditions.get(ServerAPI.FIRST_PAYMENT_DATE));
tvTotalRepayable.setText("£" + termsAndConditions.get(ServerAPI.TOTAL_REPAYABLE));
}
#Override
public void onClick(View v) {
ft = fm.beginTransaction();
howMuch = etHowMuch.getText().toString();
forHowLong = etForHowLong.getText().toString();
switch (v.getId()) {
case R.id.etHowMuch:
f = new NumberPaymentsPickerFragment();
args = new Bundle();
args.putInt(Const.HOW_MUCH, Integer.valueOf(howMuch.replace("£", "")));
args.putDouble(ServerAPI.PAYMENT_STEP, Const.PAYMENT_STEP);
args.putString(Const.STATE, ServerAPI.TERMS_AND_CONDITIONS);
f.setArguments(args);
f.setTargetFragment(this, DIALOG_FRAGMENT);
f.show(getActivity().getSupportFragmentManager(), Const.HOW_MUCH);
break;
case R.id.etForHowLong:
f = new NumberPaymentsPickerFragment();
args = new Bundle();
args.putInt(Const.FOR_HOW_LONG, Integer.valueOf(Helpers.ConvertDate2Days(forHowLong)));
args.putDouble(ServerAPI.PAYMENT_STEP, Const.PAYMENT_STEP);
args.putString(Const.STATE, ServerAPI.TERMS_AND_CONDITIONS);
f.setArguments(args);
f.setTargetFragment(this, DIALOG_FRAGMENT);
f.show(getActivity().getSupportFragmentManager(), Const.FOR_HOW_LONG);
break;
case R.id.tvPersonalDetails:
sfm.saveCurFragment(ServerAPI.PERSONAL_DETAILS, 0);
ft.replace(android.R.id.content, new PersonalDetailsFragment(), ServerAPI.PERSONAL_DETAILS).addToBackStack(null).commit();
break;
case R.id.tvAgreementDetails:
sfm.saveCurFragment(ServerAPI.AGREEMENT_DETAILS, 0);
ft.replace(android.R.id.content, new AgreementDetailsFragment(), ServerAPI.AGREEMENT_DETAILS).addToBackStack(null).commit();
break;
case R.id.bApply:
break;
}
#Override
public void onUpdateData() {
Log.d(TAG, "Update data");
}
}
DialogFragment:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle args = getArguments();
...
}
public Dialog onCreateDialog(Bundle savedInstanceState) {
...
return createDialog(v, R.string.for_how_long, etHowMuch, etForHowLong, etPromotionCode);
}
return null;
}
private Dialog createDialog(View view, int titleResID, final EditText howMuchField, final EditText forHowLongField, final EditText promotionCodeField) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(titleResID);
builder.setView(view);
builder.setPositiveButton(R.string.set, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int id) {
doShowProgress();
}
private void doShowProgress() {
ExecuteServerTaskBackground task = new
ExecuteServerTaskBackground(getActivity());
task.action = ServerAPI.GET_TERMS_AND_CONDITIONS;
onTaskListener listener = new onTaskListener() {
#Override
public void onUpdateData() {
Log.d(TAG, "Updaaate");
}
};
task.setListener(listener);
task.args = args;
task.execute();
}
}).setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
return builder.create();
}
AsyncTask:
onTaskListener mListener;
public interface onTaskListener {
void onUpdateData();
}
public void setListener(onTaskListener listener){
mListener = listener;
}
public ExecuteServerTaskBackground(Activity activity) {
this.mActivity = activity;
this.mContext = activity.getApplicationContext();
}
#Override
protected void onPreExecute() {
pb = (ProgressBar) mActivity.findViewById(R.id.progressBar1);
pb.setVisibility(View.VISIBLE);
}
#Override
protected Void doInBackground(Void... params) {
ServerAPI server = new ServerAPI(mContext);
if (!args.isEmpty())
server.serverRequest(action, args);
else
server.serverRequest(action, null);
return null;
}
#Override
protected void onPostExecute(Void result) {
mListener.onUpdateData();
//There is I just update view but how to update whole variables throughtout callback?
// tvNoOfPayments = (TextView) mActivity.findViewById(R.id.tvNoOfPaymentsValue);
// tvFirstPayment = (TextView) mActivity.findViewById(R.id.tvFirstPaymentValue);
// tvTotalRepayable = (TextView) mActivity.findViewById(R.id.tvTotalRepayableValue);
//
// lvPayments = (ListView) mActivity.findViewById(R.id.lvData);
//
// termsConditionsM = new TermsAndConditionsManager(mContext);
//
// termsAndConditions = termsConditionsM.getTermsAndConditions();
//
// int totalPayments = Integer.valueOf(termsAndConditions.get(ServerAPI.NO_OF_PAYMENTS));
//
// if (totalPayments > 0) {
// if (termsAndConditions != null) {
// tvNoOfPayments.setText(termsAndConditions.get(ServerAPI.NO_OF_PAYMENTS));
// tvFirstPayment.setText(termsAndConditions.get(ServerAPI.FIRST_PAYMENT_DATE));
// tvTotalRepayable.setText("£" + termsAndConditions.get(ServerAPI.TOTAL_REPAYABLE));
// }
//
// paymentsData = termsConditionsM.getpayments();
//
// if (paymentsData != null) {
// Log.d(TAG, paymentsData.toString());
//
// payments = new ArrayList<Payment>();
//
// for (int i = 1; i <= totalPayments; i++) {
// paymentValues = new Payment();
// paymentValues.setPaymentID(Integer.valueOf(paymentsData.get(ServerAPI.PAYMENT_NO + "_" + i)));
// paymentValues.setPaymentDate(paymentsData.get(ServerAPI.PAYMENT_DATE + "_" + i));
// paymentValues.setPaymentTotalAmount(paymentsData.get(ServerAPI.PAYMENT_TOTAL + "_" + i));
// payments.add(paymentValues);
// }
//
// PaymentAdapter adapter = new PaymentAdapter(mContext, R.layout.custom_loan_item, payments);
// lvPayments.setAdapter(adapter);
// }
//
}
pb.setVisibility(View.GONE);
super.onPostExecute(result);
}
Without taking your code in consideration I will post the most essential to make a functional callback.
TestFragment:
public class TestFragment extends Fragment {
/* Skipping most code and I will only show you the most essential. */
private void methodThatStartsTheAsyncTask() {
TestAsyncTask testAsyncTask = new TestAsyncTask(new FragmentCallback() {
#Override
public void onTaskDone() {
methodThatDoesSomethingWhenTaskIsDone();
}
});
testAsyncTask.execute();
}
private void methodThatDoesSomethingWhenTaskIsDone() {
/* Magic! */
}
public interface FragmentCallback {
public void onTaskDone();
}
}
TestAsyncTask:
public class TestAsyncTask extends AsyncTask<Void, Void, Void> {
private FragmentCallback mFragmentCallback;
public TestAsyncTask(FragmentCallback fragmentCallback) {
mFragmentCallback = fragmentCallback;
}
#Override
protected Void doInBackground(Void... params) {
/* Do your thing. */
return null;
}
#Override
protected void onPostExecute(Void result) {
mFragmentCallback.onTaskDone();
}
}
Can somebody answer this question for me:
For testing purposes I have created an activity with a for loop in which I'm creating 10 AlertDialogs or 10 DialogFragments.
Immediately after the activity is started I'm pressing the home button to send the app in the background.
If I'm running the showDialog() method to create the DialogFragments the app will crash with:
IllegalStateException: Can not perform this action after onSaveInstanceState
this is expected behavior.
But if I run the showAlert() method to create the AlertDialogs and same as before I'm sending the app to the background the app doesn't crash. When I return to the activity I can see all 10 AlertDialogs.
The question is why does the activity state loss happen with DialogFragment and not with AlertDialog?
I am still changing the UI after the activity's state has been saved. The platform on which I have tested is Android 4.4.2
public class Main extends FragmentActivity
{
private FragmentActivity activity = this;
private MyAsynk myAsynk;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_main);
myAsynk = new MyAsynk();
myAsynk.execute();
}
private class MyAsynk extends AsyncTask<Void, Void, Void>
{
private boolean run = false;
public MyAsynk()
{
run = true;
}
#Override
protected Void doInBackground(Void... params)
{
for(int i = 0; i < 10 && run; i++)
{
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
// showAlert("loop " + i);
showDialog("loop " + i);
}
return null;
}
public void stop()
{
run = false;
}
}
#Override
public void onBackPressed()
{
super.onBackPressed();
if(null != myAsynk)
{
myAsynk.stop();
myAsynk = null;
}
}
private void showAlert(final String txt)
{
try
{
Main.this.runOnUiThread(new Runnable()
{
#Override
public void run()
{
new AlertDialog.Builder(activity).setMessage(txt)
.setPositiveButton("Ok", new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface dialog, int which)
{
try
{
if(null != dialog)
{
dialog.dismiss();
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
})
.show();
}
});
}
catch(Exception e)
{
e.printStackTrace();
}
}
private void showDialog(final String txt)
{
try
{
Main.this.runOnUiThread(new Runnable()
{
#Override
public void run()
{
MyDialogFragment newFragment = MyDialogFragment.newInstance(txt);
FragmentTransaction ft = Main.this.getSupportFragmentManager().beginTransaction();
newFragment.show(ft, "newFragment");
}
});
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
MyDialogFragment.java :
public class MyDialogFragment extends DialogFragment
{
private MyDialogFragment instance;
public static MyDialogFragment newInstance(String text)
{
MyDialogFragment f = new MyDialogFragment();
Bundle args = new Bundle();
args.putString("text", text);
f.setArguments(args);
return f;
}
public MyDialogFragment()
{
instance = this;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View v = inflater.inflate(R.layout.my_dialog_fragment, container, false);
TextView tv = (TextView) v.findViewById(R.id.tv);
Button bu = (Button) v.findViewById(R.id.bu);
bu.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
try
{
if(null != instance && instance.isVisible())
{
instance.dismiss();
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
});
tv.setText(getArguments().getString("text"));
return v;
}
}
The answer is very simple, though a bit underwhelming.
The oft-seen java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState exception is actually thrown by the FragmentManager class. The reason why is explained very well in this post by Alex Lockwood.
DialogFragments are Fragments (and thus managed by FragmentManager). Therefore, showing dialogs in this way can provoke the exception. However, the implementation of AlertDialog is completely different: it doesn't use Fragments at all (indeed, it actually predates Fragments). Hence, no exceptions.
It may be a silly question but I didn't find a good way to update a dialogfragment's textview from an activity in my android app.
What I'd like to do is to update the textview every second with a counter value and once the time elapsed, a Runnable closes the dialog fragment.
The dialog is closed once the time is elapsed, no problem but I cannot update the textview I want.
Here's my code for the dialog:
public class AlertDialog extends DialogFragment {
private String message = null;
private String title = null;
private ImageView imgV = null;
private TextView msgTv = null;
private TextView counterTv = null;
private Button okBtn = null;
private int imageId = 0;
public static int AUTOMATIC_CLOSE = 100001;
private AlertDialogListener mDialogListener;
public void setImage(int i){
imageId = i;
}
public void setContent(String ttl, String msg){
message = msg;
title = ttl;
}
public boolean hasContent(){
return message != null && title != null;
}
public AlertDialog(){
}
public void performClick(){
okBtn.performClick();
}
public void updateField(String text){
counterTv.setText(text);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.dialog, container);
msgTv = (TextView)v.findViewById(R.id.textDialog);
imgV = (ImageView)v.findViewById(R.id.imageDialog);
counterTv = (TextView)v.findViewById(R.id.timeCounterDialog);
if(imageId != 0)
imgV.setImageResource(imageId);
else
imgV.setImageResource(R.drawable.error_icon);
if(hasContent()){
msgTv.setText(message);
getDialog().setTitle(title);
}
else{
getDialog().setTitle("ERROR");
msgTv.setText("An unexcepted error occured");
}
okBtn = (Button)v.findViewById(R.id.validateButton);
okBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(mDialogListener != null){
mDialogListener.onFinishedDialog();
}
}
});
return v;
}
#Override
public void onStart() {
mDialogListener.onStartedDialog();
super.onStart();
}
#Override
public void onAttach(Activity activity) {
mDialogListener = (AlertDialogListener) activity;
super.onAttach(activity);
}
#Override
public void onDetach() {
mDialogListener = null;
super.onDetach();
}
public interface AlertDialogListener{
void onStartedDialog();
void onFinishedDialog();
}
}
And this is how I launch it:
class myActivity extends Activity implements AlertDialogListener{
protected void onCreate(Bundle savedInstanceState){
"""some init stuff"""
button.setOnClickListener(new View.OnClickListener() {
showAlertDialog();
}
}
#Override
public void onStartedDialog() {
AutoCloseRunnable mAutoClose = new AutoCloseRunnable();
mHandler.postDelayed(mAutoClose, 1000);
}
#Override
public void onFinishedDialog() {
this.finish();
}
private void showAlertDialog(){
FragmentManager fm = getFragmentManager();
mAlertDialog = new AlertDialog();
mAlertDialog.setContent("No Connection available", "Please enable your internet connection.");
mAlertDialog.setImage(R.drawable.error_icon);
mAlertDialog.show(fm, "fragment_alert");
}
private void updateAlertDialog(String text){
mAlertDialog.updateField(text);
}
private void autoCloseAlertDialog(){
mAlertDialog.performClick();
}
public class AutoCloseRunnable implements Runnable{
#Override
public void run() {
int closeCpt = 10;
while(closeCpt >= 0){
try {
Thread.sleep(1000);
updateAlertDialog("Will close automatically in " + closeCpt + " seconds.");
closeCpt--;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
autoCloseAlertDialog();
}
}
}
Does anyone know how to proceed?
I solved it, simply use asynctask it's easier to handle UI updates like this.
I am trying to implement callback between AsyncTask and Fragment but cannot find correct info how to do it. The issue is that all callback implementations are between activity and asynctask but I need between fragment and asynctask. Could someone give me small working example how to implement it without activity.
My action structure: Fragment call DialogFragment -> choose something and send server request to async task -> async task process everything and update view and some variables. My main problem is that I call prepareData() only once in onCreate and when I walk between other fragment and returns come back I see old data. That is to say there is not enough to update only view in onPost of asynctask. It will be good to have callback which will update the whole variables.
public class TermsAndConditionsFragment extends SherlockFragment implements OnClickListener, OnTouchListener, OnItemClickListener, onTaskListener {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
fm = getSherlockActivity().getSupportFragmentManager();
prepareData();
}
public void prepareData() {
termsAndConditionsM = new TermsAndConditionsManager(getSherlockActivity());
termsAndConditions = termsAndConditionsM.getTermsAndConditions();
if (termsAndConditions != null) {
int totalPayments = Integer.valueOf(termsAndConditions.get(ServerAPI.NO_OF_PAYMENTS));
if (totalPayments > 0) {
paymentsData = termsAndConditionsM.getpayments();
if (paymentsData != null) {
payments = new ArrayList<Payment>();
for (int i = 1; i <= totalPayments; i++) {
paymentValues = new Payment();
paymentValues.setPaymentID(Integer.valueOf(paymentsData.get(ServerAPI.PAYMENT_NO + "_" + i)));
paymentValues.setPaymentDate(paymentsData.get(ServerAPI.PAYMENT_DATE + "_" + i));
paymentValues.setPaymentTotalAmount(paymentsData.get(ServerAPI.PAYMENT_TOTAL + "_" + i));
payments.add(paymentValues);
}
}
}
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootView = init(inflater, container);
if (payments != null || termsAndConditions != null)
updateTermsAndConditionsView();
return rootView;
}
private View init(LayoutInflater inflater, ViewGroup container) {
rootView = inflater.inflate(R.layout.fragment_terms_and_conditions, container, false);
...
return rootView;
}
public void updateTermsAndConditionsView() {
etHowMuch.setText("£" + termsAndConditions.get(ServerAPI.AMOUNT_OF_CREDIT));
etForHowLong.setText(Helpers.ConvertDays2Date(Integer.valueOf(termsAndConditions.get(ServerAPI.TERM_OF_AGREEMENT_IN_DAYS))));
PaymentAdapter adapter = new PaymentAdapter(getSherlockActivity(), R.layout.custom_loan_item, payments);
lvPayments.setAdapter(adapter);
tvNoOfPayments.setText(termsAndConditions.get(ServerAPI.NO_OF_PAYMENTS));
tvFirstPayment.setText(termsAndConditions.get(ServerAPI.FIRST_PAYMENT_DATE));
tvTotalRepayable.setText("£" + termsAndConditions.get(ServerAPI.TOTAL_REPAYABLE));
}
#Override
public void onClick(View v) {
ft = fm.beginTransaction();
howMuch = etHowMuch.getText().toString();
forHowLong = etForHowLong.getText().toString();
switch (v.getId()) {
case R.id.etHowMuch:
f = new NumberPaymentsPickerFragment();
args = new Bundle();
args.putInt(Const.HOW_MUCH, Integer.valueOf(howMuch.replace("£", "")));
args.putDouble(ServerAPI.PAYMENT_STEP, Const.PAYMENT_STEP);
args.putString(Const.STATE, ServerAPI.TERMS_AND_CONDITIONS);
f.setArguments(args);
f.setTargetFragment(this, DIALOG_FRAGMENT);
f.show(getActivity().getSupportFragmentManager(), Const.HOW_MUCH);
break;
case R.id.etForHowLong:
f = new NumberPaymentsPickerFragment();
args = new Bundle();
args.putInt(Const.FOR_HOW_LONG, Integer.valueOf(Helpers.ConvertDate2Days(forHowLong)));
args.putDouble(ServerAPI.PAYMENT_STEP, Const.PAYMENT_STEP);
args.putString(Const.STATE, ServerAPI.TERMS_AND_CONDITIONS);
f.setArguments(args);
f.setTargetFragment(this, DIALOG_FRAGMENT);
f.show(getActivity().getSupportFragmentManager(), Const.FOR_HOW_LONG);
break;
case R.id.tvPersonalDetails:
sfm.saveCurFragment(ServerAPI.PERSONAL_DETAILS, 0);
ft.replace(android.R.id.content, new PersonalDetailsFragment(), ServerAPI.PERSONAL_DETAILS).addToBackStack(null).commit();
break;
case R.id.tvAgreementDetails:
sfm.saveCurFragment(ServerAPI.AGREEMENT_DETAILS, 0);
ft.replace(android.R.id.content, new AgreementDetailsFragment(), ServerAPI.AGREEMENT_DETAILS).addToBackStack(null).commit();
break;
case R.id.bApply:
break;
}
#Override
public void onUpdateData() {
Log.d(TAG, "Update data");
}
}
DialogFragment:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle args = getArguments();
...
}
public Dialog onCreateDialog(Bundle savedInstanceState) {
...
return createDialog(v, R.string.for_how_long, etHowMuch, etForHowLong, etPromotionCode);
}
return null;
}
private Dialog createDialog(View view, int titleResID, final EditText howMuchField, final EditText forHowLongField, final EditText promotionCodeField) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(titleResID);
builder.setView(view);
builder.setPositiveButton(R.string.set, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int id) {
doShowProgress();
}
private void doShowProgress() {
ExecuteServerTaskBackground task = new
ExecuteServerTaskBackground(getActivity());
task.action = ServerAPI.GET_TERMS_AND_CONDITIONS;
onTaskListener listener = new onTaskListener() {
#Override
public void onUpdateData() {
Log.d(TAG, "Updaaate");
}
};
task.setListener(listener);
task.args = args;
task.execute();
}
}).setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
return builder.create();
}
AsyncTask:
onTaskListener mListener;
public interface onTaskListener {
void onUpdateData();
}
public void setListener(onTaskListener listener){
mListener = listener;
}
public ExecuteServerTaskBackground(Activity activity) {
this.mActivity = activity;
this.mContext = activity.getApplicationContext();
}
#Override
protected void onPreExecute() {
pb = (ProgressBar) mActivity.findViewById(R.id.progressBar1);
pb.setVisibility(View.VISIBLE);
}
#Override
protected Void doInBackground(Void... params) {
ServerAPI server = new ServerAPI(mContext);
if (!args.isEmpty())
server.serverRequest(action, args);
else
server.serverRequest(action, null);
return null;
}
#Override
protected void onPostExecute(Void result) {
mListener.onUpdateData();
//There is I just update view but how to update whole variables throughtout callback?
// tvNoOfPayments = (TextView) mActivity.findViewById(R.id.tvNoOfPaymentsValue);
// tvFirstPayment = (TextView) mActivity.findViewById(R.id.tvFirstPaymentValue);
// tvTotalRepayable = (TextView) mActivity.findViewById(R.id.tvTotalRepayableValue);
//
// lvPayments = (ListView) mActivity.findViewById(R.id.lvData);
//
// termsConditionsM = new TermsAndConditionsManager(mContext);
//
// termsAndConditions = termsConditionsM.getTermsAndConditions();
//
// int totalPayments = Integer.valueOf(termsAndConditions.get(ServerAPI.NO_OF_PAYMENTS));
//
// if (totalPayments > 0) {
// if (termsAndConditions != null) {
// tvNoOfPayments.setText(termsAndConditions.get(ServerAPI.NO_OF_PAYMENTS));
// tvFirstPayment.setText(termsAndConditions.get(ServerAPI.FIRST_PAYMENT_DATE));
// tvTotalRepayable.setText("£" + termsAndConditions.get(ServerAPI.TOTAL_REPAYABLE));
// }
//
// paymentsData = termsConditionsM.getpayments();
//
// if (paymentsData != null) {
// Log.d(TAG, paymentsData.toString());
//
// payments = new ArrayList<Payment>();
//
// for (int i = 1; i <= totalPayments; i++) {
// paymentValues = new Payment();
// paymentValues.setPaymentID(Integer.valueOf(paymentsData.get(ServerAPI.PAYMENT_NO + "_" + i)));
// paymentValues.setPaymentDate(paymentsData.get(ServerAPI.PAYMENT_DATE + "_" + i));
// paymentValues.setPaymentTotalAmount(paymentsData.get(ServerAPI.PAYMENT_TOTAL + "_" + i));
// payments.add(paymentValues);
// }
//
// PaymentAdapter adapter = new PaymentAdapter(mContext, R.layout.custom_loan_item, payments);
// lvPayments.setAdapter(adapter);
// }
//
}
pb.setVisibility(View.GONE);
super.onPostExecute(result);
}
Without taking your code in consideration I will post the most essential to make a functional callback.
TestFragment:
public class TestFragment extends Fragment {
/* Skipping most code and I will only show you the most essential. */
private void methodThatStartsTheAsyncTask() {
TestAsyncTask testAsyncTask = new TestAsyncTask(new FragmentCallback() {
#Override
public void onTaskDone() {
methodThatDoesSomethingWhenTaskIsDone();
}
});
testAsyncTask.execute();
}
private void methodThatDoesSomethingWhenTaskIsDone() {
/* Magic! */
}
public interface FragmentCallback {
public void onTaskDone();
}
}
TestAsyncTask:
public class TestAsyncTask extends AsyncTask<Void, Void, Void> {
private FragmentCallback mFragmentCallback;
public TestAsyncTask(FragmentCallback fragmentCallback) {
mFragmentCallback = fragmentCallback;
}
#Override
protected Void doInBackground(Void... params) {
/* Do your thing. */
return null;
}
#Override
protected void onPostExecute(Void result) {
mFragmentCallback.onTaskDone();
}
}