Android Parcelable object not passing properly between activities - java

This has been taxing my mind for the past two days. Oddly, the code works fine in one project, when passing an object from activity to fragment, but I cannot make this object pass from activity to activity, even when I appear to be implementing parcelable properly.
Oddly, I don't get a null object at the other end, but the object has got null values within it.
I've created a new project to test this with. This is the code so far:
MainActivity.java:
package com.example.parcleableexample;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends Activity {
Site mySite = new Site();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mySite.setSiteName("hi");
TextView myText = (TextView) findViewById(R.id.txtSiteName);
myText.setText(mySite.getSiteName());
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
public void doThing (View v) {
Intent mIntent = new Intent(this,AnotherActivity.class);
mIntent.putExtra("site", mySite);
startActivity(mIntent);
}
}
AnotherActivity.java:
package com.example.parcleableexample;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.widget.TextView;
public class AnotherActivity extends Activity {
Site mySite = new Site();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mySite = getIntent().getParcelableExtra("site");
TextView myText = (TextView) findViewById(R.id.txtSiteName);
myText.setText(mySite.getSiteName());
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
Site.Java:
package com.example.parcleableexample;
import android.os.Parcel;
import android.os.Parcelable;
public class Site implements Parcelable {
private String siteName;
Site() {
// Empty Constructor
}
public String getSiteName() {
return siteName;
}
public void setSiteName(String siteName) {
this.siteName = siteName;
}
// Parcleable Functions:
private int mData;
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel out, int flags) {
out.writeInt(mData);
}
public static final Parcelable.Creator<Site> CREATOR = new Parcelable.Creator<Site>() {
public Site createFromParcel(Parcel in) {
return new Site(in);
}
public Site[] newArray(int size) {
return new Site[size];
}
};
private Site(Parcel in) {
mData = in.readInt();
}
}
activity_main.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<TextView
android:id="#+id/txtSiteName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/hello_world" />
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/txtSiteName"
android:layout_below="#+id/txtSiteName"
android:layout_marginLeft="42dp"
android:layout_marginTop="25dp"
android:onClick="doThing"
android:text="Button" />
</RelativeLayout>
What I would expect, is for the "hi" value to appear both times, once when I start the app, and again when I click the button and the new activity creates.
However, it's only showing correctly the first time, the second time the getSiteName only returns null.
I also copied and pasted the Site object directly from the working app, with the same result, but it works in the working app as expected; the Site object is copied properly.
The working app runs this code:
Bundle arguments = new Bundle();
arguments.putParcelable("site", SearchResults.get(position));
ViewSiteFragment myFragment = new ViewSiteFragment();
myFragment.setArguments(arguments);
FragmentTransaction myTransaction = getFragmentManager().beginTransaction();
myTransaction.replace(R.id.MainFragmentContainer, myFragment);
myTransaction.addToBackStack(null);
myTransaction.commit();
And picks up the object at the other end here:
Site mSite = getArguments().getParcelable("site");
I know I'm doing something wrong... Just haven't got a clue what I've missed!

The problem is in your implementation of Parcelable. siteName is never written to the parcel, and you are writing mData instead, which is never used anywhere. You can keep mData if you need it, and ADD writes for siteName, see the code:
public void writeToParcel(Parcel out, int flags) {
out.writeInt(mData);
//we want to keep siteName in our parcel, so let's write it to the Parcel obj
out.writeString(siteName);
}
Later, add this code to read from parcel:
private Site(Parcel in) {
mData = in.readInt();
//let's read from in Parcel an set our siteName
siteName = in.readString();
}

Receive it like this with bundle object:
In activity2, in onCreate(), you can get the String message/object by retrieving a bundle (which contains all the messages sent by the calling activity) and call:
Bundle bundle = getIntent().getExtras();
mySite = bundle.getParcelableExtra("site");

Related

My app crashes when the device is in airplane mode

I tested my app setting the device in airplane mode, and it crashed.
MoviesListFragment.java
package com.example.android.popularmoviesstage_1;
import android.content.Context;
import android.content.res.Resources;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ProgressBar;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
/**
* A Class that extends Fragment to implement the Movie List structure
* A Fragment represents a behavior or a portion of user interface in a FragmentActivity.
*/
public class MoviesListFragment extends Fragment{
public static ProgressBar mLoadingIndicator;
public static TextView mErrorMessageDisplay;
public static SwipeRefreshLayout mSwipeContainer;
public static PosterAdapter mMoviesAdapter;
private Context mContext;
private MoviesRecyclerView mScrollListener;
private int mPage;
private int mSorting;
private static final int SORTING_POPULAR = 1;
private static final int SORTING_RATED = 2;
private static final String BUNDLE_MOVIES_KEY = "movieList";
private static final String BUNDLE_PAGE_KEY = "currentPage";
private static final String BUNDLE_SORTING_KEY = "currentSorting";
private static final String BUNDLE_ERROR_KEY = "errorShown";
private static final String TAG = MoviesListFragment.class.getSimpleName();
#Override
public void onCreate(#Nullable Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setHasOptionsMenu(true); //Allowing menu options in the ActionBar
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState){
Boolean errorShown = false;
if (savedInstanceState != null){
errorShown = savedInstanceState.getBoolean(BUNDLE_ERROR_KEY);
}
if (savedInstanceState != null && !errorShown){
mPage = savedInstanceState.getInt(BUNDLE_PAGE_KEY);
mSorting = savedInstanceState.getInt(BUNDLE_SORTING_KEY);
} else {
mPage = 1;
mSorting = 1;
}
//inflating the movies in this fragment
View rootView = inflater.inflate(R.layout.movie_list_fragment, container, false);
mContext = getContext();
final int columns = getResources().getInteger(R.integer.grid_columns);
// Laying the movie items in grid formation.
GridLayoutManager gridLayoutManager = new GridLayoutManager(mContext, columns, GridLayoutManager.VERTICAL, false);
RecyclerView recyclerView = rootView.findViewById(R.id.rv_posters);
recyclerView.setLayoutManager(gridLayoutManager);
//setting the size for all movie items
recyclerView.setHasFixedSize(true);
mMoviesAdapter = new PosterAdapter();
recyclerView.setAdapter(mMoviesAdapter);
//progress indicator catching movie data from the internet
mLoadingIndicator = rootView.findViewById(R.id.pb_loading_indicator);
mScrollListener = new MoviesRecyclerView(gridLayoutManager, mPage) {
#Override
public void onLoadMore(int page, int totalItemsCount, RecyclerView view) {
Log.d(TAG, "Loading page: " + String.valueOf(page));
mPage = page;
loadCards(mSorting);
}
};
recyclerView.addOnScrollListener(mScrollListener);
//The SwipeRefreshLayout is used whenever the user refresh the contents of a view via a vertical swipe gesture.
mSwipeContainer = rootView.findViewById(R.id.sr_swipe_container);
mSwipeContainer.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
mErrorMessageDisplay.setVisibility(View.INVISIBLE);
clearGridView();
loadCards(mSorting);
}
});
mSwipeContainer.setColorSchemeResources(R.color.colorAccent);
mErrorMessageDisplay = rootView.findViewById(R.id.tv_error_message_display);
if (savedInstanceState != null && !errorShown){
ArrayList<Movie> movieArrayList = savedInstanceState.getParcelableArrayList(BUNDLE_MOVIES_KEY);
mMoviesAdapter.setMoviesData(movieArrayList);
} else {
loadCards(mSorting);
}
return rootView;
}
//onSaveInstanceState() is called before your activity is paused.
// So any info that it needs after it is potentially destroyed can be retrieved from the saved Bundle
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
List<Movie> movieList = mMoviesAdapter.getMoviesData();
if (movieList != null){
ArrayList<Movie> movieArrayList = new ArrayList<>(mMoviesAdapter.getMoviesData());
outState.putParcelableArrayList(BUNDLE_MOVIES_KEY, movieArrayList);
outState.putInt(BUNDLE_PAGE_KEY, mPage);
outState.putInt(BUNDLE_SORTING_KEY, mSorting);
} else {
if (mErrorMessageDisplay.isShown()){
outState.putBoolean(BUNDLE_ERROR_KEY, true);
}
}
}
/**
* A method that invokes the AsyncTask to populate the RecyclerView,
* it's based on the sorting option selected by the user. Default is "popular movies"
*
* #param sorting the way of sorting selected by the user
*/
private void loadCards(int sorting){
if(NetworkUtils.isOnline(mContext)){
String method;
switch (sorting){
case SORTING_POPULAR:
method = NetworkUtils.getMoviesPopular();
break;
case SORTING_RATED:
method = NetworkUtils.getMoviesTopRated();
break;
default:
method = NetworkUtils.getMoviesPopular();
break;
}
String[] posters = new String[]{method, String.valueOf(mPage)};
new FetchMovieTask().execute(posters);
} else {
showErrorMessage(R.string.error_no_connectivity);
if (mSwipeContainer.isRefreshing()) {
mSwipeContainer.setRefreshing(false);
}
}
}
/**
* Reset the GridView properties and adapter
*/
private void clearGridView(){
mScrollListener.resetState();
mPage = 1;
mMoviesAdapter.clear();
}
/**
* Display the specific error message in the TextView
*
* #param messageId the resource id of the error string
*/
public static void showErrorMessage(int messageId){
mErrorMessageDisplay.setText(Resources.getSystem().getText(messageId));
mErrorMessageDisplay.setVisibility(View.VISIBLE);
}
//onCreateOptionsMenu() to specify the options menu for an activity.
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.main, menu);
switch (mSorting) {
case SORTING_POPULAR:
menu.findItem(R.id.sort_popular).setChecked(true);
break;
case SORTING_RATED:
menu.findItem(R.id.sort_rated).setChecked(true);
break;
default:
menu.findItem(R.id.sort_popular).setChecked(true);
break;
}
}
/*
*When the user selects an item from the options menu (including action items in the app bar),
* the system calls our activity's onOptionsItemSelected() method.
* This method passes the MenuItem selected. We can identify the item by calling getItemId(),
* which returns the unique ID for the menu item (defined by the android:id attribute in the menu
* resource or with an integer given to the add() method). We can match this ID against known menu
* items to perform the appropriate action.
*/
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.sort_popular || id == R.id.sort_rated) {
if (!item.isChecked()) {
mSorting = item.getOrder();
item.setChecked(true);
clearGridView();
loadCards(mSorting);
}
return true;
}
return super.onOptionsItemSelected(item);
}
}
MainActivity.java
package com.example.android.popularmoviesstage_1;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
public class MainActivity extends FragmentActivity {
/**
* MainActivity, which is presented to the user when the app is launched.
*/
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);//MoviesListFragment is used here
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.android.popularmoviesstage_1.MainActivity">
<!-- This fragment is used in MainActivity -->
<fragment
android:name="com.example.android.popularmoviesstage_1.MoviesListFragment"
android:id="#+id/f_movie_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:layout="#layout/movie_list_fragment" />
</FrameLayout>
movie_list_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="#dimen/padding_ten"
android:paddingRight="#dimen/padding_ten">
<TextView
android:id="#+id/tv_error_message_display"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="#dimen/padding_sixteen"
android:text="#string/error_message"
android:drawableRight="#android:drawable/stat_notify_error"
android:drawableEnd="#android:drawable/stat_notify_error"
android:drawableTint="#android:color/holo_red_dark"
android:drawablePadding="#dimen/padding_four"
android:textSize="#dimen/movie_detail_text_size"
android:background="#android:color/white"
android:visibility="invisible" />
<ProgressBar
android:id="#+id/pb_loading_indicator"
android:layout_width="#dimen/padding_fourty_two"
android:layout_height="#dimen/padding_fourty_two"
android:layout_gravity="center"
android:indeterminateTint="#android:color/holo_blue_bright"
android:visibility="invisible" />
<android.support.v4.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/sr_swipe_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/rv_posters"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.v4.widget.SwipeRefreshLayout>
</FrameLayout>
strings.xml
<resources>
<string name="app_name">Popular Movies</string>
<string name="sort_popular">Most Popular</string>
<string name="sort_rated">Top Rated</string>
<string name="poster_image_alt">Poster Image</string>
<string name="error_message">An error has occurred. Please try again by swiping down</string>
<string name="error_no_connectivity">Your device is not connected to the Internet.</string>
<string name="error_moviedb_list">Error from the MovieDB Service. Swipe down to try again</string>
<string name="error_movie_poster">Error loading the poster, sorry!</string>
<string name="no_internet_connection">No Internet connection</string>
<string name="button_retry">RETRY</string>
<string name="checkInternetConnection">Check Internet</string>
</resources>
This is the error description:
FATAL EXCEPTION: main
Process: com.example.android.popularmoviesstage_1, PID: 21294
android.content.res.Resources$NotFoundException: String resource ID #0x7f0d0026
Here is the stacktrace of this error:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.android.popularmoviesstage_1, PID: 21294
android.content.res.Resources$NotFoundException: String resource ID #0x7f0d0026
at android.content.res.Resources.getText(Resources.java:331)
at com.example.android.popularmoviesstage_1.MoviesListFragment.showErrorMessage(MoviesListFragment.java:185)
at com.example.android.popularmoviesstage_1.MoviesListFragment.loadCards(MoviesListFragment.java:161)
at com.example.android.popularmoviesstage_1.MoviesListFragment.access$300(MoviesListFragment.java:28)
at com.example.android.popularmoviesstage_1.MoviesListFragment$2.onRefresh(MoviesListFragment.java:104)
at android.support.v4.widget.SwipeRefreshLayout$1.onAnimationEnd(SwipeRefreshLayout.java:188)
at android.support.v4.widget.CircleImageView.onAnimationEnd(CircleImageView.java:106)
at android.view.ViewGroup.finishAnimatingView(ViewGroup.java:6278)
at android.view.View.draw(View.java:17027)
at android.view.ViewGroup.drawChild(ViewGroup.java:3768)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3554)
at android.view.View.draw(View.java:17086)
at android.view.View.updateDisplayListIfDirty(View.java:16065)
at android.view.View.draw(View.java:16849)
at android.view.ViewGroup.drawChild(ViewGroup.java:3768)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3554)
at android.view.View.updateDisplayListIfDirty(View.java:16060)
at android.view.View.draw(View.java:16849)
at android.view.ViewGroup.drawChild(ViewGroup.java:3768)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3554)
at android.view.View.updateDisplayListIfDirty(View.java:16060)
at android.view.View.draw(View.java:16849)
at android.view.ViewGroup.drawChild(ViewGroup.java:3768)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3554)
at android.view.View.updateDisplayListIfDirty(View.java:16060)
at android.view.View.draw(View.java:16849)
at android.view.ViewGroup.drawChild(ViewGroup.java:3768)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3554)
at android.view.View.updateDisplayListIfDirty(View.java:16060)
at android.view.View.draw(View.java:16849)
at android.view.ViewGroup.drawChild(ViewGroup.java:3768)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3554)
at android.view.View.draw(View.java:17086)
at com.android.internal.policy.DecorView.draw(DecorView.java:751)
at android.view.View.updateDisplayListIfDirty(View.java:16065)
at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:657)
at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:663)
at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:771)
at android.view.ViewRootImpl.draw(ViewRootImpl.java:2808)
at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2616)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2223)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1258)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6348)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:871)
at android.view.Choreographer.doCallbacks(Choreographer.java:683)
at android.view.Choreographer.doFrame(Choreographer.java:619)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:857)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6123)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:757)
In order to get a String in a fragment use the following code
getResources().getString(R.id.error_no_connectivity).
This will fix the crash for you. You are not referencing the string in your strings.xml correctly
You method should be (Removed the static keyword)
public void showErrorMessage(int messageId){
mErrorMessageDisplay.setText(getResources().getString(messageId));
mErrorMessageDisplay.setVisibility(View.VISIBLE);
}

To stop a Background Music from 1 activity to another using a checkbox?

My Main Activity has a background music, and I want to stop it whenever I can, through a checkbox. I have the codes already in order to set the background music into the Main activity, and it works perfect. The problem is that I want to stop a specific song from another activity using a CheckBox. I configured the checkbox, however, it does not work. Somehelp is really appreciated.
PD: The comunication between these two activities work well. It is the checkbox that does not work
Here are my codes used.
MainActivity.java
`
public class MainActivity extends Activity implements View.OnClickListener {
MediaPlayer bkgrdmsc;
private int lmusic_checked = SettingsActivity.music_checked;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (lmusic_checked == 0){
bkgrdmsc = MediaPlayer.create(MainActivity.this, R.raw.backgroundmusic);
bkgrdmsc.setLooping(true);
bkgrdmsc.start();
}
#Override
protected void onPause() {
if (lmusic_checked == 0){
bkgrdmsc.release();
}
SettingsActivity.music_checked =0;
super.onPause();
bkgrdmsc.release();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
//inflate the menu; this adds items to the action bar if this is present
super.onCreateOptionsMenu(menu);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
Intent s_intent = new Intent(this, SettingsActivity.class);
startActivity(s_intent);
return true;
}
else if (id == R.id.logo_home){
Intent t_intent = new Intent(this, Twitter.class);
startActivity(t_intent);
return true;
}
return super.onOptionsItemSelected(item);
}
activity_settings.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:weightSum="1">
<TextView
android:layout_width="271dp"
android:layout_height="77dp"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="#string/c_general"
android:id="#+id/textView"
android:layout_gravity="center_vertical"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="57dp"
android:textSize="26dp" />
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/turn_on_music"
android:id="#+id/CheckBox"
android:layout_below="#+id/textView"
android:layout_centerHorizontal="true"
android:checked="false"
android:singleLine="false"
android:textColor="#000000" />
</RelativeLayout>
SettingsActivity.java
package com.example.json.publicomidas;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.CheckBox;
import android.widget.CompoundButton;
public class SettingsActivity extends Activity {
public static int music_checked= 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.action_settings);
music_off();
}
public void music_off(){
CheckBox checkBox1 = (CheckBox) findViewById(R.id.CheckBox);
checkBox1.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (buttonView.isChecked()) {
music_checked = 1;
} else {
music_checked = 0;
}
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
//inflate the menu; this adds items to the action bar if this is present
super.onCreateOptionsMenu(menu);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_settings, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.home) {
Intent s_intent = new Intent(this, MainActivity.class);
startActivity(s_intent);
return true;
}
return super.onOptionsItemSelected(item);
}
}
Man, you should not do it this way... You cannot make two activities communicate each other with a static field :) When you change the value of music_checked in SetttingsActivity this changes nothing in the MainActivity.
My advice is to create a Service that runs the music. Both the activities should properly bind to the service and manipulate the music playback.
Update1
The communication you have implemented using this static field works only in one direction. You cannot stop the music by changing the music_checked property. It is a property of the SettingsActivity class and the MainActivity instance knows nothing about its state.
The proper way to implement this is using a Service that plays the music. It is not correct to play the music from an Activity if you want the playback to continue after the activity is paused/stoped. Create a bound service and bind each activity to the service in their onResume or onStart method (and unbind in onPause/onStop). By binding to the service you receive an object that exposes some API (you have to define this API and create the object according to the functionality you want to have). Using this API you can control the service from both the activities.
I'll advise you to read a bit more about activities and services in android and their lifecycle.

setOnClickListener in TextView

I'm trying to build an text view that goes to onClick but its not working they told me to add this code I did it but I'm having a lot of errors in it.
this is my MainActivity.java
package imamalsajadsayings.android.com;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void runNextTask(){
final View addView = getLayoutInflater().inflate(R.layout.addnewtracker, null);
final TrackerInfo newInfo = new TrackerInfo();
//set up for model selection
TextView modelTextview = (TextView)addView.findViewById(R.id.state1);
modelTextview.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
and is my textview
<TextView
android:id="#+id/state1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/Tracker_model"
android:clickable="true"
note : I don't have addnewtracker created
errors :
Description Resource Path Location Type
TrackerInfo cannot be resolved to a type MainActivity.java /ImamAlsajadsayings/src/imamalsajadsayings/android/com line 20 Java Problem
addnewtracker cannot be resolved or is not a field MainActivity.java /ImamAlsajadsayings/src/imamalsajadsayings/android/com line 19 Java Problem
The method setOnClickListener(View.OnClickListener) in the type View is not applicable for the arguments (new OnClickListener(){}) MainActivity.java /ImamAlsajadsayings/src/imamalsajadsayings/android/com line 23 Java Problem
TrackerInfo cannot be resolved to a type MainActivity.java /ImamAlsajadsayings/src/imamalsajadsayings/android/com line 20 Java Problem
The method onClick(View) of type new OnClickListener(){} must override or implement a supertype method MainActivity.java /ImamAlsajadsayings/src/imamalsajadsayings/android/com line 25 Java Problem
OnClickListener cannot be resolved to a type MainActivity.java /ImamAlsajadsayings/src/imamalsajadsayings/android/com line 23 Java Problem
add to activity:
public void modelTextViewClick(View v) {
//do something on click
}
and to layout:
<TextView android:id="#+id/state1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/Tracker_model"
android:clickable="true"
android:onClick="modelTextViewClick"/>
and remove your on click listener.
Change below code to your XML file
<TextView android:id="#+id/state1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/Tracker_model"
android:clickable="true"
android:onClick="runNextTask"/>
and just modify your java file as follow.
public void runNextTask(View v){
final View addView = getLayoutInflater().inflate(R.layout.addnewtracker, null);
final TrackerInfo newInfo = new TrackerInfo();
//set up for model selection
TextView modelTextview = (TextView)addView.findViewById(R.id.state1);
modelTextview.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
}
});
you need to import this package to avoid this error
missing this -> import android.view.View.OnClickListener;
Use below piece of code.
package imamalsajadsayings.android.com;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void runNextTask(){
final View addView = getLayoutInflater().inflate(R.layout.addnewtracker, null);
final TrackerInfo newInfo = new TrackerInfo();
//set up for model selection
TextView modelTextview = (TextView)addView.findViewById(R.id.state1);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
public void modelTextViewClick(View view)
{
// here view reference is your text view reference.
// put your on click handler code.
}
}
difference between this code and your code is onclick handler. In xml you have already defined a on click handler which you have to use in activity code. Other way set onclick listener handler foe your widget. Your doing both but either one of them is allowed not both for any widget in android.
You haven't call runNextTask from ur onCreate()
u r inflating a layout but didn't add that layout in any layout of ur activity_main layout using addView method
thats why it didn't work
it should be
package imamalsajadsayings.android.com;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.widget.TextView;
import android.view.View.OnClickListener;
public class MainActivity extends Activity {
private LayoutInflater inflater;
private LinearLayout someLayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
someLayout = (LinearLayout) findViewById(R.id.some_layout); //layout present in activity_main
inflater = (LayoutInflater)getSystemService(LAYOUT_INFLATER_SERVICE);
runNextTask();
}
public void runNextTask(){
LinearLayout mInflatedLayout = (LinearLayout) inflater.inflate(R.layout.addnewtracker, null);
final TrackerInfo newInfo = new TrackerInfo();
//set up for model selection
TextView modelTextview = (TextView)mInflatedLayout.findViewById(R.id.state1);
someLayout.addView(mInflatedLayout);
modelTextview.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
Assuming u r using LinearLayout in ur activity_main layout

android: null pointer exception when trying to set any property of button

i have checked everything in this but still i am getting a null pointer exception . whenever i am trying to change the properties of button in java file, app stop working and logcat showing null pointer exception. plzz help me out
here is my code
package com.example.rapid_finger;
import java.util.Random;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.NavUtils;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Button;
public class PlayScreen extends Activity {
#SuppressLint("NewApi")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Random rand = new Random();
int data = rand.nextInt(99);
String str = Integer.toString(data);
Button b = (Button) findViewById(R.id.b1);
b.setText(str);
setContentView(R.layout.activity_play_screen);
// Show the Up button in the action bar.
setupActionBar();
}
/**
* Set up the {#link android.app.ActionBar}, if the API is available.
*/
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
private void setupActionBar() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
getActionBar().setDisplayHomeAsUpEnabled(true);
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.play_screen, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
// This ID represents the Home or Up button. In the case of this
// activity, the Up button is shown. Use NavUtils to allow users
// to navigate up one level in the application structure. For
// more details, see the Navigation pattern on Android Design:
//
// http://developer.android.com/design/patterns/navigation.html#up- vs-back
//
NavUtils.navigateUpFromSameTask(this);
return true;
}
return super.onOptionsItemSelected(item);
}
}
and here is my xml file
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context=".PlayScreen" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/scores" />
<Button
android:id="#+id/b1"
android:background="#drawable/back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</RelativeLayout>
You did findViewById before you setContentView.
setContentView should come first
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_play_screen);
Random rand = new Random();
int data = rand.nextInt(99);
String str = Integer.toString(data);
Button b = (Button) findViewById(R.id.b1);
b.setText(str);
// Show the Up button in the action bar.
setupActionBar();
}
put setContentView(R.layout.activity_play_screen); after super.onCreate(savedInstanceState);
// replace this code
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_play_screen);
Random rand = new Random();
int data = rand.nextInt(99);
String str = Integer.toString(data);
Button b = (Button) findViewById(R.id.b1);
b.setText(str);
// Show the Up button in the action bar.
setupActionBar();
}

Unhandled exception type when trying to use buttons as Nav menu

I am trying to link different buttons to different activities. so in effect creating a navigation menu.
I am trying to use less code so am trying to create one function i can pass values to in order to dynamically identify the buttons id and give it a link to the activity.
Here is my xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<Button
android:id="#+id/nav1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:text="#string/nav1" />
<Button
android:id="#+id/nav2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_below="#+id/nav1"
android:text="#string/nav2" />
</RelativeLayout>
Here is my Java:
package com.example.myfirstapp;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class Nav extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_nav);
String nav1 = "nav1";
String nav2 = "nav2";
String MainActivity = "MainActivity";
String SQLite = "SQLite";
navButton(nav1, MainActivity);
navButton(nav2, SQLite);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_nav, menu);
return true;
}
private void navButton(String buttonId, String activityName){
String bId = buttonId;
final Class<?> aName = Class.forName(activityName);
int resId = getResources().getIdentifier(bId, "id", getPackageName());
Button b = (Button) findViewById(resId);
OnClickListener onClickListener = new OnClickListener(){
#Override
public void onClick(View v) {
Intent i = new Intent(Nav.this, aName);
startActivity(i);
}};
b.setOnClickListener(onClickListener);
}
}
I am getting an error on line:
final Class<?> aName = Class.forName(activityName);
And it says:
Unhandled exception type ClassNotFoundException
Or quite simply whats the best way to do this
Any time I use Class.forName I pass in a qualified name, e.g. "mypackage.myclass". I'm not sure if it works with an unqualified name.
In any case, why pass in the string and then do a forName? Why not change the signature to take a Class object and just pass in MainActivity.class, etc? Then you'd catch any missing classes or spelling errors at compile time instead of run time.
Update in response to comment
public class Nav extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_nav);
navButton("nav1", MainActivity.class);
navButton("nav2", SQLite.class);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_nav, menu);
return true;
}
private void navButton(String buttonId, Class aName){
String bId = buttonId;
// aName now passed in so doesn't need to be looked up
... etc ...
}
}
I think the above should compile and run. I haven't tried it but I've done similar things. Depending on how your packages are set up, you may need to import MainActivity and SQLite, or fully quality them, in order to take the .class.
Have you defined your activities in your application's AndroidManifest.xml?
You aren't catching the checked exception ClassNotFoundException. You need to wrap the relevant code in a try/catch block, e.g.
try {
final Class<?> aName = Class.forName(activityName);
//etc...
} catch (ClassNotFoundException e) {
//Do whatever cleanup you have to do in case this situation occurs.
}
This seems like an unusually awkward way to set a click listener, though. Why can you not just pass in the class itself to your navButton method instead of doing reflection (which should always be a last resort if there's an alternative)?

Categories