Mohamed Android Developer Ответов: 3

Почему исключение нулевого указателя появляется при запуске связанного сервиса android


Я думаю, что все сделал хорошо, но я не знаю, почему это появляется
Это MainActivity.java Код
package com.smarty_tech.boundservice;

import android.app.Service;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;


public class MainActivity extends AppCompatActivity {
    private static String LOG_TAG = "MainActivity";

    private Button btnStartService;
    private Button btnStopService;

    SmartyService service;
    boolean mBound = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        final Intent intent = new Intent(MainActivity.this, SmartyService.class);
        btnStartService = (Button) findViewById(R.id.btn_start_service);
        btnStopService = (Button) findViewById(R.id.btn_stop_service);



        btnStartService.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
               bindService(intent, connection, Service.BIND_AUTO_CREATE);
               //service.printHelloWorld();
             int x = service.getRandomNumber();
                Log.e("Start Bound Service", "Bound Successfuly and X value is ");
            }
        });

        btnStopService.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                unbindService(connection);
                Log.e("Start Bound Service", "UnBounded Successfuly");
            }
        });

    }

    /** Defines callbacks for service binding, passed to bindService() */
    public ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName className, IBinder service) {
            // We've bound to SmartyService, cast the IBinder and get SmartyService instance
            SmartyService.SmartyBinder smartyBinder = (SmartyService.SmartyBinder) service;
            MainActivity.this.service = smartyBinder.getService();
            mBound = true;
            Log.e(LOG_TAG, "onServiceConnected call");
        }

        @Override
        public void onServiceDisconnected(ComponentName className) {
            MainActivity.this.service = null;
            mBound = false;
            Log.e(LOG_TAG, "onServiceDisconnected call");
        }
    };
}


А это мой служебный код

package com.smarty_tech.boundservice;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;

import java.util.Random;

public class SmartyService extends Service {
    private static String LOG_TAG = "SmartyService";

    public SmartyService() {
    }

    // Binder given to clients
    private final IBinder binder = new SmartyBinder();
    // Random number generator
    private final Random mGenerator = new Random();

    /**
     * Class used for the client Binder.  Because we know this service always
     * runs in the same process as its clients, we don't need to deal with IPC.
     */
    public class SmartyBinder extends Binder{
        SmartyService getService(){
            // Return this instance of LocalService so clients can call public methods
            Log.v(LOG_TAG, "in SmartyBinder");
            return SmartyService.this;
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        //throw new UnsupportedOperationException("Not yet implemented");
       // printHelloWorld();
        Log.v(LOG_TAG, "in onBind");
        return binder;
    }

    @Override
    public void onRebind(Intent intent) {
        Log.v(LOG_TAG, "in onRebind");
        super.onRebind(intent);
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.v(LOG_TAG, "in onUnbind");
        return true;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.e(LOG_TAG, "onCreated Called !");
    }


    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.e(LOG_TAG, "onDestroy Called , I will miss you !");
    }

    /** method for clients */
    public void printHelloWorld(){
        //for(int i = 0; i < 1000 ; i++){
            Log.e(LOG_TAG, "Hello Wolrd");
        //}
    }

    /** method for clients */
    public int getRandomNumber() {
        return mGenerator.nextInt(100);
    }
    /*

    The SmartyBinder provides the getService() method for clients to retrieve the current instance of SmartyService.
    This allows clients to call public methods in the service. For example, clients can call printHelloWorld() from the service.
     */
}


а вот это main_activity.xml из макета

<pre><?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/btn_start_service"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Start Service"
        />

    <Button
        android:id="@+id/btn_stop_service"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Stop Service"
        />

</LinearLayout>


Что я уже пробовал:

Когда я пытаюсь запустить службу, в Logcat появляется следующее исключение

06-11 09:43:03.654 2380-2380/com.smarty_tech.boundservice E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.smarty_tech.boundservice, PID: 2380
    java.lang.NullPointerException
        at com.smarty_tech.boundservice.MainActivity$1.onClick(MainActivity.java:39)
        at android.view.View.performClick(View.java:4438)
        at android.view.View$PerformClick.run(View.java:18422)
        at android.os.Handler.handleCallback(Handler.java:733)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:136)
        at android.app.ActivityThread.main(ActivityThread.java:5019)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:515)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
        at dalvik.system.NativeStart.main(Native Method)

3 Ответов

Рейтинг:
27

User 7429338

Это вопрос времени. Вы звоните bindService чтобы связать вашу службу, которая будет асинхронно вызов onServiceConnected После этого вы можете использовать переменную service Вы используете его до того, как он будет назначен.


Рейтинг:
2

Mohamed Android Developer

Тогда самое лучшее место для звонка

getRandomNumber()

В
onServiceConnected

Как это:
public void onServiceConnected(ComponentName className, IBinder service) {
    // We've bound to SmartyService, cast the IBinder and get SmartyService instance
    SmartyService.SmartyBinder smartyBinder = (SmartyService.SmartyBinder) service;
    MainActivity.this.service = smartyBinder.getService();
    mBound = true;
    int x = MainActivity.this.service.getRandomNumber();
    Log.e(LOG_TAG, "onServiceConnected call the value of X is "+ x);
}


Это правда?


[no name]

Это будет работать, но тогда он будет вызывать его каждый раз, когда вы привязываете службу. Это может быть или не быть тем, чего вы хотите.
Вы можете добавить 3 кнопки: "привязать", "получить случайный" и "отменить привязку". Затем в обработчике для "Get random" сделайте проверку, если service не является нулевым.

Рейтинг:
1

Mohamed Android Developer

Большое вам спасибо (Таддеус Джонс), это сработало для меня ..


[no name]

В любое время :) Для дальнейшего использования; вы можете использовать комментарии для публикации ответов на решение, а не для публикации в качестве нового решения.

Mohamed Android Developer

Ладно, Спасибо ...