I followed a tutorial on youtube, to make a list app with database.
Now I get the error:
An exception was thrown for JDBC.
This is my code:
package com.example.jopri.databaseconnectie;
import android.content.AsyncQueryHandler;
import android.content.Context;
import android.content.res.Resources;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
public class MainActivity extends AppCompatActivity {
ItemAdapter itemAdapter;
Context thisContext;
ListView myListView;
TextView progressTextView;
Map<String, Double> fruitsMap = new LinkedHashMap<String, Double>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Resources res = getResources();
myListView = (ListView) findViewById(R.id.myListView);
progressTextView = (TextView) findViewById(R.id.progressTextView);
thisContext = this;
progressTextView.setText("");
Button btn = (Button) findViewById(R.id.getDataButton);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v){
GetData retrieveData = new GetData();
retrieveData.execute("");
}
});
}
private class GetData extends AsyncTask<String, String, String> {
String msg = "";
static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
static final String DB_URL = "jdbc:mysql://" +
DbStrings.DATABASE_URL + "/" +
DbStrings.DATABASE_NAME;
protected void onPreExecute() {
progressTextView.setText("Connecting to database...");
}
#Override
protected String doInBackground(String... params) {
Connection conn = null;
Statement stmt = null;
try {
Class.forName(JDBC_DRIVER);
conn = DriverManager.getConnection(DB_URL, DbStrings.USERNAME, DbStrings.PASSWORD);
stmt = conn.createStatement();
String sql = "SELECT * FROM fruit";
ResultSet rs = stmt.executeQuery(sql);
while (rs.next()) {
String soort = rs.getString("soort");
double prijs = rs.getDouble("prijs");
fruitsMap.put(soort, prijs);
}
msg = "Process complete";
rs.close();
stmt.close();
conn.close();
} catch (SQLException connError) {
msg = "An exception was thrown for JDBC";
connError.printStackTrace();
} catch (ClassNotFoundException e) {
msg = "A class not found exception was thrown.";
e.printStackTrace();
} finally {
try {
if (stmt != null) {
stmt.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (conn != null) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
return null;
}
#Override
protected void onPostExecute(String msg) {
progressTextView.setText(this.msg);
if(fruitsMap.size() > 0) {
itemAdapter = new ItemAdapter(thisContext, fruitsMap);
myListView.setAdapter(itemAdapter);
}
}
}
} // END
Connector:
package com.example.jopri.databaseconnectie;
import java.net.URL;
public class DbStrings {
static final String DATABASE_URL = "127.0.0.1:3306";
static final String DATABASE_NAME = "proef";
static final String USERNAME = "root";
static final String PASSWORD = "password";
}
Item adapter:
package com.example.jopri.databaseconnectie;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class ItemAdapter extends BaseAdapter {
LayoutInflater mInflator;
Map<String, Double> map;
List<String> soort;
List<Double> prijs;
public ItemAdapter(Context c, Map m) {
mInflator = (LayoutInflater) c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
map = m;
soort = new ArrayList<String>(map.keySet());
prijs = new ArrayList<Double>(map.values());
};
#Override
public int getCount() {
return map.size();
}
#Override
public Object getItem(int position) {
return soort.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = mInflator.inflate(R.layout.item_layout, null);
TextView nameTextView = (TextView) v.findViewById(R.id.nameTextView);
TextView priceTextView = (TextView) v.findViewById(R.id.priceTextView);
nameTextView.setText(soort.get(position));
priceTextView.setText("€" + prijs.get(position).toString());
return v;
}
}
static final String DATABASE_URL = "127.0.0.1:3306";
This line implies that you're running a MySQL server on the Android device itself, which seems highly unlikely to me. If you watch over the video again, he never used localhost/127.0.0.1.
This URL should rather be a remote IP/hostname that's resolvable within your network(s) (ideally, should work over WiFi and mobile)
Also, by doing this, you're exposing your database password to anyone that can access your app/code, because it's just a plain string in memory. Therefore, in a real world environment, you'd actually use HTTP based APIs, which can more securely hide away and store database credentials in a single location, rather than have that information copied across a bunch of mobile devices (if you publish your app for others to use).
If all you want is a database with a listview, start with SQLite, which is embedded and available as a library as part of the Android SDK
Related
I've been learning Java for a few months. Nowadays I'm creating an app which downloads web content and shows the data in a ListView. The problem is that everything takes a very long time - about 25 second from the launch of the app to fill the list with elements. What is more, there is no difference between it running on a real device or an Android emulator.
In my opinion, the Java code is not bad because most of it is from my course on Udemy.
How can I improve this? Where is the problem?
Reports from logcat and AVD setting [ss]:
Here's my code below:
MainActivity.java
package com.example.user.legionisciapp;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ListView;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MainActivity extends AppCompatActivity {
ListView listView;
List<News> newsList = new ArrayList<>();
ArrayList<String> titles = new ArrayList<>();
ArrayList<String> desc = new ArrayList<>();
ArrayList<String> urls = new ArrayList<>();
public class DownloadTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... strings) {
URL url;
HttpURLConnection connection = null;
String result = "";
try {
url = new URL(strings[0]);
connection = (HttpURLConnection) url.openConnection();
InputStream inputStream = connection.getInputStream();
InputStreamReader reader = new InputStreamReader(inputStream);
int data = reader.read();
while (data != -1) {
char current = (char) data;
result += current;
data = reader.read();
}
return result;
} catch (Exception e) {
e.printStackTrace();
return "Failed";
}
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DownloadTask downloadTask = new DownloadTask();
try {
String result = downloadTask.execute("https://www.legionisci.com").get();
String[] resultSplit = result.split("<div id=\"mecze\">");
result = resultSplit[0];
resultSplit = result.split("<div id=\"listanewsow\">");
result = resultSplit[1];
Pattern p = Pattern.compile("class=\"b\" title=\"(.*?)\">");
Matcher m = p.matcher(result);
while (m.find()) {
titles.add(m.group(1));
}
p = Pattern.compile("></a>(.*?)</div>");
m = p.matcher(result);
while (m.find()) {
desc.add(m.group(1));
}
p = Pattern.compile("alt=\"\" class=\"zl\" /></a>(.*?)<");
m = p.matcher(result);
while (m.find()) {
urls.add("https://www.legionisci.com" + m.group(1));
}
} catch (Exception e) {
e.printStackTrace();
}
listView = findViewById(R.id.listView);
for (int i = 0; i < 4; i++) {
newsList.add(new News(R.drawable.ll, titles.get(i), desc.get(i)));
NewsListAdapter newsListAdapter = new NewsListAdapter(this, R.layout.news_list, newsList);
listView.setAdapter(newsListAdapter);
}
}
}
News.java
package com.example.user.legionisciapp;
public class News {
int image;
String title, desc;
public News(int image, String title, String desc) {
this.image = image;
this.title = title;
this.desc = desc;
}
public int getImage() {
return image;
}
public String getTitle() {
return title;
}
public String getDesc() {
return desc;
}
}
NewsListAdapter.class
package com.example.user.legionisciapp;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.List;
public class NewsListAdapter extends ArrayAdapter<News> {
Context ctx;
int resource;
List<News> newsList;
public NewsListAdapter (Context ctx, int resource, List<News> newsList){
super(ctx, resource, newsList);
this.ctx = ctx;
this.resource = resource;
this.newsList = newsList;
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
LayoutInflater inflater = LayoutInflater.from(ctx);
View view = inflater.inflate(R.layout.news_list, null);
TextView title = view.findViewById(R.id.tvTitle);
TextView desc = view.findViewById(R.id.tvDesc);
ImageView image = view.findViewById(R.id.thumb);
News news = newsList.get(position);
title.setText(news.getTitle());
desc.setText(news.getDesc());
image.setImageDrawable(ctx.getResources().getDrawable(news.getImage()));
return view;
}
}
You can't do something like this:
String result = downloadTask.execute("https://www.legionisci.com").get();
That is not the right way to use an AsyncTask! The problem is that the async task is executed in a background thread but if you do .get() the main thread is paused until the async task finishes his job. So this is the reason of the long wait at startup.
What you have to do is:
Starting the task this way
downloadTask.execute("https://www.legionisci.com");
Using the onPostExecute(String result) method (executed on the main thread) to get the result and update the UI .
More on this:
https://developer.android.com/reference/android/os/AsyncTask
When I navigate to the activity that should load a ListView from a JSON hosted on AWS S3, I get nothing but a blank activity. There's no error message, no errors in the debugger, and Logcat doesn't seem to hold any relevant information.
Here's LoadJSONTask.java:
package com.teamplum.projectapple;
import android.os.AsyncTask;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import com.teamplum.projectapple.NewsDO;
import com.teamplum.projectapple.Response;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
public class LoadJSONTask extends AsyncTask<String, Void, Response> {
public LoadJSONTask(Listener listener) {
mListener = listener;
}
public interface Listener {
void onLoaded(List<NewsDO> androidList);
void onError();
}
private Listener mListener;
#Override
protected Response doInBackground(String... strings) {
try {
String stringResponse = loadJSON(strings[0]);
Gson gson = new Gson();
return gson.fromJson(stringResponse, Response.class);
} catch (IOException e) {
e.printStackTrace();
return null;
} catch (JsonSyntaxException e) {
e.printStackTrace();
return null;
}
}
#Override
protected void onPostExecute(Response response) {
if (response != null) {
mListener.onLoaded(response.getAndroid());
} else {
mListener.onError();
}
}
private String loadJSON(String jsonURL) throws IOException {
URL url = new URL(jsonURL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(10000);
conn.setConnectTimeout(15000);
conn.setRequestMethod("GET");
conn.setDoInput(true);
conn.connect();
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line;
StringBuilder response = new StringBuilder();
while ((line = in.readLine()) != null) {
response.append(line);
}
in.close();
return response.toString();
}
}
and here's MainActivity.java:
package com.teamplum.projectapple;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.Toast;
//import com.teamplum.projectapple.NewsDO;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class MainActivity extends AppCompatActivity implements LoadJSONTask.Listener, AdapterView.OnItemClickListener {
private ListView mListView;
public static final String URL = "https://s3-eu-west-1.amazonaws.com/tyi-work/Work_Experience.json";
private List<HashMap<String, String>> mAndroidMapList = new ArrayList<>();
private static final String KEY_TIT = "title";
private static final String KEY_CAT = "category";
private static final String KEY_DES = "description";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mListView = findViewById(R.id.list_view);
mListView.setOnItemClickListener(this);
new LoadJSONTask(this).execute(URL);
}
#Override
public void onLoaded(List<NewsDO> androidList) {
for (NewsDO work : androidList) {
HashMap<String, String> map = new HashMap<>();
map.put(KEY_TIT, work.getTitle());
map.put(KEY_CAT, work.getCategory());
map.put(KEY_DES, work.getDescription());
mAndroidMapList.add(map);
}
loadListView();
}
#Override
public void onError() {
Toast.makeText(this, "Error !", Toast.LENGTH_SHORT).show();
}
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Toast.makeText(this, mAndroidMapList.get(i).get(KEY_TIT),Toast.LENGTH_LONG).show();
}
private void loadListView() {
ListAdapter adapter = new SimpleAdapter(MainActivity.this, mAndroidMapList, R.layout.list_item,
new String[] { KEY_CAT, KEY_TIT, KEY_DES },
new int[] { R.id.version,R.id.name, R.id.api });
mListView.setAdapter(adapter);
}
}
I used this tutorial to help make this, if you need any extra information please feel free to ask, thank you.
I have tested the async task for the URL connection and its working fine.
The problem is either on the parsing or on the activity side. Have you tried putting breakpoints and follow the data?
I am trying to use the ProductHunt API to display a list of new posts in a ListView and further expand the list item on click.
On opening the app, the Progress bar appears but after that the app screen stays blank. I think there might be some error in my OnPostExecute method, because when I added a textview to display a string, its getting displayed but my listView is not getting displayed.
I used the standard Apache HttpClient for handling api requests.
I have 4 classes,
MainActivity.java
package com.emoji.apisoup;
/**
* Created by mdhalim on 16/05/16.
*/
import java.io.IOException;
import java.util.ArrayList;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import org.apache.http.HttpClientConnection;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicHttpResponse;
import org.apache.http.protocol.HTTP;
public class MainActivity extends Activity {
private ListView lvPosts;
private ProductHuntAdapter adapterPosts;
public static final String POST_DETAIL_KEY = "posts";
private ProgressDialog pDialog;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.phunt_main);
String serverURL = "https://api.producthunt.com/v1/posts/";
ArrayList<ProductHuntList> aPosts = new ArrayList<ProductHuntList>();
adapterPosts = new ProductHuntAdapter(MainActivity.this, aPosts);
lvPosts = (ListView) findViewById(R.id.lvPosts);
lvPosts.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
{
Intent i = new Intent(MainActivity.this, ProductHuntDetail.class);
i.putExtra(POST_DETAIL_KEY, adapterPosts.getItem(position));
startActivity(i);
}
}
});
new LongOperation().execute(serverURL);
}
private class LongOperation extends AsyncTask<String, Void, Void> {
private final HttpClient Content = new DefaultHttpClient();
private String Error = null;
#Override
protected void onPreExecute() {
super.onPreExecute();
// Showing progress dialog
pDialog = new ProgressDialog(MainActivity.this);
pDialog.setMessage("Please wait...");
pDialog.setCancelable(false);
pDialog.show();
}
protected Void doInBackground(String... urls){
JSONArray items = null;
try {
HttpGet httpget = new HttpGet(urls[0]);
httpget.setHeader("Accept","application/json");
httpget.setHeader("Content-Type","application/json");
httpget.setHeader("Authorization","Bearer 2587aa878d7334e3c89794a6b73ebffb59a06c23b82cd0f789d2ab72d2417739");
ResponseHandler<String> responseHandler = new BasicResponseHandler();
String jsonStr = Content.execute(httpget, responseHandler);
Log.d("Response: ", "> " + jsonStr);
JSONObject jsonObj = new JSONObject(jsonStr);
items = jsonObj.getJSONArray("posts");
// Parse json array into array of model objects
ArrayList<ProductHuntList> posts = ProductHuntList.fromJson(items);
// Load model objects into the adapter
for (ProductHuntList post : posts) {
adapterPosts.add(post);
}
} catch (JSONException e) {
e.printStackTrace();
} catch (IOException e) {
Error = e.getMessage();
cancel(true);
}
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
// Dismiss the progress dialog
if (pDialog.isShowing())
pDialog.dismiss();
ArrayList<ProductHuntList> aPosts = new ArrayList<ProductHuntList>();
adapterPosts = new ProductHuntAdapter(MainActivity.this, aPosts);
lvPosts.setAdapter(adapterPosts);
}
}
}
ProductHuntList.java containing the JSON Data model and deserializer and a static method for parsing an array of JSON
package com.emoji.apisoup;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.io.Serializable;
/**
* Created by mdhalim on 18/05/16.
*/
public class ProductHuntList implements Serializable {
private static final long serialVersionUID = -8959832007991513854L;
private String name;
private String tagline;
private String screenshot_url;
private String largePosterUrl;
private String discussion_Url;
private String created_at;
private int votes_count;
public String getNames() {
return name;
}
public String getCreated_at() {
return created_at;
}
public String getScreenshot_url() {
return screenshot_url;
}
public String getDiscussion_Url() {
return discussion_Url;
}
public int getVotes_count() {
return votes_count;
}
public String getLargePosterUrl() {
return largePosterUrl;
}
public String getTagline(){
return tagline;
}
public static ProductHuntList fromJson(JSONObject jsonObject) {
ProductHuntList b = new ProductHuntList();
try {
// Deserialize json into object fields
b.name = jsonObject.getString("name");
b.created_at = jsonObject.getString("created_at");
b.tagline = jsonObject.getString("tagline");
b.screenshot_url = jsonObject.getJSONObject("screenshot_url").getString("300px");
b.largePosterUrl = jsonObject.getJSONObject("screenshot_url").getString("850px");
b.votes_count = jsonObject.getInt("votes_count");
b.discussion_Url = jsonObject.getString("discussion_url");
} catch (JSONException e) {
e.printStackTrace();
return null;
}
// Return new object
return b;
}
public static ArrayList<ProductHuntList> fromJson(JSONArray jsonArray) {
ArrayList<ProductHuntList> posts = new ArrayList<ProductHuntList>(jsonArray.length());
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject productJson = null;
try {
productJson = jsonArray.getJSONObject(i);
} catch (Exception e) {
e.printStackTrace();
continue;
}
ProductHuntList post = ProductHuntList.fromJson(productJson);
if (post != null)
{
posts.add(post);
}
}
return posts;
}
}
ProductHuntAdapter.java this implements the ArrayAdapter
package com.emoji.apisoup;
/**
* Created by mdhalim on 18/05/16.
*/
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.squareup.picasso.Picasso;
import java.util.ArrayList;
/**
* Created by mdhalim on 18/05/16.
*/
public class ProductHuntAdapter extends ArrayAdapter<ProductHuntList> {
public ProductHuntAdapter(Context context, ArrayList<ProductHuntList> aPosts) {
super(context, 0, aPosts);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// Get the data item for this position
ProductHuntList posts = getItem(position);
// Check if an existing view is being reused, otherwise inflate the view
if (convertView == null) {
LayoutInflater inflater = LayoutInflater.from(getContext());
convertView = inflater.inflate(R.layout.item_product_hunt, null);
}
// Lookup view for data population
TextView name = (TextView) convertView.findViewById(R.id.name);
TextView created = (TextView) convertView.findViewById(R.id.created);
TextView tagline = (TextView) convertView.findViewById(R.id.tagline);
ImageView ivPosterImage = (ImageView) convertView.findViewById(R.id.ivPosterImage);
// Populate the data into the template view using the data object
name.setText(posts.getNames());
created.setText("Created On: " + posts.getCreated_at() + "%");
tagline.setText(posts.getTagline());
Picasso.with(getContext()).load(posts.getScreenshot_url()).into(ivPosterImage);
// Return the completed view to render on screen
return convertView;
}
}
and finally, a class implementing the activity for Item Details when a user clicks on any item on the list.
ProductHuntDetail
package com.emoji.apisoup;
/**
* Created by mdhalim on 18/05/16.
*/
import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.text.Html;
import android.widget.ImageView;
import android.widget.TextView;
import com.squareup.picasso.Picasso;
public class ProductHuntDetail extends Activity {
private ImageView ivPosterImage;
private TextView name;
private TextView discusUrl;
private TextView upvotes;
private TextView tagline;
private TextView created;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.product_hunt_detail);
// Fetch views
ivPosterImage = (ImageView) findViewById(R.id.ivPosterImage);
name = (TextView) findViewById(R.id.name);
discusUrl = (TextView) findViewById(R.id.discusUrl);
created = (TextView) findViewById(R.id.created);
upvotes = (TextView) findViewById(R.id.upvotes);
tagline = (TextView) findViewById(R.id.tagline);
// Load movie data
ProductHuntList posts = (ProductHuntList) getIntent().getSerializableExtra(MainActivity.POST_DETAIL_KEY);
loadMovie(posts);
}
// Populate the data for the movie
#SuppressLint("NewApi")
public void loadMovie(ProductHuntList posts) {
// Populate data
name.setText(posts.getNames());
upvotes.setText(Html.fromHtml("<b>Upvotes:</b> " + posts.getVotes_count() + "%"));
created.setText(posts.getCreated_at());
tagline.setText(posts.getTagline());
discusUrl.setText(Html.fromHtml("<b>Discussion Url:</b> " + posts.getDiscussion_Url()));
// R.drawable.large_movie_poster from
// http://content8.flixster.com/movie/11/15/86/11158674_pro.jpg -->
Picasso.with(this).load(posts.getLargePosterUrl()).
placeholder(R.drawable.large_movie_poster).
into(ivPosterImage);
}
}
I have been trying to debug this for hours :/
Your Async task is returning a void.
protected void onPostExecute(Void result) {
super.onPostExecute(result);
// Dismiss the progress dialog
if (pDialog.isShowing())
pDialog.dismiss();
ArrayList<ProductHuntList> aPosts = new ArrayList<ProductHuntList>();
adapterPosts = new ProductHuntAdapter(MainActivity.this, aPosts);
lvPosts.setAdapter(adapterPosts);
}
As far as I can tell from the code, aPosts is empty.
I think your Async task should be -
AsyncTask<String, Void, ProductHuntAdapter>
and remove -
adapterPosts = new ProductHuntAdapter(MainActivity.this, aPosts);
You are creating and updating this in your doInBackground() method already.
I got it!
I didnt need to declare these lines again in my onPostExecute() method
ArrayList<ProductHuntList> aPosts = new ArrayList<ProductHuntList>();
adapterPosts = new ProductHuntAdapter(MainActivity.this, aPosts);
So bascially, my new onPostExecute() method goes like this
protected void onPostExecute(Void result) {
super.onPostExecute(result);
// Dismiss the progress dialog
if (pDialog.isShowing())
pDialog.dismiss();
lvPosts.setAdapter(adapterPosts);
}
I had been trying to find this error for last 2 hours, it was harder since, I wasn't even getting any errors. As soon as I posted it on StackOverFlow, seems like I had a divine intervention.
I try send data to server but when I send Persian words it sends question marks, for example if I send "سلام" it sends "????"
How can I fix this ?
This is my FragmentForm.class :
package com.skyline.jimmy;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.util.EntityUtils;
import com.skyline.jimmy.R;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.Settings.Secure;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.RatingBar;
import android.widget.TextView;
import android.widget.Toast;
public class FragmentForm extends Fragment {
// An interface to display or dismiss of ProgressBar
public interface OnSendingRequestToServer {
public void DisplayLoding(boolean setVisibility);
}
private final String TAG = "FragmentForm";
private OnSendingRequestToServer onRequestToServer;
private Context context;
private EditText etName;
private EditText etComment;
private RatingBar ratingBar;
private ImageButton ibSubmit;
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
onRequestToServer = (OnSendingRequestToServer) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement OnConnectingToServer interface.");
}
context = activity.getApplicationContext();
Log.d(TAG, "Fragment attached to activity.");
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View view = inflater.inflate(R.layout.fragment_form, container, false);
etName = (EditText) view.findViewById(R.id.etName);
etComment = (EditText) view.findViewById(R.id.etComment);
ratingBar = (RatingBar) view.findViewById(R.id.ratingBar);
ibSubmit = (ImageButton) view.findViewById(R.id.ibSubmit);
//TextView tvcm = (TextView) view.findViewById(R.id.tvComment);
Log.d(TAG, "Fragment created.");
return view;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
ibSubmit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String strName = etName.getText().toString().trim();
if(strName.length() <= 0) {
Toast.makeText(context, "نام خود را وارد کنید", Toast.LENGTH_LONG).show();
return;
}
String strComment = etComment.getText().toString().trim();
if(strComment.length() <= 0) {
Toast.makeText(context, "متن جک را وارد کنید", Toast.LENGTH_LONG).show();
return;
}
int rate = (int) ratingBar.getRating();
if(rate <= 0) {
Toast.makeText(context, "امتیاز جکتان را وارد کنید", Toast.LENGTH_LONG).show();
return;
}
String deviceId = getDeviceId();
new SendFormTask(deviceId, strName, rate, strComment).execute();
}
private TextView findViewById(int tvcomment) {
// TODO Auto-generated method stub
return null;
}
});
}
private String getDeviceId() {
return Secure.getString(context.getContentResolver(), Secure.ANDROID_ID);
}
/*----------------------------------------------------------------------------
* This method is responsible for creating another thread in parallel with
* main UI thread in order to send a request to server and get data (if any).
* ---------------------------------------------------------------------------*/
public class SendFormTask extends AsyncTask<Void, Void, Boolean> {
String deviceId, name, comment;
int rate;
SendFormTask(String deviceId, String strName, int rate, String strComment) {
this.deviceId = deviceId;
this.name = strName;
this.rate = rate;
this.comment = strComment;
}
#Override
protected void onPreExecute() {
Log.d(TAG, "SendFormTask is about to start....");
onRequestToServer.DisplayLoding(true);
}
#Override
protected Boolean doInBackground(Void... params) {
boolean status = false;
HttpURLConnection urlConnection = null;
try {
//URL url = new URL(LinkManager.getFormAPI(deviceId, name, rate, comment));
//URL url = new URL(LinkManager.getFormAPI(deviceId, name, rate, comment));
String url1 = LinkManager.getFormAPI(deviceId, name, rate, comment) ;
//String stUrl = URLEncoder.encode(url1, "UTF-8");
URL url = new URL(url1);
Log.d(TAG, "Try to open: " + url.toString());
urlConnection = (HttpURLConnection) url.openConnection();
int responseCode = urlConnection.getResponseCode();
Log.d(TAG, "Response code is: " + responseCode);
if (responseCode == HttpURLConnection.HTTP_OK) {
BufferedReader in = new BufferedReader(
new InputStreamReader(urlConnection.getInputStream())
);
if (in != null) {
StringBuilder strBuilder = new StringBuilder();
// Read character by character
int ch = 0;
while ((ch = in.read()) != -1)
strBuilder.append((char) ch);
// get returned message and show it
String response = strBuilder.toString();
Log.d("Server response:", response);
if(response.equalsIgnoreCase("1"))
status = true;
}
in.close();
}
}
catch(MalformedURLException e){
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
finally {
urlConnection.disconnect();
}
return status;
}
#Override
protected void onPostExecute(Boolean result) {
Log.d(TAG, "SendFormTask finished its task.");
onRequestToServer.DisplayLoding(false);
if(result)
Toast.makeText(context, "جک شما ارسال شد, منتظر تایید آن باشید", Toast.LENGTH_LONG).show();
else
Toast.makeText(context, "جک شما ارسال شد , منتظر تایید آن باشید", Toast.LENGTH_LONG).show();
}
}
}
and my LinkManager.class :
package com.skyline.jimmy;
public class LinkManager {
private final static String API_FORM = "http://jimmy.ir/jimmy/sendjoke.php?p1=###&p2=####&p3=#####&p4=######";
private final static String API_Comment = "http://jimmy.ir/jimmy/index.php?p1=###";
public static String getFormAPI(String deviceId, String name, int rate, String comment) {
String url = API_FORM;
url = url.replaceAll("###", deviceId);
url = url.replaceAll("####", name);
url = url.replaceAll("#####", Integer.toString(rate));
url = url.replaceAll("######", comment);
return url;
}
public static String getCommentAPI(String deviceId) {
String url = API_Comment;
url = url.replaceAll("###", deviceId);
return url;
}
}
See this link for accepted characters in URL. Persian characters are not supported as get parameters in a url. You can use http post for sending the data to the server.
first make sure that you are sending right word (persian ) from android side , maybe your java code not sending text in UTF-8 , then make sure that your server, database , and table collection are utf8_persian_ci
and change this
BufferedReader in = new BufferedReader(
new InputStreamReader(urlConnection.getInputStream()));
to this:
BufferedReader in = new BufferedReader(
new InputStreamReader(urlConnection.getInputStream(), "utf-8"),8);
Dear Stackoverflow Comunitiy,
I'd like to have a ListView getting filled by an BackgroundTask.
This is my actual Code
HomeActivity:
package com.example.instaemgnew;
import java.util.ArrayList;
import android.app.ListActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import com.example.instaemgnew.classes.Beitrag;
import com.example.instaemgnew.classes.beitragLoader;
import com.example.instaemgnew.classes.listViewHomeActivitiyAdapter;
public class HomeActivity extends ListActivity {
listViewHomeActivitiyAdapter adapter;
ArrayList<Beitrag> beitraege = new ArrayList<Beitrag>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
adapter = new listViewHomeActivitiyAdapter(this, beitraege);
setListAdapter(adapter);
Log.e("TestPoint 1", "Adapter Set");
new beitragLoader(this).execute();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_home, menu);
return true;
}
public void addToListView(Beitrag toAddBeitrag){
beitraege.add(toAddBeitrag);
adapter.notifyDataSetChanged();
}
}
BackgroundTask:
package com.example.instaemgnew.classes;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import com.example.instaemgnew.HomeActivity;
import android.content.Context;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Environment;
import android.util.Log;
import android.widget.ArrayAdapter;
public class beitragLoader extends AsyncTask<String, String, String>{
//Array List für die Beiträge
ArrayList<Beitrag> beitraege;
//User Daten
/*mail = userManager.getMail();
grade = String.valueOf(userManager.getGrade());
school = userManager.getSchool();*/
String mail = "simon-frey#gmx.de";
String grade = String.valueOf(334);
String school = "EMG";
//JSONParser
JSONParser jsonParser = new JSONParser();
//ArrayList mit Beitrag Objekten
ArrayList<Beitrag> beitraegeList;
// Onlinedaten
private static final String SERVER_URL = "http://yooui.de/InstaEMGTest/";
private static final String PASSWORD = "8615daf406f7e2b313494f0240";
//Context
private final HomeActivity homeActivity;
//Konstruktor
public beitragLoader(HomeActivity homeActivity){
this.homeActivity = homeActivity;
Log.e("TestPoint 2", "Created beitragLoader");
}
#Override
protected void onPreExecute() {
super.onPreExecute();
//TODO: Test for InternetConnection
Log.e("TestPoint 3", "PreExectute");
}
/**
* getting All products from url
* */
protected String doInBackground(String... args) {
beitraegeList = new ArrayList<Beitrag>();
String SQLUrl = SERVER_URL + "testBeiträgeAbrufen.php";
String token = getMD5Hash("password" + "data");
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("token", token));
//TODO: params.add(new BasicNameValuePair("page", skipBeitraege))
params.add(new BasicNameValuePair("grade", grade));
params.add(new BasicNameValuePair("school", school));
JSONObject json = jsonParser.makeHttpRequest(SQLUrl, "GET", params);
if (json == null) {
// Server offline
}
Log.e("TestPoint 3,5", "FetchedJSON");
try {
JSONArray beitraege = json.getJSONArray("beitraege");
// looping through All Products
for (int i = 0; i < beitraege.length(); i++) {
Beitrag tempBeitrag = null;
Log.e("TestPoint 3,6", "StartLoop");
JSONObject c = beitraege.getJSONObject(i);
//HDImagesURLList ArrayList
ArrayList<String> HDImagesURLList = new ArrayList<String>();
// Storing each json item in variable
String id = c.getString("ID");
String url = c.getString("url");
String titel = c.getString("titel");
String tags = c.getString("tags");
String onlineDate = c.getString("onlineDate");
Log.e("TestPoint 3,7", "Stored JSON Items");
//Fetching previewImage
try {
Log.e("TestPoint 3,8", "TryImageDownload");
InputStream in = new java.net.URL(url).openStream();
String fileName = "InstaEMG" + String.valueOf(System.currentTimeMillis())+".jpg";
Log.e("imageUri", url);
Log.e("fileName", fileName);
FileOutputStream fileOutput = new FileOutputStream(new File(Environment.getExternalStorageDirectory(),fileName));
byte[] buffer = new byte[1024];
int bufferLength = 0;
while ((bufferLength = in.read(buffer)) > 0 ) {
fileOutput.write(buffer, 0, bufferLength);
Log.e("File Output", String.valueOf(bufferLength));
}
//Fill HDImagesURLList
//TODO
// creating newBeitrag
tempBeitrag = new Beitrag(Integer.parseInt(id), titel, onlineDate, fileName, HDImagesURLList);
// adding Beitrag to ArrayList
beitraegeList.add(tempBeitrag);
Log.e("TestPoint 4", "NewBeitragSet");
} catch (MalformedURLException e) {
Log.e("Exceptrion", "URL Exception");
} catch (IOException e) {
Log.e("Exceptrion", "IO Exception");
}
homeActivity.addToListView(tempBeitrag);
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} return null;
}
/**
* After completing background Safe to MainActivity
* **/
protected void onPostExecute() {
Log.e("TestPoint 5", "PostExecutre");
// homeActivity.updateListView(beitraegeList);
}
/**
* Methode zum Errechnen eines MD5Hashs
*
* #param string
* String welcher kodiert werden soll
* #return MD5 Hash des Strings, bei Fehler der ursprüngliche String.
*/
private String getMD5Hash(String string) {
try {
MessageDigest md5 = MessageDigest.getInstance("MD5");
md5.update(string.getBytes());
byte[] result = md5.digest();
StringBuffer hexString = new StringBuffer();
for (int i = 0; i < result.length; i++) {
if ((0xff & result[i]) < 0x10) {
hexString.append("0" + Integer.toHexString((0xFF & result[i])));
} else {
hexString.append(Integer.toHexString(0xFF & result[i]));
}
}
string = hexString.toString();
} catch (NoSuchAlgorithmException e1) {
e1.printStackTrace();
}
return string;
};
}
and the BaseAdapter:
package com.example.instaemgnew.classes;
import java.util.ArrayList;
import com.example.instaemgnew.R;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
public class listViewHomeActivitiyAdapter extends BaseAdapter {
private final Context context;
private ArrayList<Beitrag> beitraege;
private final LayoutInflater layoutInflater;
public listViewHomeActivitiyAdapter(Context context, ArrayList<Beitrag> beitraege) {
super();
this.beitraege = beitraege;
this.context = context;
this.layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
//Allgemeien Layout Vorgaben
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.single_beitrag_row_layout, parent, false);
if (convertView == null) {
convertView = layoutInflater.inflate(R.layout.single_beitrag_row_layout, null);
}
//getViews
TextView titelView = (TextView) rowView.findViewById(R.id.beitragTitel);
ImageView beitragImageView = (ImageView) rowView.findViewById(R.id.beitragImg);
/*
* TODO: Tags anzeigen und suchen lassen (Wunschfunktion)
* TextView tagsView = (TextView) rowView.findViewById(R.id.beitragTags);
*/
//setTitel From Object
titelView.setText(beitraege.get(position).getTitel());
//setPreviewImage From Object
beitragImageView.setImageBitmap(beitraege.get(position).getPreviewImage());
//setOnClickListener on PreviewImage for PopOutGallery
beitragImageView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
//TODO: PopOut Gallery
}
});
return rowView;
}
#Override
public int getCount() {
return beitraege.size();
}
#Override
public Object getItem(int position) {
return beitraege.get(position);
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
}
In my opinion the Bug have to be in the BaseAdapter, but I don't know where it could be.
Sincerly and thankful,
Simon
To fill listView in doInBackground you need to use Handler, or runOnUiThread, because this is not UI thread.
homeActivity.runOnUiThread(new Runnable()
{
public void run()
{
homeActivity.addToListView(tempBeitrag);
}});
adapter = new listViewHomeActivitiyAdapter(this, beitraege);
beitraege is not populated with any data.
Edit:
Instead of calling this from doInbackground. Use a Interface as a call back to the activity and then populate listview.
public void addToListView(Beitrag toAddBeitrag){
beitraege.add(toAddBeitrag);
adapter.notifyDataSetChanged();
}
How do I return a boolean from AsyncTask?
Instead of boolen value its arraylist in your case.
Then use the below and set the adapter your listview
adapter = new listViewHomeActivitiyAdapter(this, beitraege);