绑定在Service类中的Binder类的NoClassDefFoundError

时间:2014-02-11 21:42:11

标签: java android google-glass

我是Android / Glass开发的新手,但我已经开始解决看起来非常具有挑战性的任务了。我试图通过蓝牙向Glass和我的计算机发送String消息。

我有蓝牙功能的服务,我有一个嵌套在该服务中的活页夹类。但是,当我尝试调用某个绑定程序的方法时,应用程序崩溃了。

崩溃发生在这一行:

mBluetoothService.requestConnect();

导致此错误:

  

java.lang.NoClassDefFoundError:   com.riverlab.glassbluetooth.BluetoothService $ RemoteConnectionBinder

运行此代码:

MainActivity.java:处理菜单项

package com.riverlab.glassbluetooth;

import com.example.glassbluetooth.R;
import com.keyboardr.glassremote.client.RemoteMessenger;
import com.keyboardr.glassremote.client.RemoteMessengerService;

import android.os.Bundle;
import android.os.IBinder;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.view.Menu;
import android.view.MenuItem;

public class MainActivity extends Activity {

    private boolean mResumed;
    private GlassBluetoothService.MainBinder mService;
    private BluetoothService.RemoteConnectionBinder mBluetoothService;

    //Name is deceptive, this binder is for the voice control
    private ServiceConnection mConnection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName arg0, IBinder binderService) {
            if(binderService instanceof GlassBluetoothService.MainBinder) {
                mService = (GlassBluetoothService.MainBinder) binderService;
                openOptionsMenu();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName arg0) {
            // TODO Auto-generated method stub
        }
    };

    //Connection for the bluetooth binder
    private ServiceConnection mBluetoothConnection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName arg0, IBinder binderService) {
            if(binderService instanceof RemoteMessengerService.RemoteConnectionBinder){
                mBluetoothService = (BluetoothService.RemoteConnectionBinder) binderService;
                openOptionsMenu();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName arg0) {
            // TODO Auto-generated method stub
        }
    };


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if(mService == null) {
            bindService(new Intent(this, GlassBluetoothService.class), mConnection, 0);
        }

        if (mBluetoothService == null)
        {
            bindService(new Intent(this, BluetoothService.class), mBluetoothConnection, 0);
        }

    }

    @Override
    protected void onResume() {
        super.onResume();
        mResumed = true;
    }

    @Override
    protected void onPause() {
        super.onPause();
        mResumed = false;
    }

    @Override
    public void openOptionsMenu() {
        if (mResumed && mService != null) {
            super.openOptionsMenu();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu, menu);
        return true;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        finish();
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.read_connection_status:
                mService.speakConnectionStatus();
                finish();
                return true;
            case R.id.connect:
                mBluetoothService.requestConnect();
                finish();
                return true;
            case R.id.stop:
                stopService(new Intent(this, GlassBluetoothService.class));
                stopService(new Intent(this, BluetoothService.class));
                finish();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    @Override
    public void onOptionsMenuClosed(Menu menu) {
        super.onOptionsMenuClosed(menu);

        unbindService(mConnection);
    }
}

BluetoothService.java:处理蓝牙

package com.riverlab.glassbluetooth;

import java.util.UUID;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.speech.tts.TextToSpeech;

import com.example.glassbluetooth.R;
import com.keyboardr.glassremote.client.RemoteMessenger;
import com.keyboardr.glassremote.client.RemoteMessengerImpl;
import com.keyboardr.glassremote.client.StringRemoteMessengerService;
import com.keyboardr.glassremote.client.RemoteMessenger.Callback;
import com.keyboardr.glassremote.client.RemoteMessengerService.RemoteConnectionBinder;
import com.keyboardr.glassremote.common.receiver.MessageReceiver;
import com.keyboardr.glassremote.common.receiver.StringMessageReader;
import com.keyboardr.glassremote.common.sender.MessageSender;
import com.keyboardr.glassremote.common.sender.StringMessageSender;

public class BluetoothService extends Service
{
    private final RemoteConnectionBinder mBinder = new RemoteConnectionBinder();

    private RemoteMessenger<String, String> mMessenger;

    public class RemoteConnectionBinder extends Binder implements
            RemoteMessenger<String, String> {

        @Override
        public void setCallback(Callback<? super String> callback) {
            mMessenger.setCallback(callback);
        }

        @Override
        public boolean isConnected() {
            return mMessenger.isConnected();
        }

        @Override
        public void requestConnect() {
            mMessenger.requestConnect();
        }

        @Override
        public void disconnect() {
            mMessenger.disconnect();
        }

        @Override
        public void sendMessage(String arg0) throws IllegalStateException {
            // TODO Auto-generated method stub

        }

    }


    public void onCreate()
    {
        super.onCreate();
        mMessenger = new RemoteMessengerImpl<String, String>(UUID.randomUUID(), new StringMessageSender(), new StringMessageReader());
    }

    public void onStartCommand()
    {
        mMessenger.requestConnect();
        while (!mMessenger.isConnected());
        mMessenger.sendMessage("Connection Succesful");
    }

    @Override
    public void onDestroy() {
        mMessenger.disconnect();
        super.onDestroy();
    }

    @Override
    public IBinder onBind(Intent intent) {
        mMessenger.setCallback(null);
        return mBinder;
    }

    @Override
    public boolean onUnbind(Intent intent) {
        mMessenger.setCallback(null);
        mMessenger.disconnect();
        return super.onUnbind(intent);
    }

}

两个文件都在同一个包中。我在我的buildpath中添加了三个jar文件,它们似乎与问题无关,但是如果这可能会导致问题,请告诉我。我在Ubuntu 12.04上使用Eclipse ADT Build:v22.3.0-887826

提前感谢您的帮助!我无法想出这个。

编辑:这是RemoteMessenger

package com.keyboardr.glassremote.client;

import java.lang.ref.WeakReference;
import java.util.UUID;

import android.bluetooth.BluetoothDevice;

import com.keyboardr.glassremote.common.receiver.MessageReceiver;
import com.keyboardr.glassremote.common.receiver.StringMessageReader;
import com.keyboardr.glassremote.common.sender.MessageSender;
import com.keyboardr.glassremote.common.sender.StringMessageSender;

/**
 * Interface for communicating with the remote server. There should be a
 * <code>MessageService&lt;R, S></code> running on that remote server.
 * 
 * @author Joshua Brown
 * 
 * @param <S>
 *            the type of messages this <code>RemoteMessenger</code> will send
 *            to the remote server. The corresponding
 *            <code>MessageService</code> on the remote server should receive
 *            messages as <code>S</code> or some superclass thereof.
 * @param <R>
 *            the type of messages this <code>RemoteMessenger</code> will
 *            receive from the remote server. The corresponding
 *            <code>MessageService</code> on the remote server should send
 *            messages as <code>R</code> or some subclass thereof.
 */
public interface RemoteMessenger<S, R> {

    /**
     * Callback interface for <code>RemoteMessenger</code>. All callbacks will
     * be called on the main thread.
     * 
     * @param <M>
     *            message type to receive
     */
    public static interface Callback<M> {
        /**
         * The <code>RemoteMessenger</code> has connected to
         * <code>remoteDevice</code> and is able to send and receive messages
         * 
         * @param remoteDevice
         *            the <code>BluetoothDevice</code> this
         *            <code>RemoteMessenger</code> has connected to
         */
        public void onConnected(BluetoothDevice remoteDevice);

        /**
         * The <code>RemoteMessenger</code> has failed to connect to any
         * devices. Messages cannot be sent or received
         */
        public void onConnectionFailed();

        /**
         * The <code>RemoteMessenger</code> has disconnected from
         * <code>remoteDevice</code> and can no longer send or receive messages
         * 
         * @param remoteDevice
         *            the <code>BluetoothDevice</code> this
         *            <code>RemoteMessenger</code> was connected to
         */
        public void onDisconnected(BluetoothDevice remoteDevice);

        /**
         * The <code>RemoteMessenger</code> has received a message from the
         * remote server
         * 
         * @param message
         *            the <code>M</code> message received from the remote server
         */
        public void onReceiveMessage(M message);
    }

    /**
     * Sets callback destination. Implementations should use
     * {@link WeakReference WeakReferences} to ensure the
     * <code>RemoteMessenger</code> does not inadvertently keep the
     * <code>Callback</code> from being GCed
     * 
     * @param callback
     */
    public void setCallback(Callback<? super R> callback);

    /**
     * Checks if this <code>RemoteMessenger</code> is connected to a remote
     * server
     * 
     * @return <code>true</code> iff this <code>RemoteMessenger</code> can send
     *         and receive messages from a remote server
     */
    public boolean isConnected();

    /**
     * Attempts to connect to a remote server. Calls
     * {@link Callback#onConnected(BluetoothDevice) onConnected()} callback if
     * successful or {@link Callback#onConnectionFailed() onConnectionFailed()}
     * if unsuccessful
     */
    public void requestConnect();

    /**
     * Disconnects from the remote server. Calls
     * {@link Callback#onDisconnected(BluetoothDevice) onDisconnected()} when
     * finished
     */
    public void disconnect();

    /**
     * Sends a <code>S</code> message to the remote server. May be called from
     * the main thread
     * 
     * @param message
     *            the <code>S</code> message to send
     * @throws IllegalStateException
     *             If the <code>RemoteMessenger</code> is not connected
     */
    public void sendMessage(S message) throws IllegalStateException;

    public static class Factory {

        private Factory() {
        }

        /**
         * Gets an instance of <code>RemoteMessenger</code> that sends and
         * receives <code>String</code> messages<br/>
         * <br/>
         * <b>Note:</b> Messages are separated by <code>'\n'</code> characters
         * 
         * @param uuid
         *            a <code>UUID</code> shared between the remote server and
         *            this client. UUIDs can be obtained at <a
         *            href="http://www.uuidgenerator.net/">http
         *            ://www.uuidgenerator.net/</a> and instantiated using
         *            {@link UUID#fromString(String)}.
         * @return a <code>RemoteMessenger</code> that sends and receives
         *         <code>String</code> messages
         */
        public static RemoteMessenger<String, String> getStringRemoteMessenger(
                UUID uuid) {
            return new RemoteMessengerImpl<String, String>(uuid,
                    new StringMessageSender(), new StringMessageReader());
        }

        /**
         * Get an instance of <code>RemoteMessenger</code> that sends
         * <code>S</code> and receives <code>R</code> messages
         * 
         * @param uuid
         *            a <code>UUID</code> shared between the remote server and
         *            this client. UUIDs can be obtained at <a
         *            href="http://www.uuidgenerator.net/">http
         *            ://www.uuidgenerator.net/</a> and instantiated using
         *            {@link UUID#fromString(String)}.
         * @param sender
         *            the <code>MessageSender</code> providing the
         *            implementation for sending <code>S</code> messages
         * @param receiver
         *            the <code>MessageReceiver</code> providing the
         *            implementation for receiving <code>R</code> messages
         */
        public static <S, R> RemoteMessenger<S, R> getRemoteMessenger(
                UUID uuid, MessageSender<S> sender, MessageReceiver<R> receiver) {
            return new RemoteMessengerImpl<S, R>(uuid, sender, receiver);
        }

    }

}

1 个答案:

答案 0 :(得分:1)

  

至于我如何添加它们,我右键单击我的项目,选择Build Path,Add External Archive,然后我选择了我的jar

这不是您如何将JAR添加到Android项目中。请撤消该操作,然后在项目中创建一个libs/目录(如果它尚不存在),然后将JAR复制到libs/。这不仅会自动将它们添加到编译时构建路径中,而且还会将其内容打包到APK文件中。您的方法解决了编译时构建路径,但JAR未打包在APK中,并且在运行时不可用。