bindService Android AIDL всегда возвращает false - PullRequest
0 голосов
/ 09 ноября 2019

Я хотел бы предоставить услугу, которую может вызвать другое приложение. Поэтому у меня есть служба и помощь. Но когда я пытаюсь создать отдельное приложение для привязки этого сервиса (bindService), оно просто возвращает мне false, что означает сбой. Вот мой код.

Я использую код из книг Pro Android 2

Я уже пробовал много решений в других вопросах, подобных этому, но не существует никакого рабочего решениядля меня.

Я пытался исправить фильтр намерений aidl, но он все еще не работает

Я пытался исправить имя пакета и имя класса в клиентском приложении, но он все еще не работает.

Пожалуйста, помогите мне!

На клиенте:

// IStockQuoteService.aidl
package id.ac.ui.cs.mobileprogramming.ahmad_fauzan_amirul_isnain.stockquoteservice;

// Declare any non-default types here with import statements

interface IStockQuoteService {
    double getQuote(String ticker);
}
package id.ac.ui.cs.mobileprogramming.ahmad_fauzan_amirul_isnain.stockquoteclient;

import id.ac.ui.cs.mobileprogramming.ahmad_fauzan_amirul_isnain.stockquoteservice.IStockQuoteService;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends Activity {
    protected static final String TAG = "StockQuoteClient";
    private IStockQuoteService stockService = null;
    private Button bindBtn;
    private Button callBtn;
    private Button unbindBtn;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bindBtn = (Button)findViewById(R.id.bindBtn);
        bindBtn.setOnClickListener(new OnClickListener(){
            @Override
            public void onClick(View view) {
                Intent intent = new Intent();
                intent.setClassName("com.id.ac.ui.cs.mobileprogramming" +
                        ".ahmad_fauzan_amirul_isnain.stockquoteservice",
                        "com.id.ac.ui.cs.mobileprogramming.ahmad_fauzan_amirul_isnain" +
                                ".stockquoteservice.IStockQuoteService");
                Log.d("Hasil", String.valueOf(bindService(intent,
                        serConn, Context.BIND_AUTO_CREATE)));
                bindBtn.setEnabled(false);
                callBtn.setEnabled(true);
                unbindBtn.setEnabled(true);
            }});
        callBtn = (Button)findViewById(R.id.callBtn);
        callBtn.setOnClickListener(new OnClickListener(){
            @Override
            public void onClick(View view) {
                callService();
            }});
        callBtn.setEnabled(false);

        unbindBtn = (Button)findViewById(R.id.unbindBtn);
        unbindBtn.setOnClickListener(new OnClickListener(){
            @Override
            public void onClick(View view) {
                unbindService(serConn);
                bindBtn.setEnabled(true);
                callBtn.setEnabled(false);
                unbindBtn.setEnabled(false);
            }});
        unbindBtn.setEnabled(false);
    }
    private void callService() {
        try {
            double val = stockService.getQuote("SYH");
            Toast.makeText(MainActivity.this, "Value from service is "+val,
                    Toast.LENGTH_SHORT).show();
        } catch (RemoteException ee) {
            Log.e("MainActivity", ee.getMessage(), ee);
        }
    }
    private ServiceConnection serConn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service)
        {
            Log.v(TAG, "onServiceConnected() called");
            stockService = IStockQuoteService.Stub.asInterface(service);
            callService();
        }
        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.v(TAG, "onServiceDisconnected() called");
            stockService = null;
        }
    };
}

На обслуживании:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="id.ac.ui.cs.mobileprogramming.ahmad_fauzan_amirul_isnain.stockquoteservice">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service android:name="StockQuoteService">
            <intent-filter>
                <action android:name="com.id.ac.ui.cs.mobileprogramming.ahmad_fauzan_amirul_isnain.stockquoteservice.IStockQuoteService"
                    />
            </intent-filter>
        </service>
    </application>

</manifest>
package id.ac.ui.cs.mobileprogramming.ahmad_fauzan_amirul_isnain.stockquoteservice;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
public class StockQuoteService extends Service
{
    private static final String TAG = "StockQuoteService";
    public class StockQuoteServiceImpl extends IStockQuoteService.Stub
    {
        @Override
        public double getQuote(String ticker) throws RemoteException
        {
            Log.v(TAG, "getQuote() called for " + ticker);
            return 20.0;
        }
    }
    @Override
    public void onCreate() {
        super.onCreate();
        Log.v(TAG, "onCreate() called");
    }
    @Override
    public void onDestroy()
    {
        super.onDestroy();
        Log.v(TAG, "onDestroy() called");
    }
    @Override
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);
        Log.v(TAG, "onStart() called");
    }
    @Override
    public IBinder onBind(Intent intent)
    {
        Log.v(TAG, "onBind() called");
        return new StockQuoteServiceImpl();
    }
}
// IStockQuoteService.aidl
package id.ac.ui.cs.mobileprogramming.ahmad_fauzan_amirul_isnain.stockquoteservice;

// Declare any non-default types here with import statements

interface IStockQuoteService {
    double getQuote(String ticker);
}

1 Ответ

0 голосов
/ 09 ноября 2019

Я использую код из книги Pro Android 2

Эта книга с 2010 года. Большая часть этой книги устарела. Пожалуйста, используйте что-то более новое. Если ничего другого, вы можете скачать старые версии одной из моих книг бесплатно. Прямо сейчас самая последняя версия этих книг - с 2015 года - хотя она и немного устарела, она на намного более актуальна, чем книга 2010 года.

IЯ уже пробовал много решений в других вопросах, подобных этому, но для меня не существует никакого рабочего решения.

У вас есть:

            intent.setClassName("com.id.ac.ui.cs.mobileprogramming" +
                    ".ahmad_fauzan_amirul_isnain.stockquoteservice",
                    "com.id.ac.ui.cs.mobileprogramming.ahmad_fauzan_amirul_isnain" +
                            ".stockquoteservice.IStockQuoteService");

package вваш манифест имеет id.ac.ui.cs.mobileprogramming.ahmad_fauzan_amirul_isnain.stockquoteservice. Предполагая, что ваш applicationId в файле build.gradle вашего модуля совпадает, я думаю, что это совпадает с тем, что есть в вашем коде. Ваш идентификатор приложения очень длинный - в будущем я рекомендую использовать что-то более короткое и более простое для визуального сравнения.

Однако имя вашего класса неверно. Ваш <service> класс StockQuoteService, а не IStockQuoteService. IStockQuoteService - это название AIDL, а не службы, и ваш Intent должен указывать на службу. Итак, попробуйте:

            intent.setClassName("com.id.ac.ui.cs.mobileprogramming" +
                    ".ahmad_fauzan_amirul_isnain.stockquoteservice",
                    "com.id.ac.ui.cs.mobileprogramming.ahmad_fauzan_amirul_isnain" +
                            ".stockquoteservice.StockQuoteService");

Или, чтобы уменьшить дублирование:

            String packageName = "com.id.ac.ui.cs.mobileprogramming" +
                    ".ahmad_fauzan_amirul_isnain.stockquoteservice";
            intent.setClassName(packageName, packageName+".StockQuoteService");
...