Show ProgressDialog in a Service class
Asked Answered
C

1

4

I am using a Service to connect to a network using a AsyncTask. I want to show a ProgressDialog till the app is connected to the network. But how can I do this?

My Service looks like this:

package de.bertrandt.bertrandtknx;

import tuwien.auto.calimero.link.KNXNetworkLinkIP;
import tuwien.auto.calimero.process.ProcessCommunicator;
import de.bertrandt.bertrandtknx.Controls.OnOff;
import android.app.ProgressDialog;
import android.app.Service;
import android.content.Intent;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.AsyncTask;
import android.os.IBinder;
import android.widget.Toast;


public class ConnectionService  extends Service {

    public static KNXNetworkLinkIP m_netLinkIp = null;
    private static ProcessCommunicator m_pc = null;


    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
       //code to execute when the service is first created
        new Connect().execute();
    }

    @Override
    public void onDestroy() {
       //code to execute when the service is shutting down
        new Disconnect().execute();
    }

    public void onStartCommand(Intent intent, int startid) {
       //code to execute when the service is starting up
    }


    /**
     * GetIPAddress Async
     * */
    public String getIpAddr() {
           WifiManager wifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
           WifiInfo wifiInfo = wifiManager.getConnectionInfo();
           int ip = wifiInfo.getIpAddress();

           String ipString = String.format(
           "%d.%d.%d.%d",
           (ip & 0xff),
           (ip >> 8 & 0xff),
           (ip >> 16 & 0xff),
           (ip >> 24 & 0xff));

           return ipString.toString();
    }

    /**
     * Connect Async
     * */
    private class Connect extends AsyncTask<String, Void, String> {
          ProgressDialog dialog;
          boolean ok;
          @Override
          protected String doInBackground(String... params) {
              try {
                  //get local IP address
                  String ipAddress = getIpAddr();
                  System.out.println("WiFi address is " + ipAddress);

                  m_netLinkIp = Calimero.Util.connect(ipAddress, "192.168.0.2");

                  if (m_netLinkIp == null){

                      System.out.println("Can not connect to Demobard");
                      ok = false;
                  }
                  else{
                      System.out.println("Connected to Demoboard");
                      ok = true;

                      }
               } catch (Exception e) {         
                   e.printStackTrace(); 
               }
               return null;
          }      

          @Override
          protected void onPostExecute(String result) { 
            //dialog.dismiss();
            Toast.makeText(getApplicationContext(),
                    "Verbindung mit Demoboard " +
                            ((ok == true) ? "hergestellt" : "fehlgeschlagen"), Toast.LENGTH_LONG).show();
            if(ok == false){
                //show reconnect dialog
                //reconnect_dialog();
            }
          }

          @Override
          protected void onPreExecute() {
           // Setup Progress Dialog
           dialog = new ProgressDialog(OnOff.this);
           dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
           dialog.setMessage("Bitte warten, verbinde mit KNX-Board");
           dialog.setIndeterminate(true);
           dialog.show();*/
          }
    }

    /**
     * Disconnect Async
     * */
    private class Disconnect extends AsyncTask<String, Void, String> {
          @Override
          protected String doInBackground(String... params) {
                    try {
                        Calimero.Util.disconnect(m_netLinkIp);
                    } catch (Exception e) {
                        e.printStackTrace(); 
                    }
                return null;
          }      

    }

}

Of course this code makes problems how can I get the context of the activity which starts the Service?

The Dialog should be shown in the activity which starts the Service until the app is connected.

Chabot answered 12/11, 2012 at 16:14 Comment(4)
you can't, a Dialog must be start from of be itself an Activity.Nevermore
I would start the DialogActivity as a NEW_TASK, using a singleTask mode and using onNewIntent to catch value updatesNevermore
ok but if I create the dialog inside the activity itself, how can I know if the connection is established? Do I have to use a Handler?Chabot
i would start a dialog activity with an intent indicating that the connection is establishing, then send intents to this activity (calling startActivity, the singleTask activity receives calls to onNewIntent.)Nevermore
E
7

So a service is NOT the UI you have to use the observer pattern. Your activity have to register a listener in the service so that the service can inform the activity for special events (like start loading or finish loading).

You have to add following intercae into your service class:

    public interface serviceObserver {
        public void startLoading();
        public void stopLoading();
    }

Your activity has to implement serviceObserver. Your service has to store a instance from serviceObserver which is created in the activity. If your service is running without your activity i recommend to use broadcast receiver for communication.

Elegist answered 12/11, 2012 at 16:23 Comment(4)
I am not sure how I can do this because the AsyncTask inside my Service needs the dialog reference.. do you have a example or can you help me with a more detailled code snippetChabot
a service is NOT UI. So a service should not access the UI! Using the asynctask UI methods is therefore a bad idea! Using broadcast would be at better choice. If your Service is only running in your activity you dont need a service, you can therefore choose an AsyncTask or Thread class on its own without service. Giving the asynctask the context of your activity is a really bad idea. Because you never know if your context is still active. Take a look at MVC (google for it) before going on!Elegist
I could solve it using a BroadcastReceiver with a custom intent action. Thank you!Chabot
Caution: When working with interfaces you MUST NOT hold any strong references to an activity in your service, because it would be a potential memory leak! For example using it as anonymous inner class will result in holding a reference to the activity! In my opinion it is much cleaner and safer to work with (local) broadcasts.Funda

© 2022 - 2024 — McMap. All rights reserved.