Sending and receiving arraylist from one activity to another - android

I am trying to send an ArrayList from NoteActivity to MainActivity.
ArrayList<String> data = new ArrayList<String>();
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_note_pad);
final FloatingActionButton button =
(FloatingActionButton)findViewById(R.id.save_button);
button.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
SaveData();
}
});
}
public void SaveData()
{
FileOutputStream outputStream;
try
{
EditText editText = findViewById(R.id.textView3);
final String str = editText.getText().toString();
String content = findViewById(R.id.textView).toString();
Log.d("Test","inside try block");
outputStream = openFileOutput(str, Context.MODE_PRIVATE);
outputStream.write(content.getBytes());
Toast.makeText(getApplicationContext(),"Note
saved",Toast.LENGTH_SHORT).show();
Log.d("Test","save done");
final String str1 = editText.getText().toString();
data.add(str1);
SendData();
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
}
public void SendData()
{
EditText editText = findViewById(R.id.textView3);
Log.d("Check","str:"+data);
Intent intent = new Intent(NotePad.this,MainActivity.class);
intent.putExtra(EXTRA_MESSAGE, data);
startActivity(intent);
}
}
My Main Activity
public class MainActivity extends AppCompatActivity
{
private RecyclerView recyclerView;
private RecyclerView.Adapter mAdapter;
private RecyclerView.LayoutManager layoutManager;
ArrayList<String> notes = new ArrayList<String>();
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = getIntent();
notes = intent.getStringArrayListExtra(NotePad.EXTRA_MESSAGE);
Log.d("Check","title added: "+notes);
final FloatingActionButton button =
(FloatingActionButton)findViewById(R.id.add_notebutton);
button.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
Intent intent = new Intent(MainActivity.this,NotePad.class);
startActivity(intent);
}
});
recyclerView = (RecyclerView)findViewById(R.id.recycle_list);
layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
mAdapter = new MyAdapter(notes);
recyclerView.setAdapter(mAdapter);
}
}
my Adapter code
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder>
{
ArrayList<String> Notes_list = new ArrayList<String>();
public MyAdapter(ArrayList<String> notes)
{
Notes_list = notes;
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int
viewType)
{
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View view = inflater.inflate(R.layout.list_items,parent,false);
return new MyViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull MyViewHolder holder, int position)
{
holder.mTextView.setText(Notes_list.get(position));
}
#Override
public int getItemCount()
{
return Notes_list.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder
{
TextView mTextView;
public MyViewHolder(#NonNull View itemView)
{
super(itemView);
mTextView = (TextView) itemView.findViewById(R.id.view_holder);
}
}
}
I dont receive any data in my notes (arrayList). When I run the code
The app instantly crashes with a null pointer exception.
Error: java.lang.NullPointerException: Attempt to invoke virtual method 'int
java.util.ArrayList.size()' on a null object reference at
com.example.quicknote.MyAdapter.getItemCount(MyAdapter.java:39)

You are trying to pass ArrayList and you read data from intent with getStringArrayListExtra method. You have to put data like this:
intent.putStringArrayListExtra(EXTRA_MESSAGE, data);
Edit: Check if intent has key:
if (intent.hasExtra(NotePad.EXTRA_MESSAGE)) {
notes = intent.getStringArrayListExtra(NotePad.EXTRA_MESSAGE);
}
Note: If this is just a playground it is OK. But if you trying to
build something then your architecture is wrong. It is not a good idea
to pass same array every time between two activity. You can use
startActivityForResult method and get new note onActivityResult method
of MainActivity.

Try this:-
Intent intent = new Intent(NotePad.this,MainActivity.class);
Bundle bundle = new Bundle();
bundle.putSerializable("EXTRA_MESSAGE", data);
intent.putExtras(bundle);
//in MainActivity.class
Intent intent = this.getIntent();
Bundle bundle = intent.getExtras();
ArrayList<String> data=(ArrayList<String>)bundle.getSerializable("EXTRA_MESSAGE");

The best way given in android document to send the arraylist or any custom object from one activity to another to Try the light weight process for this in android
Read the full overview about it https://developer.android.com/reference/android/os/Parcelable
hope it will help for you

Related

New user is part of a group it was never added to

I'm currently working on an app in which users can create groups and add members to groups. Today I created a new user to test the app. When I logged in this new user I checked to see if it was a part of any groups, which I didn't expect it to be seeing as it was new. And it wasn't. But then when I logged in my usual user and clicked groups I saw the name of the test user. Why does it appear that this user is a part of a group it was never added to?
It should be noted that when looking through my firebase this test user doesn't appear to have been invited either. I'm using firestore recycler adapter to fetch data in a recyclerView.
Below is the code for my adapter responsible for adding members to a specific group.
FirestoreMemberAdapter.java:
public class FirestoreMemberAdapter extends FirestoreRecyclerAdapter<MemberModel, FirestoreMemberAdapter.MemberViewHolder> {
private static final String TAG = FirestoreMemberAdapter.class.getSimpleName();
private Context context;
private String projectId;
private String projectName;
public FirestoreMemberAdapter(#NonNull FirestoreRecyclerOptions<MemberModel> options, Context context, String projectId, String projectName) {
super(options);
this.context = context;
this.projectName = projectName;
this.projectId = projectId;
}
#Override
protected void onBindViewHolder(#NonNull MemberViewHolder holder, int position, #NonNull final MemberModel model) {
holder.mTextView.setText(model.getName());
if (model.getProfile_image() == null) {
Picasso.get().load(R.drawable.profile_image).into(holder.mImageview);
} else {
Picasso.get().load(model.getProfile_image()).into(holder.mImageview);
}
holder.mLinearLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Log.d(TAG, "onClick: Clicked on FirestoreMemberAdapter ");
Intent intent = new Intent(context, ProfileMemberPage.class);
intent.putExtra(StringCreator.PROJECT_TITLE, projectName);
intent.putExtra(StringCreator.PROJECT_ID, projectId);
intent.putExtra(StringCreator.NAME, model.getName());
intent.putExtra(StringCreator.EMAIL, model.getEmail());
intent.putExtra(StringCreator.USER_ID, model.getUser_id());
intent.putExtra(StringCreator.USER_INFORMATION, model.getUser_information());
context.startActivity(intent);
}
});
}
#NonNull
#Override
public MemberViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_projectmembers, parent, false);
return new MemberViewHolder(view);
}
public class MemberViewHolder extends RecyclerView.ViewHolder {
private LinearLayout mLinearLayout;
private TextView mTextView;
private ImageView mImageview;
public MemberViewHolder(#NonNull View itemView) {
super(itemView);
mTextView = itemView.findViewById(R.id.memberTitle);
mLinearLayout = itemView.findViewById(R.id.layout_members);
mImageview = itemView.findViewById(R.id.memberImage);
}
}
}
Here is the activity in wihch the adapter is used.
projectClicked.java:
//widgets
private RecyclerView recyclerViewMembers;
private TextView projectName;
private Button cameraBtn;
private FloatingActionButton addUserBtn;
//Firebase
private FirebaseFirestore firebaseFirestore = FirebaseFirestore.getInstance();
private Query query;
private FirestoreRecyclerOptions<MemberModel> options;
private FirestoreMemberAdapter adapter;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_project_clicked);
projectName = findViewById(R.id.projectName);
addUserBtn = findViewById(R.id.addUserBtn);
cameraBtn = findViewById(R.id.cameraBtn);
initRecyclerView();
addUserBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent newIntent = new Intent(projectClicked.this, UserToProject.class);
Bundle projectBundle = getIntent().getExtras();
if (projectBundle != null) {
newIntent.putExtras(projectBundle);
}
startActivity(newIntent);
}
});
}
private void initRecyclerView() {
Log.d(TAG, "InitRecyclerView: init recyclerview");
if (getIntent().hasExtra(StringCreator.PROJECT_TITLE) && getIntent().hasExtra(StringCreator.PROJECT_ID)) {
final String pName = getIntent().getStringExtra(StringCreator.PROJECT_TITLE);
final String pID = getIntent().getStringExtra(StringCreator.PROJECT_ID);
projectName.setText(pName);
recyclerViewMembers = findViewById(R.id.recyclerView_members);
query = firebaseFirestore.collection("users");
options = new FirestoreRecyclerOptions.Builder<MemberModel>().setQuery(query, MemberModel.class).build();
adapter = new FirestoreMemberAdapter(options, projectClicked.this, pID, pName);
recyclerViewMembers.setHasFixedSize(true);
recyclerViewMembers.setAdapter(adapter);
recyclerViewMembers.setLayoutManager(new LinearLayoutManager(projectClicked.this));
}
}
#Override
public void onStart() {
super.onStart();
adapter.startListening();
}
#Override
public void onStop() {
super.onStop();
adapter.stopListening();
}
Hope this makes sense, please reach out if it doesn't. Thank you in advance.
As #McSlinPlay mentioned, the reason could be pointed out to your code in projectClicked.java where you created your query and all the users (including the test user) are part of this collection:
query = firebaseFirestore.collection("users");

How to save items inside an ArrayList when an app is restarted? (Android)

Whenever I restart my app, all the information I saved inside an ArrayList during its runtime is deleted. In addition, sometimes when I go to another activity and then come back from that second activity. The information is deleted again. I'm not sure what's causing this. I want the information to be permanently saved unless deleted by the user. Usually, the error I'm receiving are IndexOutOfBounds exception when I need to call an item from my ArrayList.
Main Activity Code:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private TextView preset;
private Button add;
private ListView exercises;
private ArrayList<String> exerciseName;
public ArrayList<Exercise> Exercises;
private MyAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Exercises = new ArrayList<Exercise>();
preset = findViewById(R.id.preset_title);
add = findViewById(R.id.add_exercise);
exercises = findViewById(R.id.exercises);
exerciseName = FileHelper.readData(this);
this.adapter = new MyAdapter(exerciseName, this, Exercises);
exercises.setAdapter(adapter);
add.setOnClickListener(this);
}
#Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.add_exercise:
final int CODE = 1;
Intent i = new Intent(this, add_activity.class);
startActivityForResult(i, CODE);
break;
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch(requestCode) {
case 1:
if(resultCode == RESULT_OK && data != null) {
Bundle passBack = data.getExtras();
Exercise exercise = passBack.getParcelable("exercise");
adapter.addData(exercise);
adapter.list.add(exercise.getName());
FileHelper.writeData(exerciseName, this);
adapter.notifyDataSetChanged();
}
case 2:
if (resultCode == RESULT_OK && data != null) {
Bundle passBack = data.getExtras();
Exercise exercise = passBack.getParcelable("exercise");
int position = passBack.getInt("position");
adapter.setData(exercise, position);
adapter.notifyDataSetChanged();
}
}
}
}
Custom Adapter Code (where my ArrayList data is stored):
public class MyAdapter extends ArrayAdapter<String> {
public ArrayList<String> list;
private Context context;
private TextView list_txt;
private ArrayList<Exercise> data;
public MyAdapter(ArrayList<String> records, Context context, ArrayList<Exercise> data) {
super(context, 0, records);
this.list = records;
this.data = data;
this.context = context;
}
public void addData(Exercise d){
data.add(d);
}
public void setData(Exercise d, int position) {
data.set(position, d);
}
#Override
public View getView(final int position, View convertView, final ViewGroup parent) {
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.listview_custom, parent, false);
}
Button list_but = (Button) convertView.findViewById(R.id.list_but);
TextView list_txt = (TextView) convertView.findViewById((R.id.list_txt));
Button edit = (Button) convertView.findViewById(R.id.list_but2);
Button start = (Button) convertView.findViewById(R.id.list_but3);
list_txt.setText(list.get(position));
edit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
final int CODE2 = 2;
Activity origin = (Activity)context;
Intent edit = new Intent(parent.getContext(), add_activity.class);
Bundle newBundle = new Bundle();
newBundle.putParcelable("exercise", data.get(position));
newBundle.putInt("position", position);
edit.putExtras(newBundle);
origin.startActivityForResult(edit, CODE2);
}
});
start.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent start = new Intent(parent.getContext(), timer_activity.class);
start.putExtra("exercise", data.get(position));
parent.getContext().startActivity(start);
}
});
list_but.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
AlertDialog.Builder alert = new AlertDialog.Builder(context);
alert.setTitle("Delete?");
alert.setMessage("Are you sure you want to delete this exercise?");
alert.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
list.remove(position);
try {
data.remove(position);
} catch(IndexOutOfBoundsException ex) {
}
notifyDataSetChanged();
}
});
alert.setNegativeButton("No", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
}
});
alert.create().show();
}
});
return convertView;
}
}
Every time You destroy activity You are losing all saved data in ListView. You have to save it before destroying and restore when You start an activity. You can do it with gson and SharedPreferences.
In Your MainActivity override onSaveInstanceState and inside this method save all Your exercises from Exercises list using gson.
Gson gson = new Gson();
String exercisesJSON = gson.toJson(Exercises);
SharedPreferences sharedPref = getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putString("KEY_BETTER_USE_CONST", exercisesJSON);
editor.commit();
And then in onCreate restore this data:
SharedPreferences sharedPref = getPreferences(Context.MODE_PRIVATE);
String exercisesJSON = sharedPref.getInt("KEY_BETTER_USE_CONST", "DEFAULT_VALUE_EMPTY");
//check if exercisesJSON is equal to "DEFAULT_VALUE_EMPTY" if yes, init array as empty, if not deserialize it using gson
Gson gson = new Gson();
Exercises[] exercises = gson.fromJson(exercisesJSON, Exercise[].class);
Haven't debugged this code but I think it should look something like this. I based on: Gson — Mapping of Arrays and Lists of Objects

pass data to News_Activity from NewsAdapter class

I made one NewsAdapter with image and two texts.When u click on image it ll lead you to new activity.Now i want to pass image and text's to new activity.i know with putExtra method you can pass data but i don't know how can i use it here.
this is my News_Fragment
public class News_Fragment extends Fragment {
private List<News> newsList = new ArrayList<>();
private RecyclerView recyclerView;
private NewsAdapter newAdapter;
BottomBar bottombar;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_news_, container, false);
recyclerView = (RecyclerView) rootView.findViewById(R.id.News_recycler_view);
recyclerView.setHasFixedSize(true);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL_LIST));
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(newAdapter);
newAdapter = new NewsAdapter(newsList,getContext());
// Inflate the layout for this fragment
JSONObject jsonObject = new JSONObject();
new NewsTask() {
#Override
protected void onPostExecute(APIResponse apiResponse) {
if(apiResponse != null && apiResponse.data != null & apiResponse.data.size()>0) {
newsList = apiResponse.data;
//apiResponse.data.toArray();
//newAdapter.notifyDataSetChanged();
newAdapter = new NewsAdapter(newsList,getContext());
recyclerView.setAdapter(newAdapter);
}
Log.i("resp", "onPostExecute");
}
}.execute(jsonObject);
return rootView;
}
}
this is NewsAdapter
public class NewsAdapter extends RecyclerView.Adapter<NewsAdapter.MyViewHolder> {
private List<News> newsList;
private Context context;
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView title;
public ImageView image,nextArrowimage;
public TextView desc;
public MyViewHolder(View view) {
super(view);
title = (TextView) view.findViewById(R.id.News_title);
image = (ImageView) view.findViewById(R.id.News_imageView);
nextArrowimage = (ImageView)view.findViewById(R.id.news_NextArrow);
desc = (TextView) view.findViewById(R.id.News_desc);
}
}
public NewsAdapter(List<News> newsList,Context context) {
this.newsList = newsList;
this.context = context;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.news_list_row, parent, false);
MyViewHolder holder = new MyViewHolder(itemView);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {
final News news = newsList.get(position);
holder.title.setText(news.getTitle());
//holder.image.setImageResource(Integer.parseInt(news.getImage()));
context = holder.image.getContext();
holder.nextArrowimage.setImageResource(R.drawable.nextbutton);
//Picasso.with(context).load("https://www.simplifiedcoding.net/wp-content/uploads/2015/10/advertise.png").resize(100,100).into(holder.image);
Picasso.with(context).load("http://bitstobyte.in/upload/"+news.getImage()).placeholder(R.drawable.ic_favorite_white_24dp).error(R.drawable.ic_map_24dp).resize(100,100).into(holder.image);
//Picasso.with(context).load("http://bitstobyte.in/upload/"+ news.getImage()).resize(100,100).into(holder.image);
holder.desc.setText(news.getDesc().trim());
holder.image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
TextView title = (TextView)v.findViewById(R.id.News_title);
TextView desc = (TextView)v.findViewById(R.id.News_desc);
String str3 = "http://bitstobyte.in/api/news/"+getItemId(position)+news.getImage();
Intent intent = new Intent(context.getApplicationContext(), News_Activity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.getApplicationContext().startActivity(intent);
intent.putExtra("title",str3);
Toast.makeText(context, "You Clicked " + newsList.get(position), Toast.LENGTH_LONG).show();
}
});
}
#Override
public int getItemCount() {
return newsList.size();
}
}
this is my News_Activity
public class News_Activity extends AppCompatActivity {
TextView textView1,
textView2;
ImageView imageView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_news_);
getSupportActionBar().setTitle(Html.fromHtml("<font color='#fdfafa'> News View </font>"));
final Drawable upArrow = getResources().getDrawable(R.drawable.abc_ic_ab_back_mtrl_am_alpha);
//upArrow.setColorFilter(getResources().getColor(R.color.ActionBarText), PorterDuff.Mode.SRC_ATOP);
getSupportActionBar().setHomeAsUpIndicator(upArrow);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
String Title1 = getIntent().getStringExtra("title");
textView1 = (TextView)findViewById(R.id.activity_news_Title);
textView1.setText(Title1);
textView2 = (TextView)findViewById(R.id.activity_news_desc);
textView2.setText(Title1);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if(item.getItemId() == android.R.id.home){
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
}
From the adapter you can call this way ->
Intent intent = new Intent(context,News_Activity.class);
intent.putExtra("image",IMAGE_URL);
intent.putExtra("data", DATA_TO_PASS);
context.startActivity(intent);
Intent intent = new Intent(context, News_Activity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("title",str3);
context.startActivity(intent);
or
Intent intent = new Intent(getActivity(), News_Activity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("title",str3);
getActivity().startActivity(intent);
Did you try putting the data into intent before actually starting it?? And use getActivity() or directly context instead of context.getApplicationContext()
You need to putExtras into the intent before starting the activity to pass the values :)
The issue is the Intent flag FLAG_ACTIVITY_NEW_TASK. This opens the activity in a new task which is probably why the data isn't passed properly.
for similar issue see:
Intent from notification does not have extras
Do the following:
holder.image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
TextView title = (TextView)v.findViewById(R.id.News_title);
TextView desc = (TextView)v.findViewById(R.id.News_desc);
String str3 = "http://bitstobyte.in/api/news/"+getItemId(position)+news.getImage();
Intent intent = new Intent(context.getApplicationContext(), News_Activity.class);
//intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("title",str3);
context.getApplicationContext().startActivity(intent);
Toast.makeText(context, "You Clicked " + newsList.get(position), Toast.LENGTH_LONG).show();
}
});
If you want to pass image , you can pass it by converting to bitmap and use it.
try{
String str3 = "http://bitstobyte.in/api/news/"+getItemId(position)+news.getImage();
URL url = new URL(str3);
Bitmap imagebitmap = BitmapFactory.decodeStream(url.openConnection().getInputStream());
Intent intent = new Intent(context.getApplicationContext(), News_Activity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.getApplicationContext().startActivity(intent);
intent.putExtra("title",str3);
intent.putExtra("imagebitmap", imagebitmap);
context.startActivity(intent);
} catch (Exception e) {
Log.error("Exception", e);
}
For getting data..
Intent intent = getIntent();
String title = getIntent().getExtras().getString("title");
Bitmap bitmap = (Bitmap) intent.getParcelableExtra("imagebitmap");
Thanks..

How to pass values from RecycleAdapter to MainActivity or Other Activities

I am working on a shopping cart app,Items are displayed as below.There is a plus, minus (+/-) buttons to choose the number of quantity.
If product quantity is changed, I need to pass "productname" and "quantity" to the main activity so that I could use them to prepare final cart. I got some suggestions to use database or some content providers,
I am not sure how to do it.., please help
MainActivity.java
public class MainActivity extends AppCompatActivity {
RecyclerView recyclerView;
RecycleAdapter recycleAdapter;
List<HashMap<String, String>> onlineData;
ProgressDialog pd;
Toolbar toolbar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = (RecyclerView) findViewById(R.id.recyle_view);
toolbar= (Toolbar) findViewById(R.id.anim_toolbar);
setSupportActionBar(toolbar);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getBaseContext());
recyclerView.setLayoutManager(linearLayoutManager);
recyclerView.setHasFixedSize(true);
final String url = "http://www.qa4.org/?json=get_recent_posts&count=45";
new AsyncHttpTask().execute(url);
}
public class AsyncHttpTask extends AsyncTask<String, Void, Integer> {
#Override
protected void onPreExecute() {
pd=new ProgressDialog(MainActivity.this);
pd.requestWindowFeature(Window.FEATURE_NO_TITLE);
pd.setMessage("Loading please wait...");
pd.setCancelable(false);
pd.show();
}
#Override
protected Integer doInBackground(String... params) {
Integer result = 0;
HttpURLConnection urlConnection;
try {
URL url = new URL(params[0]);
urlConnection = (HttpURLConnection) url.openConnection();
int statusCode = urlConnection.getResponseCode();
// 200 represents HTTP OK
if (statusCode == 200) {
BufferedReader r = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
StringBuilder response = new StringBuilder();
String line;
while ((line = r.readLine()) != null) {
response.append(line);
}
parseResult(response.toString());
result = 1; // Successful
} else {
result = 0; //"Failed to fetch data!";
}
} catch (Exception e) {
e.printStackTrace();
}
return result; //"Failed to fetch data!";
}
#Override
protected void onPostExecute(Integer result) {
// Download complete. Let us update UI
pd.dismiss();
if (result == 1) {
recycleAdapter = new RecycleAdapter(MainActivity.this,onlineData);
recyclerView.setAdapter(recycleAdapter);
} else {
Toast.makeText(MainActivity.this, "Failed to fetch data!", Toast.LENGTH_SHORT).show();
}
}
}
private void parseResult(String result) {
try {
JSONObject response = new JSONObject(result);
JSONArray posts = response.optJSONArray("posts");
onlineData = new ArrayList<>();
for (int i = 0; i < posts.length(); i++) {
JSONObject post = posts.optJSONObject(i);
HashMap<String, String> item = new HashMap<>();
item.put("title", post.optString("title"));
JSONArray jsonArray = post.getJSONArray("attachments");
JSONObject jsonObject1 = jsonArray.getJSONObject(0);
JSONObject jsonArrayImages = jsonObject1.getJSONObject("images");
JSONObject jsonArrayThumb = jsonArrayImages.getJSONObject("thumbnail");
item.put("thump", jsonArrayThumb.optString("url"));
onlineData.add(item);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
RecycleAdapter.java
public class RecycleAdapter extends RecyclerView.Adapter<RecycleAdapter.ViewHolderRec> {
List<HashMap<String, String>> onlineData;
SQLiteDatabase db;
Context context;
RecycleAdapter(Context context,List<HashMap<String, String>> onlineData){
this.onlineData = onlineData;
this.context=context;
}
#Override
public ViewHolderRec onCreateViewHolder(ViewGroup parent, int viewType) {
return new ViewHolderRec( LayoutInflater.from(parent.getContext()).inflate(R.layout.item_recycle, parent, false));
}
#Override
public void onBindViewHolder(ViewHolderRec holder, int position) {
HashMap<String,String> map =onlineData.get(position);
//Download image using picasso library
Picasso.with(context).load(map.get("thump"))
.error(R.drawable.placeholder)
.placeholder(R.drawable.placeholder)
.into(holder.iv);
holder.tv.setText(map.get("title"));
}
#Override
public int getItemCount() {
return onlineData.size();
}
public class ViewHolderRec extends RecyclerView.ViewHolder implements View.OnClickListener{
ImageView iv;
TextView tv, quantity;
ImageView Add_Cart;
ImageView Remove_Cart;
public ViewHolderRec(View itemView) {
super(itemView);
iv = (ImageView) itemView.findViewById(R.id.thumbnail);
tv = (TextView) itemView.findViewById(R.id.title);
quantity = (TextView)itemView.findViewById(R.id.cart_qty);
Add_Cart = (ImageView)itemView.findViewById(R.id.cart_add);
Remove_Cart = (ImageView)itemView.findViewById(R.id.cart_remove);
itemView.setOnClickListener(this);
Add_Cart.setOnClickListener(this);
Remove_Cart.setOnClickListener(this);
}
#Override
public void onClick(View v) {
if(v.getId() == Add_Cart.getId()){
increment();
}
else if(v.getId() == Remove_Cart.getId()){
decrement();
}
}
public void increment(){
int currentNos = Integer.parseInt(quantity.getText().toString()) ;
quantity.setText(String.valueOf(++currentNos));
}
public void decrement(){
int currentNos = Integer.parseInt(quantity.getText().toString()) ;
quantity.setText(String.valueOf(--currentNos));
}
}
}
How to do this,
You should create interface, and activity implements this interface.
public interface OnItemClick {
void onClick (String value);
}
When you create adapter (last parameter is this interface)
public class MainActivity extends AppCompatActivity implements OnItemClick {
recycleAdapter = new RecycleAdapter(MainActivity.this,onlineData, this);
recyclerView.setAdapter(recycleAdapter);
#Override
void onClick (String value){
// value this data you receive when increment() / decrement() called
}
// In Adapter
private OnItemClick mCallback;
RecycleAdapter(Context context,List<HashMap<String, String>> onlineData,OnItemClick listener){
this.onlineData = onlineData;
this.context = context;
this.mCallback = listener;
}
....
public void increment(){
int currentNos = Integer.parseInt(quantity.getText().toString()) ;
quantity.setText(String.valueOf(++currentNos));
mCallback.onClick(quantity.getText().toString());
}
public void decrement(){
int currentNos = Integer.parseInt(quantity.getText().toString()) ;
quantity.setText(String.valueOf(--currentNos));
mCallback.onClick(quantity.getText().toString());
}
I failed to do it with both Interface and Observer pattern. But Local Broadcast worked for me.
In Adapter
String ItemName = tv.getText().toString();
String qty = quantity.getText().toString();
Intent intent = new Intent("custom-message");
// intent.putExtra("quantity",Integer.parseInt(quantity.getText().toString()));
intent.putExtra("quantity",qty);
intent.putExtra("item",ItemName);
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
Main Activity
public void onCreate(Bundle savedInstanceState) {
...
// Register to receive messages.
// We are registering an observer (mMessageReceiver) to receive Intents
// with actions named "custom-message".
LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver,
new IntentFilter("custom-message"));
}
...
public BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// Get extra data included in the Intent
String ItemName = intent.getStringExtra("item");
String qty = intent.getStringExtra("quantity");
Toast.makeText(MainActivity.this,ItemName +" "+qty ,Toast.LENGTH_SHORT).show();
}
};
Three popular ways to solve this problem
Interfaces
Phuoc Huynh has already explained how to use interfaces to solves this.
Observer pattern.
Try googling around observer to understand how it works. We will register the classes who want to receive events with the type of events they want to receive. There will be a manager classes to manage registering and unregistering of receivers and also to send the events to all receivers
public class EventManager {
private static EventManager eventManager;
private static Object syncObject = new Object();
private HashMap<String, ArrayList<EventListener>> listeners = new HashMap<>();
private EventManager(){}
public static EventManager getInstance() {
if (eventManager == null) {
synchronized (syncObject) {
if (eventManager == null) {
eventManager = new EventManager();
}
}
}
return eventManager;
}
public synchronized void registerListener(String event, EventListener listener) {
if (listeners.containsKey(event)) {
listeners.get(event).add(listener);
} else {
ArrayList<EventListener> arrayList = new ArrayList<>();
arrayList.add(listener);
listeners.put(event, arrayList);
}
}
public synchronized void unRegisterListener(String event, EventListener listener) {
if (listeners.containsKey(event)) {
listeners.get(event).remove(listener);
if (listeners.get(event).size() == 0) {
listeners.remove(event);
}
}
}
public void sendEvent(String event, Object o) {
if (listeners.containsKey(event)) {
ArrayList<EventListener> listener = listeners.get(event);
for (EventListener eventListener : listener) {
eventListener.onEvent(o);
}
}
}
}
Your MainActivity will register itself as a receiver of increment and decrement events and also implement onEvent method of IEventListener
public class MainActivity extends AppCompatActivity implements IEventListener{
#Override
protected void onCreate(Bundle onSavedInstanceState) {
EventManager.getInstance().registerEvent("increment", this);
EventManager.getInstance().registerEvent("decrement", this)
}
#Override
public void onEvent(String event) {
if (event.equals("increment") {
//increment
} else if (event.equals("decrement") {
//decrement
}
}
#Override
protected void onDestroy() {
EventManager.getInstance().unRegisterEvent("increment", this);
EventManager.getInstance().unRegisterEvent("decrement", this)
}
}
In you adapter class send the events
EventManager.getInstance().sendEvent("increment");
EventManager.getInstance().sendEvent("decrement");
LocalBroadcasts
LocalBroadcasts works the same way as the above example. you have get Instance of LocalBroadcastManger and send Broadcast on it. Define a broadcast receiver in the onCreate of the activity and register it using registerReceiver() in the Activity. Pass an intent filter in the register receiver with actiontype same as the broadcasts you want your activity to receive. Make sure you unregister the broadcasts whenever you don't need them or in the onDestroy of the activity
Simple solution using interface:
Create an interface with method containing objects/data as parameters:
public interface RecyclerViewDataPass {
public void pass(String productName, String quantity);
}
Implement interface method in Activity & pass it through RecyclerView Adapter:
RecyclerViewDataPass recyclerViewDataPass = new RecyclerViewDataPass() {
#Override
public void pass(String productName, String quantity) {
//we get data from adapter here
//assign parameters to activity variables or do the needed operations
}
};
recycleAdapter = new RecycleAdapter(MainActivity.this,onlineData,recyclerViewDataPass);
recyclerView.setAdapter(recycleAdapter);
Edit adapter's constructor:
public class RecycleAdapter extends RecyclerView.Adapter<RecycleAdapter.ViewHolderRec> {
List<HashMap<String, String>> onlineData;
SQLiteDatabase db;
Context context;
RecyclerViewDataPass recyclerViewDataPass; //here is our data pass object
RecycleAdapter(Context context,List<HashMap<String, String>> onlineData, RecyclerViewDataPass recyclerViewDataPass){
this.onlineData = onlineData;
this.context=context;
this.recyclerViewDataPass=recyclerViewDataPass; //get data pass object from activity
}
Inside RecyclerView Adapter call pass function to send data to activity:
recyclerViewDataPass.pass(tv.getText().toString(), quantity.getText().toString());
Check out this. It works for me.
Just Paste in Your Activity or Fragment
rvSelectedProductList = Recyclerview
selcetedItemAdapter = RecyclerView Adapter
rvSelectedProductList.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
final int itemCount = selectedItemAdapter.getItemCount();
for (int i = 0; i < itemCount; i++) {
TextView tvSelling = rvSelectedProductList.getChildAt(i).findViewById(R.id.tvSelling);
TextView textViewDrawerTitle = rvSelectedProductList.getChildAt(i).findViewById(R.id.tvCartQty);
String totalamount = tvSelling.getText().toString();
String qty = textViewDrawerTitle.getText().toString();
System.out.println("qty" + qty);
System.out.println("total" + totalamount);
}
rvSelectedProductList.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
});
//Simply it works for me
//In onBindViewHolder of RecyclerAdapter write the following code on clickEvent of any view;
Intent intent = new Intent(tContext, TargetActivity.class);
intent.putExtra("key", "value");
tContext.startActivity(intent);
//TargetActivity.java
String str = getIntent().getStringExtra("key");
//You got the value as String :)
add these codes in onBindViewHolder
Intent intent = new Intent("message_subject_intent");
intent.putExtra("name" , String.valueOf(messageSubject.getname()));
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
Add on MainActivity
public BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String name= intent.getStringExtra("name");
Toast.makeText(MainActivity.this, name, Toast.LENGTH_SHORT).show();
}
};
LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver,new IntentFilter("message_subject_intent"));

QR code reader thrown from an image of an item of a ListView

I want that when the image of the item is pressed launches QR code reader provided by the library zxing.
I tested two options.
The first option has been my custom adapter trying to launch the intent.
The second option has been following the first and a topic of this forum, and I got kind of my custom adapter in the main class and I created two methods.
This last option gives me syntax error, but if you run:
android.content.ActivityNotFoundException: No Activity found to handle Intent { act=com.google.zxing.client.android.SCAN (has extras) } at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:1659)
Actually, this is my code:
public class Inventario extends Activity implements OnItemClickListener {
private ArrayList<Obra> obras;
private ListView lvObras;
private ObrasAdapter adapter;
private TextView num, iden,ubi,hombres,material;
private int pulsado = -1;
Toast toast1 ;
private int operacion = -1;
List<String> equiDisp;
ArrayList<String> marcado;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.inventario);
equiDisp = new ArrayList<String>();
marcado = new ArrayList<String>();
for(int i=1; i<11; i++)
{
equiDisp.add(String.valueOf(i));
}
// Inicializamos las variables.
obras = new ArrayList<Obra>();
rellenarArrayList();
actualizarDisplay();
}
...
public void abrirLector(){
Intent intent = new Intent("com.google.zxing.client.android.SCAN");
intent.putExtra("SCAN_MODE", "QR_CODE_MODE");
startActivityForResult(intent, 0);
}
public void actualizarDisplay()
{
adapter = new ObrasAdapter(this, obras);
lvObras = (ListView) findViewById(R.id.lvItems);
lvObras.setAdapter(adapter);
lvObras.setOnItemClickListener(this);
}
public class ObrasAdapter extends ArrayAdapter<Obra> {
public Context context;
private ArrayList<Obra> datos;
public void DisplayProjectListAdapter(Context c) {
context = c;
}
public ObrasAdapter(Context context, ArrayList<Obra> datos) {
super(context, R.layout.listview_item, datos);
this.context = context;
this.datos = datos;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View item = convertView;
ObrasHolder holder;
if (item == null) {
item = LayoutInflater.from(context).inflate(R.layout.listview_item,
null);
holder = new ObrasHolder();
holder.qr = (ImageView) item.findViewById(R.id.qr);
item.setTag(holder);
}
holder = (ObrasHolder) item.getTag();
holder.qr.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
holder.qr.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v) {
abrirLector();
}
});
}
});
return item;
}
Can anyone help me out? Thank you
The problem you are getting related to ActivityNotFoundException can be fixed by the steps you can find in this link. This is the official documentation for zxing that tells you how to open the scanner in the yet provided dialog they have. Replace it by your code:
public void abrirLector(){
Intent intent = new Intent("com.google.zxing.client.android.SCAN");
intent.putExtra("SCAN_MODE", "QR_CODE_MODE");
startActivityForResult(intent, 0);
}
Add holder.qr.setOnClickListener(new OnImageClickListener()); to the get view method.
Then add an inner class to this class:
private class OnImageClickListener implements OnClickListener {
#Override
public void onClick(View v) {
Main sct = (Main) activity;
sct.onClick();
return void;
}
Then go ahead and add a method called onClick() to your Main activity and add the code to call the intent in that method

Categories

Resources