Reputation: 1361
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
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
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