Android服务无法从Activity启动

问题描述 投票:0回答:2

我点击按钮后尝试从Service开始一个Activity。但Service没有开始。我的想法是使用Service将一些数据从Activity发布到Handler。 我的AndroidManifest.xml文件:

<?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>  

我的Service课程:

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;
    }
}  

我的Activity课程:

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));
    }
}  

我的Handler课程:

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);
    }
}  

我调试后没有看到在调用ContextCompat.startForegroundService(getApplicationContext(), intent)后服务类中遇到任何断点。断点放在Service的构造函数,onCreate()方法(我没有在这里显示,但它在那里),onStartCommand()方法。

android android-service
2个回答
1
投票

我改变了你的服务类。请试试这个。

在CountrySearchActivity类中:

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);

服务类别:

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;
    }
}  

在AndroidManifest.xml中

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

<application
        ....

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

1
投票

您必须显示通知并请求FOREGROUND_SERVICE权限才能启动前台服务。请检查Android Developers docs

© www.soinside.com 2019 - 2024. All rights reserved.