Android服务无法从“活动”开始使用

时间:2019-04-29 09:33:54

标签: android android-service

我试图在单击按钮后从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()方法的构造函数中(这里没有显示,但它在那里)。

2 个答案:

答案 0 :(得分:1)

您必须显示通知并请求<form id="MyForm"> text 1 <input type="text"><br /> text 2 <input type="text"><br /> un-ticked checkbox <input type="checkbox"><br /> ticked checkbox <input type="checkbox" checked><br /> <select> <option>Value 1</option> <option>Value 2</option> <option>Value 3</option> <option>Value 4</option> </select><br /> <input type="radio" id="val1" name="radio" value="1" checked> <label for="val1">Value 1</label><br /> <input type="radio" id="val2" name="radio" value="2"> <label for="val2">Value 2</label><br /> <input type="radio" id="val3" name="radio" value="3"> <label for="val3">Value 3</label><br /> <input type="hidden" id="MyHidden" value="42"> <button type="button" onclick="resetForm()">Reset</button> </form>权限才能启动前台服务。 请检查Android Developers docs

答案 1 :(得分: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>