-1

Hello I have 2 Activities, 2 apps each with their classes ( around 10 classes in total), which i want to combine. I have a functional alarm and an functional MediaPlayer. I want to start the mediaplayer when the time is to set off the alarm. The problem is my app crashes when it's time to ring. The Media Player 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;
    }

}

Alarm Receiver 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();
   }
}

And the Alarm 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();
        }
    }

}

The Exception:

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) 

It is my first time posting so if there is any problem with the post i will edit it also thank you very much.

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
Never
  • 5
  • 4

1 Answers1

0

Acitivities are not started like this as you are doing in your AlarmReceiver class's onReceive i.e.

MediaPlayer ms = new MediaPlayer();

They are started by Context.startActivity (Intent). It is android system which is supposed to start the activities as it manages a stack of activities and posts life-cycle callbacks for the them. Since you start activity yourself so you miss the initial life cycle callbacks e. g. onCreate.

Birendra Singh
  • 842
  • 11
  • 19
  • Yes but if i start the media player and start playing the music and pause it after that when the alarm gets off shouldn't it work? I mean the acitivty started and i am trying only un unpause it. Also thank you for the answer i will also look forward into what you just said. – Never Jul 11 '17 at 16:16
  • @Never you are creating a new instance of the acivity class. It is not the same as previous started activity. It is same case like you have an integer `act=2` in some class (application) and in some other class (AlarmReceiver) you are defining another integer `mp`. Then you are expecting that `mp` will hold a value of `2.` – Birendra Singh Jul 11 '17 at 16:43
  • If answer really helps you, say thanks by accepting and upvoting it. – Birendra Singh Jul 11 '17 at 16:45