bindService android AIDL总是返回false

时间:2019-11-09 15:14:49

标签: java android aidl

我想提供可以被其他应用调用的服务。因此,我有服务和帮助。但是,当我尝试使用单独的应用程序来绑定此服务(bindService)时,它只是返回false,这意味着失败。这是我的代码。

我正在使用Android Pro 2中的代码

在与此类似的其他问题上,我已经尝试了许多解决方案,但是没有适合我的解决方案。

我尝试修复了辅助工具意图过滤器,但仍无法正常工作

我已经尝试在客户端应用程序中修复程序包名称和类名称,但是仍然无法正常工作。

请帮助我!

在客户端上:

// 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 :(得分:1)

  

我正在使用Android Pro 2中的代码

那本书是2010年写的。那本书的很多都已经过时了。请使用较新的东西。如果没有其他问题,您可以免费下载older editions of one of my books。目前,这些书的最新版本是2015年的书-虽然也有些陈旧,但与2010年的书相比,书中的书是最新的书。

  

在与此类似的其他问题上,我已经尝试了许多解决方案,但是没有适合我的解决方案。

您有:

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

清单中的packageid.ac.ui.cs.mobileprogramming.ahmad_fauzan_amirul_isnain.stockquoteservice。假设模块的applicationId文件中的build.gradle是相同的,我认为这与代码中的内容匹配。您的应用程序ID很长-将来,我建议您使用更短,更容易直观比较的内容。

但是,您的班级名称错误。您的<service>类是StockQuoteService,而不是IStockQuoteServiceIStockQuoteService是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");