Method not found at run time - java

I use the org.apache.commons.io.FileUtils.readFileToByteArray method in myAndroid application. I imported the jar file and I see this method is in my project. (I use Eclipse.) Actually, compilation is ok. Here's the message from LogCat:
01-26 18:43:08.177: I/dalvikvm(897): Could not find method org.apache.commons.io.FileUtils.readFileToByteArray, referenced from method com.example.anagrams.MainActivity.readFile
So this is not an error, but then I get a NullPointerException due, apparently, to the statement:
private Button button_read_file = (Button) findViewById(R.id.button_readfile);
I have no idea how to correct the NullPointerException. Also I am puzzled by the message about the method not found. The application is supposed to read a text file containing English words and then for each word to find all the anagrams that exist. For the moment I just use System.out.println to write the anagrams.
Any help is welcome. Following is my whole MainActivity (the only one so far):
public class MainActivity extends Activity {
private String[] words;
private Button button_read_file = (Button) findViewById(R.id.button_readfile);
private EditText input_file_name = (EditText) findViewById(R.id.editText1) ;
private Button button_write_file = (Button) findViewById(R.id.button_writefile);
private EditText output_file_name = (EditText) findViewById(R.id.editText2) ;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button_read_file.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
String inputFileName = input_file_name.getText().toString();
try {
words = readFile(inputFileName, Charset.defaultCharset());
} catch (FileNotFoundException e) {
e.getStackTrace();
} catch (IOException ioe) {
ioe.getStackTrace();
}
}});
button_write_file.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
for (int i = 0; i < words.length; ++i) {
String s = words[i];
System.out.println(" words[" + i + "] = " + s);
HashSet<String> a = new HashSet<String>();
permutations(s,a);
Iterator<String> iterator = a.iterator();
while(iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}});
}
public String[] readFile(String path, Charset encoding) throws IOException {
File file = new File(path);
byte[] encoded = FileUtils.readFileToByteArray(file);
String s = encoding.decode(ByteBuffer.wrap(encoded)).toString();
s = s.replace(" ","");
return s.split("[,.\\n\\s]");
}
public ArrayList<String> getDictionary(String filename) throws IOException, FileNotFoundException {
ArrayList<String> dictionary = new ArrayList<String>();
FileReader fileReader = new FileReader(filename);
BufferedReader bufferedReader = new BufferedReader(fileReader);
String line = null;
while ((line = bufferedReader.readLine()) != null) {
dictionary.add(line);
}
bufferedReader.close();
return dictionary;
}
public boolean isInDictionary(String s) {
String dictionaryname = "enable1.txt";
ArrayList<String> dictionary = new ArrayList<String>();
try {
dictionary = getDictionary(dictionaryname);
} catch (FileNotFoundException e) {
e.getStackTrace();
} catch (IOException e) {
e.getStackTrace();
}
if (dictionary.contains(s))
return true;
else
return false;
}
public void permutations(String word, HashSet<String> anagrams) {
generatePermutations("",word,anagrams);
}
public void generatePermutations(String prefix, String word, HashSet<String> anagrams) {
int n = word.length();
if (n == 0) {
if (prefix != word && isInDictionary(prefix))
anagrams.add(prefix);
}
else {
for (int i = 0; i < n; ++i) {
generatePermutations(prefix + word.charAt(i),word.substring(0,i) + word.substring(i+1),anagrams);
}
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
And here's the layout file:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<Button
android:id="#+id/button_readfile"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_marginTop="17dp"
android:text="#string/read_file" />
<Button
android:id="#+id/button_writefile"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/button_readfile"
android:layout_below="#+id/button_readfile"
android:layout_marginTop="24dp"
android:text="#string/write_file" />
<EditText
android:id="#+id/editText1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/button_readfile"
android:layout_toRightOf="#+id/button_writefile"
android:ems="10" >
<requestFocus />
</EditText>
<EditText
android:id="#+id/editText2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="#+id/button_writefile"
android:layout_alignBottom="#+id/button_writefile"
android:layout_alignLeft="#+id/editText1"
android:ems="10" >
</EditText>

You are initializing these before the layout is even set:
private Button button_read_file = (Button) findViewById(R.id.button_readfile);
private EditText input_file_name = (EditText) findViewById(R.id.editText1) ;
private Button button_write_file = (Button) findViewById(R.id.button_writefile);
private EditText output_file_name = (EditText) findViewById(R.id.editText2) ;
Change them to:
private Button button_read_file;
private EditText input_file_name;
private Button button_write_file;
private EditText output_file_name;
Then declare them after setContentView(...) in your onCreate like:
button_read_file = (Button) findViewById(R.id.button_readfile);
input_file_name = (EditText) findViewById(R.id.editText1) ;
button_write_file = (Button) findViewById(R.id.button_writefile);
output_file_name = (EditText) findViewById(R.id.editText2) ;
If you see NoClassDefFoundError, try this in Eclipse:
Go to Project Properties → Java Build Path → Order and Export tab.
Check the Android Private Libraries option.

Related

How to fix an empty fragment?

I am new to Android development, trying to create my own app. It should display a particular YouTube Channel by using the YouTube Data API. I have started with the standard bottom navigation template in Android Studio and used the following project on Github for some start-up help. https://github.com/stressGC/Remake-YouTube-Android
I had to change a few things like the deprecated http call inside the code to keep it running with the new Android APKs. Everything seems fine from my point of view: I can see that the API content looks good and that each title / description / publishdate is placed in the according variables. There is also no error message in the log. When I start the emulator, the app is running fine. But as soon as I switch to the "Dashboard" fragment (where the code is placed), it is empty.
DashboardFragment.java
public class DashboardFragment extends Fragment {
private static String API_KEY = "hidden"; //normaler API key ohne limits, kein oauth
private static String CHANNEL_ID = "hidden";
private static String CHANNEL_GET_URL = "https://www.googleapis.com/youtube/v3/search?part=snippet&order=date&channelId="+CHANNEL_ID+"&maxResults=20&key="+API_KEY+"";
private RecyclerView mList_videos = null;
private VideoPostAdapter adapter = null;
private ArrayList<YouTubeDataModel> mListData = new ArrayList<>();
public DashboardFragment () {
}
#Override
public View onCreateView(#NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_dashboard, container, false);
mList_videos = (RecyclerView) view.findViewById(R.id.mList_videos);
initList(mListData);
new RequestYouTubeAPI().execute();
return view;
}
private void initList(ArrayList<YouTubeDataModel> mListData) {
mList_videos.setLayoutManager(new LinearLayoutManager(getActivity()));
adapter = new VideoPostAdapter(getActivity(), mListData);
mList_videos.setAdapter(adapter);
}
// create asynctask to get data from youtube
private class RequestYouTubeAPI extends AsyncTask<Void, String, String>{
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(Void... params) {
URL url = null;
String json = null;
StringBuffer sb = new StringBuffer();
try {
url = new URL(CHANNEL_GET_URL);
} catch (MalformedURLException e) {
e.printStackTrace();
}
try {
//HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
HttpURLConnection urlConnection = NetCipher.getHttpsURLConnection(url);
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String inputLine = "";
while ((inputLine = br.readLine()) != null) {
sb.append(inputLine);
}
json = sb.toString();
return json;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
#Override
protected void onPostExecute(String response) {
super.onPostExecute(response);
if(response != null){
try {
JSONObject jsonObject = new JSONObject(response);
Log.e("response", jsonObject.toString());
mListData = parseVideoListFromResponse(jsonObject);
initList(mListData);
//adapter.notifyDataSetChanged();
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}
public ArrayList<YouTubeDataModel> parseVideoListFromResponse(JSONObject jsonObject) {
ArrayList<YouTubeDataModel> mList = new ArrayList<>();
if (jsonObject.has("items")) {
try {
JSONArray jsonArray = jsonObject.getJSONArray("items");
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject json = jsonArray.getJSONObject(i);
if (json.has("id")) {
JSONObject jsonID = json.getJSONObject("id");
String video_id = "";
if (jsonID.has("videoId")) {
video_id = jsonID.getString("videoId");
}
if (jsonID.has("kind")) {
if (jsonID.getString("kind").equals("youtube#video")) {
YouTubeDataModel youtubeObject = new YouTubeDataModel();
JSONObject jsonSnippet = json.getJSONObject("snippet");
String title = jsonSnippet.getString("title");
String description = jsonSnippet.getString("description");
String publishedAt = jsonSnippet.getString("publishedAt");
String thumbnail = jsonSnippet.getJSONObject("thumbnails").getJSONObject("high").getString("url");
youtubeObject.setTitle(title);
youtubeObject.setDescription(description);
youtubeObject.setPublishedAt(publishedAt);
youtubeObject.setThumbnail(thumbnail);
youtubeObject.setVideo_id(video_id);
mList.add(youtubeObject);
}
}
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
return mList;
}
}
VideoPostAdapter.java
public class VideoPostAdapter extends RecyclerView.Adapter<VideoPostAdapter.YouTubePostHolder> {
private ArrayList<YouTubeDataModel> dataSet;
private Context mContext = null;
public VideoPostAdapter(Context mContext, ArrayList<YouTubeDataModel> dataSet) {
this.dataSet = dataSet;
this.mContext = mContext;
}
#NonNull
#Override
public YouTubePostHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.youtube_post_layout,parent,false);
YouTubePostHolder postHolder = new YouTubePostHolder(view);
return postHolder;
}
#Override
public void onBindViewHolder(#NonNull YouTubePostHolder holder, int position) {
// set the views here
TextView textViewTitle = holder.textViewTitle;
TextView textViewDes = holder.textViewDes;
TextView textViewDate = holder.textViewDate;
ImageView ImageThumb = holder.ImageThumb;
YouTubeDataModel object = dataSet.get(position);
textViewTitle.setText(object.getTitle());
textViewDes.setText(object.getDescription());
textViewDate.setText(object.getPublishedAt());
// image will be downloaded from url
}
#Override
public int getItemCount() {
return dataSet.size();
}
public static class YouTubePostHolder extends RecyclerView.ViewHolder{
TextView textViewTitle;
TextView textViewDes;
TextView textViewDate;
ImageView ImageThumb;
public YouTubePostHolder(#NonNull View itemView) {
super(itemView);
this.textViewTitle = (TextView) itemView.findViewById(R.id.textViewTitle);
this.textViewDes = (TextView) itemView.findViewById(R.id.textViewDes);
this.textViewDate = (TextView) itemView.findViewById(R.id.textViewDate);
this.ImageThumb = (ImageView) itemView.findViewById(R.id.ImageThumb);
}
}
}
YouTubeDataModel.java
public class YouTubeDataModel {
private String title = "";
private String description = "";
private String publishedAt = "";
private String thumbnail = "";
public String getVideo_id() {
return video_id;
}
public void setVideo_id(String video_id) {
this.video_id = video_id;
}
private String video_id = "";
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getPublishedAt() {
return publishedAt;
}
public void setPublishedAt(String publishedAt) {
this.publishedAt = publishedAt;
}
public String getThumbnail() {
return thumbnail;
}
public void setThumbnail(String thumbnail) {
this.thumbnail = thumbnail;
}
}
youtube_post_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="wrap_content">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="200dp">
<ImageView
android:id="#+id/ImageThumb"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/colorPrimary"/>
<TextView
android:id="#+id/textViewDate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="published at"
android:singleLine="true"
android:layout_alignParentRight="true"
android:layout_margin="5dp"
android:textColor="#android:color/white"
android:textSize="12dp"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_margin="10dp"
android:orientation="vertical">
<TextView
android:id="#+id/textViewTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="video Title"
android:singleLine="true"
android:textColor="#android:color/white"
android:textSize="22dp"/>
<TextView
android:id="#+id/textViewDes"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="video description"
android:singleLine="true"
android:textColor="#android:color/white"
android:textSize="12dp"/>
</LinearLayout>
</RelativeLayout>
</LinearLayout>
fragment_dashboard.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/mList_videos"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Unfortunately I have no idea why the fragment is still empty. And without any error in Android Studio log I really hope you can help me :/
Inside your RequestYouTubeAPI ASyncTask you have this error code:
} catch (IOException e) {
e.printStackTrace();
return null;
}
Then in onPostExecute you have the following:
#Override
protected void onPostExecute(String response) {
super.onPostExecute(response);
if(response != null){
try {
JSONObject jsonObject = new JSONObject(response);
Log.e("response", jsonObject.toString());
mListData = parseVideoListFromResponse(jsonObject);
initList(mListData);
//adapter.notifyDataSetChanged();
} catch (JSONException e) {
e.printStackTrace();
}
}
}
Therefore if you get an error, you return null and if onPostExecute is given a null response it does nothing.
So this one place you could have an error and therefore a blank fragment.
Before you fix this, you can prove this is happening like so:
#Override
protected void onPostExecute(String response) {
super.onPostExecute(response);
if(response == null){
Log.e("TUT", "We did not get a response, not updating the UI.");
} else {
try {
JSONObject jsonObject = new JSONObject(response);
Log.e("response", jsonObject.toString());
mListData = parseVideoListFromResponse(jsonObject);
initList(mListData);
//adapter.notifyDataSetChanged();
} catch (JSONException e) {
e.printStackTrace();
}
}
}
You can fix this two ways:
in doInBackground change the catch to this:
} catch (IOException e) {
Log.e("TUT", "error", e);
// Change this JSON to match what the parse expects, so you can show an error on the UI
return "{\"yourJson\":\"error!\"}";
}
or onPostExecute:
if(response == null){
List errorList = new ArrayList();
// Change this data model to show an error case to the UI
errorList.add(new YouTubeDataModel("Error");
mListData = errorList;
initList(mListData);
} else {
try {
JSONObject jsonObject = new JSONObject(response);
Log.e("response", jsonObject.toString());
mListData = parseVideoListFromResponse(jsonObject);
initList(mListData);
//adapter.notifyDataSetChanged();
} catch (JSONException e) {
e.printStackTrace();
}
}
Hope that helps, there may be other errors in the code but this is one case that can happen if there is a problem with the API, the Json, the authorization, the internet etc.

Issue with multiple Volley requests

Whenever I want to perform Volley request based on user input I must press button twice to instead of click the button only one time to get the requested response.
I Used wait() function, but still have the same problem and application corrupted, while I expected the application work normally.
This is what I have reached to until now:
String URL="https://apifootball.com/api/?action=get_countries&APIkey=b4c74bf2fcf3937f783b752649018a42a3b1bde9d5d7c03ff36f61fc06c00c77";
RequestQueue rq= Volley.newRequestQueue(this);
JsonArrayRequest objreq= new JsonArrayRequest(
Request.Method.GET,
URL,
null,
new Response.Listener<JSONArray>()
{
#Override
public void onResponse(JSONArray response) {
try {
Log.e("result:",response.get(0).toString());
JSONObject obj;
for (int count = 0; count < response.length(); count++) {
obj = response.getJSONObject(count);
String name = obj.getString("country_name");
Log.e("Country:",name);
send(name,true);
// Team t=new Team(2,"mki");
//x.insertTeam(t);
//so on
}
} catch (JSONException e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener(){
#Override
public void onErrorResponse(VolleyError error) {
Log.e("rest response",error.toString());
}
}
);
rq.add(objreq);
btn_send_message.setOnClickListener(new View.OnClickListener() {
ChatModel model;
public void onClick(View v) {
String text = editText.getText().toString();
else if(text.contains("result"))
{
ChatModel model = new ChatModel(text, true); // user send message
list_chat.add(model);
String result="";
String head2Head;
String input[] = text.split(" ");
String[] arr=null ;
DBAdapter dbAdapter=new DBAdapter(x);
try{
result=dbAdapter.getResultfromDB("Bristol City","Reading");
}catch (Exception e)
{
result="error";
}
if(result.equals("error")==true) {
APIAdapter ap = new APIAdapter();
head2Head = ap.getResult("Bristol City", "Reading", "kjkn", getApplicationContext());
finres = head2Head;
Log.e("headto",head2Head);
arr = head2Head.split("\n");
}
model = new ChatModel("First team:"+arr[0]+"\nSecond team:"+arr[1]+"\n"+"Date:"+arr[2], false);
list_chat.add(model);
}
}
Now I do understand your question. The thing that is happening is the data is taking its time to be loaded. So use something like a progress bar and change its visibility inside Response.Listener and Response.ErrorListener. To make this work properly move the line rq.add(objreq); inside onClickListener and before this line change the visibility of the progress bar to visible.
Example
Layout.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/mainParentRel"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="#drawable/grad_bg_2"
android:isScrollContainer="true"
android:scrollbars="vertical">
<ScrollView
android:id="#+id/scrollView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:fillViewport="true"
android:scrollbars="vertical">
<!-- You can use any thing here
Put all your previous buttons edittext etc here.
You can replace the scrollview with any layout
Or You can completely remove the scrollview and
directly put your views here. -->
</ScrollView>
<!-- This is the progress bar layout. Always remember to set its visibility to GONE.-->
<RelativeLayout
android:id="#+id/progressRelLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:visibility="gone">
<ImageView
android:id="#+id/company_logo_progress"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_centerHorizontal="true"
android:adjustViewBounds="true"
android:contentDescription="#string/company_logo"
android:scaleType="fitCenter"
android:src="#drawable/company_logo" />
<ProgressBar
android:id="#+id/progressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/company_logo_progress"
android:layout_marginTop="5dp"
android:layout_centerHorizontal="true"
android:theme="#style/WhiteAccent"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/progressBar"
android:text="Loading..."
android:textColor="#color/white"
android:textSize="17dp"
android:layout_centerHorizontal="true"/>
</RelativeLayout>
</RelativeLayout>
Example.java
RelativeLayout progressRL;
//Inside onCreate()
progressRL= findViewById(R.id.progressRelLayout);
//Do rest of your stuff
String URL="https://apifootball.com/api/?action=get_countries&APIkey=b4c74bf2fcf3937f783b752649018a42a3b1bde9d5d7c03ff36f61fc06c00c77";
RequestQueue rq= Volley.newRequestQueue(this);
JsonArrayRequest objreq= new JsonArrayRequest(
Request.Method.GET,
URL,
null,
new Response.Listener<JSONArray>()
{
#Override
public void onResponse(JSONArray response) {
progressRL.setVisibility(View.GONE);
try {
Log.e("result:",response.get(0).toString());
JSONObject obj;
for (int count = 0; count < response.length(); count++) {
obj = response.getJSONObject(count);
String name = obj.getString("country_name");
Log.e("Country:",name);
send(name,true);
// Team t=new Team(2,"mki");
//x.insertTeam(t);
//so on
}
} catch (JSONException e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener(){
#Override
public void onErrorResponse(VolleyError error) {
progressRL.setVisibility(View.GONE);
Log.e("rest response",error.toString());
}
}
);
btn_send_message.setOnClickListener(new View.OnClickListener() {
ChatModel model;
public void onClick(View v) {
rq.add(objreq);
progressRL.setVisibility(View.VISIBLE);
String text = editText.getText().toString();
else if(text.contains("result"))
{
ChatModel model = new ChatModel(text, true); // user send message
list_chat.add(model);
String result="";
String head2Head;
String input[] = text.split(" ");
String[] arr=null ;
DBAdapter dbAdapter=new DBAdapter(x);
try{
result=dbAdapter.getResultfromDB("Bristol City","Reading");
}catch (Exception e)
{
result="error";
}
if(result.equals("error")==true) {
APIAdapter ap = new APIAdapter();
head2Head = ap.getResult("Bristol City", "Reading", "kjkn", getApplicationContext());
finres = head2Head;
Log.e("headto",head2Head);
arr = head2Head.split("\n");
}
model = new ChatModel("First team:"+arr[0]+"\nSecond team:"+arr[1]+"\n"+"Date:"+arr[2], false);
list_chat.add(model);
}
}
After doing this it might cause errors. Just move the things that will change after loading of data inside Response.Listener.

How to populate a RecyclerView with data from a Service on Button click

I have this setup in my fragment. The user makes selections from the spinners and when they click the go button a service is initiated that is meant to get data and populate a recycler view with the data.The recycler view is located right below the spinners.The code is below.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp">
<Spinner
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/weekSpinner"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_margin="5dp">
</Spinner>
<Spinner
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/sessionSpinner"
android:layout_toRightOf="#+id/weekSpinner"
android:layout_toEndOf="#+id/weekSpinner"
android:layout_margin="5dp">
</Spinner>
<Spinner
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/termSpinner"
android:layout_toRightOf="#+id/sessionSpinner"
android:layout_toEndOf="#+id/sessionSpinner"
android:layout_margin="5dp">
</Spinner>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Go"
android:id="#+id/resultsSearch"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_margin="10dp"
android:layout_below="#+id/sessionSpinner"
android:textColor="#android:color/white"
android:background="#color/toolBar"/>
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/caRecycler">
</android.support.v7.widget.RecyclerView>
</LinearLayout>
</LinearLayout>
I am getting this error.
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object android.content.Context.getSystemService(java.lang.String)' on a null object reference
I understand that it has to do with the context being used but i have no idea how to solve it as this is the first time i'm using this sort of setup. Below is my fragment code.
public class caFragment extends Fragment
{
ArrayList<String> weeks,terms,sessions;
String selectedWeek,selectedTerm,selectedSession;
String activeChild;
Button go;
private static final String selectedChildTracker = "selectedChild";
SharedPreferences sharedpreferences;
static RecyclerView caDisplay = null;
static caCardAdapter cardAdapter = null;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState)
{
View view = inflater.inflate(R.layout.results_ca,null);
sharedpreferences = this.getActivity().getSharedPreferences(selectedChildTracker, Context.MODE_PRIVATE);
activeChild = sharedpreferences.getString("selectedChild",null);
final Spinner week,term,session;
setup();
week = (Spinner) view.findViewById(R.id.weekSpinner);
ArrayAdapter<String> weekAdapter = new ArrayAdapter<>(getContext(),android.R.layout.simple_spinner_item,weeks);
weekAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
week.setAdapter(weekAdapter);
term = (Spinner) view.findViewById(R.id.termSpinner);
ArrayAdapter<String> termAdapter = new ArrayAdapter<>(getContext(),android.R.layout.simple_spinner_item,terms);
termAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
term.setAdapter(termAdapter);
session = (Spinner) view.findViewById(R.id.sessionSpinner);
ArrayAdapter<String> sessionAdapter = new ArrayAdapter<>(getContext(),android.R.layout.simple_spinner_item,sessions);
sessionAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
session.setAdapter(sessionAdapter);
caDisplay = (RecyclerView) view.findViewById(R.id.caRecycler);
go = (Button) view.findViewById(R.id.resultsSearch);
go.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View view)
{
selectedWeek = week.getSelectedItem().toString();
selectedTerm = term.getSelectedItem().toString();
selectedSession = session.getSelectedItem().toString();
Bundle extra = new Bundle();
extra.putString("selectedWeek",selectedWeek);
extra.putString("selectedTerm",selectedTerm);
extra.putString("selectedSession",selectedSession);
extra.putString("selectedChild",activeChild);
try
{
getActivity().startService(new Intent(getContext(), results.class).putExtras(extra));
}
catch (Exception ex)
{
System.out.print(ex);
}
}
});
return view;
}
public void setup()
{
weeks = new ArrayList<>();
terms = new ArrayList<>();
sessions = new ArrayList<>();
try
{
weeks.add("4");
weeks.add("8");
}
catch (Exception ex)
{
Log.e("Error adding weeks",ex.toString());
}
try
{
terms.add("First Term");
terms.add("Second Term");
terms.add("Third Term");
}
catch (Exception ex)
{
Log.e("Error adding terms",ex.toString());
}
try
{
sessions.add("2015/2016");
}
catch (Exception ex)
{
Log.e("Error adding sessions",ex.toString());
}
}
public void showResults()
{
cardAdapter = new caCardAdapter(getActivity(),cardResults.getResultSet());
caDisplay.setAdapter(cardAdapter);
caDisplay.setLayoutManager(new LinearLayoutManager(getActivity()));
}
}
and below is my service code
public class results extends Service
{
int mStartMode;
String tag_results_req = "tag_results_req";
static ArrayList<cardResults> cardResult;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
Bundle params = intent.getExtras();
Log.d("bundle param",params.toString());
String week = params.getString("selectedWeek");
String term = params.getString("selectedTerm");
String session = params.getString("selectedSession");
String child = params.getString("selectedChild");
makeRequest(week,term,session,child);
return mStartMode;
}
#Override
public void onDestroy()
{
super.onDestroy();
}
public void makeRequest(String week,String term,String session,String child)
{
String dataSet = week.trim()+","+term+","+session.trim()+","+child.trim();
byte[] data = new byte[0];
try
{
data = dataSet.getBytes("UTF-8");
}
catch (UnsupportedEncodingException e)
{
e.printStackTrace();
}
String query = Base64.encodeToString(data, Base64.DEFAULT);
Log.d("Query param",query);
//the url we are posting the request to
String url = " http://mobile.map.education/api/result/ca/"+query;
// prepare the Request
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, url, null,
new Response.Listener<JSONObject>()
{
#Override
public void onResponse(JSONObject response)
{
// display response
Log.d("results",response.toString());
cardResults(response);
}
},
new Response.ErrorListener()
{
#Override
public void onErrorResponse(VolleyError error)
{
Log.e("Error.Response", error.toString());
Toast.makeText(getApplicationContext(),"Sorry there was an error getting results data",Toast.LENGTH_LONG).show();
}
}
);
queuer.getInstance().addToRequestQueue(request, tag_results_req);
}
public void cardResults(JSONObject result)
{
cardResult = new ArrayList<>();
JSONArray res = null;
try
{
res = (JSONArray) result.get("result_details");
Log.d("results",res.toString());
}
catch (Exception ex)
{
Log.e("error getting results",ex.toString());
}
for (int i = 0; i < res.length(); i++)
{
try
{
JSONObject subject = res.getJSONObject(i);
cardResults cardModel = new cardResults();
cardModel.setAverage("50");
cardModel.setScore(subject.getString("total"));
cardModel.setSubject(subject.getString("subject"));
cardModel.setAssignment(subject.getString("ASSIGNMENT"));
cardModel.setTest(subject.getString("CLASS TEST"));
cardModel.setWork(subject.getString("CLASS WORK"));
cardModel.setTeacher(subject.getString("teacher"));
cardResult.add(cardModel);
}
catch (Exception ex)
{
Log.e("card list",ex.toString());
}
}
try {
cardResults.setResultSet(cardResult);
caFragment m = new caFragment();
m.showResults();
}
catch (Exception ex)
{
Log.e("show result",ex.toString());
}
}
}
Looks like problem with your adapter which you are setting outside the onCreate of Fragment
cardAdapter = new caCardAdapter(getActivity());
caDisplay.setAdapter(cardAdapter);
caDisplay.setLayoutManager(new LinearLayoutManager(getActivity()));
move above lines inside the onCreate and just create one data Setter method in your Adapter class and then call this method to set data.
public void showResults()
{
//create setter method inside your adapter and notify
cardAdapter.setData(cardResults.getResultSet());
cardAdapter.notifyDataSetChanged();
}
before set Data just check that your data is not null!

Android Calling API and parsing JSON

Trying to make an API call to the url below and parse the returning JSON, when the "refresh" button is called.
I can link to a button and get text (Hello world) to the screen, but can't seem to link the button click to the API request. Error message says I cannot reference non-static method "execute" from a static context
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void retrieveInformation(View view){
RetrieveFeedTask.execute();
TextView textview = (TextView) findViewById(R.id.responseView);
textview.setText("Hello world");
}
class RetrieveFeedTask extends AsyncTask<Void, Void, String> {
String jsonString = "";
private Exception exception;
protected void onPreExecute() {
}
protected String doInBackground(Void... urls) {
// Do some validation here
try {
URL url = new URL("www.liftin.co.uk/api/v1/journeys");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
try {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
StringBuilder stringBuilder = new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null) {
stringBuilder.append(line).append("\n");
}
bufferedReader.close();
return stringBuilder.toString();
} finally {
urlConnection.disconnect();
}
} catch (Exception e) {
Log.e("ERROR", e.getMessage(), e);
return null;
}
}
protected void onPostExecute(String response) {
if (response == null) {
response = "THERE WAS AN ERROR";
}
Log.i("INFO", response);
jsonString = response;
try {
getInformationFromJson(jsonString);
} catch (JSONException e) {
e.printStackTrace();
}
}
private String getInformationFromJson(String jsonString)
throws JSONException {
final String DRIVER = "driver";
final String START = "start";
final String DESTINATION = "destination";
final String TIME = "pick_up_time";
final String PASSENGERS = "passengers";
final String SEATS = "seats_available";
JSONObject journeyJson = new JSONObject(jsonString);
String time = journeyJson.getString(TIME);
String seats = journeyJson.getString(SEATS);
String results = seats + "-----" + time;
return results;
}
}
}
Main_activity.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
tools:context="com.example.android.liftin.MainActivity">
<Button
android:id="#+id/queryButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="end"
style="#style/Base.Widget.AppCompat.Button.Borderless"
android:text="Refresh"
android:onClick="retrieveInformation"/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/responseView"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</ScrollView>
</RelativeLayout>
</LinearLayout>
You should create asynchronous call for your AsyncTask like this :
public void retrieveInformation(View view){
new RetrieveFeedTask().execute(); //asynchronous call
TextView textview = (TextView) findViewById(R.id.responseView);
textview.setText("Hello world");
}
UPDATE
If you want to set data to textview after parsing data. You have to make little bit changes in your activity as follows.
You should initialize your textview in onCreate() and make it global variable for your activity, so that you can access it in full activity.
then in your onPostExecute() do this :
textview.setText(getInformationFromJson(response));
Hope it will Help :)
You must create a object of AsyncTask (RetrieveFeedTask) before calling it. For example
public void retrieveInformation(View view){
TextView textview = (TextView) findViewById(R.id.responseView);
textview.setText("Hello world");
new RetrieveFeedTask().execute();
}
You still need to pass something for Void.
public void retrieveInformation(View view){
new RetrieveFeedTask().execute(null);
TextView textview = (TextView) findViewById(R.id.responseView);
textview.setText("Hello world");
}

Why I cannot get a value from android?

In my main.xml I set two EditText to get num1 and num 2, on Buntto to run the add operation
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<EditText
android:id="#+id/num1"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
android:hint="num1"
android:inputType="number" />
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:padding="5dp"
android:text="+" />
<EditText
android:id="#+id/num2"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
android:hint="num2"
android:inputType="number" />
<TextView
android:id="#+id/result"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:padding="5dp"
android:text="=" />
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:padding="5dp" />
</LinearLayout>
<Button
android:id="#+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="add"
android:textSize="10sp" />
MainActivity.java
public class MainActivity extends Activity {
public static final int UPDATE_TEXT = 1;
private EditText etx1;
private EditText etx2;
private TextView result;
Button getresult;
private double num1;
private double num2;
private double resultnum;
private Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case UPDATE_TEXT:
new Thread(new Runnable() {
public void run() {
// TODO Auto-generated method stub
String url = "http://localhost:8080/test/index.jsp?num1="
+ num1 + "&" + "num2=" + num2;
HttpClient httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
try {
httpClient.execute(httpGet);
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
result.setText(new Double(resultnum).toString());
break;
default:
break;
}
};
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
etx1 = (EditText) findViewById(R.id.num1);
etx2 = (EditText) findViewById(R.id.num2);
result = (TextView) findViewById(R.id.result);
getresult = (Button) findViewById(R.id.btn);
getresult.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
num1 = Double.parseDouble(etx1.getText().toString());
num2 = Double.parseDouble(etx2.getText().toString());
resultnum = num1 + num2;
// TODO Auto-generated method stub
new Thread(new Runnable() {
public void run() {
// TODO Auto-generated method stub
Message message = new Message();
message.what = UPDATE_TEXT;
handler.sendMessage(message);
}
}).start();
}
});
}
}
And my index.jsp:
<body>
<h1>Using GET Method to Read Form Data</h1>
<ul>
<li><p>
<b>Num1:</b>
<%=request.getParameter("num1")%>
</p></li>
<li><p>
<b>Num2:</b>
<%=request.getParameter("num2")%>
</p></li>
<li><p>
<b>result:</b>
<%=request.getParameter("num2")+request.getParameter("num1")%>
</p></li>
</ul>
When I navigate to http://localhost:8080/test/ in Chrome I see num1 = null, num2 = null, result = nullnull. Why are the values not properly filled in?
Your server is running on a localhost and so your device cannot connect to the server. Set your server to run on 0.0.0.0 and then in your code, change the url to the IP Address of your computer instead of localhost. To find your IP Address, go to your command prompt and type ipconfig. Then look for your ipv4 address.
Your code doesn't enter the onCLick method and that's why your values are always null. Convert your code to this one:
public class MainActivity extends Activity {
public static final int UPDATE_TEXT = 1;
private EditText etx1;
private EditText etx2;
private TextView result;
Button getresult;
private double num1;
private double num2;
private double resultnum;
private Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case UPDATE_TEXT:
new Thread(new Runnable() {
public void run() {
String url = "http://localhost:8080/test/index.jsp?num1="
+ num1 + "&" + "num2=" + num2;
HttpClient httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
try {
httpClient.execute(httpGet);
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
});
result.setText(new Double(resultnum).toString());
break;
default:
break;
}
};
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
etx1 = (EditText) findViewById(R.id.num1);
etx2 = (EditText) findViewById(R.id.num2);
result = (TextView) findViewById(R.id.result);
getresult = (Button) findViewById(R.id.btn);
View.OnClickListener buttonHandler= new View.OnClickListener() {
public void onClick(View v) {
num1 = Double.parseDouble(etx1.getText().toString());
num2 = Double.parseDouble(etx2.getText().toString());
resultnum = num1 + num2;
new Thread(new Runnable() {
public void run() {
Message message = new Message();
message.what = UPDATE_TEXT;
handler.sendMessage(message);
}
}).start();
}
};
getresult.setOnClickListener(buttonHandler);
}
}
I think this will solve your problem.

Categories