My Android App "E-Mail" crashes when I try to open the "ReadActivity".
The method OpenMail(), declared in MainActivity, should start ReadActivity:
public void OpenMail(View v, int index) {
String[] mail = {"x", "y", "z"};
Intent readIntent = new Intent(this, ReadActivity.class); <-- Error occurs here
readIntent.putExtra("mail", mail);
startActivity(readIntent);
}
The method is called in the ListViewAdapter:
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
Holder holder = new Holder();
View rowView = inflater.inflate(R.layout.listview_item, null);
holder.imageView = (ImageView) rowView.findViewById(R.id.imageView);
holder.txvSenderMail = (TextView) rowView.findViewById(R.id.txvSender);
holder.txvSubject = (TextView) rowView.findViewById(R.id.txvSubject);
holder.imageView.setImageResource(ImageID[position]);
holder.txvSenderMail.setText(SenderMail[position]);
holder.txvSubject.setText(Subject[position]);
rowView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
new MainActivity().OpenMail(v, position);
}
});
return rowView;
}
The error: java.lang.NullPointerException: Attempt to invoke virtual method 'android.app.ActivityThread$ApplicationThread android.app.ActivityThread.getApplicationThread()' on a null object reference
I hope anybody can help me!
Thank you!
You are actually trying to create new MainActivity when you do
new MainActivity().OpenMail(v, context, position);
I think you wanted to do something like this, if you are currently at MainActivity class:
getActivity().OpenMail(v, context, position);
Of course, dont forget to add ReadActivity to AndroidManifest
Related
when i send some data it is give me this error java.lang.ArrayIndexOutOfBoundsException: length=15; index=-1, i dont know why . i tried to search and i didnot foung any thing related to this error.
my code
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.book_items, parent, false);
ViewHolder viewHolder = new ViewHolder(view);
viewHolder.onClick.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(context, BookContentActivity.class);
intent.putExtra("title",bookList.get(viewHolder.getAdapterPosition()).getTitle());
intent.putExtra("author",bookList.get(viewHolder.getAdapterPosition()).getAuthor());
intent.putExtra("details",bookList.get(viewHolder.getAdapterPosition()).getDetails());
intent.putExtra("imageURL",bookList.get(viewHolder.getAdapterPosition()).getImgUrl());
intent.putExtra("rating",bookList.get(viewHolder.getAdapterPosition()).getRating());
intent.putExtra("pages",bookList.get(viewHolder.getAdapterPosition()).getPages());
intent.putExtra("downloadUrl",bookList.get(viewHolder.getAdapterPosition()).getDownloadURL());
context.startActivity(intent);
}
});
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
holder.title.setText(this.bookList.get(position).getTitle());
holder.author.setText(this.bookList.get(position).getAuthor());
Glide.with(holder.itemView.getContext())
.load(this.bookList.get(position).getImgUrl())
.transforms(new CenterCrop(),new RoundedCorners(16))
.into(holder.imageBook);
holder.bookRating.setRating(this.bookList.get(position).getRating());
holder.pages.setText(this.bookList.get(position).getPages());
}
The click listener should be added where you're binding the View to the ViewHolder object (onBindViewHolder). For getting the that object and launching your next activity though, passing a custom listener interface to get the clicked object with would be better. As the adapter shouldn't be responsible for launching activities via intents.
Hopefully that helps.
How i can use textview value in other method? I want to intent value of "txtTitle.setText" to other activity (cars) but i can't use that on onclick method .
public View getView(int position, View view, ViewGroup parent) {
LayoutInflater inflater = context.getLayoutInflater();
View rowView = inflater.inflate(R.layout.single_list, null, true);
TextView txtTitle = (TextView) rowView.findViewById(R.id.txt);
txtTitle.setText(companyname[position]);
txtTitle.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent intent = new Intent(context, Cars.class);
intent.putExtra("carId", txtTitle.getText());
context.startActivity(intent);
}
});
Please edit my code
thanks
Your TextView txtTile is only know in your getView method, because you created it there - you need to declare this variable in your class, outside of any method.
Simply call:
TextView txtTitle;
and in getView you set it like this:
txtTitle = (TextView) rowView.findViewById(R.id.txt);
You can not use it that way, the scope of the txtTitle is reduced to the method getView (see), instead you should define the TextView as a global field and so you can use it wherever you want/ need.
I'd like to change the locale on my app (runtime).It works fine so far. The only thing left is refreshing the current activity.
The documentation says that updating the locale Configuration should restart the running activity (same behavior as the screen orientation) but it does restart it in my case. (I did not use the android:configChanges="locale" to prevent this behavior).
Here are the key parts :
I have my activity :
public class SettingsActivity extends Activity {
ExpandableListAdapter listAdapter;
//....
}
An Adapter where I bind a click (inside the getChildView function) :
public View getChildView(final int groupPosition, final int childPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
//...
convertView = inflater.inflate(R.layout.list_item, null);
convertView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
I18N.setLang(context, "fr");
};
});
}
And the setLang method inside my I18N class :
public class I18N {
public static void setLang(final Context context, String langCode)
{
if (langCode.equals(""))
return;
try {
final Locale newLocale;
final String[] languageRegion = langCode.split("\\-(r)?");
I18N.saveLocale(context, langCode);
newLocale = languageRegion.length > 1 ? new Locale(languageRegion[0], languageRegion[1]) : new Locale(languageRegion[0]) ;
current = newLocale;
Resources res = context.getResources();
DisplayMetrics dm = res.getDisplayMetrics();
android.content.res.Configuration conf = res.getConfiguration();
conf.locale = new Locale(languageRegion[0]);
res.updateConfiguration(conf, dm);
}
catch (Exception e) {
Log.e("exception", e.getMessage() + e.getClass());
}
}
}
I have tried this. It kind of works but I don't like this idea of refreshing the activity manually.
The main issue is that despite using the flag FLAG_ACTIVITY_NO_HISTORY, the history (using the back button of the mobile device) does not work properly (each click on the list to change the language still create an history) :
Intent refresh = new Intent(context, context.getClass());
refresh.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY|Intent.FLAG_ACTIVITY_NO_ANIMATION);
context.startActivity(refresh);
What am I doing wrong ? How can I either make the updateConfiguration restarts the activity or make the manual intent not create an history ?
Instead of relaunching the activity, you want to setContentView() once again after you change locale to change activity layout, or reinflate the fragment
convertView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
I18N.setLang(context, "fr");
//setContentView(R.layout.act_layout); // for activity
convertView = inflater.inflate(R.layout.list_item, null)
};
});
edit
Your convertView would be final so you can refresh it through a method
protected View refresh()
{
//inflate
View convertView = inflater.inflate(R.layout.list_item, null);
//setup ui controls
convertView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
I18N.setLang(context, "fr");
refresh();
};
});
return convertView ;
}
public View getChildView(final int groupPosition, final int childPosition,
boolean isLastChild, View convertView, ViewGroup parent)
{
return refresh();
}
I have added android:noHistory="true" to my settings activity in the AndroidManifest.xml
This way, i can go back to the main screen after changing the language.
This is the error i get:
03-11 08:27:48.513: E/AndroidRuntime(23647): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.plan.yeahimin/com.plan.yeahimin.PlanDetailsActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'java.io.Serializable android.os.Bundle.getSerializable(java.lang.String)' on a null object reference
I understand its due to a variable having a null value but I can't workout why. It looks like it's 'EXTRA_NEW_PLAN' in the getSerializable() method in the DetailsFragment but other than that I don't know. I'm new to Android so forgive me if it's obvious but any help would be greatly appreciated.
Here is my code for the ListFragment;
public class PlanListFragment extends ListFragment {
public final static String TAG = "com.plan.yeahimin.PlanListFragment";
public final static String EXTRA_NEW_PLAN = "com.plan.yeahimin.plan_id";
private Button mAddPlan;
private ArrayList<Plan> mPlansList;
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState){
View v = inflater.inflate(R.layout.empty_view_or_list_view, parent, false);
ListView view = (ListView) v.findViewById(android.R.id.list);
view.setEmptyView(v.findViewById(android.R.id.empty));
mAddPlan = (Button) v.findViewById(R.id.add_a_plan);
mAddPlan.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
Log.d(TAG, "add plan clicked");
Plan plan = new Plan();
Log.d(TAG, "new plan created");
PlanArrayList.get(getActivity()).addPlans(plan);
Log.d(TAG, "plan added to mPlansList");
Intent i = new Intent(getActivity(), PlanDetailsActivity.class);
i.putExtra(PlanDetailsFragment.EXTRA_NEW_PLAN, plan.getId());
startActivity(i);
return;
}
});
return v;
}
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
mPlansList = PlanArrayList.get(getActivity()).getPlans();
//ArrayList<Plan> mPlansList = new ArrayList<Plan>();
PlanArrayAdapter paa = new PlanArrayAdapter(mPlansList);
setListAdapter(paa);
}
public class PlanArrayAdapter extends ArrayAdapter<Plan>{
public PlanArrayAdapter(ArrayList<Plan> planList){
super(getActivity(), 0, planList);
}
public View getView(int position, View convertView, ViewGroup parent){
// Get the plan item for this position
Plan plan = getItem(position);
//If layout doesnt exist, inflate one
if(convertView == null){
convertView = LayoutInflater.from(getContext()).inflate(R.layout.plan_list_fragment, parent, false);
}
TextView planTitle = (TextView) convertView.findViewById(R.id.plan_title);
planTitle.setText(plan.getTitle());
TextView planDate = (TextView) convertView.findViewById(R.id.plan_date);
planDate.setText(plan.getDate().toString());
return convertView;
}
}
}
and here is my code for the DetailsFragment which opens from add button;
public class PlanDetailsFragment extends Fragment {
private static final String TAG = "com.plan.yeahimin.PlanDetailsFragment";
public static final String EXTRA_NEW_PLAN = "com.plan.yeahimin.plan_id";
private EditText mTitleField;
private Button mDateButton;
private Button mTimeButton;
private EditText mLocationField;
private EditText mAttendeesField;
private EditText mDescriptionField;
private Plan mPlan;
private ArrayList<Plan> mPlansList;
public static PlanDetailsFragment newInstance(UUID planId){
Bundle args = new Bundle();
args.putSerializable(EXTRA_NEW_PLAN, planId);
PlanDetailsFragment f = new PlanDetailsFragment();
f.setArguments(args);
Log.d(TAG, "newInstance created");
return f;
}
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
UUID planId = (UUID)getArguments().getSerializable(EXTRA_NEW_PLAN);
mPlan = PlanArrayList.get(getActivity()).getPlan(planId);
}
#Override
public View onCreateView (LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState){
View v = inflater.inflate(R.layout.plan_details_fragment, parent, false);
mTitleField = (EditText)v.findViewById(R.id.plan_title);
mLocationField = (EditText)v.findViewById(R.id.plan_location);
mAttendeesField = (EditText)v.findViewById(R.id.plan_attendees);
mDescriptionField = (EditText)v.findViewById(R.id.plan_description);
mDateButton = (Button)v.findViewById(R.id.plan_date);
mTimeButton = (Button)v.findViewById(R.id.plan_time);
return v;
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater){
inflater.inflate(R.menu.main_to_do, menu);
}
public boolean onOptionsItemSelected(MenuItem item){
switch(item.getItemId()){
case R.id.save_button:
Log.d(TAG, "save button pressed");
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}
I think you cannot send any arguments to your Fragment with .newInstance(), because this method does not accept any parameters according to the documentation. So even if you have overloaded .newInstance(UUID), the system calls .newInstance() (if calls at all, I have some doubts). Also please be aware that you put the parameter to Intent with .putExtra(), but do not recall it from the Intent.
In fact the right way to send arguments to a Fragment is as follows:
In the caller (usually it is an Activity, but maybe with another Fragment, like in your example, it would also work, I cannot say for sure):
PlanDetailsFragment fragment = new PlanDetailsFragment();
Bundle args = new Bundle();
args.putSerializable(PlanDetailsFragment.TAG_NEW_PLAN, plan.getID());
fragment.setArguments(args);
getFragmentManager().beginTransaction().add(fragment, TAG_DETAILS_FRAGMENT).commit();
In the fragment:
Bundle args = getArguments();
UUID planID = (UUID) args.getSerializable(TAG_NEW_PLAN);
It is not a ready-to-use code, you should adapt it to your classes and variables names, to where your tags are places, etc. The calls of Activity methods may also require some change if you prefer to work from another fragment. It is just an overall description.
My answer applies to the situation when both fragments are inside one activity. Your using of Intents make me have doubts in this, but I do not fully understand it.
You sent the arguments to an Activity(PlanDetailsActivity).
You should send the arguments to a Fragment through newInstance() method.
In your PlainDetailsActivity, you should create the fragment instance like:
UUID uuid = getIntent().getSerializableExtra(PlanDetailsFragment.EXTRA_NEW_PLAN);
PlanDetailsFragment f = PlanDetailsFragment.newInstance(uuid);
When i populate an ArrayAdapter, at first the rows in the visible part of the screen will be blank except the first row, which will be an undesired result. Then when I scroll it down and then come back all the screen will be set correctly...please some one tell me why this behavior happens ?
Code :
homeListView = (ListView) findViewById(R.id.home_list);
homeArrayAdapter = new HomeListArrayAdapter(this, R.id.home_list,
homeList);
homeListView.setAdapter(homeArrayAdapter);
Next Part as Class extending ArrayAdapter, an Inner Class to Activity:
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
if (view == null) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.home, null);
}
Home item = (homeList).get(position);
if (item != null) {
if (item.type_text == Home.SIMPLE_SHOUT) {
TextView tv1 = (TextView) findViewById(R.id.hTextView01);
if (tv1 != null) {
tv1
.setText(String.format(" %s\t:",
item.friend_name));
final String item_friend_id_01 = String
.valueOf(item.users_id);
tv1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Toast toast = Toast.makeText(Tranz.this,
item_friend_id_01, Toast.LENGTH_LONG);
toast.show();
}
});
}
TextView tv2 = (TextView) findViewById(R.id.hTextView02);
if (tv2 != null) {
tv2.setText(String.format("\t%s", item.message));
tv2.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
}
});
}
TextView tv3 = (TextView) findViewById(R.id.hTextView03);
if (tv3 != null) {
tv3.setVisibility(0);
tv3.setText(null);
tv3.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
}
});
}
ImageView imageView = (ImageView) findViewById(R.id.file_image);
if (imageView != null) {
imageView.setBackgroundDrawable(null);
}
} else if (item.type_text == Home.FILE_SHOUT) {
TextView tv1 = (TextView) findViewById(R.id.hTextView01);
The code is getting truncated, so the whole code is not appearing here. I'm sorry about that. Here what i have tried is to put the values in the object of class Home into two textViews and an ImageView, which may vary upon the value returned by variable item.type_text
Also if somebody can tell me another best practice to do this, please help.
I'm not sure if this is the problem, but perhaps this will help.
I see you're passing null to LayoutInflater.inflate as the second parameter. Perhaps if you pass parent (which is the ViewGroup passed in as the third argument to getView(), probably your ListView) you will get better results.
I had a problem similar to this that i solved by using view.findViewById(R.id.hTextVew01) instead of just findViewById(R.id.hTextView01)