getStringExtra returns null SINGLE_TOP flag - android

I made one Fragment (ListA) with a ListView. When I click one item of the ListView I want to start the MainActivity.
public class ListA extends Fragment {
private WearableListView ListV;
...
private WearableListView.ClickListener mClickListener = new WearableListView.ClickListener() {
#Override
public void onClick(WearableListView.ViewHolder viewHolder) {
Intent intent= new Intent(getActivity().getApplicationContext(), MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
intent.putExtra("timestamp", "AAA");
startActivity(intent);
}
This is the MainActivity:
public class MainActivity extends Activity {
#Override
public void onResume() {
super.onResume();
if(getIntent().getStringExtra("timestamp")!=null){
Toast.makeText(getApplicationContext(),"Has Timestamp",Toast.LENGTH_SHORT).show();
}
}
When I add flag Intent.FLAG_ACTIVITY_SINGLE_TOP, getIntent().getStringExtra("timestamp") returns null. If I add flag Intent.FLAG_ACTIVITY_NEW_TASK it is not null.
I want to have flag Intent.FLAG_ACTIVITY_SINGLE_TOP and it returns null, I don't know why.

I think because MainActivity was already started before so no new intents is being passed to it.
Try destroying the main activity before you go to list activity. See if this works

Related

Calling startActivity() outside of an Activity context requires FLAG_ACTIVITY_NEW_TASK

I am getting the error AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. The full stack trace:
main Process: com.kd.book, PID: 3487 android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want? at android.app.ContextImpl.startActivity(ContextImpl.java:1238) at android.app.ContextImpl.startActivity(ContextImpl.java:1225) at com.kd.book.Adapter.MyComicAdapter$1.onClick(MyComicAdapter.java:63) at com.kd.book.Adapter.MyComicAdapter$MyViewHolder.onClick(MyComicAdapter.java:99)
I am new to Android development and do not know how to solve it.
My Code:
public class MyComicAdapter extends RecyclerView.Adapter<MyComicAdapter.MyViewHolder> {
Context context;
List<Comic> comicList;
LayoutInflater inflater;
public MyComicAdapter(Context context, List<Comic> comicList) {
this.context = context;
this.comicList = comicList;
inflater=LayoutInflater.from(context);
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View itemView = inflater.inflate(R.layout.comic_item, viewGroup, false);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(#NonNull MyViewHolder myViewHolder, final int i) {
Picasso.get().load(comicList.get(i).Image).into(myViewHolder.comic_image);
myViewHolder.comic_name.setText(comicList.get(i).Name);
//Event
myViewHolder.setRecyclerItemClickListener(new IRecyclerItemClickListener(){
#Override
public void onClick(View view, int position) {
//save the comic selected
Common.comicSelected = comicList.get(position);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(new Intent(context,ChapterActivity.class));
}
});
}
#Override
public int getItemCount() {
return comicList.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView comic_name;
ImageView comic_image;
IRecyclerItemClickListener recyclerItemClickListener;
public void setRecyclerItemClickListener(IRecyclerItemClickListener recyclerItemClickListener) {
this.recyclerItemClickListener = recyclerItemClickListener;
}
public MyViewHolder(#NonNull View itemView) {
super(itemView);
comic_image = itemView.findViewById(R.id.image_comic);
comic_name = itemView.findViewById(R.id.comic_name);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View view) {
recyclerItemClickListener.onClick(view, getAdapterPosition());
}
}
}
Any ideas?
The problem is that you are doing "new Intent" twice:
Once here: Intent intent = new Intent(Intent.ACTION_VIEW);
Second time here: context.startActivity(new Intent(context,ChapterActivity.class))
FLAG_ACTIVITY_NEW_TASK is not set when the activity is started. The corrected version where the Intent is only created once looks like:
Intent intent = new Intent(context, ChapterActivity.class))
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
But your real problem is that you need to call startActivity on the Activity context.
getActivity().startActivity(new Intent(getActivity(), ChapterActivity.class));
More discussion here:
How do I start an activity from within a Fragment?
What you were attempting to do with FLAG_ACTIVITY_NEW_TASK should be reserved for rare cases like when you need to launch an Activity from a Service. But it is not necessary or desirable to set that flag when starting an Activity from within a UI context.
This is why the warnings asks:
Is this really what you want?
Setting specialised flags when launching the Activity often leads to unwanted backstack/navigation behaviours.
Also, I cannot see if your adapter is located inside an Activity or Fragment. [You can use "this" inside an Acitivity and getActivity() inside a Fragment]
Lastly, I cannot how you are creating the Adapter, but the way your code is currently organised you need to pass the Activity context into the Adapter for it to work. From a Fragment:
adapter = new MyComicAdapter(getActivity(), list);
From an Activity:
adapter = new MyComicAdapter(this, list);
This will most likely prevent the exception that you are getting.
Try this way,
1. create an interface in your adapter and pass the position to it (hope you know how to make and use an interface).
2. implement that interface to your activity class.
3. in its override method, you will get the position of a list.
4. by using that position, get the required data and call intent in it.
Done.
Change your call to the new activity as follows,
Intent intent=new Intent(context, ChapterActivity.class);
Activity activity=(Activity) context;
activity.startActivity(intent);

Android pass reference to activity

Currently I have the following code:
public class GameMenu extends Activity{
//some code
public void showOptions(View view){
if(view.equals(R.id.optionsButton){
Intent intent = new Intent(this, OptionsMenu.class);
intent.putExtra("FACADE",this.gameFacade);
startActivity(intent);
}
}
}
OptionsMenu
public class OptionsMenu extends Activity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_options_controller);
Intent calledFromIntend = getIntent();
this.facade = (Facade) calledFromIntend.getSerializableExtra("facade");
}
//some more code
}
Is it possible that the facade is the same in class GameMenu and OptionsMenu?
Because now it's a copy, so if the user checks option x in OptionsMenu, it isn't known in GameMenu.
Its not the same because it gets deserialized from the one you pass in the Intent. You can use startActivityForResult instead of startActivity in the GameMenu to get a result back from OptionsMenu. See http://developer.android.com/training/basics/intents/result.html for more info.

Check if activity that used intent still alive

I have two activities: MainActivity and EventActivity.
Whenever I open my app (in MainActivity by default) and it has a certain flag in SharedPreferences, it intents to EventActivity and finishes itself. Otherwise, it only intents.
In EventActivity I have a button that, when clicked, calls finish() and goes back to EventActivity.
The problem is, when I re-open my application, it will finish the MainActivity and, when I press my custom back button, it will close the app (because the intent handle has finished).
How do I check if MainActivity didn't used finish()?
If I can do that, checking if it is finished I can intent to it.
Thanks.
Override the onDestroy method of MainActivity in that set a public static Boolean field of MainActivity. In that method set that public static field as true. Check for its value in EventActivity before you finish it i.e. when you are coming back from EventActivity to MainActivity. And fire an intent to start MainActivity from EventActivity if it's value is true. And set it's value as false in onCreate of MainActivity.
As follows:
In MainActivity.java
public class MainActivity extends Activity {
public static boolean isMainActivityDestroyed = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
isMainActivityDestroyed = false;
.
.
.//Do something here
}
#Override
protected void onDestroy() {
super.onDestroy();
isMainActivityDestroyed = true;
.
.
.//Do something here
}
}
In EventActivity.java
public class EventActivity extends Activity {
.
.
.//Some methods
//Method which finishes EventActivity & starts MainActivity if destroyed
public void buttonOnClick()
{
if(MainActivity.isMainActivityDestroyed)
{
Intent i = new Intent(this, MainActivity.class);
startActivity(i);
finish();
}
}
}
If isMainActivityDestroyed becomes true then it is an indication that MainActivity used finish().
You could create your own Application class extending Application and launch the needed activity from your Application's onCreate. In manifest you would then remove the default intent filter for your MainActivity.

Close fragments on button click and return result?

On a click of a button within a fragment, is it possible to close the two fragments within the same activity and return the result of the fragment to another activity? One fragment is expecting input while the other fragment has information for the user to view and is not expecting input.
Also, my code worked prior to using fragments in the activity, however the fragments are no longer showing up when clicking the intent to go to the activity (NextActivity.class) that holds the fragments...does any happen to know why the fragments are not appearing?
Here is some of my code below
A piece from the original activity:
public class MessageList extends ListActivity {
private void createMessage() {
Intent i = new Intent(this, NextActivity.class);
startActivityForResult(i, ACTIVITY_CREATE); //this line is incorrect, right?
}}
Here is a snippet from a fragment class:
public class MessageEditorFragment extends Fragment {
confirmButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
getActivity().finish();
}}
Also here is the activity class that holds the fragments, just incase you want a look:
public class NextActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_next);
ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
Tab one = actionBar.newTab().setText("Message Editor");
Tab two = actionBar.newTab().setText("Information");
one.setTabListener(new MyTabListener(new MessageEditorFragment()));
two.setTabListener(new MyTabListener(new InformationFragment()));
actionBar.addTab(one);
actionBar.addTab(two);
}
public class MyTabListener implements TabListener{
Fragment fragment;
public MyTabListener(Fragment f){
fragment = f;
}}}
I deeply appreciate all and any help!! Please let me know if you need to see more code as well.. Thank you :)
When the Activity is destroyed by calling finish , both the fragments will be destroyed/closed.
So, Before you finish the Activity from fragment, you can pass the values to the Activity which started it.
When you start the Activity , You need to start the Activity for Result , to return back the result data from the Fragment/Activity
In your Activity declare a integer request code
int FRAGMENT_REQUEST_CODE = 1000;
Start the activity , as per your logic
Intent intent = new Intent(this,MainActivityEx.class);
startActivityForResult(intent, FRAGMENT_REQUEST_CODE);
Add a callback method onActivityResult to receive the result
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == FRAGMENT_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
TextView textView = (TextView)findViewById(R.id.textView1);
textView.setText(data.getExtras().getString("DATA"));
}
}
}
Now. In your Fragment, When you close the two Fragments , You can pass the data back to the caller Activity
Intent intent = new Intent();
intent.putExtra("DATA","Hai");
getActivity().setResult(Activity.RESULT_OK,intent);
getActivity().finish();

Change tabhost tab title in a different activity

I have a main activity that hold the tabs and each tab start a new activity. May I know how can I change the tab title from the new activity? Thanks.
Although CommonsWare has pointed out that having Activities as Tab content is deprecated, if you still want to do it then one possibility is to use a nested BroadcastReceiver and have the content Activity send a broadcast Intent. I'm not sure if it will work but I would try something like the following...
public class MainActivity extends Activity {
bool tabMonitorIsRegistered = false;
TabMonitor tabMonitor = null;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Other code
tabMonitor = new TabMonitor();
}
#Override
protected void onResume() {
super.onResume();
if (!tabMonitorIsRegistered) {
registerReceiver(tabMonitor, new IntentFilter(Intent.com.mydomain.myapp.ACTION_TAB_CHANGE));
tabMonitorIsRegistered = true;
}
}
#Override
protected void onPause() {
super.onPause();
if (tabMonitorIsRegistered) {
unregisterReceiver(tabMonitor);
tabMonitorIsRegistered = false;
}
}
// Nested BroadcastReceiver
private class TabMonitor extends BroadcastReceiver {
#Override
public void onReceive(Context arg0, Intent arg1) {
// Process the Intent here to change the tab title
}
}
}
At this point it occurs to me that each 'content' Activity will need to tell the MainActivity (via the Intent it sends) 'who' it is. To do this, I would use an Intent extra when adding the tab content Activities identifying each as 'tab1', tab2' etc. When the 'content' Activities start, e.g., in onCreate(), they can store this string and use it in the Intent they send as the broadcast to the MainActivity.

Categories

Resources