Services, Threading, AsyncTask in Android
Services, Threading, AsyncTask in Android
Services do not have UI because we don’t want to keep the user busy by showing download progress
continuously that’s why services run without UI
MainActivity.java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
start_btn=findViewById(R.id.start_bt);
stop_btn=findViewById(R.id.stop_bt);
service=new Intent(this,MyService.class);
Toast.makeText(this,"Main Thread
is"+Thread.currentThread().getId(),Toast.LENGTH_LONG).show();
start_btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startService(service);
}
});
}
}
MyService.java
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("Harry","Service thread is"+Thread.currentThread().getId());
// stopSelf(); without it we can not stop a service
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
Log.i("Harry","Service end "+Thread.currentThread().getId());
super.onDestroy();
}
@Override
public IBinder onBind(Intent intent) { // this will come into picture when we
will discuss Bound services.
return null;
}
}
Manifest File
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".MyService"/>
</application>
</manifest>
In the above example Service is started by an Activity. Service is running in background but running on
same UI thread. It is not using separate thread here.
Behavior of Service
We have seen onStartCommand method returns a integer value. To Understand this, let us see what
happens with app when resource crunch situation occur in android.
For example I have opened many apps in my phone. So it may arise the situation of resource crunch and
then android may need to decide to kill my app that is not running in the foreground. In this case my app
is running a service in the background then android will not try to kill that particular app because service
always get a higher priority.but that doesnot mean you keep a service u will not get killed.if resource
crunch is seviour then android may kill that app with service too.
When resource crunch happened,service app killed by os . in this case what should happen to killed
service? That is determined by the integer value returned by the onstartCommand method.
Bound Services
In Android, An app is treated as a separate process. An app can have these four components as
discussed previous Activity, Service, Broadcast Receiver and Content Provider.
An Activity may bind to a service to get some status update. It need not to be every time the activity
needed , any service can be bind with another service to get some status update. In either to these
case,Activity is trying to bind to a service and the service which is providing the information to the
activity or service is known as Bound Service.
We have seen in above diagram, the components which are interested in establishing the
connection to the service are part of the same app and that is why we can call it as Local Binding.
Lets take an example,In Background Service is continuously generating Random Numbers. Firstly Activity
will bind to the service. If binding is successful, it will ask for random number. In response service will
return a random number to Activity.
To Achieve this Service need to implement onBind method which will return IBinder
object.
The Activity will use the ServiceConnection Api to connect with service.
These four methods basically make sure that you are able to do long task in a way you
don’t disturb the main thread.
(Params) You use doinBackground() to perform long task on the separate
thread.Android automatically run anything or everything that you code in
doinBackground() on a separate thread.
onPreExecute() this part gets executed on the main thread .you typically do initialization
bfore you want to do anything in the background.
(Progress…) onPostExecute() once again execute on the UI thread. Whatever you
have done ,you want to update on your Ui.and the best way to do is on UI thread.
One more scenario where in intermediate you want to update the Ui in between
execution of doinBackground() or we can say to show the progress even you are doing
something in background , we use onProgressUpdate() (Result)
Xml file
<ScrollView
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="0dp">
<TextView
android:textSize="20sp"
android:text="CLICK"
android:id="@+id/tv_result"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</ScrollView>
<ProgressBar
android:id="@+id/progress"
android:layout_gravity="center"
style="@style/Widget.AppCompat.ProgressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:text="Show"
android:layout_weight="0.2"
android:id="@+id/bt_show"
android:layout_width="match_parent"
android:layout_height="0dp" />
</LinearLayout>
Java file
package com.example.asynctask_thread_example;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Looper;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = findViewById(R.id.tv_result);
Button b = findViewById(R.id.bt_show);
bar = findViewById(R.id.progress);
bar.setVisibility(View.INVISIBLE);
b.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
bar.setVisibility(View.VISIBLE);
// try {
// Thread.sleep(2000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// Thread tt=new Thread(runnable);
// tt.start();
new Asyn().execute(url);
}
});
@Override
protected String doInBackground(String... strings) {
try {
URL web = new URL(strings[0]);
HttpURLConnection con = (HttpURLConnection) web.openConnection();
InputStream in = con.getInputStream();
InputStreamReader isw = new InputStreamReader(in);
int data = isw.read();
while (data != -1) {
current += (char) data;
data = isw.read();
}
// tv.append(current.toString());
Log.v(TAG, current);
} catch (MalformedURLException e1) {
e1.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return current;
}
}
}
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}