Shankha057
Shankha057

Reputation: 1361

Android Service not getting started from the Activity

I am trying to start a Service from an Activity after a button click. But the Service isn't starting. My idea is to post some data from the Service to the Activity using a Handler.
My AndroidManifest.xml file:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.myfirstandroidapp">

    <uses-permission android:name="android.permission.INTERNET" />

    <application
        android:allowBackup="true">
        <activity android:name=".servicesdemo.CountrySearchActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service
            android:name="com.myfirstandroidapp.servicesdemo.MyRESTRequestService"
            android:enabled="false"
            android:exported="false" ></service>
    </application>
</manifest>  

My Service class:

public class MyRESTRequestService extends Service {
    private static final String TAG = "MyRESTRequestService";
    private ExecutorService threadPool =
            Executors.newSingleThreadExecutor();
    private Country country = null;
    private Message message = new Message();

    public MyRESTRequestService() {}

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        String countryName = (String) intent
                .getCharSequenceExtra("COUNTRY_NAME");

        Handler handler = intent.getParcelableExtra("HANDLER");

        threadPool.execute(() -> {
            try {
                country = new HTTPHandler()
                        .getCountryByName(countryName);
                message.obj = country;
                message.what = 1;
                handler.sendMessage(message);
                Log.d(TAG, country.toString());
            } catch (IOException e) {
                e.printStackTrace();
            }
        });


        return super.onStartCommand(intent, flags, startId);
    }

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

My Activity class:

public class CountrySearchActivity extends AppCompatActivity implements MyHandler.IUIUpdater {
    @BindView(R.id.btn_get_country_from_webservice)
    Button btnGetCountryFromWebService;

    @BindView(R.id.tv_container_country_name)
    EditText countryNameEntryField;

    @BindView(R.id.tv_obtained_country)
    TextView resultingCountry;

    private void getCountryFromWebService() {
        String countryNameForGetting = countryNameEntryField
                .getText()
                .toString();
        Handler handler = new MyHandler(this);

        Intent intent = new Intent(getApplicationContext(),
                MyRESTRequestService.class);
        intent.putExtra("COUNTRY_NAME", countryNameForGetting);
        intent.putExtra("HANDLER", new Messenger(handler));
        ContextCompat.startForegroundService(getApplicationContext(),
                intent);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_country_search);
        ButterKnife.bind(this);

        btnGetCountryFromWebService.setOnClickListener(v ->
                getCountryFromWebService());
    }

    @Override
    public void updateTheUi(Message message) {
        resultingCountry.setText((String) message.obj);
        stopService(new Intent(getApplicationContext(),
                MyRESTRequestService.class));
    }
}  

My Handler class:

public class MyHandler extends Handler {

    IUIUpdater iuiUpdater;

    public MyHandler(IUIUpdater iuiUpdater) {
        this.iuiUpdater = iuiUpdater;
    }

    @Override
    public void handleMessage(Message msg) {
        iuiUpdater.updateTheUi(msg);
    }

    public interface IUIUpdater {
        void updateTheUi(Message message);
    }
}  

I debugged and didn't see any breakpoints getting hit in the service class after the call to ContextCompat.startForegroundService(getApplicationContext(), intent). The breakpoints were placed at the constructor of the Service, the onCreate() method (I haven't shown here, but it's there), the onStartCommand() method.

Upvotes: 0

Views: 70

Answers (2)

Nikunj Sorathiya
Nikunj Sorathiya

Reputation: 353

I changed in your service class. PLease try this.

In CountrySearchActivity Class:

String countryNameForGetting = countryNameEntryField
                .getText()
                .toString();
        Handler handler = new MyHandler(this);

        Intent intent = new Intent(getApplicationContext(),
                MyRESTRequestService.class);
        intent.putExtra("COUNTRY_NAME", countryNameForGetting);
        intent.putExtra("HANDLER", new Messenger(handler));

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
            ContextCompat.startForegroundService(this, intent);
        else
            startService(intent);

Service Class:

public class MyRESTRequestService extends Service {

    private static final String TAG = "MyRESTRequestService";
    private ExecutorService threadPool =
            Executors.newSingleThreadExecutor();
    private Country country = null;
    private Message message = new Message();
    private static final String NOTIFICATION_CHANNEL_ID = "running_service";

    public MyRESTRequestService() {}

    @Override
    public void onCreate() {
        super.onCreate();

        NotificationCompat.Builder builder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
                .setOngoing(false)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setPriority(Notification.PRIORITY_MIN);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
            NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID,
                    NOTIFICATION_CHANNEL_ID, NotificationManager.IMPORTANCE_LOW);
            notificationChannel.setDescription(NOTIFICATION_CHANNEL_ID);
            notificationChannel.setSound(null, null);
            notificationManager.createNotificationChannel(notificationChannel);
            startForeground(1, builder.build());
        }
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        String countryName = (String) intent
                .getCharSequenceExtra("COUNTRY_NAME");

        Handler handler = intent.getParcelableExtra("HANDLER");

        threadPool.execute(() -> {
            try {
                country = new HTTPHandler()
                        .getCountryByName(countryName);
                message.obj = country;
                message.what = 1;
                handler.sendMessage(message);
                Log.d(TAG, country.toString());
            } catch (IOException e) {
                e.printStackTrace();
            }
        });

        return super.onStartCommand(intent, flags, startId);
    }

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

In AndroidManifest.xml

<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

<application
        ....

        <service
            android:name=".MyRESTRequestService"
            android:enabled="true"
            android:exported="true" />
    </application>

Upvotes: 1

budgie
budgie

Reputation: 315

You have to show notification and request FOREGROUND_SERVICE permission in order to start foreground service. Please check Android Developers docs

Upvotes: 1

Related Questions