Actully i working in a app, but i have problems to connect my Web services, i have this code:
try{
HttpServices post = new HttpServices ("http://sotem.com.mx/WebServices/controller.php");
post.add("funcion", "test");
System.out.println("Si lo mande///////////////////Jhgfdsa");
String respuesta = post.getRespueta();
System.out.println(respuesta);
Toast.makeText(getApplicationContext(),"Cool: "+respuesta, Toast.LENGTH_SHORT).show();
}catch (Exception ex) {
Toast.makeText(getApplicationContext(),"error: "+ex.toString(), Toast.LENGTH_SHORT).show();
}
but i can make connection, i try to make other thinks, but i can make the thread, i'am new in this part, the app launcher this error:
android os network on main thread exception
It is not okay to do the Network Operation on main thread.. You can use AsyncTask to perform such operations and handle the result in onPostExecute method.
class YourNetworkingTasks extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... voids) {
try{
HttpServices post = new HttpServices ("http://sotem.com.mx/WebServices/controller.php");
post.add("funcion", "test");
String respuesta = post.getRespueta();
Log.d("Output", respuesta);
// DON'T DO ANY UI CHANGES LIKE TOAST FROM BACKGROUND THREAD.. Toast.makeText(getApplicationContext(),"Cool: "+respuesta, Toast.LENGTH_SHORT).show();
}catch (Exception ex) {
// DON'T DO ANY UI CHANGES LIKE TOAST FROM BACKGROUND THREAD.. Toast.makeText(getApplicationContext(),"error: "+ex.toString(), Toast.LENGTH_SHORT).show();
}
return null;
}
protected void onPostExecute(RSSFeed feed) {
// TODO: YOU CAN MAKE U.I. Changes Like Display text in TextView, TOAST HERE.
// TODO: do something with the result
}
}
And write new YourNetworkingTasks().execute(); to run that code in background thread.
Please also not that since you are using http and not https you may get Network Security Exception and may not get any output due to recent security change in android.
Related
am using pushy for push notifications but am not able to store the device token in the database.
private class RegisterForPushNotificationsAsync extends AsyncTask<Void, Void, Exception> {
protected Exception doInBackground(Void... params) {
try {
// Assign a unique token to this device
String deviceToken = Pushy.register(getApplicationContext());
// Log it for debugging purposes
Log.d("MyApp", "Pushy device token: " + deviceToken);
// Send the token to your backend server via an HTTP GET request
new URL("https://key}/register/device?token=" + deviceToken).openConnection();
} catch (Exception exc) {
// Return exc to onPostExecute
return exc;
}
// Success
return null;
}
#Override
protected void onPostExecute(Exception exc) {
// Failed?
if (exc != null) {
// Show error as toast message
Toast.makeText(getApplicationContext(), exc.toString(), Toast.LENGTH_LONG).show();
return;
}
// Succeeded, optionally do something to alert the user
}
}
I am using retrofit for the http requests and am not using any kind of backend system
What you're doing is well enough to get you a Device Token from Pushy service.
If you want to capture the returned device token and make it accessible to the AsyncTask class and the enclosing class in general (as you stated in the comments), then you can declare a global/instance String variable, say pushy_device_token, in the enclosing class.
Then in doInBackground() method of the AsyncTask, go ahead and assign the global variable as follows:
pushy_device_token = Pushy.register(getApplicationContext());
Complete code:
public class EnclosingClass {
String pushy_device_token;
// Additional class code
private class RegisterForPushNotificationsAsync extends AsyncTask<Void, Void, Exception> {
#Override
protected Exception doInBackground(Void... params) {
try {
// Assign a unique token to this device
pushy_device_token = Pushy.register(getApplicationContext());
// Log it for debugging purposes
Log.d("MyApp", "Pushy device token: " + deviceToken);
// Send the token to your backend server via an HTTP GET request
new URL("https://key}/register/device?token=" + deviceToken).openConnection();
} catch (Exception exc) {
// Return exc to onPostExecute
return exc;
}
// Success
return null;
}
#Override
protected void onPostExecute(Exception exc) {
// Failed?
if (exc != null) {
// Show error as toast message
Toast.makeText(getApplicationContext(), exc.toString(), Toast.LENGTH_LONG).show();
return;
}
// Succeeded, optionally do something to alert the user
}
}
}
Best practice recommendation:
It's best to have the result of processing in doInBackground(), returned in the onPostExecute() method, especially if you're going to do some UI work. So from onPostExecute(), you can do anything you want with the result, e.g. display to the user, report an error, etc.
To do this, you'll have to modify your doInBackground() method to return something as generic as Object. And so onPostExecute() will take in an Object as a parameter variable.
You'll modify by:
private class RegisterForPushNotificationsAsync extends AsyncTask<Void, Void, Object> { . . .
From this, you can check if the Object taken in by onPostExecute() is of type Exception, in which case, you'll display an error notification, or check if it's of type String, in which case you'll have the device token which you can then proceed to save in your DB (Firebase, SQLite, etc.).
After user press the button it fires up weather function. But it doesn't log any JSON data or any error. Should it be done in background? I've used gson libary to download JSON.
Edit: I edited my code but user must enter a city which is pasted to the link. So is it possible to run in background process when the button is tapped?
public class MainActivity extends AppCompatActivity {
public class Download extends AsyncTask<String,Void,String>{
#Override
protected String doInBackground(String... strings) {
try {
URL url = new URL("api.openweathermap.org/data/2.5/weather?q="+strings[0]+"&APPID=****");
URLConnection request = url.openConnection();
request.connect();
JsonParser jp=new JsonParser();
JsonElement root = jp.parse(new InputStreamReader((InputStream) request.getContent()));
JsonObject rootobj = root.getAsJsonObject();
String weather = rootobj.getAsString();
Log.i("weather:",weather);
}
catch (Exception e){
e.printStackTrace();;
}
return null;
}
}
public void weather(View view){
TextView textView=(TextView) findViewById(R.id.editText);
String city=textView.getText().toString();
Download download=new Download();
download.execute(city);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
All io operation should be executed in background , because all this operations are time consuming . which means you will block your main thread if you donot execute these codes in background and may cause Android Not Respond exception. IO operation in ui thread generally lead to bad user experience . so i strongly advice you do this in background.
You should definitely load your data in the background. The Main Thread i.e. the UI Thread is the thread that renders the UI components so no heavy operation should be done there. If heavy operation is done in the UI Thread, it will freeze the UI.
You should look at the AsyncTask class to perform your loading in the background.
Here is some good tutorials:
https://alvinalexander.com/android/asynctask-examples-parameters-callbacks-executing-canceling
https://www.journaldev.com/9708/android-asynctask-example-tutorial
https://www.tutorialspoint.com/android-asynctask-example-and-explanation
I'm trying to play music in my app and while the media player is loading I want to allow the user to keep on using the app, but the app gets stuck for few seconds every time I start loading the media player, and when the media player is finished loading, only then the app returns to normal and starts working again, sometimes it's not just freezing, it also shows popup menu from the OS that prompts the user to quit the app.
I couldn't find any solution in Google or YouTube, anyone knows what's wrong with my code?
final Handler handler = new Handler();
Runnable runnable = new Runnable() {
#Override
public void run() {
try {
String STREAM_URL = #####; // here i put the URL of the song
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
mediaPlayer.setDataSource(STREAM_URL);
mediaPlayer.prepare();
} catch (IOException e) {
e.printStackTrace();
}
} catch (NullPointerException e) {
Log.d(TAG, "run: NullPointerException = " + e.getMessage());
FirebaseCrash.log("Tag = " + TAG + "run: NullPointerException = " + e.getMessage());
}
}
}
};
handler.post(runnable);
Even though you are creating a Handler, the creation of the MediaPlayer still happens on the main UI thread. You should call prepareAsync or use an AsyncTask or some other means to avoid calling prepare on the main thread.
From the documentation for Handler:
When you create a new Handler, it is bound to the thread / message
queue of the thread that is creating it
If you are streaming music from the network, preparing the media for playback is especially going to take a while. One option may be to call prepareAsync instead of calling prepare. In that case, you should set the OnPreparedListener, and in that callback call start.
Here is my scenario:
I have a login form which has a member key field, once the user enters this key I communicate with server to authenticate. There are two more fields namely key and type I add up these in a JSON object and send that across to the server.
Now due to a request I also have to send across the GCM token along with this login information in one call. On submit button click I start the following async task
My do in Background method looks like this:
#Override
protected String doInBackground(Void... params) {
if (checkPlayServices()) {
Intent intent = new Intent(LoginActivity.this, GcmRegistrationIntentService.class);
startService(intent);
}
/***// I want to wait here and fetch the GCM token value//***/
try {
JSONObject jObj;
jObj = new JSONObject();
jObj.put("aes_key", UtilityClass.getencryptkey());
jObj.put("client_id", key);
jObj.put("type", "Android");
// jObj.put("device_token", ); <--- Need to wait for this value
System.out.println(jObj);
String authenticateResp = authenticate(jObj);
System.out.println("Response is: " + authenticateResp);
JSONObject jResp = new JSONObject(authenticateResp);
String success = jResp.getString("success");
if (success.equalsIgnoreCase("True")) {
sessionManager.createLoginSession(key);
return "granted";
} else {
return jResp.getString("msg");
}
} catch (Exception e) {
e.printStackTrace();
return "Something went wrong, we are working to fix this, please try again after sometime";
}
}
public String authenticate(JSONObject jObject) {
return UniversalNetworkConnection.postJSONObject(getResources().getString(R.string.authentication_url), jObject);
}
So first I start with starting the intent service - which has a registered local broadcast determining that the service has finished, I get the handler to this in onCreate of the particular activity.
mRegistrationBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("Login Act", "GCM done");
}
};
I want to wait in the middle of the doInBackground till I receive the local broadcast from my intent service. So that I can add up the value to my JSON object. It is necessary for me to do this in an Async task because I have to update the UI with relevant messages of authentication success or false. Otherwise I could have migrated all my logic to the intent service - which would be a lot couples and which is not a good design.
Move all your logic to onReceive of that broadcast receiver. Declare that receiver as an inner class of your activity and then you can manipulate UI within it.
So the steps after user click are:
Start that Intent Service.
Send an broad cast in that service when you are done.
Send your JSON object in onReceive method.
Note: if you want to send that JSON in background thread, you could simply define an thread inside onReceive and do the work.
You cannot do another asynchronous task inside doInBackground. This answer might help you: https://stackoverflow.com/a/15657500/4676276
What you can do is, start the smaller async task first then wait for it to finish then start the main async on the onPostExecute of the first task.
Try this...
Check for the key and wait
#Override
protected String doInBackground(Void... params) {
if (checkPlayServices()) {
Intent intent = new Intent(LoginActivity.this, GcmRegistrationIntentService.class);
startService(intent);
}
/***// I want to wait here and fetch the GCM token value//***/
while(key==null||key.length()==0){
try {
Thread.sleep(1000);
}catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
JSONObject jObj;
jObj = new JSONObject();
jObj.put("aes_key", UtilityClass.getencryptkey());
jObj.put("client_id", key);
jObj.put("type", "Android");
/**********************/
}
I did a mistake that apparently can be solved only by uninstalling and then installing my app again.
I delivered a message to the users, but no-one seems to uninstall it.
AFAIK, if I change the certificate file, the play store won't let me upload the application, and
obviously I don't want to upload a new app.
Is there a way to force uninstall in order to update?
Thanks!
There's no killswitch to remotely force uninstalls (that'd be a security nightmare). What you can do is publish a fixed version on Google Play, and wait for users to upgrade.
I don't know if this can help you but i had the same problem. The solution for me is that i check the app version every time the user opens it and compare it with a version code stored on apache server (in a checkversion.php file).
If versions doesn't match, i show a not cancelable dialog that ask the user to go to market and download the update.
Here is an example (keep in mind that i use Volley library to handle connections):
public class UpdateManager {
private Activity ac;
private HashMap<String,String> params;
public UpdateManager(Activity ac) {
this.ac = ac;
}
public void checkForUpdates() {
Log.d("UpdateManager","checkForUpdates() - Started...");
params = new HashMap<String,String>();
params.put("request","checkforupdates");
try {
params.put("versioncode", String.valueOf(ac.getPackageManager().getPackageInfo(ac.getPackageName(), 0).versionCode));
} catch (NameNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (Helper.isInternetAvailable(ac)) { //this is a class i made to check internet connection availability
checkAppVersion();
} else { Log.d("UpdateManager","CheckForUpdates(): Impossible to update version due to lack of connection"); }
}
private void checkAppVersion() {
Log.d("UpdateManager","checkAppVersion() - Request started...");
JsonObjectRequest req = new JsonObjectRequest("http://yourserver/checkappversion.php", new JSONObject(params),
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
if (response != null && response.has("result")) {
try {
Log.d("UpdateManager","checkAppVersion() - Request finished - Response: "+response.getString("result"));
if (response.getString("result").matches("updaterequested")) { //Update requested. Show the relative dialog
Log.d("UpdateManager","Update requested");
askUserForUpdate();
}
else if (response.getString("result").matches("current")) { //Same version. Do nothing
Log.d("UpdateManager","Version is up to date");
}
else if (response.getString("result").matches("error")) { //You can return an error message if error occurred on server
Log.d("UpdateManager","checkappversion Error - "+response.getString("error"));
}
VolleyLog.v("Response:%n %s", response.toString(4));
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("UpdateManager","Volley Error - "+error.getMessage());
}
});
req.setRetryPolicy(new DefaultRetryPolicy(60000,0,DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
ConnectionController.getInstance().addToRequestQueue(req);
}
public void askUserForUpdate() {
final Dialog diag = new Dialog(ac);
diag.requestWindowFeature(Window.FEATURE_NO_TITLE);
diag.setContentView(R.layout.updatemanager_requestupdate_dialog);
diag.setCancelable(false);
diag.getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));
TextView t = (TextView)diag.findViewById(R.id.requestupdate_dialog_main_text);
ImageView im_ok = (ImageView)diag.findViewById(R.id.requestupdate_dialog_ok);
ImageView im_canc = (ImageView)diag.findViewById(R.id.requestupdate_dialog_canc);
t.setText(ac.getResources().getString(R.string.update_manager_askuserforupdate));
im_canc.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
diag.dismiss();
ac.finish();
}
});
im_ok.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("market://details?id="+ac.getPackageName()));
diag.dismiss();
ac.startActivity(intent);
ac.finish();
}
});
diag.show();
}
}
You can then use it when your main activity (or maybe login activity) starts like this:
UpdateManager updateManager = new UpdateManager(MainActivity.this); //i assume MainActicity as the calling activity
updateManager.checkForUpdates();
Obviously this has to be implemented into the application code so, the first time, you have to rely only on the user to manually upgrade it. But this can help if you have the same problem in the future.
This is an extract from my personal code so you have to rearrange it to your needings. Hope this helps someone.
Users should be able to go to Settings > Applications > Manage Applications and select the application to be removed. I've never seen a case where the application can't be removed this way, except in the case of built-in applications which require a rooted device to remove.