i have this code but every time i run the app and click on my button it crashes and i don't get why.. am i doing something wrong here any help would be great thanks
im trying to got to the "Sec.class" page/class
public class APPcalendarActivity extends Activity implements OnClickListener{
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
View continueButton = findViewById(R.id.continue_button);
continueButton.setOnClickListener( (OnClickListener) this);
}
//#Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch (v.getId()) {
case R.id.continue_button:
Intent i = new Intent(this, Sec.class);
startActivity(i);
break;
}
}
THIS IS WHAT I WAS MISSING IN THE MANISFEST.XML FILE
and i want to slap the person who downgraded my question
<activity android:name=".Sec"
android:label="#string/sec" >
</activity>
Check that you've declared an <activity> tag for the Sec activity in your AndroidManifest.xml.
But posting (or simply reading) the crash stacktrace from logcat would be more instructive.
Without knowing what the error is, it is really hard to guess what the problem is, but usually when this happens, the button (continueButton in your case) could not be found in the layout. So make sure that you have a View with id continue_button in main.xml.
Related
In Android Studio, I am trying to open the second activity when corresponding button is pressed.However, I cannot reach that listener that I create in "onCreate" from onPause. I am following an approach like this:
public class MainActivity extends Activity {
private View.OnClickListener openSecondPage = new View.OnClickListener() {
#Override
public void onClick(View v) {
Button button_newPage = findViewById(R.id.button_newpage);
button_newPage.setText("Clicked");
Intent secondPage = new Intent(getApplicationContext(), SecondActivity.class );
startActivity(secondPage);
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button_newPage = findViewById(R.id.button_newpage);
button_newPage.setOnClickListener(openSecondPage);
}
public void onPause(){
super.onPause();
Button button_newPage = findViewById(R.id.button_newpage);
//Destroy the on click listener
button_newPage.setOnClickListener(null);
}
}
Also user will be able to come back to main activity and then go back to the second activity again. In that case I don't want to open a new activity. Instead I want to open previously created activity. For that case should I create a onResume() method and in that, call startActivity(secondPage). But in that case, since the secondPage is declared in onStart I won't be able to use in onResume. How can I handle that situation?
So there are actually 2 questions.. sorry about that, I didn't want to open 2 different questions for it.
Put Button button_newPage = findViewById(R.id.button_newpage); and button_newPage.setOnClickListener(openSecondPage); inside onResume instead of onCreate, like so:
#Override
protected void onResume() {
super.onResume();
Button button_newPage = findViewById(R.id.button_newpage);
button_newPage.setOnClickListener(openSecondPage);
}
That should solve at least part of your problem.
I'm creating an app where the user can view their score histories and it works fine except that whenever I click on the fragment directly a new arraylist list is automatically created with the previous custom items. When I use the savebutton intent to get to the fragment no such issues arise and the recyclerview is updated as I want it to.
This is how I save scores using a navigation Menu item
case R.id.save_game:
Intent save = new Intent(getApplicationContext(), ScoreActivity.class);
Bundle extras = new Bundle();
extras.putString("EXTRA_DATE", format);
save.putExtras(extras);
startActivity(save);
Toast.makeText(this, "Saved", Toast.LENGTH_SHORT).show();
break;
I receive the intent in my ScoreFragment
public void saveScore(){
Intent intent = requireActivity().getIntent();
Bundle extras = intent.getExtras();
if (extras != null) {
String format = extras.getString("EXTRA_DATE");
mScoreList.add(new ScoreItem(TeamAName, TeamBName, scoreTeamA, scoreTeamB, format));
saveData(); //Saves Arraylist to sharedpreferences
}
}
And then I call saveScore() in my oncreateView method
My Score Fragment is attached to ScoreActivity like this
public class ScoreActivity extends AppCompatActivity {
#Override
protected void onCreate( Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_category);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction().replace(R.id.container,
new ScoreFragment()).commit();
}
}
}
I've tried putting my saveScore() method in onViewCreated() as well as onResume and onSaveInstanceState but it doesn't change anything.
Changing replace() to add() in my ScoreActivity also doesn't do anything.
Right after I inflate my rootView I call loadData() and I've been trying to call it somewhere else but it causes crahes.
private void loadData() {
SharedPreferences sharedPreferences = requireActivity().getSharedPreferences("shared preferences", Context.MODE_PRIVATE);
Gson gson = new Gson();
String json = sharedPreferences.getString("task list", null);
Type type = new TypeToken<ArrayList<ScoreItem>>() {
}.getType();
mScoreList = gson.fromJson(json, type);
if (mScoreList == null) {
mScoreList = new ArrayList<>();
}
}
How do I go about resolving this issue?
getIntent() always returns the Intent you used to create that Activity - so if you use that menu item to start a new one and add that extra
Intent save = new Intent(getApplicationContext(), ScoreActivity.class);
Bundle extras = new Bundle();
extras.putString("EXTRA_DATE", format);
save.putExtras(extras);
startActivity(save);
then that Activity will always return this Intent + Extras bundle when you call getIntent. So if your fragment has this in its onViewCreated:
Intent intent = requireActivity().getIntent();
Bundle extras = intent.getExtras();
and its parent activity was originally created with that Intent+Extras combo, then it will run your adding code
Honestly it depends on how your app is set up, so I can only give you ideas of things to look at
If you have an activity where fragments get swapped, so ScoreFragment can get re-added (you mentioned "using the navigation drawer to navigate to the fragment") then onViewCreated will run again with that Intent.
If it's off-screen and the system destroys its views to save memory, when it's recreated it will run onViewCreated again with that Intent.
If you call startActivity in different places, but an existing Activity gets reused (say your Activity is launched as singleTop or singleInstance) then it will have the Intent+Extras it was originally created with. So if you first create it through that menu item with the extras, and then call startActivity() without the extras from somewhere else, if the original activity gets used it will still have that Intent+Extras it was created with. (It'll receive the new intent throughonNewIntent() but it won't change the value of getIntent)
Also you're not actually checking if the extras Bundle has the EXTRA_DATE item, just if it has some extras, and then you're adding a new ScoreItem with whatever extras.getString("EXTRA_DATE") returns (which might be `null``). So if you're launching with other bundles of extras in different situations, you might still get the extra score added
I know that's a lot and it's not a solution but hope it helps! Honestly I'd recommend setting a breakpoint in saveScore, debug the app and use the debugger to see what getIntent is giving you, and if it looks right.
So I managed to solve the issue but I have no idea what I actually did. I decided to create an easy splash screen for my app and the problem just disappeared. I'm so confused right now and I would like some help in figuring it out so I can correct it in the future.
I created a new Activity called SplashScreenActivity
public class SplashScreenActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EasySplashScreen config = new EasySplashScreen(SplashScreenActivity.this)
.withFullScreen()
.withTargetActivity(MainActivity.class)
.withSplashTimeOut(5000)
.withBackgroundColor(Color.parseColor("#FF9800"))
.withHeaderText("Header")
.withFooterText("Footer")
.withBeforeLogoText("Before Logo Text")
.withAfterLogoText("After Logo Text")
.withLogo(R.mipmap.ic_launcher_round);
config.getHeaderTextView().setTextColor(Color.WHITE);
config.getFooterTextView().setTextColor(Color.WHITE);
config.getBeforeLogoTextView().setTextColor(Color.WHITE);
config.getAfterLogoTextView().setTextColor(Color.WHITE);
View easySplashScreen = config.create();
setContentView(easySplashScreen);
}
}
Then I moved MainActivity's intent-filter to the Splash Screen Activity in my Manifest.xml
file and this is what I think changed things.
<activity android:name=".SplashScreenActivity"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
I moved it back to the MainActivity a couple of times and I realized the problem came back each time the intent filter was in MainActivity. Now I keep it in .SplashScreenActivity in the Manifest and I have no such issues. I really need some explanation for this.
I have two android activities with one single button on both.
The activity DetailsActivity is my MAIN activity.
public class DetailsActivity extends Activity {
#Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.details_activity_layout);
}
#Override
public void onResume() {
super.onResume();
}
public void gotoSubDetails(View view) {
Intent intent = new Intent(this, SubDetailsActivity.class);
startActivity(intent);
finish();
}
}
And my SubDetailsActivity is as follows:
public class SubDetailsActivity extends Activity {
#Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.sub_details_activity_layout);
}
#Override
public void onResume() {
super.onResume();
}
public void gotoDetails(View view) {
Intent intent = new Intent(this, DetailsActivity.class);
startActivity(intent); // Restarting the finish()ed activity here.
finish();
}
}
And this is how I mentioned my button in details_activity_layout.xml for DetailsActivity.java:
<Button android:id="#+id/details_submit"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/to_sub_details"
android:onClick="gotoSubDetails" />
And this is how I have mentioned my button in sub_details_activity_layout.xml for SubDetailsActivity.java:
<Button android:id="#+id/sub_details_submit"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/back_to_details"
android:onClick="gotoDetails" />
These are my both activities in AndroidManifest.xml:
<activity android:name="DetailsActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="SubDetailsActivity">
</activity>
When I click the button in DetailsActivity, the activity finish()es properly and SubDetailsActivity starts up.
But when I click the button in SubDetailsActivity to get back to the finish()ed DetailsActivity, the app straight away crashes on my LG L90 phone.
Where am I going wrong? Any help? Please.
PS:
I cannot post the log cat report as I did not test it on my mac but directly on my phone. I don't have an emulator. I am compiling the code on my terminal and transferring the .apk file on my phone via bluetooth.
EDIT:
Ok guys. Now this is really funny!
I removed the
android:onClick="gotoSubDetails"
and
android:onClick="gotoDetails"
from my details_activity_layout.xml and sub_details_activity_layout.xml respectively. And I loaded the android.widget.Button's in my DetailsActivity.java and SubDetailsActivity.java and added an android.view.View.OnClickListener on both of them and overrode the onClick(View) method.
This is what I did in my DetailsActivity.java:
public class DetailsActivity extends Activity {
#Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.details_activity_layout);
Button button = (Button)findViewById(R.id.details_submit);
button.setOnClickListener(new DetailsSubmitListener());
}
#Override
public void onResume() {
super.onResume();
}
public class DetailsSubmitListener implements OnClickListener {
#Override
public void onClick(View view) {
Intent intent = new Intent(this, SubDetailsActivity.class);
startActivity(intent);
finish();
}
}
}
And this is what I did in my SubDetailsActivity.java class:
public class SubDetailsActivity extends Activity {
#Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.details_activity_layout);
Button button = (Button)findViewById(R.id.sub_details_submit);
button.setOnClickListener(new SubDetailsSubmitListener());
}
#Override
public void onResume() {
super.onResume();
}
public class SubDetailsSubmitListener implements OnClickListener {
#Override
public void onClick(View view) {
Intent intent = new Intent(this, DetailsActivity.class);
startActivity(intent);
finish();
}
}
}
And this miraculously worked fine.
So what was the problem with the .xml attributes in my layout files? And how different is it from the hardcoded listener in my .java file? This thing has confused me. finish()ed activities can be re-started. Thats what I discovered with my change in the program. Please shed some light of knowledge on this.
Aditya,
If you want to traverse between 2 activities like in your case, you should never finish Details activity. Instead without finishing Details activity, start SubDetails activity. If you want to come back, no coding required. If user presses BACK button, SubDetails Activity will be finished and DetailsActivity will come to foreground.
Finishing one activity and starting it again, is unnecessary overhead. Avoid it. Finish activity if it is absolutely necessary.
Also, there is no any way to restart finished activity.
Just like Harry answered,
I want to add something for you. If you are programming for higher API Levels (e.g. Android API 13+) you can define a parent activity.
This way you don't need to make such complex implementations.
For reference
Google Developers Guide to UP navigation
Stackoverflow ANSWER on the topic
I think you should read this!:
http://developer.android.com/guide/components/tasks-and-back-stack.html
I think it's very important how you declared the launchMode in your andriodManifest for your activities ! There should be the problem. Read carefully what is a task and how a back stack in android works.
Maybe you are finishing the task but at same time you are viewing the next activity which is in the same task ! After reopen it crashed because of this I think. Hope it helps.
I have three activities: First, Second and Third. I used this method in Second activity:
public void onBackPressed() {
super.onBackPressed();
finish();
}
and this on Third activity:
public void onBackPressed() {
super.onBackPressed();
Intent i = new Intent(Third.this, Second.class);
startActivity(i);
finish();
}
The problem is when I press back button after coming from the Third activity, I am going into First activity instead of finish(). I am successfully exiting the application when I click back button right after coming from first activity but not after coming from Third activity.
How to solve this problem?
EDIT: Thanks for the answers guys,the answer of "Ved Prakash" solved the problem for me.But i have a weird problem now.When i press back button the app is successfully exiting but the app which i minimized to Recent Apps button is coming on to the screen and exiting.For example,if i have opened Setting app before opening my app,when i press back button,my app is exiting and immediately Settings app is also opening and exiting itself.What might be the problem?
Your problem is that you don't seem to understand how Activities work. The finish() function ends the current Activity, and then you receive the previous Activity from the backstack.
My recommendation is that you should use a single Activity, and hold Fragments inside it. If you want it so that pressing the Back button ends the application at any screen that is displayed, you could do the following:
Activity XML:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/initial_container"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
Activity that holds the Fragments:
public class InitialActivity extends FragmentActivity implements ReplaceWith
{
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_initial);
getSupportFragmentManager().addOnBackStackChangedListener(new OnBackStackChangedListener()
{
public void onBackStackChanged()
{
int backCount = getSupportFragmentManager().getBackStackEntryCount();
if (backCount == 0)
{
finish();
}
}
});
if (savedInstanceState == null)
{
getSupportFragmentManager().beginTransaction().add(R.id.initial_container, new FirstFragment()).commit();
}
}
#Override
public void replaceWith(Fragment fragment)
{
getSupportFragmentManager().beginTransaction().replace(R.id.initial_container, fragment).commit();
}
}
Example for a Fragment:
public class FirstFragment extends Fragment implements View.OnClickListener
{
private ReplaceWith activity_replaceWith;
private ImageView exampleImage;
public FirstFragment()
{
super();
}
#Override
public void onAttach(Activity activity)
{
super.onAttach(activity);
try
{
activity_replaceWith = (ReplaceWith) activity;
}
catch (ClassCastException e)
{
Log.e(getClass().getSimpleName(), "Activity of " + getClass().getSimpleName() + "must implement ReplaceWith interface!", e);
throw e;
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View rootView = inflater.inflate(R.layout.fragment_first, container, false);
exampleImage = (ImageView) rootView.findViewById(R.id.fragment_first_example_image);
exampleImage.setOnClickListener(this);
return rootView;
}
#Override
public void onClick(View v)
{
if(v == exampleImage)
{
activity_replaceWith.replaceWith(new SecondFragment());
//please note that this should be done only if you are planning
//only on single-screen applications
//with no other layouts based on orientation or size
//otherwise, the Activity needs to be responsible for this, not the Fragment
}
}
}
This way, when you press the Back button, your application would end from any displayed screen.
Ok your code is wrong.
If you will look at activity source, you see that activity.onBackPressed() is calling finish(). So if call super.onBackPressed() you don't need to call finish.
Finish() is not stopping your application, it's stopping current activity.
Your code on third activity very strange. You are trying to stop activity and start another same activity.
What exactly you want to achieve?
If you want to exit application from your third activity, you need to clear your backstack. But I think you have problem with structure of your app.
Ok. then you should finish your first activity when you go to second activity like this(If you are using intent for that):
Intent it=new Intent(FirstActivity.this,SecondActivity.class);
finish();
startactivity(it);
and same for Second Activity:
Intent it=new Intent(SecondActivity.this,ThirdActivity.class);
finish();
startactivity(it);
this done your work...when you are in third activity the above activities are finished..
and when you press backButton you will be exit from application..
Good luck.
You can use -
public static final int FLAG_ACTIVITY_CLEAR_TOP
If set, and the activity being launched is already running in the
current task, then instead of launching a new instance of that
activity, all of the other activities on top of it will be closed and
this Intent will be delivered to the (now on top) old activity as a
new Intent.
And here is how -
When the user wishes to exit all open activities, they should press a button which loads the first Activity that runs when your app starts, in my case "MainActivity".
Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra("EXIT", true);
startActivity(intent);
The above code clears all the activities except for LoginActivity. LoginActivity is the first activity that is brought up when the user runs the program. Then put this code inside the LoginActivity's onCreate, to signal when it should self destruct when the 'Exit' message is passed.
if (getIntent().getBooleanExtra("EXIT", false)) {
finish();
}
This explanation part is also introduced at exit-an-android-app.
What I'm trying to do is Live Wallpaper with some action(that is already done)but the problem is there..that I've made it in Activity which "action" is an class who extends view and the Activity's setContentView() method isn't some layout ..it is this View.And what I'm trying to do now is to create option to set that activity as wallpaper,but I don't know how. This is my onCreate() method from the main Activity which is loading the View. I want that to be an Wallpaper..so how can I set it up to be one?
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SnowFall snowFallView = new SnowFall(this);
setContentView(snowFallView);
snowFallView.setBackgroundDrawable(getResources().getDrawable(
R.drawable.christmas));
}
Here's example app for what I want to create: https://play.google.com/store/apps/details?id=com.chiralcode.wallpaper.autumn&hl=bg
Did you implement wallpaper as a service? Get the basics - check Lars Vogel's tutorial on live wallpapers here
In short, you can set the wallpaper with an intent:
Intent intent = new Intent(WallpaperManager.ACTION_CHANGE_LIVE_WALLPAPER);
intent.putExtra(WallpaperManager.EXTRA_LIVE_WALLPAPER_COMPONENT, new ComponentName(this, MyWallpaperService.class));
startActivity(intent);
You will need to adapt the above to your class names, and remember to have the permission android.permission.BIND_WALLPAPER in your AndroidManifest, but again, read his tutorial.
Start Wallpaper service through activity , following is perfect working for that, you can put following in onclick(...) also, if you start livewallpaper ( your own live wallpaper directly through just one click) you just write following code,
btnInstallWallpaper.setOnClickListener(new OnClickListener() {
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
#SuppressLint("InlinedApi")
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent = new Intent();
if (android.os.Build.VERSION.SDK_INT >= 16)
{
intent.setAction("android.service.wallpaper.CHANGE_LIVE_WALLPAPER");
intent.putExtra("android.service.wallpaper.extra.LIVE_WALLPAPER_COMPONENT", new ComponentName("com.example.wall", "com.example.wall.WallpaperService"));
} else
intent.setAction("android.service.wallpaper.LIVE_WALLPAPER_CHOOSER");
intent.putExtra("android.service.wallpaper.extra.LIVE_WALLPAPER_COMPONENT", new ComponentName("com.example.wall", "com.example.wall.WallpaperService")); // package + classname
//}
startActivity(intent);
}
});