AsycTask Throwing IllegalStateException - Fragment Not Attached To Activity - java

I have the following AsyncTask in my Android application. This AsyncTask is contained with within the OnCreate() method of a class that extends PreferenceFragment.
public class NotificationsPreferenceFragment extends PreferenceFragment {
private static Context context;
public NotificationsPreferenceFragment() {
}
public NotificationsPreferenceFragment(Context context) {
this.context = context;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_notifications);
getPreferenceManager().findPreference(getString(R.string.send_all_notifications))
.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
#Override
public boolean onPreferenceClick(Preference preference) {
class NotificationSendTask extends DialogAsyncTask {
public static final String TAG = "NotificationFragment";
public NotificationSendTask(Activity activity, String dialogMsg) {
super(activity, dialogMsg);
}
#Override
protected String doInBackground(String... params) {
String url = PreferenceManager.getDefaultSharedPreferences(getActivity()).getString(getString(R.string.notification_web_service_url), getString(R.string.default_notification_web_service_url));
if (NetworkingHelper.isNetworkAvailable(getActivity())) {
NotificationDao notificationDao = new NotificationDaoImpl(DatabaseManager.getInstance(getActivity().getApplicationContext()), getActivity().getApplicationContext());
List<Notification> unsentNotificationList = notificationDao.findAllNotSent();
if (unsentNotificationList.size() != 0) {
NotificationSenderTask ns = new NotificationSenderTask(url, context);
try {
if (ns.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (unsentNotificationList)).get()) {
return getString(R.string.success);
}
} catch (InterruptedException e) {
Log.e(TAG, e.getMessage());
} catch (ExecutionException e) {
Log.e(TAG, e.getMessage());
}
return getString(R.string.failed_to_send_notifications);
} else {
return getString(R.string.no_notifications_to_send);
}
} else {
return getString(R.string.no_connection_notifications);
}
}
public void onPostExecute(String result) {
super.onPostExecute(result);
if (dialog != null && dialog.isShowing()) {
dialog.hide();
}
Toast.makeText(activity, result, Toast.LENGTH_SHORT).show();
}
}
NotificationSendTask notificationSendTask = new NotificationSendTask(getActivity(), "Sending unsent notifications...");
notificationSendTask.execute();
return true;
}
});
getPreferenceManager().findPreference(getString(R.string.export_notifications)).setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
#Override
public boolean onPreferenceClick(Preference preference) {
NotificationExportTask notificationExportTask = new NotificationExportTask(NotificationsPreferenceFragment.this.getActivity(), 1);
notificationExportTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
return true;
}
});
}
}
I am getting the following exception:
java.lang.IllegalStateException: Fragment NotificationsPreferenceFragment{416092f8} not attached to Activity
at android.app.Fragment.getResources(Fragment.java:741)
at android.app.Fragment.getString(Fragment.java:763)
Can someone please explain to me why this is happening and suggest ways to fix this issue?
UPDATE:
Here is the code for the Activity:
public class SettingsActivity extends PreferenceActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
protected void onDestroy() {
super.onDestroy();
}
#Override
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
public void onBuildHeaders(List<Header> target) {
loadHeadersFromResource(R.xml.pref_headers, target);
}
}

Since you are performing background task in your app. there is no guarantee that user will stay on same screen until task finishes so if user navigates to other screen or presses home button before task is completed; your fragment is detached from activity. So always make sure that you have fragment attached with the Activity.
try checking with
if (isAdded) {
//Do your UI stuff here
}
add above check wherever you get callback

Move your code from onCreate to onActivityCreated instead of trying to getActivity # onCreate.
That's because the fragment can be created when the activity is not yet ready, that's when you are trying to use it.
That is of course if you are adding the fragment to an activity like:
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(android.R.id.content, new PreferenceFragment()).commit();

Related

Flag from AsyncTask class doesn't work properly in main class

I've created some lines of code which are supposed to switch to the next activity if connection is set without any exceptions. But if there are some exceptions, it should make "Error!" toast and not go to the next activity.
Boolean flag in Connection class works well: if the server is off, app will say "Error!", if on, it won't. But same flag in main class (con.flag) doesn't work properly, it looks like it is always false. App always switches to the next activity, with making toast or without, depending on server status. What's wrong in my code? I suppose that there's something I don't know about AsyncTask classes' fields initialization.
So, here is my code:
public class Connection extends AsyncTask<Void, Void, String> {
Context mContext;
public Connection(Context context){
this.mContext = context;
}
static String value;
boolean flag = false;
#Override
protected String doInBackground(Void... arg0) {
try {
Jedis jedis = new Jedis("192.168.0.120", 6381);
String name = jedis.ping();
value = name;
} catch (Exception e){
flag = true;
}
return null;
}
protected void onPostExecute(String result) {
super.onPostExecute(result);
if (flag) {
Toast toast = Toast.makeText(mContext,
"Error!", Toast.LENGTH_LONG);
toast.show();
}
}
}
public class MainActivity extends AppCompatActivity {
Button click;
Context maincontext = this;
public void goTo2ndActivity(){
Intent intent = new Intent(this, Main2Activity.class);
startActivity(intent);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
click = (Button)findViewById(R.id.button);
click.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final Connection con = new Connection(maincontext);
con.execute();
if (!con.flag){
goTo2ndActivity();
}
}
});
}
}
Your problem seems to be a race condition between main thread and the asynctask, the problem is in the onClick listener:
click.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final Connection con = new Connection(maincontext);
con.execute();
if (!con.flag){
goTo2ndActivity();
}
}
});
so this part
if (!con.flag){
goTo2ndActivity();
}
must be called from on post execute of your async task, for that pass the activity to the constructor of the async task like this:
update constructor of async task:
public class Connection extends AsyncTask<Void, Void, String> {
Context mContext;
MainActivity activity;
public Connection(Context context,MainActivity activity){
this.mContext = context;
this.activity= activity
}
..........
..........
and on post execute:
protected void onPostExecute(String result) {
super.onPostExecute(result);
if (flag) {
Toast toast = Toast.makeText(mContext,
"Error!", Toast.LENGTH_LONG);
toast.show();
}else{
//go to next activity
activity.goTo2ndActivity();
}
}
now your button click becomes:
click.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//just execute
final Connection con = new Connection(maincontext,this);
con.execute();
}
});

Stop/start mediaplayer from another activity

i'm trying to play stream radio using Mediaplayer with MP1 as variable of Mediaplayer i want to play it in all Fragments app,expect one activity (ActivityOne) which is contains another Mediaplayer MP2 to play,so i want to stop MP1 when i'm in (ActivityOne) activity, and play MP2 , and when i return from (ActivityOne) i want to resume MP1, my big problem is the (ActivityOne) called when i click button which is exist in fragment
my code below works only in one direction :
when i return from (ActivityOne) activity, the music stops.
structure of the app : MainAcitivty > Fragment > ActivityOne
MainActivity.java
MediaPlayer MP1;
boolean prepared = false;
boolean started = false;
PlayerTask playerTask;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mediaPlayer = new MediaPlayer();
playerTask = new PlayerTask();
playerTask.execute(stream);
/**/
MusicButton = findViewById(R.id.toggleButton);
MusicButton.setVisibility(View.INVISIBLE);
MusicButton.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (started && MusicButton.isChecked()) {
started = false;
MP1.pause();
MusicButton.setChecked(true);
} else {
started = true;
MP1.start();
MusicButton.setChecked(false);
}
}
});
}
#SuppressLint("StaticFieldLeak")
public class PlayerTask extends AsyncTask<String, Void, Boolean> {
ProgressBar loadingRL = findViewById(R.id.progressBar);
#Override
protected void onPreExecute() {
super.onPreExecute();
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
AudioAttributes attribs = new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA).setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build();
MP1.setAudioAttributes(attribs);
} else {
MP1.setAudioStreamType(AudioManager.STREAM_MUSIC);
}
loadingRL.setVisibility(View.VISIBLE);
}
#Override
protected Boolean doInBackground(String... strings) {
try {
MP1.setDataSource(strings[0]);
MP1.prepare();
prepared = true;
} catch (IOException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
}
MP1.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer MP1) {
MP1.start();
}
});
return prepared;
}
#Override
protected void onPostExecute(Boolean aBoolean) {
super.onPostExecute(aBoolean);
MusicButton.setVisibility(View.VISIBLE);
MusicButton.setChecked(true);
loadingRL.setVisibility(View.VISIBLE);
}
ActivityOne.java
MediaPlayer MP2;
boolean prepared = false;
boolean started = false;
ToggleButton music;
PlayerTask playerTask = null;
CoordinatorLayout coordinatorLayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pop_for_ringtone);
coordinatorLayout = findViewById(R.id.coord);
MP2 = new MediaPlayer();
playerTask = new PlayerTask();
playerTask.execute(url);
}
#SuppressLint("StaticFieldLeak")
public class PlayerTask extends AsyncTask<String, Void, Boolean> {
ProgressBar pb = findViewById(R.id.progress);
#Override
protected void onPreExecute() {
super.onPreExecute();
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
AudioAttributes attribs = new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA).setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build();
MP2.setAudioAttributes(attribs);
} else {
MP2.setAudioStreamType(AudioManager.STREAM_MUSIC);
}
}
#Override
protected Boolean doInBackground(String... strings) {
if (!isCancelled()) {
try {
MP2.setDataSource(strings[0]);
MP2.prepare();
prepared = true;
} catch (IOException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
}
MP2.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer MP2) {
MP2.start();
}
});
}
return prepared;
}
#Override
protected void onPostExecute(Boolean aBoolean) {
super.onPostExecute(aBoolean);
music.setEnabled(true);
music.setVisibility(View.VISIBLE);
music.setChecked(true);
all.setVisibility(View.VISIBLE);
}
#Override
protected void onCancelled(Boolean aBoolean) {
if (isCancelled() && MP2.isPlaying()) {
MP2.stop();
}
}
}
#Override
public void onBackPressed() {
if (playerTask != null && playerTask.getStatus() == AsyncTask.Status.FINISHED) {
if (MP2.isPlaying()) {
MP2.stop();
}
} else if (playerTask != null && playerTask.getStatus() != AsyncTask.Status.FINISHED) {
playerTask.cancel(true);
}
super.onBackPressed();
}
i spent 2 days to resolve this problem without any result ,please someone help me i will be thankful to him
You could solve this by using Otto library. First create a new Java class but choose enum instead and inside enum you can add: PLAY and PAUSE for example:
public enum PlaybackEvent {
PLAY, PAUSE
}
Then if you are not using custom Application class create one and extend Application and override inside onCreate method. Inside your app gradle add compile 'com.squareup:otto:1.3.8' then create an instance of Bus inside Application class and register. For example this would look like this:
public class MApplication extends Application {
public static Bus sBus = new Bus(ThreadEnforcer.MAIN);
#Override
public void onCreate() {
super.onCreate();
sBus.register(this);
}
Don't forget to replace in manifest default application class with your new one
<application
android:name="com.packagename.MApplication"
After that in your MainActivity class override and register/unregister your event bus in onResume and in onPause.
#Override
protected void onResume() {
super.onResume();
try {
MApplication.sBus.register(this);
}
catch(Exception e){
e.printStackTrace();
}
}
#Override
protected void onDestroy() {
super.onDestroy();
try {
MApplication.sBus.unregister(this);
}
catch(Exception e){
e.printStackTrace();
}
}
After that in MainActivity create a public void method passing as parameter PlayBackEvent and Subscribe so you can listen a message which will be send from your fragment class. For example:
#Subscribe
public void handlePlaybackEvent(PlaybackEvent event) {
switch (event) {
case PLAY:
if(MP1.isPlaying())
MP1.pause();
break;
case PAUSE:
if(!MP1.isPlaying())
MP1.play();
break;
}
}
And last thing you have to do is to send the message from your fragment when starting second activity and that will go:
MApplication.sBus.post(PlaybackEvent.PAUSE);
and of course you can also send a message to play again MP1 from second activity overriding onBackPressed putting inside line of code:
MApplication.sBus.post(PlaybackEvent.PLAY);
Hope this will help you to resolve the problem.
Have you tried using startActivityForResult()?

How can I get runnable application package name [duplicate]

I used Toast to make notification, but it seems it will appear even its activity is not in the current screen and some other activity has been started.
I want to check this situation, when the activity is not the current one, I'd not send the Toast notification. But how to do ?
When your Activity comes to the foreground, its onResume() method will be invoked. When another Activity comes in front of your Activity, its onPause() method will be invoked. So all you need to do is implement a boolean indicating if your Activity is in the foreground:
private boolean isInFront;
#Override
public void onResume() {
super.onResume();
isInFront = true;
}
#Override
public void onPause() {
super.onPause();
isInFront = false;
}
ArrayList<String> runningactivities = new ArrayList<String>();
ActivityManager activityManager = (ActivityManager)getBaseContext().getSystemService (Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> services = activityManager.getRunningTasks(Integer.MAX_VALUE);
for (int i1 = 0; i1 < services.size(); i1++) {
runningactivities.add(0,services.get(i1).topActivity.toString());
}
if(runningactivities.contains("ComponentInfo{com.app/com.app.main.MyActivity}")==true){
Toast.makeText(getBaseContext(),"Activity is in foreground, active",1000).show();
}
This way you will know if the pointed activity is the current visible activity.
I prefer not to handle the state by myself, so I have implemented a class that does this for me.
package mypackage;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
// Mine extends AppCompatActivity - your's might need to extend Activity, depending on whether
// you use the support library or not.
public class StateTrackingActivity extends AppCompatActivity {
public enum ActivityState {
CREATED, RESUMED, STARTED, PAUSED, STOPPED, DESTROYED
}
private ActivityState _activityState;
protected ActivityState getActivityState() { return _activityState; }
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
_activityState = ActivityState.CREATED;
}
#Override
protected void onResume() {
super.onResume();
_activityState = ActivityState.RESUMED;
}
#Override
protected void onStart() {
super.onStart();
_activityState = ActivityState.STARTED;
}
#Override
protected void onPause() {
super.onPause();
_activityState = ActivityState.PAUSED;
}
#Override
protected void onStop() {
super.onStop();
_activityState = ActivityState.STOPPED;
}
#Override
protected void onDestroy() {
super.onDestroy();
_activityState = ActivityState.DESTROYED;
}
}
Then your activity can extend this one and you can get the state by calling getActivityState().
This is my ultimate isActivityVisible function.
protected boolean isActivityVisible() {
if (this.mActivity != null) {
Class klass = this.mActivity.getClass();
while (klass != null) {
try {
Field field = klass.getDeclaredField("mResumed");
field.setAccessible(true);
Object obj = field.get(this.mActivity);
return (Boolean)obj;
} catch (NoSuchFieldException exception1) {
// Log.e(TAG, exception1.toString());
} catch (IllegalAccessException exception2) {
// Log.e(TAG, exception2.toString());
}
klass = klass.getSuperclass();
}
}
return false;
}
if (BaseActivity.this instanceof Faq)
{
Toast.makeText(BaseActivity.this, "You are in the Same Page", Toast.LENGTH_SHORT).show();
}else {
Intent intent = new Intent(BaseActivity.this, Faq.class);
startActivity(intent);
drawer.closeDrawer(GravityCompat.START);
}
//// here am All my activities are extending on Activity called BaseActivity
There is Activity#isTaskRoot() method
if ( getActivity() instanceof ManageCardActivity){
// your code
}

To execute AsyncTask from onClick(DialogInterface dialog)

Currently I have two java class, 1 with AsyncTask and another one is with extend DialogFragment.
I would like to call CreateGroupTask(AsyncTask) in ChooseAddContact java class.
I have tried several recommended ways to execute the AsyncTask java but all failed.
Any recommendation or solution to that?
public class ChooseAddContact extends DialogFragment {
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(R.string.pick_add)
.setItems(R.array.contact_array, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
if (which == 0){
AddContactDialog dialog2 = new AddContactDialog();
dialog2.show(getFragmentManager(), "AddContactDialog");
} else if (which == 1){
**How should I CALL it here??
//new CreateGroupTask().execute();
//makegroup = new CreateGroupTask();
//makegroup.execute();
}**
}
});
return builder.create(); }
}
And
public class CreateGroupTask extends AsyncTask<Void, Void, String> {
private Context mContext;
private ProgressDialog pd;
public CreateGroupTask() {
}
public CreateGroupTask(Context mContext) {
super();
this.mContext = mContext;
}
#Override
protected void onPreExecute() {
pd = ProgressDialog.show(mContext, null, "Creating group...");
}
#Override
protected String doInBackground(Void... params) {
String chatId = ServerUtilities.create();
if (chatId == null) return null;
try {
...
} catch (SQLException sqle) {}
return chatId;
}
#Override
protected void onCancelled() {
pd.dismiss();
}
#Override
protected void onPostExecute(String result) {
pd.dismiss();
if (result != null) {
Toast.makeText(mContext, "Group created " + result, Toast.LENGTH_LONG).show();
} else {
Toast.makeText(mContext, "Group creation failed. Please retry later.", Toast.LENGTH_LONG).show();
}
}
}
In Dialog Fragment
To Start the async task you need context. In dialog Fragment you can get the context by calling getActivity(); or else you can get the context or activity reference in onAttach() lifecycle method of dialog fragment. Already parametrized constructor is there better to remove zero parametrized constructor.
new CreateGroupTask(getActivity()).execute();
(OR)
private Activity activity;
onAttach(Activity activity){
this.activity=activity;
//store this activity reference
}
//Then Call
new CreateGroupTask(activity).execute();
You can create an object of the class CreateGroupTask and execute wherever you want.
CreateGroupTask createGroupTask = new CreateGroupTask();
then
` if (which == 0){ AddContactDialog dialog2 = new AddContactDialog();
dialog2.show(getFragmentManager(), "AddContactDialog");
} else if (which == 1){
createGroupTask.execute();
// Or new CreateGroupTask().execute();
}`
try this and tell us if any error
What you are missing in AsyncTask is Context. you are using mContext in below code
pd = ProgressDialog.show(mContext, null, "Creating group...");
but you are not initializing that object in default constructor.
Use getActivity while calling task
new CreateGroupTask(getActivity()).execute();
Also remove following constructor from your code
public CreateGroupTask() {
}

Google Maps Fragment replacing current fragment

Background:
Create an app that will center on the user's location and allow for them to text their location to contacts. To do this, we need a simple credential check and server address to test on in the preferences.
Issue:
Whenever the user navigates from the original map fragment that shows their location with a marker, the proper map type (hybrid), etc. to another fragment and then wants to return to the map fragment, it defaults to LatLng 0,0 and a generic map (no indication of user location for example).
My initial thought was to try and save the state of the map fragment upon switching to another fragment and reload that when popping the other fragment from the stack. However I then thought it might be simpler to just replace the current fragment in the MainActivity whenever I need to switch. So on opening the app, MainActivity creates a new MapFragment then replaces it with a Preferences Fragment and when 'saving' creates a new MapFragment to replace the current fragment with. Thought this might fix my problem as on initial load the map functions like I want.
The code for MFragment that contains the Map Fragment:
public class MFragment extends Fragment implements android.location.LocationListener,
GooglePlayServicesClient.ConnectionCallbacks,
GooglePlayServicesClient.OnConnectionFailedListener{
private final static int CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000;
private static GoogleMap map;
private static LocationClient lClient;
private final static String TAG = "MFragment";
private String provider;
private Location loc;
private LocationManager lManager;
private LatLng currentLatLng;
private final long MIN_TIME = 1000;
private final float MIN_DIST = 10;
private Update updateMarkers = new Update();
private View view;
private MapFragment mFrag;
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
mFrag = MapFragment.newInstance();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
//sets the layout for this fragment
view = inflater.inflate(R.layout.fragment_map, container, false);
//insert MapFragment into this Fragment
getActivity().getFragmentManager().beginTransaction()
.replace(R.id.mapview, mFrag)
.commit();
//get a handle on the map from the MapFragment
// map = mFrag.getMap();
//instantiates the location manager
lManager = (LocationManager) getActivity().getSystemService(Context.LOCATION_SERVICE);
//instantiate the location client
lClient = new LocationClient(getActivity(), this, this);
lClient.connect();
//run through initialization of all objects
setUpMapIfNeeded();
Log.d(TAG, "Successfully created MFragment");
return view;
}
/**
* instantiates map from the MapFragment if map is null.
*/
private void setUpMapIfNeeded() {
if (getActivity() != null && getActivity().getFragmentManager() != null &&
map == null) {
map = mFrag.getMap();
Log.d(TAG, "Map generated.");
setUpMap();
} else if (lClient.isConnected()) {
updateMap();
} else {
setUpMap();
}
}
/**
* sets up the location data for the map. conditional clause so that the GPS doesn't crash
* if the app can't get a location straight away.
*/
private void setUpMap() {
if (map != null) {
map.setMyLocationEnabled(true);
map.setMapType(GoogleMap.MAP_TYPE_HYBRID);
Criteria crit = new Criteria();
provider = lManager.getBestProvider(crit, false);
if (lManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
loc = lManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
} else {
loc = lManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
}
lManager.requestLocationUpdates(provider, MIN_TIME, MIN_DIST, this);
}
}
protected void updateMap() {
if (servicesConnected()) {
map.clear();
currentLatLng = new LatLng(this.loc.getLatitude(), this.loc.getLongitude());
map.animateCamera(CameraUpdateFactory.newLatLngZoom(currentLatLng, 14));
map.addMarker(new MarkerOptions()
.position(currentLatLng)
.title("You"));
map.setOnMarkerClickListener(new OnMarkerClickListener() {
#Override
public boolean onMarkerClick(Marker m) {
SMSFragment sFrag = new SMSFragment();
sFrag.setMarker(m);
getActivity().getFragmentManager().beginTransaction()
.replace(android.R.id.content, sFrag)
.commit();
return false;
}
});
}
}
/**
* checks for connection to google play services
* #return
*/
private boolean servicesConnected() {
int resultCode = GooglePlayServicesUtil
.isGooglePlayServicesAvailable(getActivity().getApplicationContext());
if (ConnectionResult.SUCCESS == resultCode) {
Log.d(TAG, getString(R.string.play_available));
return true;
} else {
if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
GooglePlayServicesUtil
.getErrorDialog(resultCode, getActivity(),
CONNECTION_FAILURE_RESOLUTION_REQUEST).show();
} else {
Log.i(TAG, "This device is not supported");
}
return false;
}
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
if (connectionResult.hasResolution()) {
try {
connectionResult
.startResolutionForResult(getActivity(), CONNECTION_FAILURE_RESOLUTION_REQUEST);
} catch (IntentSender.SendIntentException e) {
e.printStackTrace();
}
} else {
Toast.makeText(getActivity(), R.string.connect_failed, Toast.LENGTH_SHORT).show();
}
}
/**
* Called after location client connects
*/
#Override
public void onConnected(Bundle arg0) {
updateMap();
}
/**
* simple display message after disconnecting.
*/
#Override
public void onDisconnected() {
Toast.makeText(getActivity(), R.string.disconnected, Toast.LENGTH_SHORT).show();
}
public void onStart() {
super.onStart();
lClient.connect();
setUpMapIfNeeded();
}
public void onResume() {
super.onResume();
lClient.connect();
setUpMapIfNeeded();
}
public void onPause() {
lClient.disconnect();
super.onPause();
}
public void onStop() {
lClient.disconnect();
super.onStop();
}
public void onDestroy() {
lClient.disconnect();
super.onDestroy();
}
#Override
public void onLocationChanged(Location location) {
this.loc = location;
updateMap();
}
#Override
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO Auto-generated method stub
}
public void updateMarkers(List<Record> records){
//update map with markers corresponding to each latitude, longitude passed back from records
for (Record r : records){
map.addMarker( new MarkerOptions()
.position(new LatLng(r.getValueOfLatitude(), r.getValueOfLongitude())));
}
}
private class Update extends AsyncTask<Void, Void, Boolean> {
private List<Record> records;
protected Update() {
super();
records = new ArrayList<Record>();
}
#Override
protected Boolean doInBackground(Void... params) {
Connect conn = new Connect(getActivity());
try {
records = conn.getAll();
return true;
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
protected void onPostExecute(Boolean result) {
if (result) {
updateMarkers(records);
} else {
Toast.makeText(getActivity(), R.string.rec_fail, Toast.LENGTH_SHORT).show();
}
}
}
}
And an example of replacing the Fragment from another Fragment (From PrefsFragment to MFragment):
register = (Button) v.findViewById(R.id.register);
save.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
saveToPreferences(v);
((MainActivity)getActivity()).replaceFragment();
}
});
register.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getActivity().getFragmentManager().beginTransaction()
.replace(android.R.id.content, new RegFragment())
.commit();
}
});
return v;
}
the save button calls a method in MainActivity to replace the current fragment with a MapFragment as an attempted work-around but doesn't function like I was hoping and using the similar method for the register button using FragmentManager doesn't fix the Map issue either.
Any help is appreciated.
Don't put a fragment inside another fragment unless you really need to. If you choose to do so, you may not use the FragmentManager of the Activity like you do. Instead you must use the child fragment manager of the container fragment to create the fragment transaction that will insert the child fragment by calling getChildFragmentManager().
This is supported since API level 17 (Android 4.2) or using the most recent Android Support Library. I suggest you to always use the support library by default.

Categories

Resources