Error in starting asynctask in android - java

I am starting two asynchronous task in two diffrent services first one works correctly and opens a socket but second one is not starting here is the code my application is based on client socket programing in wifip2p.
public class RecieveAudioService extends Service {
String tag = "Recieve Audio Service";
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(getApplicationContext(), "Recieve audio :requesting to client", Toast.LENGTH_LONG).show();
String[] param = {"h", "j", "k"};
new request().execute();
Log.v("Recieve Audio", "Inside Recieve audio service");
return super.onStartCommand(intent, flags, startId);
}
//===================== This class is sending request to server for connection when invocked
public class request extends AsyncTask<String, String, String> {
protected String doInBackground(String... arg0) {
Log.v("second asyn", "this is second asynchronous task");
try {
Toast.makeText(getApplicationContext(), "Request to connect sent to server",
Toast.LENGTH_LONG).show();
String toConnectDeviceIP = "192.168.49.1";
Integer toConnectDevicePort = 8988;
Socket connect = new Socket();
connect.bind(null);
connect.connect((new InetSocketAddress(toConnectDeviceIP, toConnectDevicePort)),
5000);
Log.v(tag, "sent the connection request to clint");
connect.close();
} catch (Exception e) {
// TODO Auto-generated catch block
Log.v(tag, "" + e.toString());
Toast.makeText(getApplicationContext(), "i found exception in connection"
+e.toString(), Toast.LENGTH_LONG).show();
}
return "success";
}
}
//====================================================================
}

It seems that you launch your app on Android 4.x/3.x. Before Android 3.0 AsyncTasks ran concurrently but later versions(>3.x) of system executes tasks one after another. So you have two choices:
a) Use Threads instead of AsyncTasks
b) Use executeOnExecutor of AsyncTask to execute tasks concurrently:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} else {
task.execute();
}

Related

In android studio, how to prevent errors with buffered reader reading from a url, when the phone has no internet

In my app, when I press a button, a buffered reader should read a line of a text from a text file online.
As a test, if the text is read correctly, I want a toast to appear saying "success". If the read fails, such as because the phone has no connection to the internet, I want a toast to appear saying "failed".
However, if I turn on airplane mode, and then press the button, it simply seems to "hang" forever, and the "failed" toast never appears -- or it just crashes the app entirely.
This is the code I am using:
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
new NotePadFileFromServer().execute();
}
});
public class NotePadFileFromServer extends AsyncTask<Void, Void, Void>{
#Override
protected Void doInBackground(Void... params) {
try {
url = new URL(TextFileURL);
bufferReader = new BufferedReader(new InputStreamReader(url.openStream()));
TextHolder = bufferReader.readLine();
bufferReader.close();
} catch (Exception e) {
Toast.makeText(MainActivity.this, "Fail!", Toast.LENGTH_SHORT).show();
}
return null;
}
#Override
protected void onPostExecute(Void finalTextHolder) {
Toast.makeText(MainActivity.this, "Success!", Toast.LENGTH_SHORT).show();
super.onPostExecute(finalTextHolder);
}
}
I tried adding in a pre-check using ConnectivityManager to test if there is an internet connection as per this code: https://stackoverflow.com/a/58146646/4250107, but that only works if the phone user has specifically turned off the internet, and the crashes occur again if the wifi function is turned on, but there is no internet. I then tried checking the internet connection, as per this code: https://stackoverflow.com/a/58146896/4250107, but this also crashes the app, as apparently (?) attempting to ping a server does not work on Samsung phones.
EDIT: Final fixed code.
public class NotePadFileFromServer extends AsyncTask<Void, Void, String>{
#Override
protected String doInBackground(Void... params) {
try {
URLConnection url = new URL(TextFileURL).openConnection());
url.setConnectTimeout(1000);
url.setReadTimeout(1000);
bufferReader = new BufferedReader(new InputStreamReader(url.getInputStream()));
TextHolder = bufferReader.readLine();
bufferReader.close();
return "Success!";
} catch (Exception e) {
return "Fail!";
}
}
#Override
protected void onPostExecute(String success) {
Toast.makeText(MainActivity.this, success, Toast.LENGTH_SHORT).show();
super.onPostExecute(success);
}
}
The app is crashing because you are trying to perform UI related task in the Background Thread when there is an exception. So, the following is responsible for the crash,
catch (Exception e) {
Toast.makeText(MainActivity.this, "Fail!", Toast.LENGTH_SHORT).show();
}
So, you can avoid the crash by refactoring you code in the following way,
public class NotePadFileFromServer extends AsyncTask<Void, Void, String>{
#Override
protected String doInBackground(Void... params) {
try {
url = new URL(TextFileURL);
bufferReader = new BufferedReader(new InputStreamReader(url.openStream()));
TextHolder = bufferReader.readLine();
bufferReader.close();
return "Success!";
} catch (Exception e) {
return "Fail!";
}
}
#Override
protected void onPostExecute(String finalTextHolder) {
Toast.makeText(MainActivity.this, finalTextHolder, Toast.LENGTH_SHORT).show();
super.onPostExecute(finalTextHolder);
}
}
And in case of timeout issue which you described here as hang, I would recommend you to use openConnection() (which returns a UrlConnection) instead of openStream(). So that you can set shorter connection and read timeout.
Yes, as you say ConnectivityManager will not help you because if you have wifi but no internet it will crash.
However, it is possible to check internet connection. I couldn't do it with ping (same as you), but i could when i try to open a socket to some of the opened ports (80 or 443). Here is a code using rxjava but you can adapt it to what you are using.
fun isOnline(context: Context?): Single<Boolean> {
return Single.fromCallable {
try {
// Connect to Google DNS to check for connection
val timeoutMs = 2500
val socket = Socket()
val address = InetAddress.getByName("www.google.com")
val socketAddress = InetSocketAddress(address, 443)
socket.connect(socketAddress, timeoutMs)
socket.close()
true
} catch (e: Exception) {
false
}
}.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
}
In my case i opened the socket with my backend so also i can check if it is working. I put www.google.com in case you don't have a backend.
The way to use it is:
isOnline(context).subscribe { hasInternet ->
//Conditional check
}

Java android GcmTaskService

I want to do a service which works all rhe time and period time. I want to do a service whic works that a phone is locked and sleep and a task never be a killed,I did this :
public static void scheduleRepeat(Context context) {
try {
Preferences prefs;
prefs = new Preferences(context);
long maxDiff = prefs.getInteger(Preferences.Key.CFG_USER_POSITION_FREQUENCY);
PeriodicTask periodic = new PeriodicTask.Builder()
.setService(MyTaskService.class)
.setPeriod(maxDiff)
.setFlex(10)
.setTag(GCM_REPEAT_TAG)
.setPersisted(true)
.setUpdateCurrent(true)
.setRequiredNetwork(Task.NETWORK_STATE_ANY)
.setRequiresCharging(false)
.build();
GcmNetworkManager.getInstance(context).schedule(periodic);
Log.v(TAG, "repeating task scheduled");
} catch (Exception e) {
Log.e(TAG, "scheduling failed");
e.printStackTrace();
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
GcmNetworkManager
.getInstance(getApplicationContext())
.cancelTask(GCM_REPEAT_TAG, MyTaskService.class);
}
#Override
public void onInitializeTasks() {
super.onInitializeTasks();
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public int onRunTask(TaskParams taskParams) {
return GcmNetworkManager.RESULT_SUCCESS;
}
but somewhere I saw that a Gcm is depreceted , is this service will be work coretly all the time ?
It has been deprecated and now you can use Firebase Job Dispatcher
This library uses the scheduling engine inside Google Play
services(formerly the GCM Network Manager component) to provide a
backwards compatible (back to Gingerbread) JobScheduler-like API.
I'm not shure, what you are trying to do, but at the first sight it seems to me that you might use Timer class and TimerTask. However you also may try using Handler.postDelayed() (this will execute on the main thread).
In general, many of the Google APIs are replaced with Firebase, visit their official site for more info.

Alarm ringing stops when cleared from ram

I am making an alarm clock which asks user to do a particular work in order to close the alarm when it rings. It is working fine but the problem is that if the user closes the alarm app from the recent activities while the alarm is ringing, the alarm stops ringing. I want that even if the user clears the app while its ringing, it should not stop ringing. It should only stop once the task given is completed. How can I implement this?
Edit #1: Activity that is called when alarm rings
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.v(LOG_TAG, "in AlarmAlert");
unlockScreen();
setContentView(R.layout.activity_alarm_alert);
Bundle bundle = this.getIntent().getExtras();
alarm = (Alarm) bundle.getSerializable("alarm");
alarmDatabase = new AlarmDatabase(this);
//Uri uri = alarm.getRingtonePath();
question = (TextView)findViewById(R.id.question);
answer = (TextView) findViewById(R.id.answer);
oldColors = answer.getTextColors();
diff = alarm.getDifficulty().toString();
questionString = GenerateMathsQuestion.generateQuestion(diff);
question.setText(questionString);
actualAnswer = EvaluateString.evaluate(questionString);
AudioManager am = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
int result = am.requestAudioFocus(focusChangeListener,
AudioManager.STREAM_MUSIC,
AudioManager.AUDIOFOCUS_GAIN);
if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
mediaPlayer = new MediaPlayer();
mediaPlayer.setVolume(1.0f, 1.0f);
mediaPlayer.setLooping(true);
mediaPlayer.setAudioStreamType(AudioManager.STREAM_ALARM);
try {
mediaPlayer.setDataSource(this, Uri.parse(alarm.getRingtonePath()));
mediaPlayer.prepare();
} catch (IOException e) {
e.printStackTrace();
}
mediaPlayer.start();
}
if(alarm.getIsVibrate()) {
vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
long[] pattern = {1000, 200, 200, 200};
vibrator.vibrate(pattern, 0);
}
}
public void closeAlarm(){
Log.v(LOG_TAG, "will now stop");
mediaPlayer.stop();
if(vibrator!=null)
vibrator.cancel();
Log.v(LOG_TAG, "will now release");
mediaPlayer.release();
Log.v(LOG_TAG, "id of ringing alarm: " + alarm.getAlarmId());
alarm.setIsActive(false);
alarmDatabase.updateData(alarm);
cursor = alarmDatabase.sortQuery();
while(cursor.moveToNext()){
int id = cursor.getInt(cursor.getColumnIndex(AlarmDatabase.COLUMN_UID));
currentAlarm = alarmDatabase.getAlarm(id);
Log.v(LOG_TAG, "id of next alarm " + id);
if(currentAlarm != null) {
if (currentAlarm.getIsActive() == true) {
currentAlarm.scheduleAlarm(this, true);
break;
}
}
}
this.finish();
}
You should use Services. Take a look at it, that is what you want it. Generally you can make it to run an operation, and a service wont return any result. But it runs indefinitely even when you kill the app from task manager or free RAM.
I suggest this tutorial for reading about services.
UPDATE
Implement your activity with the service in the following way so it can talk with the layout and stops the alarm when required.
public class HelloService extends Service {
private Looper mServiceLooper;
private ServiceHandler mServiceHandler;
// Handler that receives messages from the thread
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
#Override
public void handleMessage(Message msg) {
// Normally we would do some work here, like download a file.
// For our sample, we just sleep for 5 seconds.
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// Restore interrupt status.
Thread.currentThread().interrupt();
}
// Stop the service using the startId, so that we don't stop
// the service in the middle of handling another job
stopSelf(msg.arg1);
}
}
#Override
public void onCreate() {
// Start up the thread running the service. Note that we create a
// separate thread because the service normally runs in the process's
// main thread, which we don't want to block. We also make it
// background priority so CPU-intensive work will not disrupt our UI.
HandlerThread thread = new HandlerThread("ServiceStartArguments",
Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
// Get the HandlerThread's Looper and use it for our Handler
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
// For each start request, send a message to start a job and deliver the
// start ID so we know which request we're stopping when we finish the job
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
mServiceHandler.sendMessage(msg);
// If we get killed, after returning from here, restart
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
// We don't provide binding, so return null
return null;
}
#Override
public void onDestroy() {
Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();
}
}

Destroying activity causes service to lose data

Whenever my application is minimized I start a service that is sending pull requests to my HTTP server to check for notifications, when the application is brought back up the service gets terminated (along with the scheduled runnable). All works well until I decided to kill the application (slide it off the screen from the running apps list). Then for some reason the properties of the service get reset (even the static ones) and onStartCommand gets called again with it's first parameter Intent as null which is weird for me.
Here are some parts of the code
public class DnActivity extends Activity {
protected String cookieString = "";
protected String userAgent = "";
protected WebView webview;
#Override
protected void onStop() {
super.onStop();
try {
Intent mServiceIntent = new Intent(this, PullService.class);
mServiceIntent.putExtra("cookieString", cookieString);
mServiceIntent.putExtra("userAgent", userAgent);
startService(mServiceIntent);
} catch (Exception e) {
Log.d("DNev", e.getMessage());
}
}
#Override
protected void onStart() {
super.onStart();
Intent mServiceIntent = new Intent(this, PullService.class);
stopService(mServiceIntent);
}
#Override
public void onCreate(Bundle savedInstanceState) {
...
webview.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
try {
cookieString = getCookieFromAppCookieManager(url);
} catch (Throwable e) {
Log.e("DNev", e.getMessage());
}
}
});
}
}
And the service
public class PullService extends Service {
protected static String cookieString;
protected static String userAgent = "Mobile APP for Android";
protected Service PullService = this;
protected ScheduledFuture interval;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null) {
if (intent.hasExtra("cookieString")) {
cookieString = intent.getStringExtra("cookieString");
}
if (intent.hasExtra("userAgent")) {
userAgent = intent.getStringExtra("userAgent");
}
}
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onDestroy() {
super.onDestroy();
interval.cancel(true);
}
#Override
public void onCreate() {
super.onCreate();
Log.d("DNev", String.valueOf(cookieString));
Log.d("DNev", String.valueOf(userAgent));
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
interval = scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
public void run() {
Log.d("DNev", "1");
Log.d("DNev", String.valueOf(cookieString));
Log.d("DNev", String.valueOf(userAgent));
...
As I said, everything works fine until I destroy the activity, then the interval keeps running but cookieString and userAgent become their default values.
I need to be able to persist these values when the activity gets destroyed, how can I do that?
I'm not experienced in neither android nor java development, and I want to apologize if my code made anyone cry blood.
Here is the manifest entry for the service, it resides in <application
<service android:name=".PullService" android:exported="false"/>
All works well until I decided to kill the application (slide it off the screen from the running apps list).
When you kill the app (which I assume Force Stop from i.e. Settings -> Apps) then WHOLE app gets terminated, including its services. Everything stored in variables will go away with the process. If you want it to survive, you need to store it in persistent storage (i.e. in database or shared preferences).
Also I'd save this data once I received it, in onStartCommand() because if onDestroy() will not be called (which is not unlikely for abruptly killed process) then your data would be lost.
I start a service that is sending pull requests to my HTTP server to check for notifications
Don't. Use GCM to actually push notification to the app. Do not pull.
in the DnActivity.onDestroy() method, save the info somewhere, you could have the "shutting down" of the activity control the mServiceIntent and do alterations to it (like shutting it down as well)
For instance:
DnActivity.onDestroy(){
super.onDestroy();
stopService(mServiceIntent);
Intent mServiceIntent = new Intent(this, PullService.class);
mServiceIntent.putExtra("some_value", the_value);
mServiceIntent.putExtra("some_other_value", the_other_value);
startService(mServiceIntent);
}

How to create a thread of service or just a service in android which runs until the service is stopped explicitly?

I want a service which looks if Headphones are connected or not. If they are connected then do something & do something else while they are disconnected. I want the service or thread to run until it is stopped explicitly by pressing the stop button on it's activity.
Here is my onStartCommand() code & the code I want to run is in a function theRun().
public class MyService extends Service {
private final static String Headset_Flag = "android.intent.action.ACTION_HEADSET_PLUG";
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "Service onStartCommand " + startId);
theRun tR= new theRun();
tR.start();
return super.onStartCommand(intent, flags, startId);
}
private class theRun extends Thread
{
Runnable r = new Runnable() {
public void run() {
// Log.i(TAG, "Service In Run " + currentId);
try {
AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
if (AudioManager.ACTION_HEADSET_PLUG.equals(Headset_Flag)) {
switch (am.getRingerMode()) {
case AudioManager.RINGER_MODE_SILENT:
am.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
Log.i(TAG, "Silent mode" + am.getRingerMode());
break;
case AudioManager.RINGER_MODE_VIBRATE:
am.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
Log.i(TAG, "Vibrate mode");
break;
case AudioManager.RINGER_MODE_NORMAL:
Log.i(TAG, "Normal mode");
break;
}
}
}
catch(Exception e){
String msg = e.getMessage();
msg.toString();
}
}
};
}
The service will only execute once on onStartCommand() if I insert my code there. But how to run a service or thread until it is explicitly stopped by Activity? Please guide me.
return START_STICKY in onStartCommand method do this
try this
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("LocalService", "Received start id " + startId + ": " + intent);
theRun tR= new theRun();
tR.start();
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return START_STICKY;
}
refer this

Categories