onBackPressed() Internet no longer detected - android

I have an application that detects if internet is available or not.
I have changed the behaviour of the back button to avoid closing the application when pressed. The issue I'm facing is that when I have 4G or WIFI running and I run the app, it detects that internet is available, however, when I press the back button, the app is put on the background and internet is no longer detected by it.
I noticed that if I remove the permissions in the manifest file, the application works fine, it detects internet both when it is running and when put on background, but I need those permissions for making http post requests later.
Any help on this please?
Thanks.
MainActivity.java
public class MainActivity extends AppCompatActivity {
Timer timer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
init();
}
#Override
public void onBackPressed() {
this.moveTaskToBack(true);
}
private void init() {
timer = new Timer();
Tasker task = new Tasker(MainActivity.this, timer);
task.execute();
}
}
Tasker .java
public class Tasker extends AsyncTask<Void,Void,String> {
final Handler handler = new Handler();
static Timer timer;
Context context;
Toast toast;
private TimerTask doAsynchronousTask;
public Tasker(MainActivity context, Timer timer) {
this.timer = timer;
this.context = context;
}
#Override
protected void onPreExecute() {
}
#Override
protected String doInBackground(Void... voids) {
doTimerTask();
return null;
}
#Override
protected void onPostExecute(String response) {
}
private void showToast(String message){
toast = Toast.makeText(context, message, Toast.LENGTH_LONG);
toast.setGravity(Gravity.CENTER, 0, 0);
if(!((Activity) context).isFinishing()){
toast.show();
}
}
private void doTimerTask() {
doAsynchronousTask = new TimerTask() {
#Override
public void run() {
handler.post(new Runnable() {
#SuppressWarnings("unchecked")
public void run() {
if(haveNetworkConnection()){
showToast("Online");
}else{
showToast("Offline");
}
}
});
}
};
timer.schedule(doAsynchronousTask, 0, 10000);
}
private boolean haveNetworkConnection() {
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
boolean isConnected = activeNetwork != null && activeNetwork.isConnectedOrConnecting();
return isConnected;
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.e.myapplication">
<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>
</application>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
</manifest>

Actually, it may not be your desirable answer, but I think there is a way simpler way to do what you really want to do using a Broadcast receiver. you don't need to check network state using the timer. here's the link

I would suggest you to use a WorkManager or AlarmManager, or even Services for background related periodic tasks.
Using the Timer-AsyncTask combination is not a feasible approach and it could lead to many problems, one of which being it could easily be terminated by Android once it's in background.
My top pick would be WorkManager as it handles the condition for the tasks for you nicely, for example, if you want to only launch your task if there's internet connection, then you simply add a Work Constraint to your work request like this
Constraint networkConstraint = new Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.build();
workRequest.setConstraints(constraints)
And your task will only be executed if the network is connected. BTW, they don't need to be manually re-set after reboot like AlarmManagers does.
However, there are downsides to it, one of them being the perodic requests can only occur every 15 minutes, which you can circumvent (though not recommended) by setting more one time work requests in each perodic request with smaller intervals of delayed start time.
Anyways, stop using the AsyncTask approach you are using now, and use one of the "legitimate" approaches Android approves to do background tasks, I recommend WorkManager, but based on your situation, you can choose whatever approach you like as long as it's meant to work in background.

Related

Issue in creating a full time running Background service in android app

I am creating an android app which needs a background service that fetches location and sends data to firebase every 20 seconds.The service has to start on button click and run continuously even when screen is turned off and should stop again on button click. At first , I tried using alarm Manager but it was not performing tasks at regular intervals. Next I tired using an Async Task and it was invoking a service which was performing task of sending data to firebase. But this approach, did not work on android 8+ versions. Then later on I used the similar approach but with JobIntent service and this approach worked well in android 7(appo) and even in android 8(lava) but in 8+ version(appo reno and mi) maybe due to custom OS , the service does not work if screen is turned off . I tried alternatives like workmanager but it did not work well in higher versions.
I created an activity named punch activity which has two buttons and code is as follows -
This button uses an async activity which calls service every 20 seconds.
#Override
public void onClick(View v) {
if (punchedIn){
Toast.makeText(PunchActivity.this, "Already PunchedIn",
Toast.LENGTH_LONG).show();
}
else {
timertask = new TimerTask() {
#Override
public void run() {
handler.post(new Runnable() {
public void run() {
Intent intent = new Intent(PunchActivity.this, BackgroundService.class);
//sendBroadcast(intent);
BackgroundService.enqueueWork(PunchActivity.this, intent);
}
});
}
};
timer = new Timer();
timer.schedule(timertask, 0, 20000);
}
}
}};
This button stops the service
#Override
public void onClick(View v) {
punchedIn = false;
Toast.makeText(getApplicationContext(),"PUNCHED OUT",Toast.LENGTH_SHORT).show();
Log.d("Message","Process "+timer.toString());
if (timer != null) {
Log.d("Message","Process is killed");
timer.cancel();
timer = null;
wakeLock.release();
}
}
});```
The code for JobIntentService is as below
public class BackgroundService extends JobIntentService implements com.google.android.gms.location.LocationListener {
private static Context mContext;
private FusedLocationProviderClient fusedLocationProviderClient;
public static String latitude = "", longitude = "";
public static void enqueueWork(Context context, Intent work) {
mContext = context;
enqueueWork(context, BackgroundService.class, JOB_ID, work);
}
#Override
protected void onHandleWork(#NonNull Intent intent) {
fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);
//This task does the task of fetching location and sending data to firebase
YourTask();
}
}```
I have made use of power manager in punch activity but it did not work fine. So please give some suggestions or even rectify my approach if you find any issue, based on my use case . Any small clue could be helpful.
Thanks,
Vrashab
Just create a sub thread and request location in a loop like below:
private HandlerThread thread = new HandlerThread("location_thread");
private Handler locationHandler = new Handler(thread.getLoop())
private boolean sholdStop = false
private Runnable locationRunnable = new Runnable() {
while(!sholdStop) {
// location logic
...
Thread.sleep(20000);
}
});
// start to location per 20 seconds
public void startLocation() {
locationHandler.removeCallbacks(locationRunnable);
sholdStop = false;
locationHandler.post(locationRunnable);
}
public void stopLocation() {
sholdStop = true;
locationHandler.removeCallbacks(locationRunnable);
}
But if your app is killed by Android system, this code will be invalid. To solve this problem you might need some method to keep your app lives as long as possible when running background.

Espresso - Taking screenshot during an AsyncTask

I'm currently using Espresso to programmatically take screenshots of an Android app. I'm successfully using
android.support.test.runner.screenshot.Screenshot
Problem is, given the following assumptions from official Espresso docs:
The message queue is empty.
There are no instances of AsyncTask currently executing a task.
All developer-defined idling resources are idle.
By performing these checks, Espresso substantially increases the likelihood that only one UI action or assertion can occur at any given time. This capability gives you more reliable and dependable test results.
I can't perform any test while any AsyncTask is running. I need to take some screenshots while my AsyncTask is running, but can't get my head around the docs on how to perform such task. The most similar SO thread I found doesn't seem to work, don't know if this is because the AsyncTask is too fast to take the screenshot.
// Start the async task
onView(withId(R.id.start_task_button)).perform(click());
// Then "press" the back button (in the ui thread of the app under test)
mActivityTestRule.runOnUiThread(new Runnable() {
#Override
public void run() {
mScreenshotWatcher.captureScreenshot("screenshot1");
}
});
Any clue about this? Is this the correct approach or should I implement IdlingResource in my AsyncTask?
thanks
nicola
From how I understood your question you'd like to take a screenshot when there's an AsyncTask in progress.
I created a minimum Android app to verify your scenario and it didn't work when click() from Espresso was used. The problem is that once Espresso performs its click() it invokes loopMainThreadUntilIdle() afterwards. As your AsyncTask has started at this point already the loop inside UiControllerImpl#loopMainThreadUntilIdle() gets run over and over again until the AsyncTask has finished.
The easiest way to overcome this is to use a custom ViewMatcher making a click and returning immediately.
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.test_edit_text).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
v.setVisibility(View.INVISIBLE);
new AsyncTask<Object, Object, Object>() {
#Override
protected Object doInBackground(Object... objects) {
SystemClock.sleep(20000000);
return null;
}
#Override
protected void onPostExecute(Object o) {
findViewById(R.id.test_edit_text)
.setVisibility(View.VISIBLE);
}
}.execute();
}});
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.question.stackoverflow"
xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
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>
</application>
</manifest>
MainActivityTest.java
#RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
#Rule
public ActivityTestRule<MainActivity> activityActivityTestRule = new ActivityTestRule<MainActivity>(MainActivity.class);
#Test
public void testTakeScreenshot() throws Exception {
Espresso.onView(withId(R.id.test_edit_text)).check(matches(isDisplayed()));
// use a custom ViewAction here because this call has be non-blocking
Espresso.onView(withId(R.id.test_edit_text)).perform(new ViewAction() {
#Override
public Matcher<View> getConstraints() {
return isDisplayingAtLeast(90);
}
#Override
public String getDescription() {
return "NonBlockingTap";
}
#Override
public void perform(UiController uiController, View view) {
view.performClick();
}
});
ScreenCapture screenCapture = Screenshot.capture();
screenCapture.setFormat(Bitmap.CompressFormat.PNG);
screenCapture.setName("test.png");
screenCapture.process();
Espresso.onView(withId(R.id.test_edit_text)).check(matches(isDisplayed()));
}
}

Unable to update UI from IntentService

A seemingly simple requirement - to update UI from an IntentService. In the shot below, when the Start Service button is clicked, I need to show a ProgressBar above the only TextView and after a delay, remove the ProgressBar.
Found a lot of answers on SO, but somehow unable to still crack it. I understand from this that LocalBroadcastManager is a good way to go. I have also tried following this, (an approach with Handlers), but it fails to show the ProgressBar too. Finally, based on this answer, here's what I have ended up with. The output I've managed so far is just the Toasts appearing in succession, after all the logging is done.
Greatly appreciate if you could point out where I am going wrong, been struggling for quite some time now. Many thanks in advance!
MainActivity updated
public class MainActivity extends AppCompatActivity
{
private static final String TAG = "MainActivity";
private ProgressBar pb;
private MyBroadcastReceiver myBroadcastReceiver;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pb = (ProgressBar) findViewById(R.id.pb);
myBroadcastReceiver = new MyBroadcastReceiver();
LocalBroadcastManager.getInstance(this).registerReceiver(myBroadcastReceiver, new IntentFilter("ACTION"));
}
private void updateUI(boolean show)
{
if (show)
pb.setVisibility(View.VISIBLE);
else
pb.setVisibility(View.GONE);
// Toast.makeText(this, "UI Updated...", Toast.LENGTH_LONG).show();
}
public void startIt(View view)
{
Intent intent = new Intent(this, NanisIntentService.class);
startService(intent);
}
public class MyBroadcastReceiver extends BroadcastReceiver
{
#Override
public void onReceive(final Context context, Intent intent)
{
String action = intent.getAction();
Log.e(TAG, "In onReceive(): " + action);
if (action.equals("ACTION"))
{
updateUI(true);
} // of if (action = "ACTION")
else if (action.equals("NOITCA"))
{
updateUI(false);
} // of else of if (action = "ACTION")
} // of onReceive()
} // of class MyBroadcastReceiver
}
IntentService updated
public class NanisIntentService extends IntentService
{
private static final String TAG = "NanisIntentService";
public NanisIntentService()
{
super("NanisIntentService");
}
#Override
protected void onHandleIntent(Intent intent)
{
Log.e(TAG, "In onHandleIntent(): Intent is being serviced");
LocalBroadcastManager.getInstance(testing.com.myintentservice.NanisIntentService.this).sendBroadcast(new Intent().setAction("ACTION"));
int i = 0;
while (i <= 50)
{
try
{
Thread.sleep(50);
i++;
Log.e("", "" + i);
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
#Override
public void onDestroy()
{
super.onDestroy();
LocalBroadcastManager.getInstance(testing.com.myintentservice.NanisIntentService.this).sendBroadcast(new Intent().setAction("NOITCA"));
Log.e(TAG, "In onDestroy(): The service has been destroyed");
}
}
#Override
public void onStart(Intent intent, int startId)
{
super.onStart(intent, startId);
LocalBroadcastManager.getInstance(testing.com.myintentservice.NanisIntentService.this).sendBroadcast(new Intent().setAction("ACTION"));
}
#Override
public void onDestroy()
{
super.onDestroy();
LocalBroadcastManager.getInstance(testing.com.myintentservice.NanisIntentService.this).sendBroadcast(new Intent().setAction("NOITCA"));
Log.e(TAG, "In onDestroy(): The service has been destroyed");
}
}
#Override
public void onDestroy()
{
super.onDestroy();
LocalBroadcastManager.getInstance(testing.com.myintentservice.NanisIntentService.this).sendBroadcast(new Intent().setAction("NOITCA"));
Log.e(TAG, "In onDestroy(): The service has been destroyed");
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="testing.com.myintentservice.MainActivity">
<ProgressBar
android:id="#+id/pb"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="#+id/tv"
android:layout_centerHorizontal="true"
android:indeterminate="true"
android:visibility="gone"/>
<TextView
android:id="#+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="Hello IntentService!"
android:textColor="#1298CE"
android:textSize="32sp"/>
<Button
android:id="#+id/bt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:text="Start Service"
android:onClick="startIt"/>
</RelativeLayout>
AndroidManifest
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
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="testing.com.myintentservice.NanisIntentService"/>
</application>
First, you are tying up the main application thread for ~2.5 seconds. This will freeze your UI during this period of time. Do not do this.
Second, you are calling updateUI() once before the ~2.5 seconds, and once after. Since you are tying up the main application thread during that time, this will have the same visual effect as calling updateUI() twice in succession after the delay. updateUI() toggles the ProgressBar visibility, so two calls will cancel each other out, leaving you in the same state as you started.
I need to show a ProgressBar above the only TextView and after a delay, remove the ProgressBar.
Showing a ProgressBar for 2.5 seconds, irrespective of any actual work being done, is rather arbitrary.
That being said, call updateUI() once, then use pb.postDelayed() to schedule a Runnable to run 2500 milliseconds later, where the run() method in the Runnable calls updateUI() the second time. This avoids you blocking the main application thread, so it allows the first updateUI() call to take effect, while still giving you the 2.5-second duration.
Thanks so much, #CommonsWare! Finally got it to work. It needed two receivers for the two different actions, which I discovered here.
For the benefit of those looking for the final working code...
MainActivity
NanisIntentService
Result screens:- after clicking and after processing
Pardon any copy-paste ghosts in the code, it is after all a PoC, albeit functional.

In Android AsyncTasks run before splash screen displays?

I have a splash screen that I'm trying to run some AsyncTasks on. It appears the AsyncTasks are running before it shows the splash screen. I need the splash screen to show (logo and each process shows a different message) and the start running the asynctasks. I'm using books in the blow code only as an example of what I have:
SplashScreen.java:
// Splash screen timer
private static int SPLASH_TIME_OUT = 3000;
TextView statusMessage;
BookClubDB bookClubDB = new BookClubDB(this);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash_screen);
statusMessage = (TextView) findViewById(R.id.statusMessage);
statusMessage.setText("Checking For Connection");
if(isNetworkAvailable()){
statusMessage.setText("Connection Found");
String appUpdateDate = null;
appUpdateDate = lastUpdate();
update1(appUpdateDate);
update2(appUpdateDate);
update3(appUpdateDate);
update4(appUpdateDate);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
endSplash();
}
}, SPLASH_TIME_OUT);
}
else {
statusMessage.setText("No Connection Found");
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
endSplash();
}
}, SPLASH_TIME_OUT);
}
}
public void endSplash(){
Intent i = new Intent(SplashScreen.this, MainActivity.class);
startActivity(i);
// close this activity
finish();
}
private boolean isNetworkAvailable() {
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}
private String lastUpdate(){
String updateDate = null;
updateDate = bookClubDB.getUpdateDate();
return updateDate;
}
private void update1(String appUpdateDate){
statusMessage.setText("Updating Regions");
bookClubDB.getAPI1(appUpdateDate);
}
private void update2(String appUpdateDate){
statusMessage.setText("Updating Vehicles");
bookClubDB.getAPI2(appUpdateDate);
}
private void update3(String appUpdateDate){
statusMessage.setText("Updating Products");
bookClubDB.getAPI3(appUpdateDate);
}
private void update4(String appUpdateDate){
statusMessage.setText("Updating Documents, Images, and Video");
bookClubDB.getAPI4(appUpdateDate);
}
The functions being called (updated1...4) call another function (getAPI1...4) in a file called BookClubDB.java. The second set is what runs the asynctasts in a file named JASONParser.java. The functions and parser work. Only the asynctasks run before the splash screen shows.
I want the splash screen to pop up with "checking for connection" -> "connection found" -> each updated from the functions as they are ran.
The JSONParser.java is a simple json parser that returns the json results back to the BookClubDB.java:
JSONObject output = new JSONParser().execute(new String[] {bookClubURL,consumerKey,sharedSecret}).get();
The function takes the json, converts it into a jsonArray and I populate a database with it. Again everything is working as needed, only the asynctasks are running too soon.
How can I start the thread for the splash screen before the asynctask thread? I've looked at other SO answers but they never really answered it for me.
You are running all of your code in the OnCreate method of your activity. The UI is not yet visible at this point.
Check out the activity lifecycle in the Android docs and rewrite according to that.
I guess this is happening because you are firing asynctasks in activity's onCreate, when the activity is still being created.
If I understood correctly, you want them to be triggered only after the splash screen was displayed.
onResume is a good callback for that.
Moreover, notice that you are firing all the updatexx methods at the same time, and the status message will be overridden every time.
It is probably because you are setting the message text on main thread.
If you run some changes on main thread too quickly, they don't have to be performed or may result in lags in the UI.
Basically your app is doing something like this:
-> OnCreate
-> setText("Checking For Connection")
-> setText("OnConnectionFound")
-> setText("Updating Regions")
-> schedule new AsyncTask to update regions
-> setText("Updating Vehicles")
-> schedule new AsyncTask to update vehicles
..... update3,4......
and only now the system starts to execute the async tasks.
(It does not have to be this strict, especially on multicore processors. It is possible that f.e. the regions asyncTask starts before the update3 setText, but it certainly does not finish before that)
But there is one thing you need to realize: all these calls are quite fast, probably no more then few miliseconds. And the UI is not updated that often (nor would you notice it).
Therefore the text updates too quickly/does not update at all.
You mentioned you are using AsyncTask, that's good. You will probably just have to place your setText calls into onPreExecute/onPostExecute/onProgressChanged methods (based on when you want the text to be changed) and it will work fine. These methods are designed to be called on UI thread in the right time, therefore ensure all your UI actions will be rendered :)

How to communicate a service with a running thread in Android

my goal is to lunch a service that will take care for all of the application network needs.
i thought maybe to open 2 sockets for data transfer. i want the data to be handled asynchronously, so i was thinking my be i should run them in two separated threads, each for every socket, and that way the data could be streamed in two different "links" async..
so, i would appreciate two things:
a better overall design. maybe i completely got it all wrong..
can someone explain to me how can i communicate with those threds once i need to pass data to/from them to/from the main service? as far as i learnt (OS) i need to use SIGNALS:) (just kidding..)
Well, I can say i finally got it, just before giving up. Here is a super duper extremely simple app that runs a thread inside an activity and handles a bi-directional communication using two different Handlers for each entity!
The code:
public class MainActivity extends Activity {
//Properties:
private final String TAG = "Activity"; //Log tag
private MyThread mThread; //spawned thread
Bundle myB = new Bundle(); //used for creating the msgs
public Handler mHandler = new Handler(){ //handles the INcoming msgs
#Override public void handleMessage(Message msg)
{
myB = msg.getData();
Log.i(TAG, "Handler got message"+ myB.getInt("THREAD DELIVERY"));
}
};
//Methods:
//--------------------------
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mThread = new MyThread(mHandler);
mThread.start();
sendMsgToThread();
}
//--------------------------
void sendMsgToThread()
{
Message msg = mThread.getHandler().obtainMessage();
myB.putInt("MAIN DELIVERY", 321);
msg.setData(myB);
mThread.getHandler().sendMessage(msg);
}
}
//=========================================================================================
//=========================================================================================
public class MyThread extends Thread{
//Properties:
private final String TAG = "MyThread"; //Log tag
private Handler outHandler; //handles the OUTgoing msgs
Bundle myB = new Bundle(); //used for creating the msgs
private Handler inHandler = new Handler(){ //handles the INcoming msgs
#Override public void handleMessage(Message msg)
{
myB = msg.getData();
Log.i(TAG, "Handler got message"+ myB.getInt("MAIN DELIVERY"));
}
};
//Methods:
//--------------------------
public void run(){
sendMsgToMainThread(); //send to the main activity a msg
Looper.prepare();
Looper.loop();
//after this line nothing happens because of the LOOP!
Log.i(TAG, "Lost message");
}
//--------------------------
public MyThread(Handler mHandler) {
//C-tor that get a reference object to the MainActivity handler.
//this is how we know to whom we need to connect with.
outHandler = mHandler;
}
//--------------------------
public Handler getHandler(){
//a Get method which return the handler which This Thread is connected with.
return inHandler;
}
//--------------------------
private void sendMsgToMainThread(){
Message msg = outHandler.obtainMessage();
myB.putInt("THREAD DELIVERY", 123);
msg.setData(myB);
outHandler.sendMessage(msg);
}
}
//=========================================================================================
//=========================================================================================
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="test.test.namespace"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="10" />
<application android:icon="#drawable/icon" android:label="#string/app_name">
<activity android:name=".MainActivity" android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
the output is:
01-26 06:25:40.683: I/Activity(19560): Handler got message123
01-26 06:25:40.683: I/MyThread(19560): Handler got message321
I figured this out while reading the offered post by endian, here.
I hope others will find this useful. good luck:)
Here is good post explaining threads and communication using handlers. Also, the same blog has a number of posts regarding various thread constructs in Android.
Another possibility is to use AsyncTasks. Find some explanation here

Categories

Resources