Android 闹钟空异常

Android Alarm Clock NullException

我是 Android Studio 的初学者。

目前,我正在尝试使用 Android Studio 制作闹钟。我在尝试 运行 代码时遇到了一些错误。当它开始 运行 时,它给了我这些错误行。

E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.google.alarmclock, PID: 2837
java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.google.alarmclock/com.google.alarmclock.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.content.Context.getPackageName()' on a null object reference
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2548)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2707)
    at android.app.ActivityThread.-wrap12(ActivityThread.java)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1460)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:154)
    at android.app.ActivityThread.main(ActivityThread.java:6077)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
 Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.content.Context.getPackageName()' on a null object reference
    at android.content.ComponentName.<init>(ComponentName.java:128)
    at android.content.Intent.<init>(Intent.java:4868)
    at com.google.alarmclock.MainActivity.<init>(MainActivity.java:30)
    at java.lang.Class.newInstance(Native Method)
    at android.app.Instrumentation.newActivity(Instrumentation.java:1078)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2538)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2707) 
    at android.app.ActivityThread.-wrap12(ActivityThread.java) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1460) 
    at android.os.Handler.dispatchMessage(Handler.java:102) 
    at android.os.Looper.loop(Looper.java:154) 
    at android.app.ActivityThread.main(ActivityThread.java:6077) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755) 

这是我的 java 文件。

Alarm_Receiver.java

package com.google.alarmclock;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

public class Alarm_Receiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.e("We are in the Receiver","yaa");

        //fetch extra strings from the intent
        String get_your_string = intent.getExtras().getString("extra");

        Log.e("What is the key?", get_your_string);

        //create an intent to the ringtone service
        Intent service_intent=new Intent(context,RingtonePlayingService.class);

        //pass the extra string from Main Activity to the Ringtone Playing Service
        service_intent.putExtra("extra",get_your_string);

        //start the ringtone service
        context.startService(service_intent);
    }
}

RingtonePlayingService.java

package com.google.alarmclock;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.util.Log;
import android.widget.Toast;

import java.security.Provider;
import java.util.List;
import java.util.Map;   

public class RingtonePlayingService extends Service {

    MediaPlayer media_song;
    int startId;
    boolean isRunning;

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i("LocalService", "Received start id " + startId + ": " + intent);

        //fetch the extra string values
        String state = intent.getExtras().getString("extra");

        Log.e("Ringtone extra is",state);

        //this converts the extra strings from the intent
        //to start IDs, values 0 or 1
        assert state !=null;
        switch (state) {
            case "alarm on":
                startId = 1;
                break;
            case "alarm off":
                startId = 0;
                Log.e("Start ID is ",state);
                break;
            default:
                startId = 0;
                break;
        }

        //if else statements

        //if there is no music playing, and the user pressed "alarm on"
        //music should start playing
        if (!this.isRunning && startId==1) {
            Log.e("there is no music, ","and you want start");
            //create an instance of the media player
            media_song = MediaPlayer.create(this,R.raw.i_am_singer);
            media_song.start();

            this.isRunning=true;
            this.startId=0;

            //put the notification here,test it out
            //notification
            //set up the notification service
            NotificationManager notify_manager=(NotificationManager)
                    getSystemService(NOTIFICATION_SERVICE);
            //set up an intent that goes to the Main Activity
            Intent intent_main_activity=new Intent(this.getApplicationContext(),MainActivity.class);

            //set up a pending intent
            PendingIntent pending_intent_main_activity=PendingIntent.getActivity(this,0,
                    intent_main_activity,0);

            //make the notification parameters
            Notification notification_popup=new Notification.Builder(this)
                    .setContentTitle("An alarm is going off!")
                    .setContentText("Click Me")
                    .setContentIntent(pending_intent_main_activity)
                    .setAutoCancel(true)
                    .build();

            //set up the notification call command
            notify_manager.notify(0,notification_popup);

        }
        //if there is music playing, and the user pressed "alarm off"
        //music should stop playing
        else if (this.isRunning && startId == 0) {
            Log.e("there is music, ","and you want end");

            //stop the ringtone
            media_song.stop();
            media_song.reset();

            this.isRunning=false;
            this.startId=0;

        }
        //there are if user presses random buttons
        //just to bug-proof the app
        //if there is no music playing, and the user pressed "alarm off"
        //do nothing
        else if (!this.isRunning && startId == 0) {
            Log.e("there is no music, ","and you want end");

            //stop the ringtone
            this.isRunning=false;
            this.startId=0;

        }
        //if there is music playing and the user pressed "alarm on"
        //do nothing
        else if (this.isRunning && startId ==1) {
            Log.e("there is music, ","and you want start");

            this.isRunning =true;
            this.startId=1;

        }
        //can't think of anything else, just to catch the odd event
        else {
            Log.e("else ","somehow you reached ");
        }
        return START_NOT_STICKY;
    }

    @Override
    public void onDestroy() {
        // Tell the user we stopped.
        Log.e("on Destroy called","ta da");
        super.onDestroy();;
        this.isRunning=false;
        Toast.makeText(this, "on Destroy called ", Toast.LENGTH_SHORT).show();
    }
}

MainActivity.java

package com.google.alarmclock;

import android.annotation.TargetApi;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Button;
import android.widget.TextView;
import android.widget.TimePicker;
import java.util.Calendar;

public class MainActivity extends AppCompatActivity {
    //to make alarm manager
    AlarmManager alarm_manager;
    TimePicker alarm_timepicker;
    TextView update_text;
    Context context;
    PendingIntent pendingIntent;
    final Intent my_intent=new Intent(this.context,Alarm_Receiver.class);

    //create an instance of a calender
    final Calendar calendar= Calendar.getInstance();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        this.context = this;

        //initialize alarm manager
        alarm_manager=(AlarmManager)getSystemService(ALARM_SERVICE);

        //initialize timepicker
        alarm_timepicker=(TimePicker)findViewById(R.id.timePicker);

        //initialize our text update box
        update_text=(TextView)findViewById(R.id.update_text);



        //initialize start buttons
      // Button start_alarm=(Button)findViewById(R.id.start_alarm);



        //initialize the stop button
        //Button stop_button=(Button)findViewById(R.id.end_alarm);

        //Create an intent to the Alarm Receiver class


    }

    //create an onClick listener to start the alarm
    @TargetApi(Build.VERSION_CODES.M)
    public void onClickStartAlarm(View view)
    {
        //setting calendar instance with the hour and minute that have picked
        //on the time picker
        calendar.set(Calendar.HOUR_OF_DAY,alarm_timepicker.getHour());
        calendar.set(Calendar.MINUTE,alarm_timepicker.getMinute());

        //get the string values of the hour and minute
        int hour=alarm_timepicker.getHour();
        int minute=alarm_timepicker.getMinute();

        //convert the int values to Strings
        String hour_string=String.valueOf(hour);
        String minute_string=String.valueOf(minute);

        //convert 24 hour time to 12 hour time
        if(hour>12)
        {
            hour_string="0" + String.valueOf(hour -12);
        }


        if(minute<10)
        {
            //10:7 --> 10:07
            minute_string=String.valueOf(minute);
        }

        //method that changes the update text Textbox
        set_alarm_text("Alarm On: " + hour_string + ":" +minute_string);

        //put in extra string into my_intent
        //tells the clock that you pressed the "alarm on" button
        my_intent.putExtra("extra","on");


        //Create a pending intent that delays the intent
        //until the specified calendar time
        pendingIntent = PendingIntent.getBroadcast(MainActivity.this,0,my_intent,PendingIntent.FLAG_UPDATE_CURRENT);

        //set the alarm manager
        alarm_manager.set(AlarmManager.RTC_WAKEUP,calendar.getTimeInMillis(),pendingIntent);
    }

    private void set_alarm_text(String output) {
        update_text.setText(output);
    }

    //create an onClick listener to stop the alarm or undo an alarm set
    public void onClickStopAlarm(View view)
    {
        //method that changes the update text Textbox
        set_alarm_text("Alarm off!");

        //Cancel the alarm
        alarm_manager.cancel(pendingIntent);

        //put extra string into my_intent
        //tells the clock that you pressed the "alarm off" button
        my_intent.putExtra("extra","off");


        //Stop the ringtone
        sendBroadcast(my_intent);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>

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

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

    <receiver android:name=".Alarm_Receiver"/>
    <service android:name=".RingtonePlayingService"
        android:enabled="true"/>
</application>

build.gradle

apply plugin: 'com.android.application'

android {
    compileSdkVersion 24
    buildToolsVersion "24.0.2"
    defaultConfig {
        applicationId "com.google.alarmclock"
        minSdkVersion 16
        targetSdkVersion 24
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:24.2.1'
    compile 'com.android.support:design:24.2.1'
    testCompile 'junit:junit:4.12'
}

请帮我解决问题。谢谢

更改此行 final Calendar calendar = Calendar.getInstance(); 如下。

onCreate()

中初始化
 ...    
//create an instance of a calender
//final Calendar calendar= Calendar.getInstance();
Calendar calendar;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    calendar= Calendar.getInstance();
 ...
}

您应该在 onCreate 外声明 Calender 对象并在 onCreate 内初始化它。

Calendar calendar;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    calendar= Calendar.getInstance();
 ...
}

此外,您仍然会得到 NullPointerException,因为在这一行

final Intent my_intent=new Intent(this.context,Alarm_Receiver.class);

您的上下文将为空。所以你也可以这样做。

Intent my_intent;
Calendar calendar;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    this.context = this;

    calendar= Calendar.getInstance();

    my_intent=new Intent(this.context,Alarm_Receiver.class);

 ...
}

编码愉快。