2016-10-03 36 views
0

我是Android Studio的初學者 我試圖製作Android鬧鐘,現在它不能顯示通知,沒有音樂播放,也有停止按鈕的錯誤。這是我的代碼,希望有人能幫我解決它。謝謝沒有通知顯示,無法播放歌曲和錯誤的Android鬧鐘啓動按鈕

AlarmReceiver.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,pass to the start service 
    service_intent.putExtra("extra",get_your_string); 

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

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 pending_intent; 

@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); 

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

    //create an intent to the Alarm Receiver class 
    final Intent my_intent=new Intent(MainActivity.this,Alarm_Receiver.class); 

    //initialize start buttons 
    Button alarm_on=(Button)findViewById(R.id.start_alarm); 
    //create an onClick listener to start the alarm 
    alarm_on.setOnClickListener(new View.OnClickListener() { 
     @TargetApi(Build.VERSION_CODES.M) 
     @Override 
     public void onClick(View view) { 

      //setting calendar instance with the hour and minute that ve picked 
      //on the time picker 
      calendar.set(Calendar.HOUR_OF_DAY,alarm_timepicker.getCurrentHour()); 
      calendar.set(Calendar.MINUTE,alarm_timepicker.getCurrentMinute()); 

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

      //converts the int value to strings 
      String hour_string=String.valueOf(hour); 
      String minute_string=String.valueOf(minute); 

      //conver 24hour time to 12 hour time 
      if(hour>12) 
      { 
       hour_string=String.valueOf(hour-12); 
      } 

      if(minute<10){ 
       minute_string="0" +String.valueOf(minute); 
      } 

      //method that changes the update text Textbox 
      set_alarm_text("Alarm set to: "+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","alarm on"); 

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

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

    //initialize the stop button 
    Button alarm_off=(Button)findViewById(R.id.end_alarm); 
    //create an onClick listener to undo an alarm set 
    alarm_off.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View view) { 
      //method that changes the update text Textbox 
      set_alarm_text("Alarm off!"); 

      //cancel the alarm 
      alarm_manager.cancel(pending_intent); 

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


      //stop the ringtone 
      sendBroadcast(my_intent); 
     } 
    }); 
} 

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

} 

@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); 
} 
} 

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 player=MediaPlayer.create(this, Settings.System.DEFAULT_RINGTONE_URI); 
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 
     player = MediaPlayer.create(this,R.raw.singer); 
     player.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) 
       .setSmallIcon(R.mipmap.ic_launcher) 
       .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 
     player.stop(); 
     player.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 "); 

    } 
    //if something is wrong, it can restart 
    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(); 
} 

}

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' 
} 

this is the error when clicking the start button

Is this an error for the music?

java.lang.RuntimeException: Unable to start service [email protected] with Intent { cmp=com.google.alarmclock/.RingtonePlayingService (has extras) }: java.lang.IllegalArgumentException: Invalid notification (no valid small icon): Notification(pri=0 contentView=null vibrate=null sound=null defaults=0x0 flags=0x10 color=0x00000000 vis=PRIVATE) 
        at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3314) 
        at android.app.ActivityThread.-wrap21(ActivityThread.java) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1565) 
        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.IllegalArgumentException: Invalid notification (no valid small icon): Notification(pri=0 contentView=null vibrate=null sound=null defaults=0x0 flags=0x10 color=0x00000000 vis=PRIVATE) 
        at android.app.NotificationManager.notifyAsUser(NotificationManager.java:306) 
        at android.app.NotificationManager.notify(NotificationManager.java:284) 
        at android.app.NotificationManager.notify(NotificationManager.java:268) 
        at com.google.alarmclock.RingtonePlayingService.onStartCommand(RingtonePlayingService.java:96) 
        at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3297) 
        at android.app.ActivityThread.-wrap21(ActivityThread.java)  
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1565)  
        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)  

當點擊停止按鈕

E/AndroidRuntime: FATAL EXCEPTION: main 
        Process: com.google.alarmclock, PID: 2665 
        java.lang.NullPointerException: cancel() called with a null PendingIntent 
         at android.app.AlarmManager.cancel(AlarmManager.java:890) 
         at com.google.alarmclock.MainActivity$2.onClick(MainActivity.java:111) 
         at android.view.View.performClick(View.java:5609) 
         at android.view.View$PerformClick.run(View.java:22259) 
         at android.os.Handler.handleCallback(Handler.java:751) 
         at android.os.Handler.dispatchMessage(Handler.java:95) 
         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) 

回答

0

從你的build.gradle我可以看到爲什麼noSuchMethod拋出異常。 爲了使用函數alarm_timepicker.getHour()。您必須定位23分鐘的API,才能毫無問題地使用此功能。

你包裝你的功能的註釋並沒有太多的作用。它只是防止在編碼過程中顯示警告/錯誤。當應用程序處於運行狀態時,由於無法找到該方法,因此將拋出運行時異常。

如果您希望使用timepicker.getHour保持(),請確保你在你的build.gradle的minSdkVersion指定23.注意,這將需要你安裝你的應用程序到運行的設備SDK 23

如果您不想對build.gradle進行這樣的修改,那麼我建議你使用這個函數。 timepicker.getCurrentHour()和timepicker.getCurrentMinute()。

爲了解決問題#2:有關java.lang.RuntimeException: Unable to start service [email protected] with Intent { cmp=com.google.alarmclock/.RingtonePlayingService (has extras) }: java.lang.IllegalArgumentException: Invalid notification (no valid small icon)

確保您設置一個小圖標,您的通知。通知對象要求您設置此屬性。

試試這個:

Notification notification_popup=new Notification.Builder(this) 
        .setContentTitle("An alarm is going off!") 
        .setContentText("Click Me") 
        .setContentIntent(pending_intent_main_activity) 
        .setAutoCancel(true) 
        .setSmallIcon(R.mipmap.ic_launcher) 
        .build(); 

請務必注意.setSmallIcon一段代碼。您的項目可能沒有mipmap文件夾。您可能必須更改爲R.drawable。ic_launcher

相關的聲音。我無法確定這是否是一個問題,但我會盡快更新。

感謝。

+0

但仍然有RunTime錯誤和IllegalArguement錯誤 – Jane

+0

你可以發佈實際的錯誤,所以我可以看到你現在得到什麼。 – TerNovi

+0

我已更新我的答案以解決您的非法設備錯誤。 – TerNovi