I am trying to fix up my app code and transition from Activities to Fragments, in order to transition to the navigation draw and eventually have some sliding tabs too.
Currently for navigation I am using the 3 dots drop down menu from the action bar which I know is not really right. Which is why I am trying to transition to fragments.
I want to keep my action bar menu so I can keep my search icon in the action bar but I want to add a navigation draw to it.
I currentley have a class called ActionBarMenu which extends activity. All my activities come form this because this class holds all the functions which open new activities for the action bar menu I have set up right now.
public class ActionbarMenu extends Activity {
public void goToSearch (MenuItem item) {
// go to search page
Intent i = new Intent(this,Search.class);
startActivity(i);
}
public void goToStatistics (MenuItem item) {
// go to search page
Intent i = new Intent(this,StatisticsPage.class);
startActivity(i);
}
public void goToFindBrewery (MenuItem item) {
// go to search page
Intent i = new Intent(this,FindBrewery.class);
startActivity(i);
}
public void goToContact (MenuItem item) {
// go to search page
Intent i = new Intent(this,ContactPage.class);
startActivity(i);
}
public void goToPortfolio (MenuItem item) {
// go to search page
Intent i = new Intent(this,Portfolio.class);
startActivity(i);
}
public void goToDiscover (MenuItem item) {
// go to search page
Intent i = new Intent(this,Discover.class);
startActivity(i);
}
public void scanBarcode (MenuItem item) {
//open scanner
IntentIntegrator scanIntegrator = new IntentIntegrator(this);
scanIntegrator.initiateScan();
}
//get result value
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
// retrieve scan result
IntentResult scanningResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
if (scanningResult != null) {
// we have a result
String scanContent = scanningResult.getContents();
// launch async task for results
String url = "http://api.brewerydb.com/v2/search/upc?code=" + scanContent + "&key=0cdb22f84315834cc807c0176a927060&format=json&withBreweries=y";
new GetBeerDataFromUPCJSON(this).execute(url);
} else {
Toast toast = Toast.makeText(getApplicationContext(), "No scan data received!", Toast.LENGTH_SHORT);
toast.show();
}
}
}
I tried to change it to a fragment by changing extends activity to extends Fragment and all intents I build to launch new activities all get the red squiggly underline. I am just experimenting and trying to learn what's going on and whats the best way to transition my app from activities to Fragments, without having to recode everything.
Your problem is probably because in a line such as
Intent i = new Intent(this, Discover.class);
this now refers to a Fragment instead of an Activity. Intent() expects a Context as the first argument; Activity extends Context, but Fragment does not. To fix your problem, you should change this to getActivity().
For future reference, mousing over the little red x that appears next to the error should tell you exactly what the problem is.
Instead of using intents, you'll use the fragment manager to load new fragments. Read this page on the android website about fragments.
The finished code for quick replacement would be:
Intent i = new Intent(getActivity(), Discover.class);
startActivity(i);
you just need to make it same like backpressed if the activity is just next from your fragment like... it should work ....
#Override
public void onClick(View view) {
onBackPressed();
}
Intent i = new Intent(this, Discover.class);
Related
Hello i have made a fragment which has one button and I am using it in two activities. The problem which arises from this is that the fragment will do the same intent
Onclick(Type variable is which activity it should run and is not implemented into the onclick, this does not work):
runBtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if (type == 0){
Intent sendToMain = new Intent(getActivity(), MainActivity.class);
sendToMain.putExtra("newStory", story);
}
if (type ==1){
Intent reviewStoryIntent = new Intent(getActivity(),storyReviewActivity.class);
reviewStoryIntent.putExtra("Story", story);
}
}
});
Is there any way to differentiate between which activity the fragment is placed in?
You can check your different activity as below in your fragment:
if(getActivity() instanceof YourFirstActivity) // type == 0
{
// Do your stuff here for First Activity
}else if(getActivity() instanceof YourSecondActivity) // type ==1
{
// Do your stuff here for Second Activity
}
I'm thinking on a different approach. What not to let your activities handle the intents?
So, your activities implements a callback method and your fragment call it so, every activity will know where that Intent should directed.
Hope it helps.
In my main activity (where everything happens in my application) I call a variety as of now just two other activities which end up calling back to my MainActivity via button press. How do I distinguish between these two Intents back to my MainActivity? I have seperate operations I want to prefrom based on things I did back in the two seperate activites.
Heres what I tried:
Intent intent = getIntent();
String s_message = intent.getStringExtra(AppSettings.EXTRA_MESSAGE);
String f_message = intent.getStringExtra(ViewFavorites.EXTRA_MESSAGE);
if(s_message != null) {
//do something
} else if (f_message != null) {
//do something
}
But when I run my application I find when exiting the two activities that they are prefroming the methods I do not wish them to...am I going about this wrong?
What I do is simply set an Extra in my passing Intent then compare that. Something like this. When creating the Intent add an Extra to compare to
intent.putExtra("source", "appSettings");
then in your Activity check what that value is
Intent intent = getIntent();
String source = intent.getStringExtra("source"); // get that value here
if(s_message != null) {
if ("appSettings".equals(source)){
//do something
} else if (viewFavorites.equals(source)) {
//do something else
}
}
You could use variations of this as far as how you assign the Extra but this is a simple example that works well for me, especially when there are just a few Activites that will be calling this one.
Set a different ACTION on each intent, then use if(getIntent().getAction().equals(ACTION)) to distinguish between intents.
public class MainActivity extends Activity {
public static final String ACTION_ONE = "com.yourpackage.ACTION_ONE";
public static final String ACTION_TWO = "com.yourpackage.ACTION_TWO";
#Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
Intent intent = getIntent();
if(intent.getAction() != null){
if(intent.getAction.equals(ACTION_ONE){
//DO SOMETHING
} else if (intent.getAction.equals(ACTION_TWO){
//DO SOMETHING
}
}
}
.....
}
Then when you start your main activity with an intent:
Intent intent = new Intent(MY_CURRENT_CONTEXT, MainActivity.class); //Or MainActivity subclass
add
intent.setAction(ACTION_ONE);
or whichever action is specific to what your intent is trying to accomplish.
I'm new to android and trying to find out how to show a new screen when the user clicks something in the menu item.
I'm using ActionbarSherlock and looking at the sample github-android app.
When the user clicks on an item in the menu, I want to show them a new screen. Github code is doing that like so:
startActivityForResult(new Intent(getActivity(), CreateGistActivity.class), GIST_CREATE);
But I've seen some code samples do:
Intent i = new Intent(getApplicationContext(), SomeActivity.class);
My code looks like this:
public class MainActivity extends SherlockActivity {
....
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.create) {
//show createactivity class
return true;
}
return true;
}
What is the right way to do ?
You can do it just like that:
public class MainActivity extends SherlockActivity {
....
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.create) {
//show createactivity class
Intent i = new Intent(MainActivity.this, SomeActivity.class);
startActivity(i);
return true;
}
return true;
}
startActivityForResult is used when you have to return some value/data to the first screen like a user selection. More here
As far as the context to use getActivity() or getApplicationContext(), I prefer to use the context of current activity MainActivity.this its more straitforward similar to documentation example
/** Called when the user clicks the Send button */
public void sendMessage(View view) {
Intent intent = new Intent(this, DisplayMessageActivity.class);
EditText editText = (EditText) findViewById(R.id.edit_message);
String message = editText.getText().toString();
intent.putExtra(EXTRA_MESSAGE, message);
startActivity(intent);
}
Inside a fragment use getSherlockActivity() instead of getActivity() as getActivity() can cause crashes to older devices.
Of course getApplicationContext() would always work and not crash but I feel that it may mess the garbage collector and do not let activities to be cleared (but not sure about it)
Just use startActivityForResult
There is no 'right' way. The Github code doesn't first declare the variable. The onther does. I believe for a menu, you normally need to declare the Intent as a local variable, if not a field.
Create an intent: Intent i = new Intent(MainActivity.this, CreateGistActivity.class);
where MainActivity is the activity you're in, and CreateGistActivity is the class you want to launch.
Then use startActivity(Intent) to launch the new activity: startActivity(i);
Or just combine them:
startActivity(new Intent(MainActivity.this, CreateGistActivity.class));
Full code:
public class MainActivity extends SherlockActivity {
....
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.create)
{
Intent i = new Intent(MainActivity.this, CreateGistActivity.class);
startActivity(i);
return true;
}
return true;
}
startActivityForResult probably isn't needed in your case, unless you're expecting to send values between the classes.
My problem is in understanding how to correctly use intents. After googling and reading all the documentations and articles on this topic, I still cannot sort out my problem. I have two activities: "Searchable" and "ActivityWordInfo". The "Searchable" activity searches a word in the database, and displays search results or suggestions. After the user cliks one of the search results, "ActivityWordInfo" activity is launched and diplays the word definition. Here is some part of the code:
Searchable:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.search);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
// Get the intent, verify the action and get the query
if( savedInstanceState != null ){
//the application is being reloaded
query = savedInstanceState.getString("searchedWord");
doMySearch(query); //does the search in the database
}else{
Intent intent = getIntent();
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
query = intent.getStringExtra(SearchManager.QUERY);
doMySearch(query);
}
}
}
#Override
public void onSaveInstanceState(Bundle savedInstanceState){
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putString("searchedWord", query);
//saves the searched word if this activity is killed
}
#Override
public void onClick(View v) { //when one of the search results is clicked
int wordID = (Integer) v.getTag();
Intent intent = new Intent(Searchable.this, ActivityWordInfo.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_SINGLE_TOP);
Bundle b = new Bundle();
b.putInt("key", wordID);
b.putInt("calling_activity", callingActivityId);
intent.putExtras(b);
startActivity(intent);
}
ActivityWordInfo:
public void onCreate(Bundle savedInstanceState) {
...
Bundle b = getIntent().getExtras();
current_word_id = b.getInt("key", 0);
callingActivityId = b.getInt("calling_activity", 0);
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
switch(callingActivityId){
case 3: //which is the ID of Searchable activity
Intent intent3 = new Intent(ActivityWordInfo.this, Searchable.class);
intent3.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent3);
break;
}
break;
}
When the user is in ActivityWordInfo and navigates up, I expect to go to Searchable activity, which should have saved its instance state (the list of results should be still there). What in reality happens:
-The word typed by the user is assigned to 'query' variable and then the results and suggestions are displayed in "Searchable"
-the user clicks one of the words and "ActivityWordInfo" is created
-then, when the user navigates up, the onSaveInstanceState is called for the "Searchable" activity, then it is destryed and created. The result is an empty layout :(
I cannot understand why "Searchable" is destroyed and then created! This only happens in Android 4.2 and not in lower APIs (in 2.3.3 worked perfectly as I expected). Is there any difference in the activity lifecycle in JellyBean?
Note: I cannot use the parentActivity attribute in the manifest since the ActivityWordInfo is called by multiple parents.
The behavior of "up" navigation changed between 2.3 and 4.0. I suggest you look at the topic "Tasks and Back Stack" at developer.android.com.
I have two Activities in which I want to call the second one from the first one's Context Menu. This is what it should do.
Activity A Context Menu click should start Activity B.
In the onCreate of Activity B, depending on the extras passed in, automatically display a AlertBuilder dialog and then either take a picture or select an image.
What is happening is that when Activity A's Context Menu item is clicked, it launches Activity B and the AlertDialog displays. If I select the option to take a picture, the MediaStore.ACTION_IMAGE_CAPTURE intent is started and once the picture is taken, Activity B is re-launched again and the AlertDialog shows.
Activity A - Context Menu
#Override
public boolean onContextItemSelected(MenuItem item) {
AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
final ItemClass selItem = (ItemClass)this.getListView().getItemAtPosition(info.position);
Intent intent;
SyncData sync;
switch (item.getItemId()) {
case R.id.start_activity_b:
Intent intent = new Intent(ActivityA.this, ActivityB.class);
intent.putExtra("data1", selItem.itemID);
intent.putExtra("data2", "AUTO");
Measurements.this.startActivityForResult(intent, REQUESTCODE_ACTIVITYB);
return true;
default:
return super.onContextItemSelected(item);
}
}
Activity B - onCreate Code
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.listview_main);
Bundle extras = getIntent().getExtras();
if ((extras != null) && (extras.containsKey("data1"))) {
this.itemID = extras.getString("data1");
}
if ((extras != null) && (extra.containsKey("data2"))) {
this.createAlertDialog();
}
}
As I stated in my comment, you shouldn't need runOnUiThread() since you are already on the UI Thread. There are a couple ways that may be better than doing this. Again, as in my comment, you should be able to call setResult and finish ActivityB when the Dialog dismisses since you are using startActivityForResult() to start ActivityB.
With just what I see that should be fine. But if it causes problems due to whatever you have in your Dialog or from something else, you can make your Dialog an Activity and give it aDialog themeby adjusting yourmanifest`. Use
<activity android:name=".ActivityName"
android:theme="#android:style/Theme.Dialog"> // add this line to give it the effect of a dialog
</activity>
You can start this Activity for result using startActivityForResult(). Then when that result returns to ActivityB you can finish and return to ActivityA or whatever you need to do.
Hope this helped.
I found the solution to it, after trying over and over to understand why. All that needs to be done is to create a runnable in the Context menu, as it seems to need to be returned quickly otherwise it recreates the Activity. I could be wrong and please feel free to correct me on this one.
Activity A - Context Menu
#Override
public boolean onContextItemSelected(MenuItem item) {
AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
final ItemClass selItem = (ItemClass)this.getListView().getItemAtPosition(info.position);
Intent intent;
SyncData sync;
switch (item.getItemId()) {
case R.id.start_activity_b:
runOnUiThread(new Runnable() {
#Override
public void run() {
Intent intent = new Intent(ActivityA.this, ActivityB.class);
intent.putExtra("data1", selItem.itemID);
intent.putExtra("data2", "AUTO");
Measurements.this.startActivityForResult(intent, REQUESTCODE_ACTIVITYB);
}
});
return true;
default:
return super.onContextItemSelected(item);
}
}