i am creating an app for my final year project at uni.. i am trying to get an rss feed working.. My issue at the moment is that i created a project (RSSActivity) and got the RSS feeds to work. I then copy and pasted all the files (5 classes and 2 layouts) into the appropriate places. There were a few errors: R cannot be found, but this was easily fixed by changing the package to that of the project (football_app). What i am tring to do is be able to click on a button called 'News' and the news appears.. the problem that i am have is that the when i now click on the 'News' button, it say 'Unfortunately football app has stopped'.. i have tried every single class in the intent, and changed the intent activity name appropriately.. can anyone help me.. code below...
/////////////// HttpFeedSource.java
package com.julian.football_app;
import java.util.ArrayList;
import java.util.List;
class HttpFeedSource implements FeedSource {
protected static final String URL = "http://www.skysports.com/rss/0,20514,11661,00.xml";
public List<RSSItem> getFeed() {
List<RSSItem> itemList = new ArrayList<RSSItem>();
NewsParser parser = new NewsParser(URL);
parser.parse();
NewsParser.RssFeed feed = parser.getFeed();
for (NewsParser.Item i : feed.getItems()) {
itemList.add(new RSSItem(i.getUrl(), i.getTitle(), i.getDescription(), i.getimageUrl()));
}
return itemList;
}
}
////////////////////// FeedSource.java
package com.julian.football_app;
import java.util.List;
interface FeedSource {
List<RSSItem> getFeed();
}
<code>
/////////////////////////////////////////////////////////////////////////////////////////// //MockFeedSource.java
package com.julian.football_app;
import java.util.ArrayList;
import java.util.List;
class MockFeedSource implements FeedSource {
public List<RSSItem> getFeed() {
RSSItem item;
final List<RSSItem> items = new ArrayList<RSSItem>();
item = new RSSItem("Android Workshop er gøy", "http://www.ap.no", " this is the desc", "");
items.add(item);
item = new RSSItem("Android Workshop er gøy 2", "http://www.ap.no", "this is the desc", "");
items.add(item);
item = new RSSItem("Android Workshop er gøy3", "http://www.ap.no", "this is the desc", "");
items.add(item);
return items;
}
}
</code>
/////////////////////////////////////////////////////////////////////////////////////////// NewsParser.java
package com.julian.football_app;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.InputStream;
import java.net.URL;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
class NewsParser extends DefaultHandler {
public static SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.ENGLISH);
private String urlString;
private RssFeed rssFeed;
private StringBuilder text;
private Item item;
private boolean imgStatus;
public NewsParser(String url) {
this.urlString = url;
this.text = new StringBuilder();
}
public void parse() {
InputStream urlInputStream = null;
SAXParserFactory spf;
SAXParser sp;
try {
URL url = new URL(this.urlString);
urlInputStream = url.openConnection().getInputStream();
InputSource is = new InputSource(urlInputStream);
is.setEncoding("ISO-8859-1");
spf = SAXParserFactory.newInstance();
if (spf != null) {
sp = spf.newSAXParser();
sp.parse(is, this);
}
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
try {
if (urlInputStream != null) urlInputStream.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
public RssFeed getFeed() {
return (this.rssFeed);
}
public void startElement(String uri, String localName, String qName,
Attributes attributes) {
if (qName.equalsIgnoreCase("channel"))
this.rssFeed = new RssFeed();
else if (qName.equalsIgnoreCase("item") && (this.rssFeed != null)) {
this.item = new Item();
this.rssFeed.addItem(this.item);
} else if (qName.equalsIgnoreCase("image") && (this.rssFeed != null))
this.imgStatus = true;
}
public void endElement(String uri, String localName, String qName) {
if (this.rssFeed == null)
return;
if (qName.equalsIgnoreCase("item"))
this.item = null;
else if (qName.equalsIgnoreCase("image"))
this.imgStatus = false;
else if (qName.equalsIgnoreCase("title")) {
if (this.item != null) this.item.title = this.text.toString().trim();
else if (this.imgStatus) this.rssFeed.imageTitle = this.text.toString().trim();
else this.rssFeed.title = this.text.toString().trim();
} else if (qName.equalsIgnoreCase("link")) {
if (this.item != null) this.item.link = this.text.toString().trim();
else if (this.imgStatus) this.rssFeed.imageLink = this.text.toString().trim();
else this.rssFeed.link = this.text.toString().trim();
} else if (qName.equalsIgnoreCase("description")) {
if (this.item != null) this.item.description = this.text.toString().trim();
else this.rssFeed.description = this.text.toString().trim();
} else if (qName.equalsIgnoreCase("url") && this.imgStatus)
this.rssFeed.imageUrl = this.text.toString().trim();
else if (qName.equalsIgnoreCase("language"))
this.rssFeed.language = this.text.toString().trim();
else if (qName.equalsIgnoreCase("generator"))
this.rssFeed.generator = this.text.toString().trim();
else if (qName.equalsIgnoreCase("copyright"))
this.rssFeed.copyright = this.text.toString().trim();
else if (qName.equalsIgnoreCase("pubDate") && (this.item != null)) {
try {
this.item.pubDate = sdf.parse(this.text.toString().trim());
} catch (ParseException e) {
throw new RuntimeException();
}
} else if (qName.equalsIgnoreCase("category") && (this.item != null))
this.rssFeed.addItem(this.text.toString().trim(), this.item);
this.text.setLength(0);
}
public void characters(char[] ch, int start, int length) {
this.text.append(ch, start, length);
}
public static class RssFeed {
public String title;
public String description;
public String link;
public String language;
public String generator;
public String copyright;
public String imageUrl;
public String imageTitle;
public String imageLink;
private ArrayList<Item> items;
private HashMap<String, ArrayList<Item>> category;
public void addItem(Item item) {
if (this.items == null)
this.items = new ArrayList<Item>();
this.items.add(item);
}
public void addItem(String category, Item item) {
if (this.category == null)
this.category = new HashMap<String, ArrayList<Item>>();
if (!this.category.containsKey(category))
this.category.put(category, new ArrayList<Item>());
this.category.get(category).add(item);
}
public ArrayList<Item> getItems() {
return items;
}
}
public static class Item implements Comparable<Item> {
public String title;
public String description;
public String link;
public Date pubDate;
private String url;
private String imageUrl;
public String toString() {
return (this.title + ": ");
}
public int compareTo(Item o) {
return (int) (o.pubDate.getTime() - pubDate.getTime());
}
public Date getPubDate() {
return pubDate;
}
public String getDescription() {
return description;
}
public String getTitle() {
return title;
}
public String getUrl() {
return url;
}
public String getimageUrl() {
return imageUrl;
}
}
}
package com.julian.football_app;
import com.julian.football_app.R;
import android.app.Activity;
import android.os.Bundle;
import android.widget.ListView;
public class RSSActivity extends Activity {
/**
* Called when the activity is first created.
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main2);
ListView rssItemList = (ListView) findViewById(R.id.rssListview);
FeedSource feedSource = new HttpFeedSource();
RSSItemAdapter adapter = new RSSItemAdapter(this, R.layout.rssitem, feedSource.getFeed());
rssItemList.setAdapter(adapter);
}
}
/////////RssItem
package com.julian.football_app;
import java.util.Date;
class RSSItem {
private String url;
private String title;
private String description;
private String imageUrl;
private Date pubDate;
public RSSItem() {
}
public RSSItem(String url, String title, String description, String imageUrl) {
this.url = url;
this.title = title;
this.description = description;
this.imageUrl = imageUrl;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDesc(String description) {
this.description = description;
}
public void setImageUrl(String imageUrl) {
this.imageUrl = imageUrl;
}
public String getimageUrl() {
return imageUrl;
}
public void setpubDate(Date pubDate){
this.pubDate = pubDate;
}
public Date getpubDate(){
return pubDate;
}
}
////////////////// RssItemAdaptor
package com.julian.football_app;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import java.util.List;
import com.julian.football_app.R;
class RSSItemAdapter extends ArrayAdapter<RSSItem> {
private final Context context;
public RSSItemAdapter(Context context, int textViewResourceId,
List<RSSItem> items) {
super(context, textViewResourceId, items);
this.context = context;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.rssitem, null);
}
final RSSItem item = getItem(position);
TextView title = (TextView) v.findViewById(R.id.title);
TextView desc = (TextView) v.findViewById(R.id.description);
TextView url = (TextView) v.findViewById(R.id.url);
// this is what is viewed
title.setText(item.getTitle());
desc.setText(item.getDescription());
url.setText(item.getimageUrl());
return v;
}
}
///This is the button i want to display the Rss Feed
package com.julian.football_app;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class Menu extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.menu);
//setting the buttons
Button btnews1 = (Button) findViewById(R.id.news_1);
btnews1.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
Intent news1intent = new Intent(Menu.this, news_1.class);
Menu.this.startActivity(news1intent);
}
});
Thank you for looking at my code... It would be much appreciated if someone could help me :) (i know its says news_1.class in the intent.. its only cuz i tried everything and went back to original state..)
These are the errors that appear in the LogCat:
03-23 13:54:16.118: E/AndroidRuntime(553): FATAL EXCEPTION: main
03-23 13:54:16.118: E/AndroidRuntime(553): at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:1508)
03-23 13:54:16.118: E/AndroidRuntime(553): at android.app.Instrumentation.execStartActivity(Instrumentation.java:1384)
03-23 13:54:16.118: E/AndroidRuntime(553): at android.app.Activity.startActivityForResult(Activity.java:3190)
03-23 13:54:16.118: E/AndroidRuntime(553): at android.app.Activity.startActivity(Activity.java:3297)
03-23 13:54:16.118: E/AndroidRuntime(553): at com.julian.football_app.Menu$1.onClick(Menu.java:24)
03-23 13:54:16.118: E/AndroidRuntime(553): at android.view.View.performClick(View.java:3460)
03-23 13:54:16.118: E/AndroidRuntime(553): at android.view.View$PerformClick.run(View.java:13955)
03-23 13:54:16.118: E/AndroidRuntime(553): at android.os.Handler.handleCallback(Handler.java:605)
03-23 13:54:16.118: E/AndroidRuntime(553): at android.os.Handler.dispatchMessage(Handler.java:92)
03-23 13:54:16.118: E/AndroidRuntime(553): at android.os.Looper.loop(Looper.java:137)
03-23 13:54:16.118: E/AndroidRuntime(553): at android.app.ActivityThread.main(ActivityThread.java:4340)
03-23 13:54:16.118: E/AndroidRuntime(553): at java.lang.reflect.Method.invokeNative(Native Method)
03-23 13:54:16.118: E/AndroidRuntime(553): at java.lang.reflect.Method.invoke(Method.java:511)
03-23 13:54:16.118: E/AndroidRuntime(553): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
03-23 13:54:16.118: E/AndroidRuntime(553): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
03-23 13:54:16.118: E/AndroidRuntime(553): at dalvik.system.NativeStart.main(Native Method)
It sounds like the app is experiencing an exception. To find the cause you need to use LogCat to look at the exception details, which will show you where in your code there is a problem.
See how your application goes off the rails right around:
E/AndroidRuntime(553): at android.app.Activity.startActivity(Activity.java:3297) 03-23 13:54:16.118:
E/AndroidRuntime(553): at com.julian.football_app.Menu$1.onClick(Menu.java:24) 03-23 13:54:16.118:
My feeling is this isn't about the RSS at all. I think you need to fix the Intent navigation between the Activities in your application. You might try blocking out all the behavior from your Activities (comment out the interesting bits of onCreate() or whatever) and make sure you can navigate smoothly between Activities. Then re-enable the Activities and make sure they don't blow up when you enter them.
See also MH's comment about checking that all Activities are in your Manifest.
And take out that line that says:
import com.julian.football_app.R;
If you can't get your code to compile without including a .R, then you're doing something wrong. Try saving all the source files, deleting the contents of your gen directory, and selecting Project > Clean.
Related
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 9 months ago.
When ever I try to send messages from device to device the app works fine a
,But when ever i try to react in a message the app crashes and returns back to main activity page, i don't know what is causing the error
here is the messageAdapter.java code :
package com.example.baatcheet.Adapters;
import com.bumptech.glide.Glide;
import com.example.baatcheet.Models.Message;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.example.baatcheet.R;
import com.example.baatcheet.databinding.ItemReceiveBinding;
import com.example.baatcheet.databinding.ItemSentBinding;
import com.github.pgreze.reactions.ReactionPopup;
import com.github.pgreze.reactions.ReactionsConfig;
import com.github.pgreze.reactions.ReactionsConfigBuilder;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.database.FirebaseDatabase;
import java.util.ArrayList;
public class MessagesAdapter extends RecyclerView.Adapter {
Context context;
ArrayList<Message> messages;
final int ITEM_SENT = 1;
final int ITEM_RECEIVE = 2;
String senderRoom;
String receiverRoom;
public MessagesAdapter(Context context , ArrayList<Message> messages , String senderRoom , String receiverRoom){
this.context = context;
this.messages = messages;
this.senderRoom = senderRoom;
this.receiverRoom = receiverRoom;
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
if(viewType == ITEM_SENT){
View view = LayoutInflater.from(context).inflate(R.layout.item_sent, parent, false);
return new SentViewHolder(view);
}else{
View view = LayoutInflater.from(context).inflate(R.layout.item_receive, parent, false);
return new ReceiverViewHolder(view);
}
}
#Override
public int getItemViewType(int position) {
Message message = messages.get(position);
if(FirebaseAuth.getInstance().getUid().equals(message.getSenderId())){
return ITEM_SENT;
}else{
return ITEM_RECEIVE;
}
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
Message message = messages.get(position);
int[] reactions = new int[]{
R.drawable.ic_fb_like,
R.drawable.ic_fb_love,
R.drawable.ic_fb_laugh,
R.drawable.ic_fb_wow,
R.drawable.ic_fb_sad,
R.drawable.ic_fb_angry
};
ReactionsConfig config = new ReactionsConfigBuilder(context)
.withReactions(reactions)
.build();
ReactionPopup popup = new ReactionPopup(context, config, (pos) -> {
if(holder.getClass() == SentViewHolder.class){
SentViewHolder viewHolder = (SentViewHolder)holder;
if(pos >= 0 && pos <= 6) {
viewHolder.binding.feeling.setImageResource(reactions[pos]);
viewHolder.binding.feeling.setVisibility(View.VISIBLE);
}
}else {
ReceiverViewHolder viewHolder = (ReceiverViewHolder) holder;
if (pos >= 0 && pos <= 6) {
viewHolder.binding.feeling.setImageResource(reactions[pos]);
viewHolder.binding.feeling.setVisibility(View.VISIBLE);
}
}
message.setFeeling(pos);
FirebaseDatabase.getInstance().getReference()
.child("chats")
.child(senderRoom)
.child("messages")
.child(message.getMessageId())
.setValue(message);
FirebaseDatabase.getInstance().getReference()
.child("chats")
.child(receiverRoom)
.child("messages")
.child(message.getMessageId())
.setValue(message);
return true; // true is closing popup, false is requesting a new selection
});
if(holder.getClass() == SentViewHolder.class){
SentViewHolder viewHolder = (SentViewHolder)holder;
viewHolder.binding.message.setText(message.getMessage());
if(message.getFeeling() >= 0){
// message.setFeeling(reactions[(int)message.getFeeling()]);
viewHolder.binding.feeling.setImageResource(reactions[message.getFeeling()]);
viewHolder.binding.feeling.setVisibility(View.VISIBLE);
}
else{
viewHolder.binding.feeling.setVisibility(View.GONE);
}
viewHolder.binding.message.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
popup.onTouch(v,event);
return false;
}
});
}else{
ReceiverViewHolder viewHolder = (ReceiverViewHolder) holder;
viewHolder.binding.message.setText(message.getMessage());
if(message.getFeeling() >= 0){
// message.setFeeling(reactions[(int)message.getFeeling()]);
viewHolder.binding.feeling.setImageResource(reactions[message.getFeeling()]);
viewHolder.binding.feeling.setVisibility(View.VISIBLE);
}
else{
viewHolder.binding.feeling.setVisibility(View.GONE);
}
viewHolder.binding.message.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
popup.onTouch(v,event);
return false;
}
});
}
}
#Override
public int getItemCount() {
return messages.size();
}
public class SentViewHolder extends RecyclerView.ViewHolder{
ItemSentBinding binding;
public SentViewHolder(#NonNull View itemView) {
super(itemView);
binding = ItemSentBinding.bind(itemView);
}
}
public class ReceiverViewHolder extends RecyclerView.ViewHolder{
ItemReceiveBinding binding;
public ReceiverViewHolder(#NonNull View itemView) {
super(itemView);
binding = ItemReceiveBinding.bind(itemView);
}
}
}
Here is the getter and setter class for above adapter class ,
messgaes.java :
package com.example.baatcheet.Models;
public class Message {
private String messageId , message , senderId;
private long timeStamp;
private int feeling = -1;
public String imageUrl;
public Message() {
}
public Message(String message, String senderId, long timeStamp) {
this.message = message;
this.senderId = senderId;
this.timeStamp = timeStamp;
}
public void setMessageId(String messageId) {
this.messageId = messageId;
}
public void setMessage(String message) {
this.message = message;
}
public void setSenderId(String senderId) {
this.senderId = senderId;
}
public void setTimeStamp(long timeStamp) {
this.timeStamp = timeStamp;
}
public void setFeeling(int feeling) {
this.feeling = feeling;
}
public String getImageUrl() {
return imageUrl;
}
public void setImageUrl(String imageUrl) {
this.imageUrl = imageUrl;
}
public String getMessageId() {
return messageId;
}
public String getMessage() {
return message;
}
public String getSenderId() {
return senderId;
}
public long getTimeStamp() {
return timeStamp;
}
public int getFeeling() {
return feeling;
}
}
I dont actually know where my app is getting crashed
the logcat shows the following error when ever i try to react on a message
[samsung-sm_m305f-52001052ca7b863f]: E/InputEventReceiver: Exception dispatching input event.
[samsung-sm_m305f-52001052ca7b863f]: E/MessageQueue-JNI: Exception in MessageQueue callback: handleReceiveCallback
[samsung-sm_m305f-52001052ca7b863f]: E/MessageQueue-JNI: java.lang.NullPointerException: Can't pass null for argument 'pathString' in child()
at com.google.firebase.database.DatabaseReference.child(DatabaseReference.java:96)
at com.example.baatcheet.Adapters.MessagesAdapter.lambda$onBindViewHolder$0$com-example-baatcheet-Adapters-MessagesAdapter(MessagesAdapter.java:104)
at com.example.baatcheet.Adapters.MessagesAdapter$$ExternalSyntheticLambda0.invoke(Unknown Source:10)
at com.github.pgreze.reactions.ReactionViewGroup.onTouchEvent(ReactionViewGroup.kt:247)
at android.view.View.dispatchTouchEvent(View.java:14376)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3857)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:3535)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3863)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:3551)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3863)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:3551)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3863)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:3551)
at android.widget.PopupWindow$PopupDecorView.dispatchTouchEvent(PopupWindow.java:2850)
at android.view.View.dispatchPointerEvent(View.java:14644)
at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:6486)
at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:6273)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5711)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:5764)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:5730)
at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:5886)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:5738)
at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:5943)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5711)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:5764)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:5730)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:5738)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5711)
at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:8870)
at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:8731)
at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:8684)
at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:9006)
at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:194)
at android.os.MessageQueue.nativePollOnce(Native Method)
at android.os.MessageQueue.next(MessageQueue.java:336)
at android.os.Looper.loop(Looper.java:197)
at android.app.ActivityThread.main(ActivityThread.java:7807)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1047)
[samsung-sm_m305f-52001052ca7b863f]: D/AndroidRuntime: Shutting down VM
[samsung-sm_m305f-52001052ca7b863f]: E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.baatcheet, PID: 28114
java.lang.NullPointerException: Can't pass null for argument 'pathString' in child()
at com.google.firebase.database.DatabaseReference.child(DatabaseReference.java:96)
at com.example.baatcheet.Adapters.MessagesAdapter.lambda$onBindViewHolder$0$com-example-baatcheet-Adapters-MessagesAdapter(MessagesAdapter.java:104)
at com.example.baatcheet.Adapters.MessagesAdapter$$ExternalSyntheticLambda0.invoke(Unknown Source:10)
at com.github.pgreze.reactions.ReactionViewGroup.onTouchEvent(ReactionViewGroup.kt:247)
at android.view.View.dispatchTouchEvent(View.java:14376)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3857)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:3535)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3863)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:3551)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3863)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:3551)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3863)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:3551)
at android.widget.PopupWindow$PopupDecorView.dispatchTouchEvent(PopupWindow.java:2850)
at android.view.View.dispatchPointerEvent(View.java:14644)
at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:6486)
at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:6273)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5711)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:5764)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:5730)
at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:5886)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:5738)
at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:5943)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5711)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:5764)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:5730)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:5738)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5711)
at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:8870)
at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:8731)
at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:8684)
at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:9006)
at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:194)
at android.os.MessageQueue.nativePollOnce(Native Method)
at android.os.MessageQueue.next(MessageQueue.java:336)
at android.os.Looper.loop(Looper.java:197)
at android.app.ActivityThread.main(ActivityThread.java:7807)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1047)
You have a NPE for the argument pathString but I cannot find it in your code. You should add a null-check to the relevant part and see if it works.
E/MessageQueue-JNI: java.lang.NullPointerException: Can't pass null for argument 'pathString' in child()
This is the error I've run into and there seem to be no proper fixes to this code since my understanding of the back4app and android studio is very limited (com.parse.ParseException: java.lang.IllegalStateException: Unable to encode an unsaved ParseFile.).
Some of the solution I've tried was not doable and it seem to be that the ParseFile wasn't saved properly. I've tried the callback function and progress function but it doesn't seem to work. So at this point I'm out of idea on how to fix this
here is the code for my compose fragment
package com.example.rentahome.fragments;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageDecoder;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.text.SpannableStringBuilder;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.FileProvider;
import androidx.fragment.app.Fragment;
import com.example.rentahome.ImageFilePath;
import com.example.rentahome.Post;
import com.example.rentahome.R;
import com.example.rentahome.Reviews;
import com.example.rentahome.databinding.FragmentComposeBinding;
import com.parse.Parse;
import com.parse.ParseException;
import com.parse.ParseFile;
import com.parse.ParseObject;
import com.parse.ParseRelation;
import com.parse.ParseUser;
import com.parse.ProgressCallback;
import com.parse.SaveCallback;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import static android.app.Activity.RESULT_OK;
import static com.parse.Parse.getApplicationContext;
public class ComposeFragment extends Fragment {
public static final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 43;
public static final int PICK_PHOTO_CODE = 21;
private File photoFile;
FragmentComposeBinding fragmentComposeBinding;
private String photoFileName = "photo.jpg";
public String realPath = new String();
public static final String TAG = "ComposeFragment";
public ComposeFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_compose, container, false);
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
fragmentComposeBinding = FragmentComposeBinding.bind(view);
fragmentComposeBinding.btnPicture.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
uploadImage();
}
});
fragmentComposeBinding.btnSubmit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String address = fragmentComposeBinding.etAddress.getText().toString();
String price = fragmentComposeBinding.etPrice.getText().toString();
String description = fragmentComposeBinding.etDescription.getText().toString();
if(address.isEmpty()){
Toast.makeText(getContext(), "Address cannot be empty", Toast.LENGTH_SHORT).show();
return;
}
if(price.isEmpty()){
Toast.makeText(getContext(), "Price cannot be empty", Toast.LENGTH_SHORT).show();
return;
}
if(description.isEmpty()){
Toast.makeText(getContext(), "Description cannot be empty", Toast.LENGTH_SHORT).show();
return;
}
if(realPath == null || fragmentComposeBinding.ivPostImage.getDrawable()==null){
Toast.makeText(getContext(),"There is no image", Toast.LENGTH_SHORT).show();
return;
}
ParseUser currentUser = ParseUser.getCurrentUser();
savePost(address, price, description, currentUser);
}
});
}
private void uploadImage() {
// create Intent to upload a picture and return control to the calling application
// Edit action for MediaStore
Intent intent = new Intent(Intent.ACTION_PICK,
MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
// Create a File reference for future access
//photoFile = getPhotoFileUri(photoFileName);
// wrap File object into a content provider
// required for API >= 24
// See https://guides.codepath.com/android/Sharing-Content-with-Intents#sharing-files-with-api-24-or-higher
//Uri fileProvider = FileProvider.getUriForFile(getContext(), "com.example.rentahome.fileprovider", photoFile);
//intent.putExtra(MediaStore.EXTRA_OUTPUT, fileProvider);
// If you call startActivityForResult() using an intent that no app can handle, your app will crash.
// So as long as the result is not null, it's safe to use the intent.
if (intent.resolveActivity(getContext().getPackageManager()) != null) {
// Start the image pick intent to pick photo from external folder
startActivityForResult(intent, PICK_PHOTO_CODE);
}
}
public Bitmap loadFromUri(Uri photoUri) {
Bitmap image = null;
try {
// check version of Anrdoid on device
if(Build.VERSION.SDK_INT > 27) {
// newer version
ImageDecoder.Source source = ImageDecoder.createSource(this.getContext().getContentResolver(), photoUri);
image = ImageDecoder.decodeBitmap(source);
} else {
//support older
image = MediaStore.Images.Media.getBitmap(this.getContext().getContentResolver(),photoUri);
}
} catch (IOException e) {
e.printStackTrace();
}
return image;
}
private File getPhotoFileUri(String fileName) {
// Get safe storage directory for photos
// Use `getExternalFilesDir` on Context to access package-specific directories.
// This way, we don't need to request external read/write runtime permissions.
File mediaStorageDir = new File(getContext().getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), TAG);
// Create the storage directory if it does not exist
if (!mediaStorageDir.exists() && !mediaStorageDir.mkdirs()){
Log.d(TAG, "failed to create directory..");
}
// Return the file target for the photo based on filename
File file = new File(mediaStorageDir.getPath() + File.separator + fileName);
return file;
}
#Override
public void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PICK_PHOTO_CODE && resultCode == RESULT_OK && data != null && data.getData() != null) {
Uri uri = data.getData();
realPath = ImageFilePath.getPath(getContext(), data.getData());
// realPath = RealPathUtil.getRealPathFromURI_API19(this, data.getData());
Log.i(TAG, "onActivityResult: file path : " + realPath);
Log.i(TAG, "onActivityResult: file path : " + getContext().getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).getPath() );
try {
Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContext().getContentResolver(), uri);
// Log.d(TAG, String.valueOf(bitmap));
fragmentComposeBinding.ivPostImage.setImageBitmap(bitmap);
} catch (IOException e) {
e.printStackTrace();
}
} else {
Toast.makeText(getContext(), "Something Went Wrong", Toast.LENGTH_SHORT).show();
}
// if ((data != null) && requestCode == PICK_PHOTO_CODE) {
// if (resultCode == RESULT_OK) {
// Uri photoUri = data.getData();
// // by this point we have the camera photo on disk
// //Bitmap selectedImage = BitmapFactory.decodeFile(photoFile.getAbsolutePath());
// //Load the image located at photoUri into selectedImage
// Bitmap selectedImage = loadFromUri(photoUri);
// // RESIZE BITMAP, see section below
// // Load the taken image into a preview
// fragmentComposeBinding.ivPostImage.setImageBitmap(selectedImage);
//
// } else { // Result was a failure
// Toast.makeText(getContext(), "Image not found", Toast.LENGTH_SHORT).show();
// }
// }
}
private void savePost(String address, String price, String description, ParseUser currentUser) {
//Post post = new Post();
ParseObject post = ParseObject.create("Post");
File file = new File(realPath);
ParseFile photo = new ParseFile(file);
photo.saveInBackground();
// post.setImage(photo);
// int parsed_price = Integer.parseInt(price);
// post.setPrice(parsed_price);
// post.setDescription(description);
// post.setUser(currentUser);
// post.setAddress(address);
// //photo.saveInBackground();
ParseRelation<ParseObject> hi;
//parse String price to int..
post.put("image",photo);
post.put("description",description);
post.put("address",address);
post.put("user",currentUser);
post.put("price",price);
//post.put("Reviews",hi);
// Reviews gameScore = new Reviews();
//
// gameScore.setlikesCount(0);
// gameScore.setdislikesCount(0);
// gameScore.setAuthor(currentUser);
// gameScore.setRating((float) (5.0));
// gameScore.setDescription("hi");
////
//// gameScore.put("Description","Hi ");
//// gameScore.put("author",currentUser);
//// gameScore.put("rating",(float)(5.0));
//// gameScore.put("likesCount",0);
//// gameScore.put("dislikesCount",0);
//
// ParseRelation<Reviews> temp = new ParseRelation<Reviews>();
// temp.add(gameScore);
post.saveInBackground(new SaveCallback() {
#Override
public void done(com.parse.ParseException e) {
if(e!=null){
Log.e(TAG,"Issue with saving posts..", e);
Toast.makeText(getContext(), "Error while saving", Toast.LENGTH_SHORT).show();
return;
}
Log.i(TAG,"Saved successfully!");
fragmentComposeBinding.etDescription.setText("");
fragmentComposeBinding.ivPostImage.setImageResource(0);
}
});
}
}
Here is my post class, and one of the special thing about it was the relation I have inside the post class. There is a reviews relation which contain objects reviews
package com.example.rentahome;
import com.parse.ParseClassName;
import com.parse.ParseFile;
import com.parse.ParseObject;
import com.parse.ParseRelation;
import com.parse.ParseUser;
import java.util.ArrayList;
#ParseClassName("Post")
public class Post extends ParseObject {
public static final String KEY_DESCRIPTION = "description";
public static final String KEY_IMAGE = "image"; //image should be 'uploaded'
public static final String KEY_USER = "user";
public static final String KEY_CREATED_KEY = "createdAt"; //have to figure out how to implement
public static final String KEY_address = "address";
public static final String KEY_price = "price";
public static final String KEY_reviews = "Reviews";
public static final String KEY_objectID = "objectID";
public String getDescription(){
return getString(KEY_DESCRIPTION);
}
public void setDescription(String description){
put(KEY_DESCRIPTION, description);
}
public ParseFile getImage(){
return getParseFile(KEY_IMAGE);
}
public void setImage(ParseFile parseFile){
put(KEY_IMAGE, parseFile);
}
public ParseUser getUser(){
return getParseUser(KEY_USER);
}
public void setUser(ParseUser user){put(KEY_USER, user);}
public String getAddress() {return getString(KEY_address);}
public void setAddress(String address){ put(KEY_address, address);}
public int getPrice(){return getInt(KEY_price);}
public void setPrice(int price){put(KEY_price,price);}
public String getobjectID(){return getString(KEY_objectID);}
public ParseRelation<ParseObject> getrelation() {return getRelation(KEY_reviews);}
public void setrelation(ParseRelation<ParseObject> relation){put(KEY_reviews, relation);}
//public ParseRelation<ParseObject> getReviews(){return getRelation(KEY_reviews);}
//public void setReviews(ParseRelation<ParseObject> reviews){put(KEY_reviews, reviews);}
//public Date getCreatedAt() { return getDate(KEY_CREATED_KEY);}
My review class
package com.example.rentahome;
import com.parse.ParseClassName;
import com.parse.ParseObject;
import com.parse.ParseUser;
#ParseClassName("Reviews")
public class Reviews extends ParseObject {
public static final String KEY_author = "author";
public static final String KEY_description = "Description";
public static final String KEY_likesCount = "likesCount";
public static final String KEY_dislikesCount = "dislikesCount";
public static final String KEY_rating = "rating";
public String getDescription(){return getString(KEY_description);}
public void setDescription(String description){put(KEY_description, description);}
public ParseUser getAuthor(){return getParseUser(KEY_author); }
public void setAuthor(ParseUser author){put(KEY_author,author);}
public float getRating(){return (float)getDouble(KEY_rating);}
public void setRating(float rating) {put(KEY_rating, rating);}
public int getlikesCount() {return getInt(KEY_likesCount);}
public void setlikesCount(int likesCount){put(KEY_likesCount, likesCount);}
public int getdislikesCount() {return getInt(KEY_dislikesCount);}
public void setdislikesCount(int dislikesCount){put(KEY_dislikesCount, dislikesCount);}
}
Here is the error message
E/ComposeFragment: Issue with saving posts..
com.parse.ParseException: java.lang.IllegalStateException: Unable to encode an unsaved ParseFile.
at com.parse.ParseTaskUtils$2$1.run(ParseTaskUtils.java:119)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
Caused by: java.lang.IllegalStateException: Unable to encode an unsaved ParseFile.
at com.parse.ParseFile.encode(ParseFile.java:653)
at com.parse.ParseEncoder.encode(ParseEncoder.java:77)
at com.parse.ParseSetOperation.encode(ParseSetOperation.java:31)
at com.parse.ParseEncoder.encode(ParseEncoder.java:126)
at com.parse.ParseObjectCoder.encode(ParseObjectCoder.java:57)
at com.parse.NetworkObjectController.saveAsync(NetworkObjectController.java:60)
at com.parse.ParseObject$32.then(ParseObject.java:2282)
at com.parse.ParseObject$32.then(ParseObject.java:2277)
at com.parse.boltsinternal.Task$15.run(Task.java:907)
at com.parse.boltsinternal.BoltsExecutors$ImmediateExecutor.execute(BoltsExecutors.java:113)
at com.parse.boltsinternal.Task.completeAfterTask(Task.java:898)
at com.parse.boltsinternal.Task.continueWithTask(Task.java:713)
at com.parse.boltsinternal.Task.continueWithTask(Task.java:724)
at com.parse.boltsinternal.Task$13.then(Task.java:816)
at com.parse.boltsinternal.Task$13.then(Task.java:804)
at com.parse.boltsinternal.Task$15.run(Task.java:907)
at com.parse.boltsinternal.BoltsExecutors$ImmediateExecutor.execute(BoltsExecutors.java:113)
at com.parse.boltsinternal.Task.completeAfterTask(Task.java:898)
at com.parse.boltsinternal.Task.access$100(Task.java:28)
at com.parse.boltsinternal.Task$11.then(Task.java:706)
at com.parse.boltsinternal.Task$11.then(Task.java:703)
at com.parse.boltsinternal.Task.runContinuations(Task.java:946)
at com.parse.boltsinternal.Task.trySetResult(Task.java:984)
at com.parse.boltsinternal.TaskCompletionSource.trySetResult(TaskCompletionSource.java:45)
at com.parse.boltsinternal.TaskCompletionSource.setResult(TaskCompletionSource.java:68)
at com.parse.boltsinternal.Task$15$1.then(Task.java:924)
at com.parse.boltsinternal.Task$15$1.then(Task.java:911)
at com.parse.boltsinternal.Task$14.run(Task.java:866)
at com.parse.boltsinternal.BoltsExecutors$ImmediateExecutor.execute(BoltsExecutors.java:113)
at com.parse.boltsinternal.Task.completeImmediately(Task.java:857)
at com.parse.boltsinternal.Task.continueWith(Task.java:659)
at com.parse.boltsinternal.Task.continueWith(Task.java:670)
at com.parse.boltsinternal.Task$15.run(Task.java:911)
at com.parse.boltsinternal.BoltsExecutors$ImmediateExecutor.execute(BoltsExecutors.java:113)
at com.parse.boltsinternal.Task.completeAfterTask(Task.java:898)
at com.parse.boltsinternal.Task.access$100(Task.java:28)
at com.parse.boltsinternal.Task$11.then(Task.java:706)
at com.parse.boltsinternal.Task$11.then(Task.java:703)
at com.parse.boltsinternal.Task.runContinuations(Task.java:946)
at com.parse.boltsinternal.Task.trySetResult(Task.java:984)
at com.parse.boltsinternal.TaskCompletionSource.trySetResult(TaskCompletionSource.java:45)
at com.parse.boltsinternal.TaskCompletionSource.setResult(TaskCompletionSource.java:68)
at com.parse.boltsinternal.Task$8.then(Task.java:562)
at com.parse.boltsinternal.Task$8.then(Task.java:536)
at com.parse.boltsinternal.Task$14.run(Task.java:866)
at com.parse.boltsinternal.BoltsExecutors$ImmediateExecutor.execute(BoltsExecutors.java:113)
at com.parse.boltsinternal.Task.completeImmediately(Task.java:857)
at com.parse.boltsinternal.Task.access$000(Task.java:28)
at com.parse.boltsinternal.Task$10.then(Task.java:652)
at com.parse.boltsinternal.Task$10.then(Task.java:649)
E/ComposeFragment: at com.parse.boltsinternal.Task.runContinuations(Task.java:946)
at com.parse.boltsinternal.Task.trySetResult(Task.java:984)
at com.parse.boltsinternal.TaskCompletionSource.trySetResult(TaskCompletionSource.java:45)
at com.parse.boltsinternal.TaskCompletionSource.setResult(TaskCompletionSource.java:68)
at com.parse.boltsinternal.Task$14.run(Task.java:867)
at com.parse.boltsinternal.BoltsExecutors$ImmediateExecutor.execute(BoltsExecutors.java:113)
at com.parse.boltsinternal.Task.completeImmediately(Task.java:857)
at com.parse.boltsinternal.Task.access$000(Task.java:28)
at com.parse.boltsinternal.Task$10.then(Task.java:652)
at com.parse.boltsinternal.Task$10.then(Task.java:649)
at com.parse.boltsinternal.Task.runContinuations(Task.java:946)
at com.parse.boltsinternal.Task.trySetError(Task.java:1001)
at com.parse.boltsinternal.TaskCompletionSource.trySetError(TaskCompletionSource.java:52)
at com.parse.boltsinternal.TaskCompletionSource.setError(TaskCompletionSource.java:77)
at com.parse.boltsinternal.Task$8.then(Task.java:552)
at com.parse.boltsinternal.Task$8.then(Task.java:536)
at com.parse.boltsinternal.Task$14.run(Task.java:866)
at com.parse.boltsinternal.BoltsExecutors$ImmediateExecutor.execute(BoltsExecutors.java:113)
at com.parse.boltsinternal.Task.completeImmediately(Task.java:857)
at com.parse.boltsinternal.Task.access$000(Task.java:28)
at com.parse.boltsinternal.Task$10.then(Task.java:652)
at com.parse.boltsinternal.Task$10.then(Task.java:649)
at com.parse.boltsinternal.Task.runContinuations(Task.java:946)
at com.parse.boltsinternal.Task.trySetError(Task.java:1001)
at com.parse.boltsinternal.TaskCompletionSource.trySetError(TaskCompletionSource.java:52)
at com.parse.boltsinternal.TaskCompletionSource.setError(TaskCompletionSource.java:77)
at com.parse.boltsinternal.Task$15$1.then(Task.java:922)
at com.parse.boltsinternal.Task$15$1.then(Task.java:911)
at com.parse.boltsinternal.Task$14.run(Task.java:866)
at com.parse.boltsinternal.BoltsExecutors$ImmediateExecutor.execute(BoltsExecutors.java:113)
at com.parse.boltsinternal.Task.completeImmediately(Task.java:857)
at com.parse.boltsinternal.Task.access$000(Task.java:28)
at com.parse.boltsinternal.Task$10.then(Task.java:652)
at com.parse.boltsinternal.Task$10.then(Task.java:649)
at com.parse.boltsinternal.Task.runContinuations(Task.java:946)
at com.parse.boltsinternal.Task.trySetError(Task.java:1001)
at com.parse.boltsinternal.TaskCompletionSource.trySetError(TaskCompletionSource.java:52)
at com.parse.boltsinternal.TaskCompletionSource.setError(TaskCompletionSource.java:77)
at com.parse.boltsinternal.Task$15$1.then(Task.java:922)
at com.parse.boltsinternal.Task$15$1.then(Task.java:911)
at com.parse.boltsinternal.Task$14.run(Task.java:866)
at com.parse.boltsinternal.BoltsExecutors$ImmediateExecutor.execute(BoltsExecutors.java:113)
at com.parse.boltsinternal.Task.completeImmediately(Task.java:857)
at com.parse.boltsinternal.Task.continueWith(Task.java:659)
at com.parse.boltsinternal.Task.continueWith(Task.java:670)
at com.parse.boltsinternal.Task$15.run(Task.java:911)
at com.parse.boltsinternal.BoltsExecutors$ImmediateExecutor.execute(BoltsExecutors.java:113)
at com.parse.boltsinternal.Task.completeAfterTask(Task.java:898)
at com.parse.boltsinternal.Task.access$100(Task.java:28)
at com.parse.boltsinternal.Task$11.then(Task.java:706)
at com.parse.boltsinternal.Task$11.then(Task.java:703)
at com.parse.boltsinternal.Task.runContinuations(Task.java:946)
at com.parse.boltsinternal.Task.trySetError(Task.java:1001)
at com.parse.boltsinternal.TaskCompletionSource.trySetError(TaskCompletionSource.java:52)
at com.parse.boltsinternal.TaskCompletionSource.setError(TaskCompletionSource.java:77)
at com.parse.boltsinternal.Task$15$1.then(Task.java:922)
at com.parse.boltsinternal.Task$15$1.then(Task.java:911)
at com.parse.boltsinternal.Task$14.run(Task.java:866)
at com.parse.boltsinternal.BoltsExecutors$ImmediateExecutor.execute(BoltsExecutors.java:113)
at com.parse.boltsinternal.Task.completeImmediately(Task.java:857)
at com.parse.boltsinternal.Task.continueWith(Task.java:659)
at com.parse.boltsinternal.Task.continueWith(Task.java:670)
at com.parse.boltsinternal.Task$15.run(Task.java:911)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:923)
Your problem happens because you are not awaiting photo.saveInBackground to complete. Your code should look like this:
ParseObject post = ParseObject.create("Post");
File file = new File(realPath);
ParseFile photo = new ParseFile(file);
photo.saveInBackground(new SaveCallback() {
#Override
public void done(com.parse.ParseException e) {
// Handle success or failure here ...
post.put("image",photo);
post.put("description",description);
post.put("address",address);
post.put("user",currentUser);
post.put("price",price);
post.saveInBackground(new SaveCallback() {
#Override
public void done(com.parse.ParseException e) {
// Handle success or failure here ...
}
});
}
});
In my case, there is a listVIew in the first activity and by clicking on a listItem it redirects to another activity which allows to edit to edit details of the particular object item. once the selected item is edited in the second activity I want it to be updated in the first activity as well. I have used parcelable extra to pass data between two activities.
The first activity passes data to the second activity correctly but when it comes to updating the listView in the first activity using updated data in the second activity it throws a NullPointerException saying that the received object is null.
Please help me figure this out. thanks in advance.
Parcelable object class
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.RequiresApi;
import java.io.Serializable;
public class Movie implements Parcelable {
private String title;
private int releasedYear;
private String director;
private String cast;
private int rating;
private String review;
private boolean favourite;
public Movie(String title, int releasedYear, String director, String cast, int rating, String review) {
this.title = title;
this.releasedYear = releasedYear;
this.director = director;
this.cast = cast;
this.rating = rating;
this.review = review;
}
public Movie(String title, int releasedYear, String director, String cast, int rating, String review, boolean favourite) {
this.title = title;
this.releasedYear = releasedYear;
this.director = director;
this.cast = cast;
this.rating = rating;
this.review = review;
this.favourite = favourite;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public int getReleasedYear() {
return releasedYear;
}
public void setReleasedYear(int releasedYear) {
this.releasedYear = releasedYear;
}
public String getDirector() {
return director;
}
public void setDirector(String director) {
this.director = director;
}
public String getCast() {
return cast;
}
public void setCast(String cast) {
this.cast = cast;
}
public int getRating() {
return rating;
}
public void setRating(int rating) {
this.rating = rating;
}
public String getReview() {
return review;
}
public void setReview(String review) {
this.review = review;
}
public boolean isFavourite() {
return favourite;
}
public void setFavourite(boolean favourite) {
this.favourite = favourite;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.title);
dest.writeInt(this.releasedYear);
dest.writeString(this.director);
dest.writeString(this.cast);
dest.writeInt(this.rating);
dest.writeString(this.review);
dest.writeByte(this.favourite ? (byte) 1 : (byte) 0);
}
public void readFromParcel(Parcel source) {
this.title = source.readString();
this.releasedYear = source.readInt();
this.director = source.readString();
this.cast = source.readString();
this.rating = source.readInt();
this.review = source.readString();
this.favourite = source.readByte() != 0;
}
protected Movie(Parcel in) {
this.title = in.readString();
this.releasedYear = in.readInt();
this.director = in.readString();
this.cast = in.readString();
this.rating = in.readInt();
this.review = in.readString();
this.favourite = in.readByte() != 0;
}
public static final Creator<Movie> CREATOR = new Creator<Movie>() {
#Override
public Movie createFromParcel(Parcel source) {
return new Movie(source);
}
#Override
public Movie[] newArray(int size) {
return new Movie[size];
}
};
}
First activity
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.os.Parcelable;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.RelativeLayout;
import com.example.movietracker.database.CoreDatabase;
import java.util.ArrayList;
import java.util.List;
import static com.example.movietracker.database.Constants.TABLE_NAME;
import static com.example.movietracker.database.Constants.TITLE;
public class EditMovie extends AppCompatActivity {
private final int REQ_COE = 1;
CoreDatabase database;
List<Movie> movies;
Movie movieReturn;
RelativeLayout layout;
ListView listView;
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQ_COE) {
if (resultCode == RESULT_OK) {
movieReturn = getIntent().getParcelableExtra("movieReturn");
movies.add(movieReturn);
}
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_edit_movie);
layout = findViewById(R.id.edit_relative_layout);
listView = findViewById(R.id.edit_listView);
movies = new ArrayList<>();
database = new CoreDatabase(this);
String query = "select * from "+ TABLE_NAME + " order by "+ TITLE + " ASC";
Cursor cursor = database.getData(query);
retrieveData(cursor);
System.out.println(movies.size());
MovieArrayAdapter adapter = new MovieArrayAdapter(this, movies);
adapter.notifyDataSetChanged();
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent intent = new Intent(EditMovie.this, EditMovieItemView.class);
intent.putExtra("movie", movies.get(position));
startActivityForResult(intent, 1);
movies.remove(position);
adapter.notifyDataSetChanged();
System.out.println(movies.size());
}
});
}
public void retrieveData(Cursor cursor){
while (cursor.moveToNext()) {
String title = cursor.getString(1);
int year = cursor.getInt(2);
String director = cursor.getString(3);
String cast = cursor.getString(4);
int rating = cursor.getInt(5);
String review = cursor.getString(6);
boolean favourite = cursor.getInt(7) > 0;
movies.add(new Movie(title, year, director, cast, rating, review, favourite));
}
}
}
Second Activity
import androidx.appcompat.app.AppCompatActivity;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.text.InputFilter;
import android.view.View;
import android.widget.CheckBox;
import android.widget.NumberPicker;
import android.widget.RatingBar;
import android.widget.Toast;
import com.example.movietracker.database.CoreDatabase;
import com.google.android.material.textfield.TextInputEditText;
import com.google.android.material.textfield.TextInputLayout;
import java.util.List;
public class EditMovieItemView extends AppCompatActivity {
CoreDatabase database;
Movie movie;
String pickedDate, defaultTitle;
String updatedTitle, updatedDirector, updatedCast, updatedReview;
int updatedYear, updatedRating;
CheckBox favourite;
TextInputLayout title, year, director, cast, review;
NumberPicker yearPicker;
RatingBar rating1, rating2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_edit_movie_item_view);
database = new CoreDatabase(this);
favourite = findViewById(R.id.edit_fav_checkbox);
title = findViewById(R.id.edit_movie_title);
year = findViewById(R.id.edit_movie_year);
year.getEditText().setFilters(new InputFilter[]{new MinMaxFilter(1895, 2021)});
director = findViewById(R.id.edit_movie_director);
cast = findViewById(R.id.edit_movie_cast);
rating1 = findViewById(R.id.edit_ratingBar1);
rating2 = findViewById(R.id.edit_ratingBar2);
review = findViewById(R.id.edit_movie_review);
yearPicker = findViewById(R.id.edit_year_picker);
yearPicker.setMinValue(1895);
yearPicker.setMaxValue(2021);
yearPicker.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
#Override
public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
pickedDate = String.valueOf(picker.getValue());
year.getEditText().setText(pickedDate);
}
});
if (getIntent().getExtras() != null){
movie = getIntent().getParcelableExtra("movie");
}
title.getEditText().setText(movie.getTitle());
year.getEditText().setText(String.valueOf(movie.getReleasedYear()));
director.getEditText().setText(movie.getDirector());
cast.getEditText().setText(movie.getCast());
review.getEditText().setText(movie.getReview());
if (movie.getRating() <= 5){
rating1.setRating(movie.getRating());
rating2.setRating(0);
} else {
rating1.setRating(5);
rating2.setRating(movie.getRating() - 5);
}
favourite.setChecked(movie.isFavourite());
defaultTitle = title.getEditText().getText().toString();
}
public void updateMovie(View view){
updatedTitle = title.getEditText().getText().toString();
updatedYear = Integer.parseInt(year.getEditText().getText().toString());
updatedDirector = director.getEditText().getText().toString();
updatedCast = cast.getEditText().getText().toString();
updatedReview = review.getEditText().getText().toString();
updatedRating = (int) (rating1.getRating() + rating2.getRating());
database.updateAllData(updatedTitle, updatedYear, updatedDirector, updatedCast, updatedRating, updatedReview, favourite.isChecked(), defaultTitle);
Toast.makeText(getApplicationContext(), "Successfully updated!", Toast.LENGTH_SHORT).show();
movie.setTitle(updatedTitle);
movie.setReleasedYear(updatedYear);
movie.setDirector(updatedDirector);
movie.setCast(updatedCast);
movie.setRating(updatedRating);
movie.setReview(updatedReview);
movie.setFavourite(favourite.isChecked());
Intent returnIntent = new Intent();
returnIntent.putExtra("movieReturn", movie);
setResult(RESULT_OK, returnIntent);
finish();
}
}
i tried in onCreate() method to make new thread and start it but the app freezes and the message still same (Cannot access database on the main thread since it may potentially lock the UI for a long period of time.)
also tried Runnable and Handler same message
i searched alot for the same issue i found runOnUIThread still same issue
any Articles or videos that would help please refer it
any missing code you want to review refer it too
thanks in advance.
package com.example.android.popularmovies;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.Toast;
import com.example.android.popularmovies.DataBase.AppDatabase;
import com.example.android.popularmovies.DataBase.FavoriteMovies;
import org.json.JSONArray;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
public class MainActivity extends AppCompatActivity {
private ArrayList<ListItem> arrayMovies = new ArrayList<>();
private RecyclerView mRecyclerView;
private RecyclerViewAdapter adapter;
private RecyclerViewAdapterFavorite adapterFavorite;
private String dataRetrieved;
private static final String TAG = "MAINACTIVITY";
private String top_rated = "http://api.themoviedb.org/3/movie/top_rated?api_key=*****";
private String MoviesURL = "http://api.themoviedb.org/3/movie/popular?api_key=*****";
private AppDatabase mDb;
private List<FavoriteMovies> allFavoriteMovies=new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDb=AppDatabase.getInstance(getApplicationContext());
networkUtilites(false);
getArrayMovies();
RecyclerViewAdapter();
MainActivity.this.runOnUiThread(new Runnable()
{
#Override
public void run() {
allFavoriteMovies= mDb.taskDao().loadAllTasks();
}
});
for(int i=0;i<allFavoriteMovies.size();i++)
{
System.out.println(allFavoriteMovies.get(i).getTitle());
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.sorting_menu, menu);
return true;
}
#Override
protected void onResume() {
super.onResume();
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.most_popular:
Toast.makeText(this, "MostPopularClicked", Toast.LENGTH_SHORT).show();
arrayMovies.clear();
networkUtilites(false);
getArrayMovies();
RecyclerViewAdapter();
return true;
case R.id.top_rated:
Toast.makeText(this, "TopRatedClicked", Toast.LENGTH_SHORT).show();
arrayMovies.clear();
networkUtilites(true);
getArrayMovies();
RecyclerViewAdapter();
return true;
case R.id.favorite:
Toast.makeText(this, "Favorite", Toast.LENGTH_SHORT).show();
RecyclerViewAdapterFavorite();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
public void networkUtilites(Boolean check) {
NetworkUtilites ob = new NetworkUtilites();
if (check) {
ob.setMoviesURL(top_rated);
} else {
ob.setMoviesURL(MoviesURL);
}
try {
dataRetrieved = ob.execute().get();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void getArrayMovies() {
try {
if (!dataRetrieved.equals(null)) {
JSONObject parentObject = new JSONObject(dataRetrieved);
JSONArray parentArray = parentObject.getJSONArray("results");
//System.out.println(parentArray.length());
for (int i = 0; i < parentArray.length(); i++) {
JSONObject movieDetails = parentArray.getJSONObject(i);
String poster_path = "http://image.tmdb.org/t/p/w500";
poster_path += movieDetails.getString("poster_path");
String original_title = movieDetails.getString("original_title");
String overview = movieDetails.getString("overview");
int vote_average = movieDetails.getInt("vote_average");
String release_date = movieDetails.getString("release_date");
int id =movieDetails.getInt("id");
ListItem ob = new ListItem(original_title, poster_path, overview, vote_average, release_date,id);
arrayMovies.add(ob);
}
}
} catch (Exception e) {
}
}
public void RecyclerViewAdapter() {
adapter = new RecyclerViewAdapter(this, arrayMovies);
mRecyclerView = findViewById(R.id.recycler_view);
mRecyclerView.setAdapter(adapter);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new GridLayoutManager(this, 2));
}
public void RecyclerViewAdapterFavorite()
{
if (allFavoriteMovies != null) {
adapterFavorite = new RecyclerViewAdapterFavorite(this, allFavoriteMovies);
mRecyclerView = findViewById(R.id.recycler_view);
mRecyclerView.setAdapter(adapterFavorite);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
}
}
}
TaskDao
package com.example.android.popularmovies.DataBase;
import androidx.room.Dao;
import androidx.room.Delete;
import androidx.room.Insert;
import androidx.room.Query;
import java.util.List;
#Dao
public interface TaskDao
{
#Query("SELECT * From movies")
List<FavoriteMovies> loadAllTasks();
#Query("DELETE From movies")
void deleteallTasks();
#Insert
void insertMovie(FavoriteMovies favoriteMovies);
#Delete
void deleteMovie(FavoriteMovies favoriteMovies);
}
FavoriteMovies
package com.example.android.popularmovies.DataBase;
import androidx.room.Entity;
import androidx.room.Ignore;
import androidx.room.PrimaryKey;
#Entity(tableName = "movies")
public class FavoriteMovies
{
#PrimaryKey
private int id;
private String image;
private String title;
private String overview;
#Ignore
public FavoriteMovies(String image, String title, String overview) {
this.image = image;
this.title = title;
this.overview = overview;
}
public FavoriteMovies(int id, String image, String title, String overview) {
this.id = id;
this.image = image;
this.title = title;
this.overview = overview;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getOverview() {
return overview;
}
public void setOverview(String overview) {
this.overview = overview;
}
}
AppDatabase
package com.example.android.popularmovies.DataBase;
import android.content.Context;
import androidx.room.Database;
import androidx.room.Room;
import androidx.room.RoomDatabase;
#Database(entities = {FavoriteMovies.class},version = 1,exportSchema = false)
public abstract class AppDatabase extends RoomDatabase
{
private static final String DATABASE_NAME="FavouriteMovies";
private static final Object LOCK = new Object();
private static AppDatabase sInstance;
public static AppDatabase getInstance(Context context)
{
if(sInstance==null)
{
synchronized (LOCK){
sInstance= Room.databaseBuilder(context.getApplicationContext(),AppDatabase.class,AppDatabase.DATABASE_NAME)
.build();
}
}
return sInstance;
}
public abstract TaskDao taskDao();
}
Stacktrace:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.android.popularmovies, PID: 5342
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.android.popularmovies/com.example.android.popularmovies.MainActivity}: java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2817)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2892)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1593)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
Caused by: java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.
The reason for freezing is because you are putting the task on runonuithread this means its running on the same thread as the UI and would block the system.
You can try https://developer.android.com/reference/android/os/AsyncTask. Which has an easy to use API for short multithreading purposes.
Another way is to create new java threads in onCreate that does no run on the ui thread.
Thread t = new Thread(new Runnable(){yourcodehere})
t.start()
Hello everyone i was trying to make Custom list of view with volley feed following this tutorial: http://www.androidhive.info/2014/06/android-facebook-like-custom-listview-feed-using-volley/
but i got an error with the image loader i can't get the hang of it , i hope if someone can tell me what is the problem and how should i solve it in the first place :)
thanks in advance
this is the error:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.asro9.customfeed/com.example.asro9.customfeed.MainActivity}: java.lang.NullPointerException
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2184)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2233)
at android.app.ActivityThread.access$800(ActivityThread.java:135)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
at android.os.Handler.dispatchMessage(Handler.java:102)
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)
Caused by: java.lang.NullPointerException
at Adapter.FeedListAdapter.<init>(FeedListAdapter.java:33)
at com.example.asro9.customfeed.MainActivity.onCreate(MainActivity.java:50)
at android.app.Activity.performCreate(Activity.java:5231)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2148)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2233)
at android.app.ActivityThread.access$800(ActivityThread.java:135)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
at android.os.Handler.dispatchMessage(Handler.java:102)
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)
i will show up the classes i have created !
FeedListAdapter.java
package Adapter;
import java.util.List;
import android.app.Activity;
import android.content.Context;
import android.text.Html;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.text.method.LinkMovementMethod;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.NetworkImageView;
import com.example.asro9.customfeed.FeedImageView;
import com.example.asro9.customfeed.R;
import CustomFeed.AppController;
import Data.FeedItem;
/**
* Created by asro9 on 3/7/2016.
*/
public class FeedListAdapter extends BaseAdapter {
private Activity activity;
private LayoutInflater inflater;
private List<FeedItem> feedItems;
ImageLoader imageLoader = AppController.getInstance().getImageLoader();
public FeedListAdapter(Activity activity, List<FeedItem> feedItems) {
this.activity = activity;
this.feedItems = feedItems;
}
#Override
public int getCount() {
return feedItems.size();
}
#Override
public Object getItem(int location) {
return feedItems.get(location);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (inflater == null)
inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null)
convertView = inflater.inflate(R.layout.feed_item, null);
if (imageLoader == null)
imageLoader = AppController.getInstance().getImageLoader();
TextView name = (TextView) convertView.findViewById(R.id.name);
TextView timestamp = (TextView) convertView
.findViewById(R.id.timestamp);
TextView statusMsg = (TextView) convertView
.findViewById(R.id.txtStatusMsg);
TextView url = (TextView) convertView.findViewById(R.id.txtUrl);
NetworkImageView profilePic = (NetworkImageView) convertView
.findViewById(R.id.profilePic);
FeedImageView feedImageView = (FeedImageView) convertView
.findViewById(R.id.feedImage1);
FeedItem item = feedItems.get(position);
name.setText(item.getName());
// Converting timestamp into x ago format
CharSequence timeAgo = DateUtils.getRelativeTimeSpanString(
Long.parseLong(item.getTimeStamp()),
System.currentTimeMillis(), DateUtils.SECOND_IN_MILLIS);
timestamp.setText(timeAgo);
// Chcek for empty status message
if (!TextUtils.isEmpty(item.getStatus())) {
statusMsg.setText(item.getStatus());
statusMsg.setVisibility(View.VISIBLE);
} else {
// status is empty, remove from view
statusMsg.setVisibility(View.GONE);
}
// Checking for null feed url
if (item.getUrl() != null) {
url.setText(Html.fromHtml("<a href=\"" + item.getUrl() + "\">"
+ item.getUrl() + "</a> "));
// Making url clickable
url.setMovementMethod(LinkMovementMethod.getInstance());
url.setVisibility(View.VISIBLE);
} else {
// url is null, remove from the view
url.setVisibility(View.GONE);
}
// user profile pic
profilePic.setImageUrl(item.getProfilePic(), imageLoader);
// Feed image
if (item.getImge() != null) {
feedImageView.setImageUrl(item.getImge(), imageLoader);
feedImageView.setVisibility(View.VISIBLE);
feedImageView
.setResponseObserver(new FeedImageView.ResponseObserver() {
#Override
public void onError() {
}
#Override
public void onSuccess() {
}
});
} else {
feedImageView.setVisibility(View.GONE);
}
return convertView;
}
}
FeedImageVie.java
package com.example.asro9.customfeed;
import android.content.Context;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.ImageLoader.ImageContainer;
import com.android.volley.toolbox.ImageLoader.ImageListener;
/**
* Created by asro9 on 3/7/2016.
*/
public class FeedImageView extends ImageView {
public interface ResponseObserver {
public void onError();
public void onSuccess();
}
private ResponseObserver mObserver;
public void setResponseObserver(ResponseObserver observer) {
mObserver = observer;
}
/**
* The URL of the network image to load
*/
private String mUrl;
/**
* Resource ID of the image to be used as a placeholder until the network
* image is loaded.
*/
private int mDefaultImageId;
/**
* Resource ID of the image to be used if the network response fails.
*/
private int mErrorImageId;
/**
* Local copy of the ImageLoader.
*/
private ImageLoader mImageLoader;
/**
* Current ImageContainer. (either in-flight or finished)
*/
private ImageContainer mImageContainer;
public FeedImageView(Context context) {
this(context, null);
}
public FeedImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public FeedImageView(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
}
/**
* Sets URL of the image that should be loaded into this view. Note that
* calling this will immediately either set the cached image (if available)
* or the default image specified by
* {#link VolleyImageView#setDefaultImageResId(int)} on the view.
*
* NOTE: If applicable, {#link VolleyImageView#setDefaultImageResId(int)}
* and {#link VolleyImageView#setErrorImageResId(int)} should be called
* prior to calling this function.
*
* #param url
* The URL that should be loaded into this ImageView.
* #param imageLoader
* ImageLoader that will be used to make the request.
*/
public void setImageUrl(String url, ImageLoader imageLoader) {
mUrl = url;
mImageLoader = imageLoader;
// The URL has potentially changed. See if we need to load it.
loadImageIfNecessary(false);
}
/**
* Sets the default image resource ID to be used for this view until the
* attempt to load it completes.
*/
public void setDefaultImageResId(int defaultImage) {
mDefaultImageId = defaultImage;
}
/**
* Sets the error image resource ID to be used for this view in the event
* that the image requested fails to load.
*/
public void setErrorImageResId(int errorImage) {
mErrorImageId = errorImage;
}
/**
* Loads the image for the view if it isn't already loaded.
*
* #param isInLayoutPass
* True if this was invoked from a layout pass, false otherwise.
*/
private void loadImageIfNecessary(final boolean isInLayoutPass) {
final int width = getWidth();
int height = getHeight();
boolean isFullyWrapContent = getLayoutParams() != null
&& getLayoutParams().height == LayoutParams.WRAP_CONTENT
&& getLayoutParams().width == LayoutParams.WRAP_CONTENT;
// if the view's bounds aren't known yet, and this is not a
// wrap-content/wrap-content
// view, hold off on loading the image.
if (width == 0 && height == 0 && !isFullyWrapContent) {
return;
}
// if the URL to be loaded in this view is empty, cancel any old
// requests and clear the
// currently loaded image.
if (TextUtils.isEmpty(mUrl)) {
if (mImageContainer != null) {
mImageContainer.cancelRequest();
mImageContainer = null;
}
setDefaultImageOrNull();
return;
}
// if there was an old request in this view, check if it needs to be
// canceled.
if (mImageContainer != null && mImageContainer.getRequestUrl() != null) {
if (mImageContainer.getRequestUrl().equals(mUrl)) {
// if the request is from the same URL, return.
return;
} else {
// if there is a pre-existing request, cancel it if it's
// fetching a different URL.
mImageContainer.cancelRequest();
setDefaultImageOrNull();
}
}
// The pre-existing content of this view didn't match the current URL.
// Load the new image
// from the network.
ImageContainer newContainer = mImageLoader.get(mUrl,
new ImageListener() {
#Override
public void onErrorResponse(VolleyError error) {
if (mErrorImageId != 0) {
setImageResource(mErrorImageId);
}
if (mObserver != null) {
mObserver.onError();
}
}
#Override
public void onResponse(final ImageContainer response,
boolean isImmediate) {
// If this was an immediate response that was delivered
// inside of a layout
// pass do not set the image immediately as it will
// trigger a requestLayout
// inside of a layout. Instead, defer setting the image
// by posting back to
// the main thread.
if (isImmediate && isInLayoutPass) {
post(new Runnable() {
#Override
public void run() {
onResponse(response, false);
}
});
return;
}
int bWidth = 0, bHeight = 0;
if (response.getBitmap() != null) {
setImageBitmap(response.getBitmap());
bWidth = response.getBitmap().getWidth();
bHeight = response.getBitmap().getHeight();
adjustImageAspect(bWidth, bHeight);
} else if (mDefaultImageId != 0) {
setImageResource(mDefaultImageId);
}
if (mObserver != null) {
mObserver.onSuccess();
}
}
});
// update the ImageContainer to be the new bitmap container.
mImageContainer = newContainer;
}
private void setDefaultImageOrNull() {
if (mDefaultImageId != 0) {
setImageResource(mDefaultImageId);
} else {
setImageBitmap(null);
}
}
#Override
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
super.onLayout(changed, left, top, right, bottom);
loadImageIfNecessary(true);
}
#Override
protected void onDetachedFromWindow() {
if (mImageContainer != null) {
// If the view was bound to an image request, cancel it and clear
// out the image from the view.
mImageContainer.cancelRequest();
setImageBitmap(null);
// also clear out the container so we can reload the image if
// necessary.
mImageContainer = null;
}
super.onDetachedFromWindow();
}
#Override
protected void drawableStateChanged() {
super.drawableStateChanged();
invalidate();
}
/*
* Adjusting imageview height
* */
private void adjustImageAspect(int bWidth, int bHeight) {
LinearLayout.LayoutParams params = (LayoutParams) getLayoutParams();
if (bWidth == 0 || bHeight == 0)
return;
int swidth = getWidth();
int new_height = 0;
new_height = swidth * bHeight / bWidth;
params.width = swidth;
params.height = new_height;
setLayoutParams(params);
}
}
the MainActivity.java
package com.example.asro9.customfeed;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.view.Menu;
import android.widget.ListView;
import org.json.JSONException;
import java.util.ArrayList;
import java.util.List;
import Adapter.FeedListAdapter;
import CustomFeed.AppController;
import Data.FeedItem;
import com.android.volley.Cache;
import com.android.volley.Cache.Entry;
import com.android.volley.Request.Method;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.VolleyLog;
import com.android.volley.toolbox.JsonObjectRequest;
import java.io.UnsupportedEncodingException;
import org.json.JSONArray;
import org.json.JSONObject;
public class MainActivity extends Activity {
private static final String TAG = MainActivity.class.getSimpleName();
private ListView listView;
private FeedListAdapter listAdapter;
private List<FeedItem> feedItems;
private String URL_FEED = "http://api.androidhive.info/feed/feed.json";
#SuppressLint("NewApi")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView) findViewById(R.id.list);
feedItems = new ArrayList<FeedItem>();
listAdapter = new FeedListAdapter(this, feedItems);
listView.setAdapter(listAdapter);
// These two lines not needed,
// just to get the look of facebook (changing background color & hiding the icon)
getActionBar().setBackgroundDrawable(new ColorDrawable(Color.parseColor("#3b5998")));
getActionBar().setIcon(
new ColorDrawable(getResources().getColor(android.R.color.transparent)));
// We first check for cached request
Cache cache = AppController.getInstance().getRequestQueue().getCache();
Entry entry = cache.get(URL_FEED);
if (entry != null) {
// fetch the data from cache
try {
String data = new String(entry.data, "UTF-8");
try {
parseJsonFeed(new JSONObject(data));
} catch (JSONException e) {
e.printStackTrace();
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
} else {
// making fresh volley request and getting json
JsonObjectRequest jsonReq = new JsonObjectRequest(Method.GET,
URL_FEED, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
VolleyLog.d(TAG, "Response: " + response.toString());
if (response != null) {
parseJsonFeed(response);
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d(TAG, "Error: " + error.getMessage());
}
});
// Adding request to volley request queue
AppController.getInstance().addToRequestQueue(jsonReq);
}
}
/**
* Parsing json reponse and passing the data to feed view list adapter
* */
private void parseJsonFeed(JSONObject response) {
try {
JSONArray feedArray = response.getJSONArray("feed");
for (int i = 0; i < feedArray.length(); i++) {
JSONObject feedObj = (JSONObject) feedArray.get(i);
FeedItem item = new FeedItem();
item.setId(feedObj.getInt("id"));
item.setName(feedObj.getString("name"));
// Image might be null sometimes
String image = feedObj.isNull("image") ? null : feedObj
.getString("image");
item.setImge(image);
item.setStatus(feedObj.getString("status"));
item.setProfilePic(feedObj.getString("profilePic"));
item.setTimeStamp(feedObj.getString("timeStamp"));
// url might be null sometimes
String feedUrl = feedObj.isNull("url") ? null : feedObj
.getString("url");
item.setUrl(feedUrl);
feedItems.add(item);
}
// notify data changes to list adapater
listAdapter.notifyDataSetChanged();
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
}
AppController.java
package CustomFeed;
import android.app.Application;
import android.text.TextUtils;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.Volley;
import Volly.LruBitmapCache;
/**
* Created by asro9 on 3/9/2016.
*/
public class AppController extends Application {
public static final String TAG = AppController.class.getSimpleName();
private RequestQueue mRequestQueue;
private ImageLoader mImageLoader;
LruBitmapCache mLruBitmapCache;
private static AppController mInstance;
#Override
public void onCreate() {
super.onCreate();
mInstance = this;
}
public static synchronized AppController getInstance() {
return mInstance;
}
public RequestQueue getRequestQueue() {
if (mRequestQueue == null) {
mRequestQueue = Volley.newRequestQueue(getApplicationContext());
}
return mRequestQueue;
}
public ImageLoader getImageLoader() {
getRequestQueue();
if (mImageLoader == null) {
getLruBitmapCache();
mImageLoader = new ImageLoader(this.mRequestQueue, mLruBitmapCache);
}
return this.mImageLoader;
}
public LruBitmapCache getLruBitmapCache() {
if (mLruBitmapCache == null)
mLruBitmapCache = new LruBitmapCache();
return this.mLruBitmapCache;
}
public <T> void addToRequestQueue(Request<T> req, String tag) {
req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
getRequestQueue().add(req);
}
public <T> void addToRequestQueue(Request<T> req) {
req.setTag(TAG);
getRequestQueue().add(req);
}
public void cancelPendingRequests(Object tag) {
if (mRequestQueue != null) {
mRequestQueue.cancelAll(tag);
}
}
}
feeditem.java
package Data;
/**
* Created by asro9 on 3/7/2016.
*/
public class FeedItem {
private int id;
private String name, status, image, profilePic, timeStamp, url;
public FeedItem() {
}
public FeedItem(int id, String name, String image, String status,
String profilePic, String timeStamp, String url) {
super();
this.id = id;
this.name = name;
this.image = image;
this.status = status;
this.profilePic = profilePic;
this.timeStamp = timeStamp;
this.url = url;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getImge() {
return image;
}
public void setImge(String image) {
this.image = image;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getProfilePic() {
return profilePic;
}
public void setProfilePic(String profilePic) {
this.profilePic = profilePic;
}
public String getTimeStamp() {
return timeStamp;
}
public void setTimeStamp(String timeStamp) {
this.timeStamp = timeStamp;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
volley cache
LruBitmapCache :
package Volly;
import android.graphics.Bitmap;
import android.support.v4.util.LruCache;
import com.android.volley.toolbox.ImageLoader.ImageCache;
/**
* Created by asro9 on 3/7/2016.
*/
public class LruBitmapCache extends LruCache<String, Bitmap> implements
ImageCache {
public static int getDefaultLruCacheSize() {
final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
final int cacheSize = maxMemory / 8;
return cacheSize;
}
public LruBitmapCache() {
this(getDefaultLruCacheSize());
}
public LruBitmapCache(int sizeInKiloBytes) {
super(sizeInKiloBytes);
}
#Override
protected int sizeOf(String key, Bitmap value) {
return value.getRowBytes() * value.getHeight() / 1024;
}
#Override
public Bitmap getBitmap(String url) {
return get(url);
}
#Override
public void putBitmap(String url, Bitmap bitmap) {
put(url, bitmap);
}
}
The error is self explanatory, the crash is here:
ImageLoader imageLoader = AppController.getInstance().getImageLoader();
getInstance is returning null.