HTTP Requests very slow on Samsung Galaxy phones - Android Software Development

Hey,
i experience a very anoying "issue" on my app, but only on Samsung Galaxy S* phones (tested on S2 Plus with JB and S3).
A HTTPGet request pulls a web page and parses it (parsing works fine). On samsung phones pulling the web page takes over 2 mins. On my Nexus 4, it only talkes around 3 seconds.
I use an AsyncTask.
Code:
protected String doInBackground(String... message) {
HttpClient httpclient;
HttpGet request;
HttpResponse response = null;
String result = "";
try {
httpclient = new DefaultHttpClient();
request = new HttpGet("http://www.gymnasium-sonneberg.de/Informationen/vp.html");
response = httpclient.execute(request);
}
catch (Exception e) {
result = "E";
e.printStackTrace();
}
try {
BufferedReader rd = new BufferedReader(new InputStreamReader(
response.getEntity().getContent()));
String line = "";
while ((line = rd.readLine()) != null) {
result = result + line + "\n" ;
}
} catch (Exception e) {
result = "E";
e.printStackTrace();
}
return result;
}
This is my doInBackground method
You can see the complete class here: https://github.com/XorgMC/gsapp/blob/gino/src/de/xorg/gsapp/VPlanViewer.java
I've already tried to use HttpURLConnection, no difference.
Any ideas?
Cheers Xorg

TheXorg said:
Hey,
i experience a very anoying "issue" on my app, but only on Samsung Galaxy S* phones (tested on S2 Plus with JB and S3).
A HTTPGet request pulls a web page and parses it (parsing works fine). On samsung phones pulling the web page takes over 2 mins. On my Nexus 4, it only talkes around 3 seconds.
I use an AsyncTask.
Code:
protected String doInBackground(String... message) {
HttpClient httpclient;
HttpGet request;
HttpResponse response = null;
String result = "";
try {
httpclient = new DefaultHttpClient();
request = new HttpGet("http://www.gymnasium-sonneberg.de/Informationen/vp.html");
response = httpclient.execute(request);
}
catch (Exception e) {
result = "E";
e.printStackTrace();
}
try {
BufferedReader rd = new BufferedReader(new InputStreamReader(
response.getEntity().getContent()));
String line = "";
while ((line = rd.readLine()) != null) {
result = result + line + "\n" ;
}
} catch (Exception e) {
result = "E";
e.printStackTrace();
}
return result;
}
This is my doInBackground method
You can see the complete class here: https://github.com/XorgMC/gsapp/blob/gino/src/de/xorg/gsapp/VPlanViewer.java
I've already tried to use HttpURLConnection, no difference.
Any ideas?
Cheers Xorg
Click to expand...
Click to collapse
"Fixed" it by using it synchron. But that can't be the solution, such things should never done synchronized AFAIK.

Related

HttpClient Issues

I am making an application that requires maintaining a session with a server, aka Cookie management. I am currently unable to hold a session with my current code, though I was able to with code that was not separated into methods. I am not sure if that is the problem. If anyone is able to help I'd really appreciate it.
Here is the relevant code
Code:
public class MYHTTP
{
DefaultHttpClient client = new DefaultHttpClient();
HttpGet request;
HttpEntity entity;
HttpResponse response;
HttpPost post;;
public void getPage(String url) throws Exception
{
request = new HttpGet(url);
response = client.execute(request);
PARSER.preParse(url, response);
entity = response.getEntity();
if(entity != null)
{
entity.consumeContent();
}
}
public HttpResponse postPage(List<NameValuePair> params, String host, String action) throws Exception
{
post = new HttpPost(host + action);
post.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));
response = client.execute(post);
entity = response.getEntity();
if(entity != null)
{
entity.consumeContent();
}
return response;
}
public void destoyHttp()
{
client.getConnectionManager().shutdown();
}
}

Loading a new fragment from an OnClick set in asyncTask

I have a fragment, which contains a button that when pressed loads a new fragment. The new fragment runs an async task to populate a listview with data.
I am running into trouble, trying to load a new fragment from the onClick. The problem is I can not get the getFragmentManager();
My async task looks like this:
Code:
public class GetStyleStatisticsJSON extends AsyncTask<String, Void, String> {
Context c;
private ProgressDialog Dialog;
android.support.v4.app.Fragment Fragment_one;
public GetStyleStatisticsJSON(Context context)
{
c = context;
Dialog = new ProgressDialog(c);
}
@Override
protected String doInBackground(String... arg0) {
// TODO Auto-generated method stub
return readJSONFeed(arg0[0]);
}
protected void onPreExecute() {
Dialog.setMessage("Analyzing Statistics");
Dialog.setTitle("Loading");
Dialog.setCancelable(false);
Dialog.show();
}
protected void onPostExecute(String result){
//decode json here
try{
JSONArray jsonArray = new JSONArray(result);
//acces listview
ListView lv = (ListView) ((Activity) c).findViewById(R.id.yourStyleStatistics);
//make array list for beer
final List<StyleInfo> tasteList = new ArrayList<StyleInfo>();
for(int i = 0; i < jsonArray.length(); i++) {
String style = jsonArray.getJSONObject(i).getString("style");
String rate = jsonArray.getJSONObject(i).getString("rate");
String beerID = jsonArray.getJSONObject(i).getString("id");
int count = i + 1;
style = count + ". " + style;
//create object
StyleInfo tempTaste = new StyleInfo(style, rate, beerID);
//add to arraylist
tasteList.add(tempTaste);
//add items to listview
StyleInfoAdapter adapter1 = new StyleInfoAdapter(c ,R.layout.brewer_stats_listview, tasteList);
lv.setAdapter(adapter1);
//set up clicks
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1,
int arg2, long arg3) {
StyleInfo o=(StyleInfo)arg0.getItemAtPosition(arg2);
String bID = o.id;
//todo: add onclick for fragment to load
FragmentManager man= (Activity)c.getFragmentManager();
FragmentTransaction tran = man.beginTransaction();
Fragment_one = new StylePage2();
final Bundle bundle = new Bundle();
bundle.putString("beerIDSent", bID);
Fragment_one.setArguments(bundle);
tran.replace(R.id.main, Fragment_one);//tran.
tran.addToBackStack(null);
tran.commit();
}
});
}
}
catch(Exception e){
}
Dialog.dismiss();
}
public String readJSONFeed(String URL) {
StringBuilder stringBuilder = new StringBuilder();
HttpClient httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(URL);
try {
HttpResponse response = httpClient.execute(httpGet);
StatusLine statusLine = response.getStatusLine();
int statusCode = statusLine.getStatusCode();
if (statusCode == 200) {
HttpEntity entity = response.getEntity();
InputStream inputStream = entity.getContent();
BufferedReader reader = new BufferedReader(
new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
stringBuilder.append(line);
}
inputStream.close();
} else {
Log.d("JSON", "Failed to download file");
}
} catch (Exception e) {
Log.d("readJSONFeed", e.getLocalizedMessage());
}
return stringBuilder.toString();
}
}
can not resolve method FragmentManager() is the error I am receiving
Hi,
To be able to call getFragmentManager() or getSupportFragmentManager() you'll need to use FragmentActivity, so what I would do is:
1. Make sure the activity that calls the asycTask is a FragmentActivity.
2. Pass this actvity to the asycTask.
Something like: (asyncTask method)
setActivity(Activity activity)
{
fm = activity.getFragmentManager();
}
mrsegev said:
Hi,
To be able to call getFragmentManager() or getSupportFragmentManager() you'll need to use FragmentActivity, so what I would do is:
1. Make sure the activity that calls the asycTask is a FragmentActivity.
2. Pass this actvity to the asycTask.
Something like: (asyncTask method)
setActivity(Activity activity)
{
fm = activity.getFragmentManager();
}
Click to expand...
Click to collapse
thats the problem, I launch the asyncTask from a fragment....
Oh! So you'll access your activity like this:
getActivity().getFragmentManager();

Java is too complex for begginer lovers

I love Android. I want to learn to develop apps. I keep reading tutorials. I got dissapointed and read about HTML frameworks (phonegap, etc). I came back to Android Native Java. I want to learn from the roots. However, some things discourages me....
All this part of the code is just for making a request to the Openweather API and get the json data (plus a little debugging stuff); which in Python or similar languages you only have to care about
- importing the library that handles http requests
- make the request in one function and save it into a json object
Code:
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
// Will contain the raw JSON response as a string.
String forecastJsonStr = null;
String format = "json";
String units = "metric";
int numDays = 7;
try {
final String FORECAST_BASE_URL =
"<the-domain>/data/2.5/forecast/daily?";
final String QUERY_PARAM = "q";
final String FORMAT_PARAM = "mode";
final String UNITS_PARAM = "units";
final String DAYS_PARAM = "cnt";
Uri builtUri = Uri.parse(FORECAST_BASE_URL).buildUpon()
.appendQueryParameter(QUERY_PARAM, params[0])
.appendQueryParameter(FORMAT_PARAM, format)
.appendQueryParameter(UNITS_PARAM, units)
.appendQueryParameter(DAYS_PARAM, Integer.toString(numDays))
.build();
URL url = new URL(builtUri.toString());
Log.v(LOG_TAG, "Built URI " + builtUri.toString());
// Create the request to OpenWeatherMap, and open the connection
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
// Read the input stream into a String
InputStream inputStream = urlConnection.getInputStream();
StringBuffer buffer = new StringBuffer();
if (inputStream == null) {
// Nothing to do.
return null;
}
reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
buffer.append(line + "\n");
}
if (buffer.length() == 0) {
// Stream was empty. No point in parsing.
return null;
}
forecastJsonStr = buffer.toString();
Log.v(LOG_TAG, "Forecast string: " + forecastJsonStr);
} catch (IOException e) {
Log.e(LOG_TAG, "Error ", e);
// If the code didn't successfully get the weather data, there's no point in attemping
// to parse it.
return null;
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e(LOG_TAG, "Error closing stream", e);
}
}
}
This is the complete Class:
Code:
public class FetchWeatherTask extends AsyncTask<String, Void, String[]> {
private final String LOG_TAG = FetchWeatherTask.class.getSimpleName();
/* The date/time conversion code is going to be moved outside the asynctask later,
* so for convenience we're breaking it out into its own method now.
*/
private String getReadableDateString(long time){
// Because the API returns a unix timestamp (measured in seconds),
// it must be converted to milliseconds in order to be converted to valid date.
Date date = new Date(time * 1000);
SimpleDateFormat format = new SimpleDateFormat("E, MMM d");
return format.format(date).toString();
}
/**
* Prepare the weather high/lows for presentation.
*/
private String formatHighLows(double high, double low) {
// For presentation, assume the user doesn't care about tenths of a degree.
long roundedHigh = Math.round(high);
long roundedLow = Math.round(low);
String highLowStr = roundedHigh + "/" + roundedLow;
return highLowStr;
}
/**
* Take the String representing the complete forecast in JSON Format and
* pull out the data we need to construct the Strings needed for the wireframes.
*
* Fortunately parsing is easy: constructor takes the JSON string and converts it
* into an Object hierarchy for us.
*/
private String[] getWeatherDataFromJson(String forecastJsonStr, int numDays)
throws JSONException {
// These are the names of the JSON objects that need to be extracted.
final String OWM_LIST = "list";
final String OWM_WEATHER = "weather";
final String OWM_TEMPERATURE = "temp";
final String OWM_MAX = "max";
final String OWM_MIN = "min";
final String OWM_DATETIME = "dt";
final String OWM_DESCRIPTION = "main";
JSONObject forecastJson = new JSONObject(forecastJsonStr);
JSONArray weatherArray = forecastJson.getJSONArray(OWM_LIST);
String[] resultStrs = new String[numDays];
for(int i = 0; i < weatherArray.length(); i++) {
// For now, using the format "Day, description, hi/low"
String day;
String description;
String highAndLow;
// Get the JSON object representing the day
JSONObject dayForecast = weatherArray.getJSONObject(i);
// The date/time is returned as a long. We need to convert that
// into something human-readable, since most people won't read "1400356800" as
// "this saturday".
long dateTime = dayForecast.getLong(OWM_DATETIME);
day = getReadableDateString(dateTime);
// description is in a child array called "weather", which is 1 element long.
JSONObject weatherObject = dayForecast.getJSONArray(OWM_WEATHER).getJSONObject(0);
description = weatherObject.getString(OWM_DESCRIPTION);
// Temperatures are in a child object called "temp". Try not to name variables
// "temp" when working with temperature. It confuses everybody.
JSONObject temperatureObject = dayForecast.getJSONObject(OWM_TEMPERATURE);
double high = temperatureObject.getDouble(OWM_MAX);
double low = temperatureObject.getDouble(OWM_MIN);
highAndLow = formatHighLows(high, low);
resultStrs[i] = day + " - " + description + " - " + highAndLow;
}
for (String s : resultStrs) {
Log.v(LOG_TAG, "Forecast entry: " + s);
}
return resultStrs;
}
@Override
protected String[] doInBackground(String... params) {
// If there's no zip code, there's nothing to look up. Verify size of params.
if (params.length == 0) {
return null;
}
// These two need to be declared outside the try/catch
// so that they can be closed in the finally block.
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
// Will contain the raw JSON response as a string.
String forecastJsonStr = null;
String format = "json";
String units = "metric";
int numDays = 7;
try {
// Construct the URL for the OpenWeatherMap query
// Possible parameters are avaiable at OWM's forecast API page
final String FORECAST_BASE_URL =
"<the-domain>/data/2.5/forecast/daily?";
final String QUERY_PARAM = "q";
final String FORMAT_PARAM = "mode";
final String UNITS_PARAM = "units";
final String DAYS_PARAM = "cnt";
Uri builtUri = Uri.parse(FORECAST_BASE_URL).buildUpon()
.appendQueryParameter(QUERY_PARAM, params[0])
.appendQueryParameter(FORMAT_PARAM, format)
.appendQueryParameter(UNITS_PARAM, units)
.appendQueryParameter(DAYS_PARAM, Integer.toString(numDays))
.build();
URL url = new URL(builtUri.toString());
Log.v(LOG_TAG, "Built URI " + builtUri.toString());
// Create the request to OpenWeatherMap, and open the connection
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
// Read the input stream into a String
InputStream inputStream = urlConnection.getInputStream();
StringBuffer buffer = new StringBuffer();
if (inputStream == null) {
// Nothing to do.
return null;
}
reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
// Since it's JSON, adding a newline isn't necessary (it won't affect parsing)
// But it does make debugging a *lot* easier if you print out the completed
// buffer for debugging.
buffer.append(line + "\n");
}
if (buffer.length() == 0) {
// Stream was empty. No point in parsing.
return null;
}
forecastJsonStr = buffer.toString();
Log.v(LOG_TAG, "Forecast string: " + forecastJsonStr);
} catch (IOException e) {
Log.e(LOG_TAG, "Error ", e);
// If the code didn't successfully get the weather data, there's no point in attemping
// to parse it.
return null;
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e(LOG_TAG, "Error closing stream", e);
}
}
}
try {
return getWeatherDataFromJson(forecastJsonStr, numDays);
} catch (JSONException e) {
Log.e(LOG_TAG, e.getMessage(), e);
e.printStackTrace();
}
// This will only happen if there was an error getting or parsing the forecast.
return null;
}
}
I mean, I know this code can be reduced, but I'm angry about the way it works. Everything needs to be passed to another object! And even rembember all those castings! Castings everywhere!
- The builded URI to the URL.
- The URL to the HttpConection variable.
- Once you connect, save that into the InputStream.
- Make a StringBuffer because we are going to send line by line everything.
- Then create the reader = new BufferedReader(new InputStreamReader(inputStream)).
- Append the lines to the buffer and return if it's ok.
- Else catch all the errors and be sure to close all the connections.
Damn Java !
Forgive me. You'll hate me.
Java is readable, that's the truth... but don't tell me that it is easy for a normal person.
Am I the only one?
If you are a beginner and will straight move to these classes. You will obviously find Java difficult. But Java is very easy if you move step by step from start
Sent from my XT1033 using XDA Premium 4 mobile app
---------- Post added at 04:18 PM ---------- Previous post was at 04:16 PM ----------
And that library also does the same thing inside. Only difference is, your work is already done by author of the library.
Sent from my XT1033 using XDA Premium 4 mobile app
Java is definitely a very verbose language but it's also widely used and so you will find many libraries that do tasks like grab JSON data from a service that have already been implemented for you
manwoman said:
Damn Java !
Forgive me. You'll hate me.
Java is readable, that's the truth... but don't tell me that it is easy for a normal person.
Am I the only one?
Click to expand...
Click to collapse
I don't think you're the only one. It's easy to get scared away by the many too verbose examples available, the key is to look at what you're trying to achieve and then break it up into those parts.
Your code listing is (I think) an attempt to show all steps to get the forecast data, but if that would have been broken up into smaller steps I don't think you'd look at it as quite as bad.
You would then have methods like
Code:
URL getForecastUrl(String parameter);
Code:
BufferedReader getUrl(URL url) { }
Code:
String readAll(BufferedReader reader) {}
Each of which would have had something like 6-7 lines of simple, cohesive code.
I understand your point, but in this particular scenario I think you're the victim of a poorly structured code sample rather than a too verbose language.
If you think the default implementation is too complicated, here are also many java libraries which will make your life easier.

Starting chronometer with if condition comparing strings

I have an android application that is receiving a string from an arduino via Bluetooth, names the string "data" and displays it by setting a TextView to the string "data". I want a chronometer to start when the incoming string matches a predefined string.
For example:
Code:
if data.equals(startChrono)){
chronometerLeft.setBase(SystemClock.elapsedRealtime());
chronometerLeft.start();
I actually have the arduino sending a "g" and am setting my string goL to be "g" but cannot get the chronometer to start when the g is received. My TextView shows the g. Code is below. I've tried several things and at a loss. Using same code for chronometer.start() with onClickListener with a button works great. I just need it to start the chronometer when i receive a specific string from the arduino.
Code:
beginListenForData();
// text.setText("Bluetooth Opened");
}
void beginListenForData() {
final Handler handler = new Handler();
final byte delimiter = 10; // This is the ASCII code for a newline
// character
stopWorker = false;
readBufferPosition = 0;
readBuffer = new byte[1024];
workerThread = new Thread(new Runnable() {
public void run() {
while (!Thread.currentThread().isInterrupted() && !stopWorker) {
try {
int bytesAvailable = mmInputStream.available();
if (bytesAvailable > 0) {
byte[] packetBytes = new byte[bytesAvailable];
mmInputStream.read(packetBytes);
for (int i = 0; i < bytesAvailable; i++) {
byte b = packetBytes[i];
if (b == delimiter) {
byte[] encodedBytes = new byte[readBufferPosition];
System.arraycopy(readBuffer, 0,
encodedBytes, 0,
encodedBytes.length);
final String data = new String(
encodedBytes, "US-ASCII");
readBufferPosition = 0;
handler.post(new Runnable() {
public void run() {
text.setText(data);
String goL = "g";
String goR = "f";
chronometerLeft = (Chronometer)findViewById(R.id.chronometerLeft);
chronometerRight = (Chronometer)findViewById(R.id.chronometerRight);
if(data.equals(goL)){
chronometerLeft.setBase(SystemClock.elapsedRealtime());
chronometerLeft.start();
if(data.equals(goR))
chronometerRight.setBase(SystemClock.elapsedRealtime());
chronometerRight.start();
}
}
});
} else {
readBuffer[readBufferPosition++] = b;
}
}
}
} catch (IOException ex) {
stopWorker = true;
}
}
}
});
workerThread.start();
}
Sorry to bother, but in your while loop condition, what does the '!' before Thread do?

Help with Apple WeatherKit

I hope someone can help me.
I'm having trouble getting an Apple WeatherKit REST request working. I'm trying to follow all of the requirements listed on https://developer.apple.com/documen...equest_authentication_for_weatherkit_rest_api, but I still get a 403 response code -- and I can't locate any Java samples to follow. I've been sweating this for weeks and haven't gotten anywhere.
Here's what I have:
URL url = new URL ("https://weatherkit.apple.com/api/v1/weather/en/40.75/-73.00?dataSets=currentWeather&timezone=Europe/London");
PrivateKey pkey = getPrivateKey ("AuthKey_CXXXXXXXXX.p8");
String jwts = getJwtsString (pkey);
HttpURLConnection conn = getConnection (url, jwts);
conn.connect();
int responsecode = conn.getResponseCode();
Just in case I've got something wrong, here are the three functions I'm calling. First, the one that creates the PrivateKey from the p8 file (I'm pretty sure this one is OK):
private PrivateKey getPrivateKey (String filename) {
PrivateKey privateKey = null;
try {
AssetManager assetManager = this.getAssets();
InputStream stream = assetManager.open(filename);
byte[] bytes = new byte[stream.available()];
int bytesRead = stream.read(bytes);
byte[] pkcs8EncodedKey = new byte[0];
pkcs8EncodedKey = Base64.getDecoder().decode(bytes);
KeyFactory factory = KeyFactory.getInstance("EC");
privateKey = factory.generatePrivate(new PKCS8EncodedKeySpec(pkcs8EncodedKey));
} catch (Exception e) { }
return privateKey;
}
Next, creating the JWTS string:
private String getJwtsString(PrivateKey privateKey) {
long t1 = System.currentTimeMillis();
return Jwts.builder()
.setHeaderParam ("alg", "ES256")
.setHeaderParam ("kid", "CXXXXXXXXX")
.setHeaderParam ("id", "QXXXXXXXXX.com.mydomain.myproject")
.claim ("iss", "Q5DC438ZG4")
.claim ("iat", t1)
.claim ("exp", t1 + 60000)
.claim ("sub", "com.mydomain.myproject") // obviously, replaced with my project info
.signWith (privateKey, SignatureAlgorithm.ES256)
.compact ();
}
And finally, creating the connection:
private HttpURLConnection getConnection(URL url, String jws) {
HttpURLConnection conn = (HttpURLConnection) Objects.requireNonNull(url).openConnection();
conn.setRequestMethod ("GET")
conn.setRequestProperty ("Authorization", "Bearer "+ jws);
conn.setRequestProperty ("Content-Type", "application/x-www-form-urlencoded");
conn.setRequestProperty ("Content-Language", "en-US");
conn.setUseCaches (false);
conn.setDoInput (true);
conn.setDoOutput (true);
conn.setConnectTimeout (30000); //set timeout to 30 seconds
return conn;
}
Obviously, this is the first time I've tried creating an authenticated http call, so I wouldn't be at all surprised if this is wrong.
Can anybody supply some sample code that I could follow?
Thanks in advance...

Categories

Resources