I have tried to show a message By using the Toast function In different formats I have served many parameters Like : getBaseContext(), getContext(),.getApplication(),Context()
But in the end there are mistakes and he did not succeed in showing a message
//My logCat:
AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.android.login, PID: 9911
java.lang.NullPointerException at com.example.android.login.retrieveUserLogin$1.onResponse(retrieveUserLogin.java:76) at retrofit.ExecutorCallAdapterFactory$ExecutorCallback$1.run(ExecutorCallAdapterFactory.java:86 at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5001)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
at dalvik.system.NativeStart.main(Native Method)
My class:
public class retrieveUserLogin {
public Activity activity;
private ProgressDialog progressDialog;
private HttpApi api;
public int value_array;
private List<Users> user;
private String UserAccount_;
private Call<HttpApi.HttpBinResponse> call;
private Call<List<Users>> getUsersCall;
private List<Integer>collection;
// private Context context;
Context mContext;
public retrieveUserLogin(final String t1 ,final String t2){
// context = context;
api = HttpApi.getInstance();
api.addHeader("Authorization","MyT23");
getUsersCall = api.getService().getAllChatRooms();
getUsersCall.enqueue(new retrofit.Callback<List<Users>>(){
String UserAccuent;
#Override
public void onResponse(retrofit.Response<List<Users>>response, Retrofit retrofit){
collection = new ArrayList<>();
user = response.body();
String [] arrayString = new String[user.size()];
String [] arrayString2 = new String[user.size()];
int[] arrayInt = new int[user.size()];
for(int i=0; i<response.body().size(); i++){
arrayString[i] = user.get(i).user_name;
arrayString2[i] = user.get(i).email;
arrayInt[i] = user.get(i).password;
if(Arrays.asList(arrayString2).contains(t1)){
UserAccuent = arrayString[i];
break;
}
}
boolean Check = Arrays.asList(arrayString2).contains(t1);
boolean Check2 = contains(arrayInt , Integer.parseInt(t2));
if(Check == true && Check2 == true){
Toast.makeText(activity.getApplication(),"تم تسجيل الدخول يا......" +UserAccuent.toString() ,Toast.LENGTH_LONG).show();
// Toast.makeText(getContext(), "sdfasd"+5, Toast.LENGTH_LONG).show();
}else{
Toast.makeText(activity.getBaseContext(),"خطأ فى اسم البريد او كلمة السر" ,Toast.LENGTH_LONG).show();
}
}
#Override
public void onFailure(Throwable t){
progressDialog.dismiss();
// Toast.makeText(getContext(),"XXX" ,Toast.LENGTH_LONG).show();
}});
}
public static boolean contains(int[] arr,int item) {
for (int n : arr){
if (item == n){
return true;
}
}
return false;
}
// End ;
}
//Call from Activity
retrieveUserLogin("username","userpassword",Activity.this)
//Change in Constructor
public retrieveUserLogin(final String t1 ,final String t2, final Context context){
mContext = context;
Toast.makeText(mContext ,"خطأ فى اسم البريد او كلمة السر" ,Toast.LENGTH_LONG).show();}
Try this
In your non-activity class
public class NonActivity {
public void showToast(Context context, String message){
Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
}
}
change your constractor from public retrieveUserLogin(final String t1 ,final String t2){ to public retrieveUserLogin(Context context, final String t1 ,final String t2){
and assign mContext=context, then pass your activity instance to it.
DO NOT store activities and contexts in fields. Instead pass them as parameters to the method.
public void retrieveUserLogin(
final Context context,
final String t1 ,final String t2) {
// ...
// then change your toasts to
Toast.makeText(context, "...", Toast.LENGTH_LONG).show();
}
The problem was probably that you did not assign a value to activity, but passing context as a parameter solves that issue. That way, you can only call the method if you have a context to give it.
Toast does not show any message because the activity is null:
Toast.makeText(activity.getApplication(),"تم تسجيل الدخول يا......" +UserAccuent.toString() ,Toast.LENGTH_LONG).show();
That is also why you are seeing a NullPointerException in LogCat.
You need to initialize the activity of retrieveUserLogin class:
public Activity activity;
inside the class constructor, and probably you will need to change your constructor a bit by adding one more parameter:
public retrieveUserLogin(Activity activity, final String t1 ,final String t2){
// init activity here
this.activity = activity;
// your code
}
Related
I'm working on app that will use biometric as an option to login. Before I use the actual biometric prompt I need to check one thing from server - I use AsyncTask to do it. So, to sum up - I invoke AsyncTask from Parent Activity (login.java), and then AsyncTask uses biometricUtils.java class, that makes biometric prompt. The point is, I keep passing null instead of context to biometricUtils.java:
Attempt to invoke virtual method 'java.util.concurrent.Executor android.content.Context.getMainExecutor()' on a null object reference at biometricUtils.<init>(biometricUtils.java:34)
I have no idea to pass the context correctly.
Here's my code:
login.java
public class login extends AppCompatActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.login);
Bundle bundle = getIntent().getExtras();
final boolean flag = false;
final String androidID = bundle.getString("androidID");
final Activity thisActivity = this;
final Context context = getApplicationContext();
// login using biometrics
Button btnBiometricLogin = findViewById(R.id.btnBiometricLogin);
btnBiometricLogin.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
checkAndroidID async = new checkAndroidID(context);
async.getParentActivity(thisActivity);
async.setFlag(flag);
async.execute(androidID);
}
});
}
}
checkAndroidID.java
public class checkAndroidID extends AsyncTask <String, Void, String> {
openHTTP openHTTP = new openHTTP();
requestHTTP requests = new requestHTTP();
Activity parentActivity;
private WeakReference<Context> contextRef;
Boolean flag;
public checkAndroidID(Context context){
contextRef = new WeakReference<>(context);
}
public void getParentActivity(Activity parentActivity){
this.parentActivity = parentActivity;
}
public void setFlag (Boolean flag){
this.flag = flag;
}
#Override
protected String doInBackground(String... strings) {
try {
HttpURLConnection httpConn = openHTTP.prepareConnection("url");
String json = "{ \"androidID\": \"" + strings[0] + "\" }";
requests.sendData(json, httpConn);
return requests.receiveData(httpConn);
} catch (Exception e){
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String s) {
String[] result = s.split(";");
Context ctx = contextRef.get();
if (result[0].equals("TRUE")) flag = true;
if (!flag) Toast.makeText(parentActivity, "Biometric authentication is now unavailable." +
" Please login using username and password", Toast.LENGTH_SHORT).show();
else {
biometricUtils biometrics = new biometricUtils(ctx);
biometrics.getParentActivity(parentActivity);
biometrics.getUsername(result[1]);
biometrics.inovkeBiometricPrompt();
}
super.onPostExecute(s);
}
}
and biometricUtlis.java
public class biometricUtils {
Activity parentActivity;
String username;
Context context;
public void getParentActivity(Activity parentActivity){
this.parentActivity = parentActivity;
}
public void getUsername(String s){
this.username = s;
}
public biometricUtils(Context context){
this.context = context;
}
// creating a variable for our Executor
Executor executor = ContextCompat.getMainExecutor(context); // LINE 34
// this will give us result of AUTHENTICATION
final BiometricPrompt biometricPrompt = new BiometricPrompt((FragmentActivity) parentActivity, executor, new BiometricPrompt.AuthenticationCallback() {
#Override
public void onAuthenticationError(int errorCode, #NonNull CharSequence errString) {
super.onAuthenticationError(errorCode, errString);
}
// THIS METHOD IS CALLED WHEN AUTHENTICATION IS SUCCESS
#Override
public void onAuthenticationSucceeded(#NonNull BiometricPrompt.AuthenticationResult result) {
super.onAuthenticationSucceeded(result);
Intent intent = new Intent(parentActivity.getApplicationContext(), tmp.class);
intent.putExtra("username", username);
parentActivity.startActivity(intent);
}
#Override
public void onAuthenticationFailed() {
super.onAuthenticationFailed();
}
});
// creating a variable for our promptInfo
// BIOMETRIC DIALOG
final BiometricPrompt.PromptInfo promptInfo = new BiometricPrompt.PromptInfo.Builder().setTitle("Biometrical login")
.setDescription("Place your fingerprint on scanner to proceed").setNegativeButtonText("Cancel").build();
public void inovkeBiometricPrompt() {
biometricPrompt.authenticate(promptInfo);
}
}
In my app, I use a Contacts database and display those contacts using a RecyclerView . When I click on a contact, I want to fetch its data from the tables in the DB, and load them in a new Activity, ContactCard. I have an AsyncTask() which fetches the PhoneNumber objects that match the selected contactId, but I will also need to retrieve the Address and Email objects from the other tables.
I would like to be able to start the activity after all the relevant data is fetched, and I tried doing this in the activity with the Contacts RecyclerView, but the application crashes as the data has not been fetched yet.
I can call the new activity using an intent, but how can I ensure data from different tables is fetched first, before I start the new activity (which effectively displays this data)?
Some of my code:
public class PhoneNumberRepository {
private WorksideDatabase worksideDatabase;
private List<PhoneNumber> returnedNumbers;
private Context mContext;
public PhoneNumberRepository(Context context) {
String DB_NAME = "workside_database";
worksideDatabase = Room.databaseBuilder(context, WorksideDatabase.class, DB_NAME).build();
mContext = context;
}
public List<PhoneNumber> fetchPhoneNumbers(final int id) {
new AsyncTask<Integer, Void, List<PhoneNumber>>() {
#Override
protected List<PhoneNumber> doInBackground(Integer... ids) {
returnedNumbers = worksideDatabase.phoneNumberDao().getPhoneNumbersById(id);
System.out.println(returnedNumbers);
for (PhoneNumber pn : returnedNumbers) {
System.out.println("Number: " + pn.getPhoneNumber());
}
return returnedNumbers;
}
// This runs in UI when background thread finishes
#Override
protected void onPostExecute(List<PhoneNumber> result) {
super.onPostExecute(result);
System.out.println("Entered onPostExecute of fetchPhoneNumbers");
// for (PhoneNumber pn : result) {
// Toast.makeText(mContext, pn + "", Toast.LENGTH_SHORT).show();
// }
}
}.execute();
return returnedNumbers;
}
public List<PhoneNumber> getPhoneNumbers(int id) {
return fetchPhoneNumbers(id);
}
}
ContactsFragment:
adapter.setOnItemClickListener(
contact -> {
Intent viewContact = new Intent(getActivity(), WorksideContactCard.class);
viewContact.putExtra(WORKSIDE_CONTACT, contact);
PhoneNumberRepository phoneNumberRepository =
new PhoneNumberRepository(getActivity().getApplicationContext());
List<PhoneNumber> phoneNumberList;
phoneNumberList = phoneNumberRepository.getPhoneNumbers(contact.getId());
ArrayList<PhoneNumber> arrlistPhoneNumbers =
new ArrayList<>(phoneNumberList);
viewContact.putParcelableArrayListExtra(
WORKSIDE_CONTACT_PHONE_NO, arrlistPhoneNumbers);
startActivity(viewContact);
}
You can do this when you click on an item start the asyntask like this
adapter.setOnItemClickListener(
contact -> {
PhoneNumberRepository phoneNumberRepository =
new PhoneNumberRepository(getActivity().getApplicationContext());
List<PhoneNumber> phoneNumberList;
phoneNumberRepository.getPhoneNumbers(contact.getId());
}
and change your PhoneNumberRepository to this class
public class PhoneNumberRepository {
private WorksideDatabase worksideDatabase;
private List<PhoneNumber> returnedNumbers;
private Context mContext;
public PhoneNumberRepository(Context context) {
String DB_NAME = "workside_database";
worksideDatabase = Room.databaseBuilder(context, WorksideDatabase.class, DB_NAME).build();
mContext = context;
}
public void fetchPhoneNumbers(final int id) {
new AsyncTask<Integer, Void, List<PhoneNumber>>() {
#Override
protected List<PhoneNumber> doInBackground(Integer... ids) {
returnedNumbers = worksideDatabase.phoneNumberDao().getPhoneNumbersById(id);
System.out.println(returnedNumbers);
for (PhoneNumber pn : returnedNumbers) {
System.out.println("Number: " + pn.getPhoneNumber());
}
return returnedNumbers;
}
// This runs in UI when background thread finishes
#Override
protected void onPostExecute(List<PhoneNumber> result) {
super.onPostExecute(result);
Intent viewContact = new Intent(context, WorksideContactCard.class);
ArrayList<PhoneNumber> arrlistPhoneNumbers =
new ArrayList<>(result);
viewContact.putParcelableArrayListExtra(
WORKSIDE_CONTACT_PHONE_NO, arrlistPhoneNumbers);
context.startActivity(viewContact);
System.out.println("Entered onPostExecute of fetchPhoneNumbers");
}
}.execute();
}
public void getPhoneNumbers(int id) {
return fetchPhoneNumbers(id);
}
}
store the contacts in a list in the doInBackground() method and start an intent to the new activity in the onPostExecute() method and with this intent pass the list of contacts as intent.extra() variables, retrieve and use them in the called activity.
Change your repository class to something like this
public class PhoneNumberRepository {
private WorksideDatabase worksideDatabase;
private List<PhoneNumber> returnedNumbers;
private Context mContext;
private boolean dataDownloaded;
public PhoneNumberRepository(Context context) {
String DB_NAME = "workside_database";
worksideDatabase = Room.databaseBuilder(context, WorksideDatabase.class, DB_NAME).build();
mContext = context;
}
public List<PhoneNumber> fetchPhoneNumbers(final int id) {
new AsyncTask<Integer, Void, List<PhoneNumber>>() {
#Override
protected List<PhoneNumber> doInBackground(Integer... ids) {
returnedNumbers = worksideDatabase.phoneNumberDao().getPhoneNumbersById(id);
System.out.println(returnedNumbers);
for (PhoneNumber pn : returnedNumbers) {
System.out.println("Number: " + pn.getPhoneNumber());
}
return returnedNumbers;
}
// This runs in UI when background thread finishes
#Override
protected void onPreExecute(List<PhoneNumber> result) {
//set flag to false when download starts
dataDownloaded = false;
}
// This runs in UI when background thread finishes
#Override
protected void onPostExecute(Object obj) {
super.onPostExecute(result);
//set flag to true once download completes, you can also check if response is null and update it accordingly
dataDownloaded = true;
System.out.println("Entered onPostExecute of fetchPhoneNumbers");
// for (PhoneNumber pn : result) {
// Toast.makeText(mContext, pn + "", Toast.LENGTH_SHORT).show();
// }
}
}.execute();
return returnedNumbers;
}
public List<PhoneNumber> getPhoneNumbers(int id) {
return fetchPhoneNumbers(id);
}
public boolean isDataDownloaded(int id) {
return dataDownloaded;
}
}
Use this function in onItemClick() whether your data is downloaded or not
if(phoneNumberRepository.isDataDownloaded()) {
//code to fetch data from phonenumberrepo and start activity
}
I have 5 fragments inside my activity where one fragment stays active at one time. Clicking on a recyclerview item opens another fragment and puts current fragment in the backstack.
The same code was working fine some days ago, but now the app is throwing NotSerializableException whenever I click the home button to put the app in background. I have tried putting the initializing the variables inside onStart and then giving the null value in onStop but that didn't work.
Fragment Code:
public class PaperListFragment extends Fragment implements Serializable {
private static final String TAG = "PaperListFragment";
private static final String QUESTIONS_FRAGMENT_TAG = "questions_fragment";
private static final String ADD_PAPER_FRAGMENT_TAG = "add_paper_fragment";
private OnFragmentActiveListener mOnFragmentActiveListener;
private TextView mHeadingText;
private Bundle mOutState;
private FirebaseAuth mAuth;
private DatabaseReference mDatabaseReference;
private ProgressBar mProgressBar;
private OnItemClickListener mOnItemClickListener;
private FloatingActionButton mFab;
private RecyclerView mRecyclerViewPaper;
private ArrayList<Paper> mPaperList = new ArrayList<>();
private Subject mSubject = new Subject();
private Exam mExam = new Exam();
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_recycler_list, container, false);
mProgressBar = (ProgressBar) rootView.findViewById(R.id.progressbar_news);
mFab = (FloatingActionButton) rootView.findViewById(R.id.floatingActionButton);
mProgressBar.setVisibility(View.VISIBLE);
Log.d(TAG, "onCreateView: Fragment created");
mAuth = FirebaseAuth.getInstance();
mDatabaseReference = FirebaseDatabase.getInstance().getReference();
if (mAuth.getCurrentUser() == null) {
startActivity(new Intent(getActivity(), LoginActivity.class));
getActivity().finish();
return null;
}
if (getArguments() != null) {
mOnFragmentActiveListener = (OnFragmentActiveListener) getArguments().getSerializable(Keys.FRAGMENT_ACTIVE_LISTENER);
mSubject = (Subject) getArguments().getSerializable(Keys.SUBJECT_KEY);
mExam = (Exam) getArguments().getSerializable(Keys.EXAMS_KEY);
}
mRecyclerViewPaper = (RecyclerView) rootView.findViewById(R.id.recycler_list);
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity()) {
#Override
public boolean canScrollVertically() {
return false;
}
};
mRecyclerViewPaper.setLayoutManager(layoutManager);
Log.d(TAG, "onCreateView: Layout Manager Set.");
mFab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
startAddPaperFragment();
}
});
mOnItemClickListener = new OnItemClickListener() {
#Override
public void onItemClicked(RecyclerView.ViewHolder holder, int position) {
Log.d(TAG, "onItemClicked: Clicked item position is: "+ position);
QuestionListFragment questionFragment = new QuestionListFragment();
questionFragment.setRetainInstance(true);
startFragment(position, questionFragment, QUESTIONS_FRAGMENT_TAG);
}
#Override
public void OnItemLongClicked(RecyclerView.ViewHolder holder, int position) {
}
};
mHeadingText = (TextView) rootView.findViewById(R.id.heading_textview);
mHeadingText.setText(mExam.getExam_name()+" > "+ mSubject.getSubject_name());
if (mOutState != null) {
mPaperList = (ArrayList<Paper>) mOutState.getSerializable(Keys.PAPER_LIST_KEY);
updateUI();
} else {
updateUIFromDatabase();
}
return rootView;
}
private void startFragment(int position, Fragment fragment, String fragmentTag) {
Paper paper = new Paper();
if (mPaperList.size() > 0) {
paper = mPaperList.get(position);
}
Bundle args = new Bundle();
args.putSerializable(Keys.EXAMS_KEY, mExam);
args.putSerializable(Keys.SUBJECT_KEY, mSubject);
args.putSerializable(Keys.PAPER, paper);
args.putSerializable(Keys.FRAGMENT_ACTIVE_LISTENER, mOnFragmentActiveListener);
fragment.setArguments(args);
FragmentTransaction fragmentTransaction = getActivity().getSupportFragmentManager().beginTransaction();
fragmentTransaction.setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_left, R.anim.slide_in_left, R.anim.slide_out_right);
fragmentTransaction.replace(R.id.questions_fragment_container, fragment, fragmentTag);
fragmentTransaction.addToBackStack(fragmentTag);
fragmentTransaction.commit();
}
private void startAddPaperFragment() {
AddPaperFragment addPaperFragment = new AddPaperFragment();
addPaperFragment.setRetainInstance(true);
startFragment(0, addPaperFragment, ADD_PAPER_FRAGMENT_TAG);
}
private void updateUIFromDatabase() {
if (getArguments() != null){
Exam exam = (Exam) getArguments().getSerializable(Keys.EXAMS_KEY);
Subject subject = (Subject) getArguments().getSerializable(Keys.SUBJECT_KEY);
DatabaseReference paperReference =
mDatabaseReference
.child(Keys.APP_DATA_KEY)
.child(Keys.EXAM_PAPERS)
.child(exam.getExam_name())
.child(subject.getSubject_name());
Query query = paperReference.orderByChild(Keys.TIME_ADDED);
query.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
mPaperList.clear();
for (DataSnapshot paperChild : dataSnapshot.getChildren()) {
mPaperList.add(paperChild.getValue(Paper.class));
}
updateUI();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
}
private void updateUI() {
PaperRecyclerAdapter adapter = new PaperRecyclerAdapter(
getActivity(),
mRecyclerViewPaper,
mPaperList,
mOnItemClickListener
);
mRecyclerViewPaper.setAdapter(adapter);
mProgressBar.setVisibility(View.GONE);
}
#Override
public void onResume() {
super.onResume();
if (getArguments()!=null){
mOnFragmentActiveListener.onFragmentActive(
this,
"Topics"
);
}
}
#Override
public void onPause() {
super.onPause();
mOutState = new Bundle();
mOutState.putSerializable(Keys.PAPER_LIST_KEY, mPaperList);
}
}
Exception:
2018-12-26 17:49:38.344 14834-14834/in.crazybytes.bankmaniaadmin E/AndroidRuntime: FATAL EXCEPTION: main
Process: in.crazybytes.bankmaniaadmin, PID: 14834
java.lang.RuntimeException: Parcelable encountered IOException writing serializable object (name = in.crazybytes.bankmaniaadmin.activities.QuestionsActivity)
at android.os.Parcel.writeSerializable(Parcel.java:1526)
at android.os.Parcel.writeValue(Parcel.java:1474)
at android.os.Parcel.writeArrayMapInternal(Parcel.java:723)
at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1408)
at android.os.Bundle.writeToParcel(Bundle.java:1133)
at android.os.Parcel.writeBundle(Parcel.java:763)
at android.support.v4.app.FragmentState.writeToParcel(FragmentState.java:124)
at android.os.Parcel.writeTypedArray(Parcel.java:1306)
at android.support.v4.app.FragmentManagerState.writeToParcel(FragmentManager.java:639)
at android.os.Parcel.writeParcelable(Parcel.java:1495)
at android.os.Parcel.writeValue(Parcel.java:1401)
at android.os.Parcel.writeArrayMapInternal(Parcel.java:723)
at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1408)
at android.os.Bundle.writeToParcel(Bundle.java:1133)
at android.os.Parcel.writeBundle(Parcel.java:763)
at android.app.ActivityManagerProxy.activityStopped(ActivityManagerNative.java:3697)
at android.app.ActivityThread$StopInfo.run(ActivityThread.java:3768)
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)
Caused by: java.io.NotSerializableException: com.google.firebase.auth.internal.zzj
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1224)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1584)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1549)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1472)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1218)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1584)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1549)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1472)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1218)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:346)
at android.os.Parcel.writeSerializable(Parcel.java:1521)
at android.os.Parcel.writeValue(Parcel.java:1474)
at android.os.Parcel.writeArrayMapInternal(Parcel.java:723)
at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1408)
at android.os.Bundle.writeToParcel(Bundle.java:1133)
at android.os.Parcel.writeBundle(Parcel.java:763)
at android.support.v4.app.FragmentState.writeToParcel(FragmentState.java:124)
at android.os.Parcel.writeTypedArray(Parcel.java:1306)
at android.support.v4.app.FragmentManagerState.writeToParcel(FragmentManager.java:639)
at android.os.Parcel.writeParcelable(Parcel.java:1495)
at android.os.Parcel.writeValue(Parcel.java:1401)
at android.os.Parcel.writeArrayMapInternal(Parcel.java:723)
at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1408)
at android.os.Bundle.writeToParcel(Bundle.java:1133)
at android.os.Parcel.writeBundle(Parcel.java:763)
at android.app.ActivityManagerProxy.activityStopped(ActivityManagerNative.java:3697)
at android.app.ActivityThread$StopInfo.run(ActivityThread.java:3768)
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)
Note: The weird thing is that one of fragment has the exact same code and is hosted inside the same activity, but when that fragment is active and app goes to background, interestingly the app is not crashing.
**Exam Model Class:
package in.crazybytes.bankmaniaadmin.models;
import java.io.Serializable;
public class Exam implements Serializable {
private String mExam_name;
private String mExam_key;
private Long mTime_added;
private int mNum_subjects;
private int mNum_questions;
public Exam(String exam_name, String exam_key, Long time_added, int num_subjects, int num_questions) {
mExam_name = exam_name;
mExam_key = exam_key;
mTime_added = time_added;
mNum_subjects = num_subjects;
mNum_questions = num_questions;
}
public Exam() {
}
public String getExam_name() {
return mExam_name;
}
public void setExam_name(String exam_name) {
mExam_name = exam_name;
}
public String getExam_key() {
return mExam_key;
}
public void setExam_key(String exam_key) {
mExam_key = exam_key;
}
public Long getTime_added() {
return mTime_added;
}
public void setTime_added(Long time_added) {
mTime_added = time_added;
}
public int getNum_subjects() {
return mNum_subjects;
}
public void setNum_subjects(int num_subjects) {
mNum_subjects = num_subjects;
}
public int getNum_questions() {
return mNum_questions;
}
public void setNum_questions(int num_questions) {
mNum_questions = num_questions;
}
}
Paper Model Class
package in.crazybytes.bankmaniaadmin.models;
import java.io.Serializable;
public class Paper implements Serializable {
private String mPaper_name;
private String mPaper_key;
private Long mTime_added;
private int mNum_questions;
public Paper(String paper_name, String paper_key, Long time_added, int num_questions) {
mPaper_name = paper_name;
mPaper_key = paper_key;
mTime_added = time_added;
mNum_questions = num_questions;
}
public Paper() {
}
public String getPaper_key() {
return mPaper_key;
}
public void setPaper_key(String paper_key) {
mPaper_key = paper_key;
}
public Long getTime_added() {
return mTime_added;
}
public void setTime_added(Long time_added) {
mTime_added = time_added;
}
public int getNum_questions() {
return mNum_questions;
}
public void setNum_questions(int num_questions) {
mNum_questions = num_questions;
}
public String getPaper_name() {
return mPaper_name;
}
public void setPaper_name(String paper_name) {
mPaper_name = paper_name;
}
}
Subject Model Class:
package in.crazybytes.bankmaniaadmin.models;
import java.io.Serializable;
public class Subject implements Serializable {
private String mSubject_name;
private String mSubject_key;
private Long mTime_added;
private int mNum_papers;
private int mNum_questions;
public Subject(String subject_name, String subject_key, Long time_added, int num_papers, int num_questions) {
mSubject_name = subject_name;
mSubject_key = subject_key;
mTime_added = time_added;
mNum_papers = num_papers;
mNum_questions = num_questions;
}
public Subject() {
}
public String getSubject_name() {
return mSubject_name;
}
public void setSubject_name(String subject_name) {
mSubject_name = subject_name;
}
public String getSubject_key() {
return mSubject_key;
}
public void setSubject_key(String subject_key) {
mSubject_key = subject_key;
}
public Long getTime_added() {
return mTime_added;
}
public void setTime_added(Long time_added) {
mTime_added = time_added;
}
public int getNum_papers() {
return mNum_papers;
}
public void setNum_papers(int num_papers) {
mNum_papers = num_papers;
}
public int getNum_questions() {
return mNum_questions;
}
public void setNum_questions(int num_questions) {
mNum_questions = num_questions;
}
}
Somehow QuestionsActivity is getting into the fragment save state, even if you don't intend for that to happen. While QuestionsActivity is being serialized, another object that is not serializable is being encountered. That's why you see TextViews and other things attempting to get serialized because all the instance variables of QuestionsActivity get serialized by default.
My best guess for why this is happening is due to this line:
args.putSerializable(Keys.FRAGMENT_ACTIVE_LISTENER, mOnFragmentActiveListener);
But it's difficult to know for sure without seeing where OnFragmentActiveListener is defined. I'm assuming either QuestionsActivity implements OnFragmentActiveListener, or QuestionsActivity defines OnFragmentActiveListener as an inner class. Either way, if you put an OnFragmentActiveListener into fragment arguments, you will encounter an exception because you indirectly are storing the entire QuestionsActivity as a fragment arg too. When a fragment stops, all fragment args become part of the fragment save state. And that's the cause of the error.
I would suggest not passing the OnFragmentActiveListener around as a fragment arg. If the OnFragmentActiveListener comes from the activity, just use getActivity() to get a reference to the activity and then get a reference to the listener.
I also noticed PaperListFragment implements Serializable and I'm assuming you did the same thing for QuestionsActivity. You probably did this to get around compile errors. But this has led to runtime errors because the instance variables on both of these classes are not all serializable. So to avoid more runtime issues, I would suggest never having activities or fragments implement serializable because these classes are inherently not serializable due to their members.
I have two activities Select and Upload. I am passing two strings id and scan_id from one activity to another. The value passes correctly when I pass the id alone. But when I try to pass both the values the one value overrides the other value. Is there a separate way to pass the two strings???
SelectActivity.java
public class SelectActivity extends Activity {
String v1;
public static String EXTRA_MESSAGE_ID;
public static String EXTRA_MESSAGE_SCAN;
int flag;
String strflag;
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
.permitAll()
.build();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_select);
Bundle b = getIntent().getExtras();
EditText ed=(EditText)findViewById(R.id.patient_id);
ed.setText(b.getCharSequence("Contents"));
Button button = (Button) findViewById(R.id.button1);
StrictMode.setThreadPolicy(policy);
Button CTbutton = (Button) findViewById(R.id.CTScan);
CTbutton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
flag=1;
strflag = String.valueOf(flag);
Log.e("log_tag", "sel id"+flag);
Log.e("log_tag", "sel scan"+v1);
Intent intent = new Intent(SelectActivity.this,MainActivity.class);
intent.putExtra(EXTRA_MESSAGE_ID,v1);
intent.putExtra(EXTRA_MESSAGE_SCAN,strflag);
startActivity(intent);
}
});
}
}
MainActivity.java
public class MainActivity extends Activity {
private static final String TAG = MainActivity.class.getSimpleName();
private static final int CAMERA_CAPTURE_IMAGE_REQUEST_CODE = 100;
public static final int MEDIA_TYPE_IMAGE = 1;
private Uri fileUri;
private Button btnCapturePicture;
public static String EXTRA_MESSAGE_ID;
public static String EXTRA_MESSAGE_SCAN;
String message_id;
String message_scan;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getActionBar().setBackgroundDrawable(new ColorDrawable(Color.parseColor(getResources().getString(R.color.action_bar))));
Intent intent = getIntent();
message_id = intent.getStringExtra(SelectActivity.EXTRA_MESSAGE_ID);
message_scan = intent.getStringExtra(SelectActivity.EXTRA_MESSAGE_SCAN);
Log.e("log_tag", "id"+message_id);
Log.e("log_tag", "scan"+message_scan);
btnCapturePicture = (Button) findViewById(R.id.btnCapturePicture);
/**
* Capture image button click event
*/
btnCapturePicture.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
captureImage();
}
});
}
}
The logcat looks like this:
04-01 10:57:43.671: E/log_tag(12649): connection success
04-01 10:57:50.374: E/log_tag(12649): sel id1
04-01 10:57:50.374: E/log_tag(12649): sel scan2
04-01 10:57:50.403: E/log_tag(12649): id1
04-01 10:57:50.403: E/log_tag(12649): scan1
initialize the strings in both activity with same values
public static String EXTRA_MESSAGE_ID="something1";
public static String EXTRA_MESSAGE_SCAN="something2";
Your logic is correct but problem in below code
public static String EXTRA_MESSAGE_ID;
public static String EXTRA_MESSAGE_SCAN;
you don't have assign the value to a both variable. so by default both variable have blank value. so when you put the value, the second one will overwrite it. because both varable same key as blank value
So, try to use give unique value to a variable.
public static String EXTRA_MESSAGE_ID = "MSG_ID";
public static String EXTRA_MESSAGE_SCAN = "MSG_SCAN";
I hope you understand.
You should try like this:
Change in SelectActivity:
public static String EXTRA_MESSAGE_ID="ExtraMsgId";
public static String EXTRA_MESSAGE_SCAN="ExtraMsgScan";
Should not do like this. If you give like this
public static String EXTRA_MESSAGE_ID;
public static String EXTRA_MESSAGE_SCAN;
This is look like empty string.
I am writing a simple stopwatch application for android which will just keep the counter updating each second when pressed start, and pause it with the same button. In my main.xml layout I have a TextView and a Button, and nothing else.
Here's what I've written so far.
public class MainActivity extends Activity implements View.OnClickListener {
private Button btnToggle;
private TextView tvStopwatch;
public Handler updateStopwatch;
private enum Status {
WORKING,
STOPPED
}
private Status stopwatchStatus;
private void toggleStatus() {
if (stopwatchStatus == Status.WORKING) {
stopwatchStatus = Status.STOPPED;
Stopwatch.getStopwatch().dispose();
btnToggle.setText("Start");
}else{
stopwatchStatus = Status.WORKING;
Stopwatch.getStopwatch().start();
btnToggle.setText("Stop");
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
initView();
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btnToggle:
toggleStatus();
break;
}
}
private void initView() {
btnToggle = (Button) findViewById(R.id.btnToggle);
tvStopwatch = (TextView) findViewById(R.id.tvStopwatch);
updateStopwatch = new Handler(){
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
tvStopwatch.setText(msg.what);
}
};
Stopwatch.getStopwatch().setHandler(updateStopwatch);
btnToggle.setOnClickListener(this);
stopwatchStatus = Status.STOPPED;
}
public static class Stopwatch {
private int timestamp;
private boolean working;
private Handler updateStopwatch;
private Stopwatch() {
}
private static Stopwatch stopwatch;
public static Stopwatch getStopwatch() {
if (stopwatch == null) {
stopwatch = new Stopwatch();
}
return stopwatch;
}
public void setHandler(Handler updateStopwatch){
this.updateStopwatch = updateStopwatch;
}
public void start() {
if (!working) {
working = true;
Thread tick = new Thread() {
public void run() {
while (working) {
try {
sleep(1000);
} catch (InterruptedException ex) {
ex.printStackTrace();
} finally {
timestamp++;
updateStopwatch.sendEmptyMessage(timestamp);
}
}
}
};
tick.start();
}
}
public void dispose() {
working = false;
}
}
}
The point is, I want my Stopwatch work in it's separate thread, and to have a handler in my main UI thread which will keep updating the TextView, but when I debug my app, it keeps throwing an exception on this line
tvStopwatch.setText(msg.what);
I am quite new to Handlers, so I guess I'm just missing something fundamental.
Here is also the log for the exception
android.content.res.Resources$NotFoundException: String resource ID #0x1
at android.content.res.Resources.getText(Resources.java:1057)
at android.widget.TextView.setText(TextView.java:4186)
at unisoftdevelopment.com.stopwatch.MainActivity$1.handleMessage(MainActivity.java:61)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5279)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869)
at dalvik.system.NativeStart.main(Native Method)
Please help to find out the problem, thanks in advance.
Common mistake to make: setText() has an overload that takes an integer (which must be a string resource ID, e.g. R.string.my_string).
When you receive the message:
tvStopwatch.setText(msg.what);
It's attempting to resolve msg.what as a string resource, and crashing when it can't be found. You should instead cast the timestamp to a string, and use that instead:
tvStopwatch.setText(String.valueOf(msg.what));