ОШИБКА: попытка вызвать виртуальный метод «java.lang.Object android.content.Context.getSystemService (java.lang.String)» для нулевой ссылки на объект

Я пытаюсь внедрить MovementDetector в свою программную клавиатуру, но получаю эту ошибку. Когда я компилирую свой код, все работает, но когда я начинаю использовать свою клавиатуру, он показывает ошибку в logcat. Вот мой код:

public class MovementDetector implements SensorEventListener {

protected final String TAG = getClass().getSimpleName();
private Sensor accelerometer;
private SensorManager mSensorMgr;
public static Context mContext;
float [] history = new float[2];
public static String [] direction = {"NONE","NONE"};

private MovementDetector(Context context) {
    mContext = context;
}

private static MovementDetector mInstance;

public static MovementDetector getInstance() {
    if (mInstance == null) {
        mInstance = new MovementDetector(mContext);
        mInstance.init();
    }
    return mInstance;
}

private HashSet<Listener> mListeners = new HashSet<MovementDetector.Listener>();

private void init() {
    mSensorMgr = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
    accelerometer = mSensorMgr.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION);
}

public void start() {
    mSensorMgr.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL);
}

public void stop() {
    mSensorMgr.unregisterListener(this);
}

public void addListener(Listener listener) {
    mListeners.add(listener);
}

@Override
public void onSensorChanged(SensorEvent event) {
    if (event.sensor.getType() == Sensor.TYPE_LINEAR_ACCELERATION) {

        float x = event.values[0];
        float y = event.values[1];
        float z = event.values[2];

        float xChange = history[0] - event.values[0];
        float yChange = history[1] - event.values[1];

        history[0] = event.values[0];
        history[1] = event.values[1];

        float diff = (float) Math.sqrt(x * x + y * y + z * z);
        if (diff > 0.5)
            if (xChange > 2){
                direction[0] = "LEFT";
            }else if (xChange < -2){
                direction[0] = "RIGHT";
            }

            if (yChange > 2){
                direction[1] = "DOWN";
            }else if (yChange < -2){
                direction[1] = "UP";
            }

        for (Listener listener : mListeners) {
            listener.onMotionDetected(event, diff);
        }
    }
}

@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {

}

public interface Listener {
    void onMotionDetected(SensorEvent event, float acceleration);
}

}

Я получаю ошибку в этой строке:

mSensorMgr = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);

Я запускаю MovementDetector в OnCreateInputView() и останавливаю его в OnDestory(), но проблема не в этом. Проблема в классе MovementDetector. Может кто-нибудь, пожалуйста, скажите мне, что мне делать и что я сделал не так? Заранее спасибо. Действительно нужно, чтобы этот MovementDetector работал.


person jelic98    schedule 12.08.2015    source источник
comment
Ваша переменная mContext равна нулю. Его не передают должным образом в конструкторе. Поставьте точку останова в конструкторе и посмотрите, получите ли вы там значение.   -  person Antrromet    schedule 12.08.2015
comment
Извините, я новичок в Android-разработке и мало что знаю о контексте и экземпляре. Вот что я пробовал, но это не сработало: private MovementDetector(Context context) { if(context != null) { mContext = context; } }   -  person jelic98    schedule 12.08.2015
comment
Это нормально. Но убедитесь, что вы правильно передаете context конструктору. Проверьте место, где вы инициализируете MovementDetector cariable.   -  person Antrromet    schedule 15.08.2015
comment
Здесь я инициализирую его mSensorMgr = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);, и ошибка в этой строке   -  person jelic98    schedule 15.08.2015
comment
Я спрашиваю об инициализации класса MovementDetector. Это будет выглядеть примерно так: mMovementDetector = new MovementDetector();. Не могли бы вы вставить эту строку?   -  person Antrromet    schedule 15.08.2015
comment
Этот код находится в основном классе, который расширяет InputMethodService: MovementDetector.getInstance().start(); MovementDetector.getInstance().addListener(new MovementDetector.Listener() {/*detection of the movement*/} и нигде больше я не могу найти new MovementDetector   -  person jelic98    schedule 15.08.2015


Ответы (1)


Итак, наконец, основываясь на ваших комментариях сверху, я смог определить проблему. Кажется, что класс MovementDetector использует шаблон проектирования singleton.

Чтобы получить экземпляр MovementDetector, вы используете следующий код

MovementDetector.getInstance()

а метод getInstance() в MovementDetector определяется как

public static MovementDetector getInstance() {
    if (mInstance == null) {
        mInstance = new MovementDetector(mContext);
        mInstance.init();
    }
    return mInstance;
}

Теперь, когда этот код (getInstance()) вызывается в первый раз, mInstance имеет значение null, поэтому он создает его экземпляр.

mInstance = new MovementDetector(mContext);

Но проблема выше в том, что mContext равно null, и поэтому вы получаете ошибку! Чтобы решить вашу проблему, вы должны передать context методу getInstance(). Это должно выглядеть примерно так.

public static MovementDetector getInstance(Context context) {
        if (mInstance == null) {
            mInstance = new MovementDetector(context);
            mInstance.init();
        }
        return mInstance;
    }

И где бы вы ни вызывали этот метод getInstance(), он должен измениться на что-то вроде

MovementDetector.getInstance(context).start(); 
person Antrromet    schedule 15.08.2015
comment
Рад, что смог помочь! Удачного кодирования :) - person Antrromet; 15.08.2015