Android Studio 在闹钟就绪时启动媒体播放器

Android Studio Starting the Mediaplayer when the alarm is ready

你好,我有 2 个活动,2 个应用程序,每个应用程序都有 classes(总共大约 10 classes),我想将它们结合起来。我有一个功能性警报和一个功能性 MediaPlayer。我想在触发闹钟的时候启动媒体播放器。问题是我的应用程序在响铃时崩溃了。 媒体播放器 class:

package com.never.mediaalarmplayer;

import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.ListView;
import android.widget.MediaController;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

/**
 * Created by Never on 5/14/2017.
 */

public class MediaPlayer extends AppCompatActivity implements MediaController.MediaPlayerControl {
    private ArrayList<Song> songList;
    private ListView songView;
    private MusicService musicSrv;
    private Intent playIntent;
    private boolean musicBound=false;
    private MusicController controller;
    private boolean paused=false, playbackPaused=false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.mediaplayer);
        songView = (ListView)findViewById(R.id.song_list);
        songList = new ArrayList<>();
        getSongList();
        Collections.sort(songList, new Comparator<Song>(){
            public int compare(Song a, Song b){
                return a.getTitle().compareTo(b.getTitle());
            }
        });
        SongAdapter songAdt = new SongAdapter(this, songList);
        songView.setAdapter(songAdt);
        setController();
        Button btn = (Button)findViewById(R.id.open_alarm);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(new Intent(MediaPlayer.this, Alarm.class));
            }
        });
    }
    //connect to the service
    private ServiceConnection musicConnection = new ServiceConnection(){

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            MusicService.MusicBinder binder = (MusicService.MusicBinder)service;
            //get service
            musicSrv = binder.getService();
            //pass list
            musicSrv.setList(songList);
            musicBound = true;
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            musicBound = false;
        }
    };
    @Override
    protected void onStart() {
        super.onStart();
        if(playIntent==null){
            playIntent = new Intent(this, MusicService.class);
            bindService(playIntent, musicConnection, Context.BIND_AUTO_CREATE);
            startService(playIntent);
        }
    }
    @Override
    protected void onPause(){
        super.onPause();
        paused=true;
    }
    @Override
    protected void onResume(){
        super.onResume();
        if(paused){
            setController();
            paused=false;
        }
    }
    @Override
    protected void onStop(){
        controller.hide();
        super.onStop();
    }
    public void songPicked(View view){
        musicSrv.setSong(Integer.parseInt(view.getTag().toString()));
        musicSrv.playSong();
        if(playbackPaused){
            setController();
            playbackPaused=false;
        }
        controller.show(0);
    }
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        //menu item selected
        switch (item.getItemId()) {
            case R.id.action_shuffle:
                //shuffle
                musicSrv.setShuffle();
                break;
            case R.id.action_end:
                stopService(playIntent);
                musicSrv=null;
                System.exit(0);
                break;
        }
        return super.onOptionsItemSelected(item);
    }
    @Override
    protected void onDestroy() {
        stopService(playIntent);
        musicSrv=null;
        super.onDestroy();
    }
    public void getSongList() {
        //retrieve song info
        ContentResolver musicResolver = getContentResolver();
        Uri musicUri = android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
        Cursor musicCursor = musicResolver.query(musicUri, null, null, null, null);
        if(musicCursor!=null && musicCursor.moveToFirst()){
            //get columns
            int titleColumn = musicCursor.getColumnIndex
                    (android.provider.MediaStore.Audio.Media.TITLE);
            int idColumn = musicCursor.getColumnIndex
                    (android.provider.MediaStore.Audio.Media._ID);
            int artistColumn = musicCursor.getColumnIndex
                    (android.provider.MediaStore.Audio.Media.ARTIST);
            //add songs to list
            do {
                long thisId = musicCursor.getLong(idColumn);
                String thisTitle = musicCursor.getString(titleColumn);
                String thisArtist = musicCursor.getString(artistColumn);
                songList.add(new Song(thisId, thisTitle, thisArtist));
            }
            while (musicCursor.moveToNext());
        }
    }
    private void setController(){
        //set the controller up
        controller = new MusicController(this);
        controller.setPrevNextListeners(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                playNext();
            }
        }, new View.OnClickListener(){
            @Override
            public void onClick(View v){
                playPrev();
            }
        });
        controller.setMediaPlayer(this);
        controller.setAnchorView(findViewById(R.id.song_list));
        controller.setEnabled(true);
    }
    //play next
    private void playNext(){
            musicSrv.playNext();
        if(playbackPaused){
            setController();
            playbackPaused=false;
        }
            controller.show(0);
        }
        //play prev
    private void playPrev(){
        musicSrv.playPrev();
        if(playbackPaused) {
            setController();
            playbackPaused = false;
        }
        controller.show(0);
    }

    @Override
    public void start() {
        musicSrv.go();
    }

    @Override
    public void pause() {
        playbackPaused=true;
        musicSrv.pausePlayer();;
    }

    @Override
    public int getDuration() {
        if(musicSrv!=null &&musicBound&&musicSrv.isPng())
            return musicSrv.getDur();
        else
        return 0;
    }

    @Override
    public int getCurrentPosition() {
        if(musicSrv!=null&&musicBound&&musicSrv.isPng())
            return musicSrv.getPosn();
        else
        return 0;
    }

    @Override
    public void seekTo(int pos) {
        musicSrv.seek(pos);
    }

    @Override
    public boolean isPlaying() {
        if(musicSrv!=null&&musicBound)
            return musicSrv.isPng();
        else
        return false;
    }

    @Override
    public int getBufferPercentage() {
        return 0;
    }

    @Override
    public boolean canPause() {
        return true;
    }

    @Override
    public boolean canSeekBackward() {
        return true;
    }

    @Override
    public boolean canSeekForward() {
        return true;
    }

    @Override
    public int getAudioSessionId() {
        return 0;
    }

}

报警接收器class:

package com.never.mediaalarmplayer;

import android.content.Context;
import android.content.Intent;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.support.v4.content.WakefulBroadcastReceiver;

/**
 * Created by Never on 4/29/2017.
 */

public class AlarmReceiver extends WakefulBroadcastReceiver{
    private static Ringtone ringtone  = null;
    @Override
    public void onReceive(Context context, Intent intent) {
       Alarm.getTextView2().setText("It's time to wake up!");
        Uri uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
          ringtone = RingtoneManager.getRingtone(context, uri);
       // ringtone.play();
        MediaPlayer ms = new MediaPlayer();
        ms.onStart();
    }
    public static void stopRingtone() {
        ringtone.stop();
   }
}

和警报 class:

package com.never.mediaalarmplayer;

import android.annotation.TargetApi;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Build;
import android.os.Message;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.view.View.OnClickListener;

import java.util.Calendar;

public class Alarm extends AppCompatActivity {

    private static int timeHour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
    private static int timeMinute = Calendar.getInstance().get(Calendar.MINUTE);
    TextView textView1;
    private static TextView textView2;
    public static TextView getTextView2(){
        return textView2;
    }
    AlarmManager alarmManager;
    private PendingIntent pendingIntent;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //setam layoutul pe care ne uitam si pe care lucram
        setContentView(R.layout.activity_alarm);
        // spunem ca textView1 este textviewul cu id-ul msg1
        textView1 = (TextView)findViewById(R.id.msg1);
        // afisam ora curenta
        if(timeHour>9&&timeMinute>9)
        textView1.setText(timeHour + ":" + timeMinute);
        else if(timeHour>9&&timeMinute<=9)
            textView1.setText(timeHour + ":" + "0" + timeMinute);
        else if(timeHour<=9&&timeMinute>9)
            textView1.setText("0" + timeHour + ":" + timeMinute);
        else if(timeHour<=9&&timeMinute<=9)
            textView1.setText("0" + timeHour + ":" + "0" + timeMinute);
        textView2 = (TextView) findViewById(R.id.msg2);
        alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
        Intent myIntent = new Intent (Alarm.this,AlarmReceiver.class);
        pendingIntent = PendingIntent.getBroadcast(Alarm.this,0,myIntent,0);
        OnClickListener listener1 = new OnClickListener(){
            @Override
            public void onClick(View v) {
                textView2.setText("");
                Bundle bundle = new Bundle();
                bundle.putInt(MyConstants.HOUR, timeHour);
                bundle.putInt(MyConstants.MINUTE, timeMinute);
                MyDialogFragment fragment = new MyDialogFragment(new MyHandler());
                fragment.setArguments(bundle);
                FragmentManager manager = getSupportFragmentManager();
                FragmentTransaction transaction = manager.beginTransaction();
                transaction.add(fragment, MyConstants.TIME_PICKER);
                transaction.commit();
            }
        };
        Button btn1 = (Button)findViewById(R.id.button1);
        btn1.setOnClickListener(listener1);
        OnClickListener listener2 = new OnClickListener() {
            @Override
            public void onClick(View v) {
                textView2.setText("");
                cancelAlarm();
            }
        };
        Button btn2 = (Button)findViewById(R.id.button2);
        btn2.setOnClickListener(listener2);
        Button btn = (Button)findViewById(R.id.open_mp);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
               startActivity(new Intent(Alarm.this, MediaPlayer.class));
            }
        });
    }
    //A Handler allows you to send and process Message and Runnable objects associated with a thread's MessageQueue.
    //There are two main uses for a Handler: (1) to schedule messages and runnables to be executed as some point in the future; and (2) to enqueue an action to be performed on a different thread than your own.
    //Practic folosim un handler pentru a afisa ora la care am setat alarma dupa ce am setat-o
    class MyHandler extends Handler
    {
        @Override
        public void handleMessage (Message msg){
            //A mapping from String keys to various Parcelable values.
            //Bundle getBundle (String key)
            //Returns the value associated with the given key, or null if no mapping of the desired type exists for the given key or a null value is explicitly associated with the key.
            Bundle bundle = msg.getData();
            //preluam ora si minutul la care am setat alarma
            timeHour=bundle.getInt(MyConstants.HOUR);
            timeMinute = bundle.getInt(MyConstants.MINUTE);
            //afisam ora la care am setat alarma
            if(timeHour>9&&timeMinute>9)
                textView1.setText(timeHour + ":" + timeMinute);
            else if(timeHour>9&&timeMinute<=9)
                textView1.setText(timeHour + ":" + "0" + timeMinute);
            else if(timeHour<=9&&timeMinute>9)
                textView1.setText("0" + timeHour + ":" + timeMinute);
            else if(timeHour<=9&&timeMinute<=9)
                textView1.setText("0" + timeHour + ":" + "0" + timeMinute);
            setAlarm();
        }
    }
    @TargetApi(Build.VERSION_CODES.KITKAT)
    private void setAlarm(){
        // getInstance()
        //Gets a calendar using the default time zone and locale.
        Calendar calendar = Calendar.getInstance();
     //  set(int field, int value)
       // Sets the given calendar field to the given value.
        calendar.set(Calendar.HOUR_OF_DAY,timeHour);
        calendar.set(Calendar.MINUTE,timeMinute);
       // setExact(int type, long triggerAtMillis, PendingIntent operation)
       // Schedules the alarm and if there is already an alarm by the intent then previous one will be canceled.
        //RTC_WAKEUP
        //It is used to fire pending intent at specified time forcing the phone to wake up.
        //Practic prin linia asta de cod setam alarma si verificam daca ora curenta este egala cu ora programata pentru trezire si in caz afirmativ trimitem semnalul(pendingintent) ce este legat la intent astfel stim ca trebuie trimis catre AlarmRceiver, in acelasi timp ii spunem sa "trezeasca" telefonul
                alarmManager.setExact(
                        //ii spunem sa "trezeasca telefonul" in cazul in care trebuie sa sune alarma
                        AlarmManager.RTC_WAKEUP,
                        // preluam ora la care setam alarma si retinem totul transformat in milisecunde
                        calendar.getTimeInMillis(),
                        //verificam daca este timpul sa sunam alarma
                        pendingIntent);
    }
    private void cancelAlarm(){
        if(alarmManager!=null){
            alarmManager.cancel(pendingIntent);
           pendingIntent.cancel();
            AlarmReceiver.stopRingtone();
        }
    }

}

异常:

07-11 10:43:43.392 1915-1915/com.never.mediaalarmplayer D/Ringtone: Successfully created local player
07-11 10:43:43.397 1915-1915/com.never.mediaalarmplayer D/AndroidRuntime: Shutting down VM
07-11 10:43:43.397 1915-1915/com.never.mediaalarmplayer E/AndroidRuntime: FATAL EXCEPTION: main
                                                                          Process: com.never.mediaalarmplayer, PID: 1915
                                                                          java.lang.RuntimeException: Unable to start receiver com.never.mediaalarmplayer.AlarmReceiver: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.app.Application.dispatchActivityStarted(android.app.Activity)' on a null object reference
                                                                              at android.app.ActivityThread.handleReceiver(ActivityThread.java:2732)
                                                                              at android.app.ActivityThread.-wrap14(ActivityThread.java)
                                                                              at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1421)
                                                                              at android.os.Handler.dispatchMessage(Handler.java:102)
                                                                              at android.os.Looper.loop(Looper.java:148)
                                                                              at android.app.ActivityThread.main(ActivityThread.java:5417)
                                                                              at java.lang.reflect.Method.invoke(Native Method)
                                                                              at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                                                                              at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
                                                                           Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.app.Application.dispatchActivityStarted(android.app.Activity)' on a null object reference
                                                                              at android.app.Activity.onStart(Activity.java:1146)
                                                                              at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:595)
                                                                              at android.support.v7.app.AppCompatActivity.onStart(AppCompatActivity.java:178)
                                                                              at com.never.mediaalarmplayer.MediaPlayer.onStart(MediaPlayer.java:78)
                                                                              at com.never.mediaalarmplayer.AlarmReceiver.onReceive(AlarmReceiver.java:23)
                                                                              at android.app.ActivityThread.handleReceiver(ActivityThread.java:2725)
                                                                              at android.app.ActivityThread.-wrap14(ActivityThread.java) 
                                                                              at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1421) 
                                                                              at android.os.Handler.dispatchMessage(Handler.java:102) 
                                                                              at android.os.Looper.loop(Looper.java:148) 
                                                                              at android.app.ActivityThread.main(ActivityThread.java:5417) 
                                                                              at java.lang.reflect.Method.invoke(Native Method) 
                                                                              at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
                                                                              at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 

这是我第一次post所以如果post有任何问题我会编辑它也非常感谢你。

活动不是像您在 AlarmReceiver class 的 onReceive 中那样开始的,即

MediaPlayer ms = new MediaPlayer();

它们由 Context.startActivity (Intent) 启动。它是 android 系统,它应该启动活动,因为它管理一堆活动并为它们发布生命周期回调。因为你自己开始 activity 所以你错过了初始生命周期回调 e。 G。 onCreate.