I am making an chat application while implementing it i need to update the messages automatically for this i am using asyntacks. For this i am having doubt that every time we cant able to refresh through asyntaks option. So, is there any way or any other method to refresh the chat activity for every second.
Chat.java
public class chatclass extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
String receiverid = getIntent().getStringExtra("Rid");
try {
URL url = new URL("" + Constant.cht);
Map<String, Object> paramm = new LinkedHashMap<>();
paramm.put("sid", "" + Session.getUserID(getApplicationContext()));
paramm.put("rid", "" + receiverid);
StringBuilder postData = new StringBuilder();
for (Map.Entry<String, Object> param : paramm.entrySet()) {
if (postData.length() != 0) postData.append('&');
postData.append(URLEncoder.encode(param.getKey(), "UTF-8"));
postData.append('=');
postData.append(URLEncoder.encode(String.valueOf(param.getValue()), "UTF-8"));
}
String urlParameters = postData.toString();
URLConnection conn = url.openConnection();
conn.setDoOutput(true);
OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream());
writer.write(urlParameters);
writer.flush();
String result = "";
String line;
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
while ((line = reader.readLine()) != null) {
result += line;
}
writer.close();
reader.close();
JSONObject response = new JSONObject(result);
JSONArray array = response.getJSONArray("data");
chatslistdata.clear();
for (int i = 0; i < array.length(); i++) {
JSONObject chatobj = array.getJSONObject(i);
ChatBeanData chatBeanData = new ChatBeanData();
chatBeanData.setChat_id(chatobj.getString("chat_id"));
chatBeanData.setRid(chatobj.getString("rid"));
chatBeanData.setReciever_name(chatobj.getString("reciever_name"));
chatBeanData.setReciever_image(chatobj.getString("reciever_image"));
chatBeanData.setSid(chatobj.getString("sid"));
chatBeanData.setSender_name(chatobj.getString("sender_name"));
chatBeanData.setSender_image(chatobj.getString("sender_image"));
chatBeanData.setMessage(chatobj.getString("message"));
chatBeanData.setSeen_status(chatobj.getInt("seen_status"));
chatBeanData.setTime(chatobj.getString("time"));
chatslistdata.add(chatBeanData);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
chatadapter = new ChatAdapter(ChatsPage.this, chatslistdata);
LinearLayoutManager mychatmanager = new LinearLayoutManager(ChatsPage.this, LinearLayoutManager.VERTICAL, false);
mychatmanager.setStackFromEnd(true);
chatlist.setLayoutManager(mychatmanager);
chatlist.setAdapter(chatadapter);
chatclass chatclass = new chatclass();
chatclass.execute();
}
}
It's really bad idea to refresh your chat every seconds because you lose a lot of server efficiency. You should do It like this:
Download all messages from server,
Download all messages with greater ID than last one message has (for example with long-polling or polling),
If there is any message, update list.
Or use Soket.io for example, or weboskect.
Then:
Create connection with server,
Download all messages,
Then server should send information if you will have new message,
If you receive this information, download messages with greater ID than last one message has.
I thing, it is good idea for chat. Here you have demo of chat on socket.io
Have fun
It is not really good approach to refresh your chat every second to retrieve messages.
This might overload your server with excessive requests which can be avoided.
To achieve real-time chat your server should send information if you have received any new messages.
On client-side you need to set a listener for that purpose. Once the listener is triggered, you can download the new messages.
Check ConnectyCube Android implementation as an example:
IncomingMessagesManager incomingMessagesManager = chatService.getIncomingMessagesManager();
incomingMessagesManager.addDialogMessageListener(new ChatDialogMessageListener() {
#Override
public void processMessage(String dialogId, ConnectycubeChatMessage message, Integer senderId) {
}
#Override
public void processError(String dialogId, ChatException exception, ConnectycubeChatMessage message, Integer senderId) {
}
});
Related
I am trying to get a JSON string from a url and save it into SQLite in my android app.
I was trying some tutorials then realize the suggested methods has a void return type. Are there a more simple straight forward way of getting a JSON String and putting it into an arraylist ready to be saved into SQLite?
Below is what I was stuck at a helper class that gets the data from the url
as they said that the main thread OnCreate does not allow a background process like this. Is there a way to change the return type of AsyncTask or is there a more simple way to fetch JSON String with android?
public class FetchData extends AsyncTask<Void, Void, Void> {
#Override
protected void doInBackground(ArrayList<String>... voids) {
try {
URL url = new URL("http://192.168.403.211/api/wordsupdate.php");
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
InputStream inputStream = httpURLConnection.getInputStream();
BufferedReader bufferedReader = new BufferedReader (new InputStreamReader(inputStream));
String line ="";
while (line != null) {
line = bufferedReader.readLine();
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
Go with Volley API. Check the code below which demonstrate POST request. Hope you'll get useful information.
public void getAddress(final String uid) {
String url = "Add Url Here"; // Request a string response from the provided URL.
StringRequest stringRequest = new StringRequest(Request.Method.POST, url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
JSONArray dataArray;
JSONObject jsonObject;
address_ids = new ArrayList<>();
address_names = new ArrayList<>();
address_line1 = new ArrayList<>();
address_line2 = new ArrayList<>();
address_state = new ArrayList<>();
address_district = new ArrayList<>();
address_taluka = new ArrayList<>();
address_pincode = new ArrayList<>();
address_status = new ArrayList<>();
address_default = new ArrayList<>();
try {
jsonObject = new JSONObject(response);
dataArray = jsonObject.getJSONArray(JSON_ARRAY);
//adding response values to respective array
for (int i = 0; i < dataArray.length(); i++) {
//Creating a json object of the current index
JSONObject obj;
try {
//getting json object from current index
obj = dataArray.getJSONObject(i);
address_ids.add(obj.getString(TAG_ADDRESS_ID));
address_names.add(obj.getString(TAG_ADDRESS_NAME));
address_line1.add(obj.getString(TAG_ADDRESSLINE_FIRST));
address_line2.add(obj.getString(TAG_ADDRESSLINE_SECOND));
address_state.add(obj.getString(TAG_STATE));
address_district.add(obj.getString(TAG_DISTRICT));
address_taluka.add(obj.getString(TAG_TALUKA));
address_pincode.add(obj.getString(TAG_PINCODE));
address_status.add(obj.getString(TAG_ADDRESS_STATUS));
} catch (JSONException e) {
e.printStackTrace();
}
}
} catch (JSONException e) {
e.printStackTrace();
}
//setting up response values to the fragment
//Toast.makeText(getActivity(), "Error:"+response, Toast.LENGTH_LONG).show();
Log.e(TAG, "onResponse: " + response);
address_name.setText("Name : " + address_names.get(0));
address.setText("Address : " + address_line1.get(0) + "," + address_line2.get(0) + "-" + address_pincode.get(0));
taluka.setText("Taluka : " + address_taluka.get(0));
district.setText("District : " + address_district.get(0));
state.setText("State : " + address_state.get(0));
mCircularProgressBar.setIndeterminate(false);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(getApplication(), "Taking bit longer", Toast.LENGTH_LONG).show();
}
}) {
#Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
params.put("mk_address_id", address_id);
return params;
}
};
queue.add(stringRequest);
}
Check this link from Android developer, you can find more info their.
In your code change the "extends" from
AsyncTask<Void, Void, Void>
to
AsyncTask<Void, Void, String>
and the doInBackground method to
protected String doInBackground(ArrayList<String>... voids)
and you will get the string back in the onPostExecute method
Yes there is a way to change the return types: Have a look at your extends AsyncTask: It says AsyncTask<Void, Void, Void>.
According to Android Developers, this means <Params, Progress, Result>.
This means that your
ArrayList<String>... voids won't work too, because you have the Params part set to Void but try to get an ArrayList<String>.
So, to solve your problem, change the three Voids to whatever you need it to input and output.
However, to deserialize JSON you should use an external library (or use a 3rd party library for REST calls altogether).
//AsyncTask has onPostExecute which will be called after background execution, where you will get the result in mainthread
class FetchData extends AsyncTask<Void, Void, String> {
#Override
protected String doInBackground(Void... voids) {
try {
URL url = new URL("http://192.168.403.211/api/wordsupdate.php");
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
InputStream inputStream = httpURLConnection.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder builder = new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null) {
builder.append(line);
}
return builder.toString();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String result) {
//Your result String is here which runs on MAIN THREAD
super.onPostExecute(result);
}
}
Retrofit 2 will help you - easy and simple
Edit : For Async task see the top answer here
What arguments are passed into AsyncTask<arg1, arg2, arg3>?
In your code snippet , you specified AsyncTask params types are Void. Void means , it does't have any return value. As per AsyncTask Syntax,
You have to specify three arguments.
1- InputType- DoInBanckground
2- ProgressType - Publish Progress.
3- OutputType - OnPostExecute.
The three types used by an asynchronous task are the following:
Params, the type of the parameters sent to the task upon execution.
Progress, the type of the progress units published during the background computation.
Result, the type of the result of the background computation.
In your snippet doInBackground method and AsycTask types are mismatching .
For more information : https://developer.android.com/reference/android/os/AsyncTask.html
I am storing the data that I parsed from the JSON that is returned by my API request into the Firebase database.
submitButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String APIURL = "https://api.github.com/users/" + idInput.getText().toString();
String repoURL = "https://api.github.com/users/" + idInput.getText().toString() + "/repos";
new JSONTask().execute(APIURL);
//new JSONTask().execute(repoURL);
String parsedUserID = idInput.getText().toString();
SM.sendDataToProfile(parsedUserID);
viewPager.setCurrentItem(1);
//addUser(parsedUserID);
}
});
When the button is clicked, it calls a new JSONTask (asynctask) on the APIURL.
JSONTask
public class JSONTask extends AsyncTask<String, String, String> {
#Override
// Any non-UI thread process is running in this method. After completion, it sends the result to OnPostExecute
protected String doInBackground(String... params) {
HttpURLConnection connection = null;
BufferedReader reader = null;
try {
// Pass in a String and convert to URL
URL url = new URL(params[0]);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
InputStream stream = connection.getInputStream();
// Reads the data line by line
reader = new BufferedReader(new InputStreamReader(stream));
StringBuffer strBuffer = new StringBuffer();
String line = "";
while ((line = reader.readLine()) != null) {
strBuffer.append(line);
}
// If we are able to get the data do below :
String retreivedJson = strBuffer.toString();
return retreivedJson;
// When we are not able to retreive the Data
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (connection != null) {
// close both connection and the reader
connection.disconnect();
}
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
And it does parsing in another function.
My question is, as you can see on my setOnClickListener, I tried to make two JSONTask on two different URLs because the first URL gives me the information of the user and the second URL (repoURL) gives me the information of the user's repositories. I tried to fetch the repo info of the user and store it into the DB, but it seems like this is a wrong approach.
What is a right way to call two separate AsyncTasks on two different URLs?
EDIT
private void addUserRepo(final String githubID, final String[] repoList) {
DatabaseReference users = databaseReference.child("users");
users.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
List list = new ArrayList<String>(Arrays.asList(repoList));
databaseReference.child("users").child(githubID).child("Repos").setValue(list);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
Using data parsed from
public void formatJSONArray(String results){
try {
JSONArray jsonArray = new JSONArray(results);
RepoInfo[] repoList = new RepoInfo[jsonArray.length()];
for(int i = 0; i < jsonArray.length(); i++){
JSONObject jsonObject=jsonArray.getJSONObject(i);
if(jsonObject.optString("name") != null) {
repoList[i].setRepoName(jsonObject.getString("name"));
//repoNameList.add(jsonObject.getString("name"));
}
if(jsonObject.optString("description") != null) {
repoList[i].setDescription(jsonObject.getString("description"));
//descriptionList.add(jsonObject.getString("description"));
}
if(jsonObject.optJSONObject("owner") != null){
JSONObject ownerObject=jsonObject.getJSONObject("owner");
if(ownerObject.optString("login")!=null) {
repoList[i].setOwner(ownerObject.getString("login"));
//userNameList.add(ownerObject.getString("login"));
}
}
}
} catch (JSONException jsonException){
}
}
The response of two different URLs will surely not be similar. So you need different parse methods for them.
One lazy way would be to use two different AsyncTasks subclasses for two different urls.
Another way would be to store a flag inside the asynctask indicating whether it is dealing with user or repo.
public class JSONTask extends AsyncTask <String , String , String> {
boolean fetchingRepo;
#Override
protected String doInBackground (String... params) {
fetchingRepo = params[0].endsWith("/repos");
//other statements
}
Now inside onPostExecute:
if(fetchingRepo){
//parse one way
} else {
//parse another way
}
I am trying to click a hyperlink and call method in android programming...
But the problem is , the link is not showing up and neither the method is getting called. How to achieve this result?
I am basically a javascript/jsp developer, this is my first android application , which i am learning. Accordingly i am trying to click link and call method with parameter....
Results looking like
Java code
private class CallAPI extends AsyncTask<String, String, String> {
private String Content;
#Override
protected String doInBackground(String... params) {
String urlString=params[0]; // URL to call
String resultToDisplay = "";
InputStream in = null;
emailVerificationResult result = null;
// HTTP Get
try {
URL url = new URL(urlString);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
in = new BufferedInputStream(urlConnection.getInputStream());
System.out.println("test");
BufferedReader reader = null;
// Get the server response
reader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
StringBuilder sb = new StringBuilder();
String line = null;
// Read Server Response
while ((line = reader.readLine()) != null) {
// Append server response in string
sb.append(line + "\n");
}
// Append Server Response To Content String
Content = sb.toString();
} catch (Exception e ) {
System.out.println(e.getMessage());
return e.getMessage();
}
/****************** Start Parse Response JSON Data *************/
String OutputData = "<center><b><u>Weight Training</u></b></center><br/><br/>";
JSONObject jsonResponse;
try {
/****** Creates a new JSONObject with name/value mappings from the JSON string. ********/
jsonResponse = new JSONObject(Content);
/***** Returns the value mapped by name if it exists and is a JSONArray. ***/
/******* Returns null otherwise. *******/
JSONArray jsonMainNode = jsonResponse.optJSONArray("articleList");
/*********** Process each JSON Node ************/
int lengthJsonArr = jsonMainNode.length();
for (int i = 0; i < lengthJsonArr; i++) {
/****** Get Object for each JSON node.***********/
JSONObject jsonChildNode = jsonMainNode.getJSONObject(i);
/******* Fetch node values **********/
String name = jsonChildNode.optString("menu_name").toString();
String number = jsonChildNode.optString("id").toString();
String date_added = jsonChildNode.optString("parent_id").toString();
OutputData += " " +
String.format("<a onClick='verifyEmail("+number+","+date_added+")'><b>"+name+"<b> "+ number+" "+ date_added+"</a> ") +"<br/><br/>";
}
/****************** End Parse Response JSON Data *************/
/* Show Parsed Output on screen (activity) */
} catch (JSONException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
resultToDisplay =OutputData ;
return resultToDisplay;
}
// This is the method that is called when the submit button is clicked
public void verifyEmail(String m,String p) {
String urlString = apiURL + "mid=" + m + "&pid=" + p;
new CallAPI().execute(urlString);
}
protected void onPostExecute(String result) {
Intent intent = new Intent(getApplicationContext(), ResultActivity.class);
intent.putExtra(EXTRA_MESSAGE, result);
startActivity(intent);
}
Update:
Instead of link, can i put a button and provide on click method and pass parameter to the method
(Thankfully) You cannot call a function using HTML tags in android. Instead try setting ClickableSpan on you you TextView to get the desired effect
SpannableString ss = new SpannableString("Click Me to do magic");
ClickableSpan clickableSpan = new ClickableSpan() {
#Override
public void onClick(View textView) {
doSomeMagic();
}
#Override
public void updateDrawState(TextPaint ds) {
super.updateDrawState(ds);
}
};
// apply the clickable span on "Click Me" part which is on index 0 -> 7
// 8 is used because it goes from a -> b-1
ss.setSpan(clickableSpan, 0, 8, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
TextView textView = (TextView) findViewById(R.id.foo);
textView.setText(ss);
I have an object, contact, with a detailsURL String. At that URL is some JSON with more information about the contact that I need to set. The way I'm attempting to do this AsyncTask is like this:
class detailDownloader extends AsyncTask<String, Void, Void> {
String detail;
private contact c;
public detailDownloader(String detail, contact c) {
this.c = c;
this.detail = detail;
}
protected Void doInBackground(String... urls) {
String url = urls[0];
Log.d("contact", "1");
String s;
try {
InputStream in = new java.net.URL(url).openStream();
Log.d("contact", "2");
BufferedReader br2 = null;
br2 = new BufferedReader(new InputStreamReader(in, "UTF-8"));
StringBuilder sb2 = new StringBuilder();
Log.d("contact", "3");
while((s = br2.readLine()) != null) {
sb2.append(s);
}
s = sb2.toString();
JSONArray detail = new JSONArray(s);
for(int j = 0; j < detail.length(); j++){
JSONObject obj2 = detail.getJSONObject(j);
boolean favorite = obj2.getBoolean("favorite");
String email = obj2.getString("email");
String largeURL = obj2.getString("largeImageURL");
JSONObject address = obj2.getJSONObject("address");
String street = address.getString("street");
String city = address.getString("city");
String state = address.getString("state");
c.setFavorite(favorite);
c.setLargeURL(largeURL);
c.setEmail(email);
c.setStreet(street);
c.setCityState(city + ", " + state);
}
in.close();
} catch (Exception e) {
Log.e("Error", e.getMessage());
}
return null;
}
}
The detailDownloader is called by:
new detailDownloader(c.getDetailsURL(), c).execute();
But I get a response in my Log: "03-06 16:30:24.724: I/Choreographer(29237): Skipped 370 frames! The application may be doing too much work on its main thread."
Any idea how to fix this issue?
This code looks OK to me at first glance. Are you sure it's this class that's causing the skipped frames? Are you sure that you're not doing something else on the main thread that's causing this problem?
Does your detailsDownloader class implement onPreExecute or onPostExecute? If so, you should post your code for those methods, too.
Such kind of error is usually caused by using too much UI threads, check this for more information.
I want to show huge data (+50,000 records) in android listview using Async.
The data comes from web services(dot net) in pages(1000 records in each page).
As I get 1000 records I have to update the listview automatically (without scrolling).This process continues till all the records are fetched.
Am able to fetch all the records but unable to update listview.
My code is :
class XYZ extends AsyncTask<String, Integer, String>
{
#Override
protected String doInBackground(String... params) {
for(int i=1;i<=noOfPagesFromServer;i++)
{
String url="http://182.72.123.138:9523/Service.svc/GetData/"+i;
try
{
HttpGet get =new HttpGet(url );
HttpClient httpClient = new DefaultHttpClient();
HttpResponse httpResponse = httpClient.execute(get);
BufferedReader reader = new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent()));
StringBuilder stringBuilder = new StringBuilder();
String line = null;
while((line = reader.readLine()) != null)
{
stringBuilder.append(line + "\n");
}
String responseString = stringBuilder.toString();
JSONObject serverJSONObj = new JSONObject(responseString);
JSONArray serverJSONArray = serverJSONObj .getJSONArray("ABC");
for(int l=0;l<serverJSONArray.length();l++)
{
JSONObject tempJSONObject=serverJSONArray.getJSONObject(l);
a = tempJSONObject.getString("A");
b =tempJSONObject.getString("B");
Model model=new Model(a,b);
arrayList.add(model);}
} catch (Exception e) {
e.printStackTrace();
}
publishProgress(null);
SystemClock.sleep(6000);
}return null;}
protected void onProgressUpdate(Integer... values)
{
super.onProgressUpdate(values);
adapter1 = new CustomListViewAdapter(SearchActivity.this,R.layout.row,arrayList);
listView.setAdapter(adapter1);
listView.this.adapter1.notifyDataSetChanged();
}
#Override
protected void onPostExecute(String result) {
try{
super.onPostExecute(result);
runOnUiThread(new Runnable() {
#Override
public void run() {
adapter1 = new CustomListViewAdapter(SearchActivity.this,R.layout.row,arrayList);
adapter1.notifyDataSetChanged();
listView.setAdapter(adapter1);
}
});
}
catch(Exception e){
e.printStackTrace();
}
}
Thanks for your replies
You can use onProgressUpdate() and acheive the required result...update your model once you receive the 1000 records and update the list...