user45678
user45678

Reputation: 1514

How to use AsyncTask in Services in Android?

I am trying to run below code it gives exception saying:

 java.lang.RuntimeException: Unable to start service com.example.testfeeds.UpdateWidgetService@410a33c8 with Intent {  cmp=com.example.testfeeds/.UpdateWidgetService (has extras) }: android.os.NetworkOnMainThreadException

which i understand that new version of Android won't allow network operations in main thread. People suggested me to use Async Task but I don't know how to use that. Can someone show me in below code?

Thanks in advance

public class WidgetService extends Service {
/*
 * So pretty simple just defining the Adapter of the listview
 * here Adapter is ListProvider
 * */

/*@Override
public RemoteViewsFactory onGetViewFactory(Intent intent) {
    int appWidgetId = intent.getIntExtra(
            AppWidgetManager.EXTRA_APPWIDGET_ID,
            AppWidgetManager.INVALID_APPWIDGET_ID);

    return (new ListProvider(this.getApplicationContext(), intent));
}*/

public static int numberOfItems=0;
  //numberOfItems=0;
    private static  String LOG = "testwidgets";
    ArrayList<String> feedsPubDate;
      @SuppressWarnings("deprecation")
    @Override
      public void onStart(Intent intent, int startId) {
        Log.i(LOG, "Called");
        // Create some random data
        feedsPubDate=new ArrayList<String>(); 
        AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this .getApplicationContext());
        int[] allWidgetIds = intent
            .getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS);
        ComponentName thisWidget = new ComponentName(getApplicationContext(), WidgetProvider.class);
        int[] allWidgetIds2 = appWidgetManager.getAppWidgetIds(thisWidget);
        Log.w(LOG, "From Intent" + String.valueOf(allWidgetIds.length));
        Log.w(LOG, "Direct" + String.valueOf(allWidgetIds2.length));
        for (int widgetId : allWidgetIds) {
          // Create some random data
/////////////////////////////////////////////////////////////////////////// 

              RemoteViews remoteViews = new RemoteViews(this.getApplicationContext().getPackageName(),
              R.layout.widget_layout);
          Log.d("numberOfItems intially", String.valueOf(numberOfItems));
              try {
                numberOfItems=doTestFeed();
            } catch (MalformedURLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ParseException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
          // Set the text
          remoteViews.setTextColor(R.id.empty_view,Color.WHITE);
          remoteViews.setTextViewText(R.id.empty_view,"  "+ String.valueOf(numberOfItems));
          Log.w(LOG, String.valueOf(numberOfItems));
////////////////////////////////////////////////////////////////////////////

          // Register an onClickListener
          Intent clickIntent = new Intent(this.getApplicationContext(),
              WidgetProvider.class);
          clickIntent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
          clickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS,
              allWidgetIds);
          PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, clickIntent,
              PendingIntent.FLAG_UPDATE_CURRENT);
          remoteViews.setOnClickPendingIntent(R.id.empty_view, pendingIntent);
          appWidgetManager.updateAppWidget(widgetId, remoteViews);
        }
        stopSelf();
        super.onStart(intent, startId);

      }



    @Override
    public IBinder onBind(Intent arg0) {
        // TODO Auto-generated method stub
        return null;
    }


    int doTestFeed() throws MalformedURLException, ParseException
    {  
        Log.d("msg"," in do test feed");
        InputStream is = null;
        int x = 0;
        URL myURL = new URL("http://yunn.yu.edu.jo/index.php?option=com_content&view=category&id=55&layout=blog&Itemid=104&format=feed&type=rss");
        try {
            URLConnection conn = myURL.openConnection();
             is = conn.getInputStream();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        XmlPullParserFactory pullParserFactory;
        try {
            pullParserFactory = XmlPullParserFactory.newInstance();
            XmlPullParser parser = pullParserFactory.newPullParser();
                parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
                parser.setInput(is, null);
                Log.d("msg","before making parsing");
                x=parseXML(parser);
                Log.d("msg","after making parsing");
        } catch (XmlPullParserException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        Log.d("msg"," done testing");
        return x;
    }
//////////////////////////////////////////////////////////////////////////////////
    @SuppressLint("SimpleDateFormat")
    private int parseXML(XmlPullParser parser) throws XmlPullParserException,IOException, ParseException
    {
        Log.d("msg"," in parser");
        int eventType = parser.getEventType();
        int getElement=0;
        String pubDate=null;
        while (eventType != XmlPullParser.END_DOCUMENT){
            String tagName = null;
            switch (eventType){
            //----------------------------------//
            case XmlPullParser.START_DOCUMENT: 
                {
                    // do nothing
                }
                break;
           //----------------------------------//
             case XmlPullParser.START_TAG:
             { tagName = parser.getName();
                 if ("item".equals(tagName)){
                      getElement=1;
                 } else if (getElement!=0){
                      if ("pubDate".equals(tagName)){
                         pubDate= parser.nextText();
                         feedsPubDate.add(pubDate);
                         Log.d("value",pubDate);
                     }
                 }
             }
                 break;                     
           //----------------------------------//
             case XmlPullParser.END_TAG:
             { tagName = parser.getName();
                 if (tagName.equalsIgnoreCase("item") && getElement != 0){
                 }
             }
                 break;
          //----------------------------------//
            }// end-switch.
            eventType= parser.next();
        }// end-while.
        int i=0;
        SharedPreferences sp = getSharedPreferences("tempData", 0);
        String dateStringA=sp.getString("recentPubDate", null);
        Log.d("oldest date",dateStringA);
        for(String s : feedsPubDate )
        {
        String dateStringB = feedsPubDate.get(i);
        SimpleDateFormat parserSDF = new SimpleDateFormat("EEE, DD MMM yyyy HH:mm:ss");
        Date dateA = null;
        try {
            dateA = parserSDF.parse(dateStringA);
        } catch (java.text.ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        Date dateB = null;
        try {
            dateB = parserSDF.parse(dateStringB);
        } catch (java.text.ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        if (dateA.compareTo(dateB) < 0) {
            Log.d("imp msg","one new item");
            numberOfItems++;
        }
        i++;
        }
        Log.d("update result", String.valueOf(numberOfItems));
      // Toast.makeText(GeneralNews.this,"The size of the list"+feedsTitles.size() , Toast.LENGTH_LONG).show();
   return numberOfItems;
    } //end xmlParser method.
//////////////////////////////////////////////////////////////////////////////////
 }

Upvotes: 8

Views: 37317

Answers (5)

tvshajeer
tvshajeer

Reputation: 1329

If API version is 11 or above android:targetSDk does not allow netwrok on main thread But it works in below in HoneyComb.n

Try to remove android:targetSdkVersion line from your manifest. I did this in 3rd party code and work for me most of time.

It worked for me.

Upvotes: 0

Adem
Adem

Reputation: 9429

it is about ui thread. I guess Services have some issues with ui thread. onPostExecutes have to be run on ui thread. so, because of Services have not ui thread, it breaks on executing onPostExecute on non-ui thread.

I suggest

new Thread(){
        public void run() {
            Object result=null;


            Looper l = Looper.getMainLooper();
            Handler h = new Handler(l);
            h.post(new Runnable() {
                @Override
                public void run() {
                    if (result != null){
                        response.OnResponse(true, "", result);
                    } else {
                        response.OnResponse(false, errMessage, null);
                    }
                }
            });
        };
    }.start();

of course, this has not Thread pool in AsyncTask, but you can convert this code to use a Thread pool.

Upvotes: 2

Maxim Shoustin
Maxim Shoustin

Reputation: 77904

As example:

You have log in Activity and when you press "Login" application need to validate against Service and switch to main Activity:

private class HeavyTask extends AsyncTask<String, Void, Void> {


    protected Void doInBackground(String... args) {

        //do something here
        // like tell to Service to do some async task

        return null;
    }

    protected void onPostExecute(Void results) {

       // here actually we wait any event from Service about task done

        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                mHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {                         
                        startActivity(new Intent().setClass(FirstLoginActivity.this, MainActivity.class).setData(getIntent().getData()));

                        finish();
                    }
                }, 1000);
            }
        }, 500);            
    }       
}

And this is how I call it:

HeavyTask task = new HeavyTask();
task.execute(user, passwordText, login_outbound_proxy); // as example

Pretty simple example that will help you to sort things out in addition to theory

Upvotes: 0

Lazy Ninja
Lazy Ninja

Reputation: 22527

A simple example:

public class YourAsyncTask extends AsyncTask<String, Void, String>{

    @Override
    protected String doInBackground(String... params) {
        // your load work
        return myString;
    }

    @Override
    protected void onPostExecute(String result) {

    }

}

Use new YourAsyncTask ().execute() to call it.

Upvotes: 1

Philipp Jahoda
Philipp Jahoda

Reputation: 51411

I think this question might be helpful for you: How to use AsyncTask

You can make your AsyncTask an inner class of your Service, and do your network-operations in the doInBackground() method of AsyncTask. From doInBackground() you can return any kind of data to the onPostExecute() method of AsyncTask, where you can do further stuff with the received data.

And here, an AsyncTask example: AsyncTask Android example

Upvotes: 10

Related Questions