0

我有一个基本的声音机应用程序,在很多帮助下,我终于设法让声音播放并在按下后退按钮时停止播放。现在我遇到的问题是当我加载屏幕并播放声音时,点击后退按钮并尝试播放新声音整个应用程序强制关闭。这里是home.java,和两个健全的java 类。

package com.androidsleepmachine.gamble;


import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TabHost;
import android.widget.TabHost.TabSpec;

public class Home extends Activity implements View.OnClickListener {
Button Sleep1;
Button Sleep2;
Button Sleep3;
Button Relax1;
Button Relax2;
Button Relax3;
Button Well1;
Button Well2;
Button Well3;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.home_layout);

    TabHost tabHost = (TabHost) findViewById(R.id.tabHost);
    tabHost.setup();
    TabSpec spec1 = tabHost.newTabSpec("Sleep");
    spec1.setContent(R.id.tab1);
    spec1.setIndicator("Sleep", 
getResources().getDrawable(R.drawable.sleep_icon));

    TabSpec spec2 = tabHost.newTabSpec("Relaxation");
    spec2.setIndicator("Relaxation",    
getResources().getDrawable(R.drawable.zen_icon));
    spec2.setContent(R.id.tab2);

    TabSpec spec3 = tabHost.newTabSpec("Wellness");
    spec3.setIndicator("Wellness", 
getResources().getDrawable(R.drawable.brain_icon));
    spec3.setContent(R.id.tab3);

    tabHost.addTab(spec1);
    tabHost.addTab(spec2);
    tabHost.addTab(spec3);
    Sleep1 = (Button) findViewById(R.id.button1);
    Sleep1.setOnClickListener(this);
    Sleep2 = (Button) findViewById(R.id.button2);
    Sleep2.setOnClickListener(this);
    Sleep3 = (Button) findViewById(R.id.button3);
    Sleep3.setOnClickListener(this);
    Relax1 = (Button) findViewById(R.id.button4);
    Relax1.setOnClickListener(this);
    Relax2 = (Button) findViewById(R.id.button5);
    Relax2.setOnClickListener(this);
    Relax3 = (Button) findViewById(R.id.button6);
    Relax3.setOnClickListener(this);
    Well1 = (Button) findViewById(R.id.button7);
    Well1.setOnClickListener(this);
    Well2 = (Button) findViewById(R.id.button8);
    Well2.setOnClickListener(this);
    Well3 = (Button) findViewById(R.id.button9);
    Well3.setOnClickListener(this);
}

// Handle button callbacks
@Override
public void onClick(View v) {
    switch (v.getId()) {
        case R.id.button1:
            Intent a = new Intent(this, Ocean.class);
            startActivity(a);
            break;
        case R.id.button2:
            Intent i = new Intent(this, Ship.class);
            startActivity(i);
            break;
        case R.id.button3:
            Intent c = new Intent(this, OceanThunder.class);
            startActivity(c);
            break;
    }
}
}

这是Ocean.Java

package com.androidsleepmachine.gamble;

import android.app.Activity;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Spinner;

public class Ocean extends Activity implements View.OnClickListener {
public static final Integer[] TIME_IN_MINUTES = { 30, 45, 60, 180, 360 };
public MediaPlayer mediaPlayer;
public Handler handler = new Handler();
public Button button1;
public Spinner spinner1;

// Initialize the activity
@Override
public void onCreate(Bundle bundle) {
    super.onCreate(bundle);
    setContentView(R.layout.ocean);

    button1 = (Button) findViewById(R.id.btn1);
    button1.setOnClickListener(this);
    spinner1 = (Spinner) findViewById(R.id.spinner1);
    ArrayAdapter<Integer> adapter = new ArrayAdapter<Integer>(this,   
android.R.layout.simple_spinner_item, TIME_IN_MINUTES);

adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);          
    spinner1.setAdapter(adapter); 
}
  protected void onStop()
  {
    if (this.mediaPlayer != null)
      this.mediaPlayer.stop();
    super.onStop();
  }

// Play the sound and start the timer
private void playSound(int resourceId) {
    // Cleanup any previous sound files
    cleanup();
    // Create a new media player instance and start it
    mediaPlayer = MediaPlayer.create(this, resourceId);
    mediaPlayer.start();
    // Create the timer to stop the sound after x number of milliseconds
    int selectedTime = TIME_IN_MINUTES[spinner1.getSelectedItemPosition()];
    handler.postDelayed(runnable, selectedTime * 60 * 1000);
}

// Handle button callback
@Override
public void onClick(View v) {
    switch (v.getId()) {
        case R.id.btn1:
            playSound(R.raw.ocean_birds);
            break;
    }
}

// Stop the sound and cleanup the media player
public void cleanup() {
    if (mediaPlayer != null) {
        mediaPlayer.stop();
        mediaPlayer.release();
        mediaPlayer = null;
    }
    // Cancel any previously running tasks
    handler.removeCallbacks(runnable);
}

// Runnable task used by the handler to stop the sound
public Runnable runnable = new Runnable() {
    public void run() {
        cleanup();
    }
};

和 Ship.Java

package com.androidsleepmachine.gamble;

import android.app.Activity;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Handler;
import android.view.KeyEvent;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Spinner;

public class Ship extends Activity implements View.OnClickListener {
public static final Integer[] TIME_IN_MINUTES = { 30, 45, 60, 180, 360 };
public MediaPlayer mediaPlayer;
public Handler handler = new Handler();
public Button button2;
public Spinner spinner2;

// Initialize the activity
@Override
public void onCreate(Bundle savedInstanceState) {  
super.onCreate(savedInstanceState);
    super.onCreate(savedInstanceState);
    setContentView(R.layout.ship);



    button2 = (Button) findViewById(R.id.btn2);
    button2.setOnClickListener(this);
    spinner2 = (Spinner) findViewById(R.id.spinner2);
    ArrayAdapter<Integer> adapter = new ArrayAdapter<Integer>(this,    
android.R.layout.simple_spinner_item, TIME_IN_MINUTES);

adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);          
    spinner2.setAdapter(adapter); 
}

  protected void onStop()
  {
    if (this.mediaPlayer != null)
      this.mediaPlayer.stop();
    super.onStop();
  }

// Play the sound and start the timer
private void playSound(int resourceId) {
    // Cleanup any previous sound files
    cleanup();
    // Create a new media player instance and start it
    mediaPlayer = MediaPlayer.create(this, resourceId);
    mediaPlayer.start();
    // Create the timer to stop the sound after x number of milliseconds
    int selectedTime = TIME_IN_MINUTES[spinner2.getSelectedItemPosition()];
    handler.postDelayed(runnable, selectedTime * 60 * 1000);
}

// Handle button callback
@Override
public void onClick(View v) {
    switch (v.getId()) {
        case R.id.btn2:
            playSound(R.raw.ocean_ship);
            break;
    }
}

// Stop the sound and cleanup the media player
public void cleanup() {
    if (mediaPlayer != null) {
        mediaPlayer.stop();
        mediaPlayer.release();
        mediaPlayer = null;
    }
    // Cancel any previously running tasks
    handler.removeCallbacks(runnable);
}

// Runnable task used by the handler to stop the sound
public Runnable runnable = new Runnable() {
    public void run() {
        cleanup();
    }
};
}

日志猫

09-19 14:58:17.533: D/dalvikvm(1675): GC_FOR_ALLOC freed 5637K, 22% free 40867K/51783K, paused 35ms, total 37ms
09-19 14:58:17.533: I/dalvikvm-heap(1675): Grow heap (frag case) to 44.671MB for 4915212-byte allocation
09-19 14:58:17.554: D/dalvikvm(1675): GC_CONCURRENT freed 2K, 12% free 45664K/51783K, paused 16ms+1ms, total 21ms
09-19 14:58:17.688: D/dalvikvm(1675): GC_FOR_ALLOC freed 0K, 12% free 45664K/51783K, paused 33ms, total 33ms
09-19 14:58:17.693: I/dalvikvm-heap(1675): Grow heap (frag case) to 53.004MB for 8739852-byte allocation
09-19 14:58:17.713: D/dalvikvm(1675): GC_CONCURRENT freed 0K, 11% free 54199K/60359K, paused 13ms+2ms, total 20ms
09-19 14:59:00.994: D/dalvikvm(1675): GC_FOR_ALLOC freed 4816K, 19% free 49464K/60359K, paused 35ms, total 40ms
09-19 14:59:00.994: I/dalvikvm-heap(1675): Grow heap (frag case) to 52.286MB for 4096012-byte allocation
09-19 14:59:01.014: D/dalvikvm(1675): GC_CONCURRENT freed 8K, 12% free 53455K/60359K, paused 13ms+1ms, total 21ms
09-19 14:59:01.154: D/dalvikvm(1675): GC_FOR_ALLOC freed <1K, 12% free 53455K/60359K, paused 5ms, total 5ms
09-19 14:59:01.154: I/dalvikvm-heap(1675): Forcing collection of SoftReferences for 7285488-byte allocation
09-19 14:59:01.174: D/dalvikvm(1675): GC_BEFORE_OOM freed 9K, 12% free 53446K/60359K, paused 19ms, total 20ms
09-19 14:59:01.174: E/dalvikvm-heap(1675): Out of memory on a 7285488-byte allocation.
09-19 14:59:01.174: I/dalvikvm(1675): "main" prio=5 tid=1 RUNNABLE
09-19 14:59:01.174: I/dalvikvm(1675):   | group="main" sCount=0 dsCount=0 obj=0xb2e454b0 self=0xb9b594e0
09-19 14:59:01.174: I/dalvikvm(1675):   | sysTid=1675 nice=0 sched=0/0 cgrp=[fopen-error:2] handle=-1208622016
09-19 14:59:01.174: I/dalvikvm(1675):   | schedstat=( 0 0 0 ) utm=158 stm=17 core=0
09-19 14:59:01.184: I/dalvikvm(1675):   at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
09-19 14:59:01.184: I/dalvikvm(1675):   at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:500)
09-19 14:59:01.184: I/dalvikvm(1675):   at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:353)
09-19 14:59:01.184: I/dalvikvm(1675):   at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:781)
09-19 14:59:01.184: I/dalvikvm(1675):   at android.content.res.Resources.loadDrawable(Resources.java:1930)
09-19 14:59:01.184: I/dalvikvm(1675):   at android.content.res.TypedArray.getDrawable(TypedArray.java:601)
09-19 14:59:01.184: I/dalvikvm(1675):   at android.view.View.<init>(View.java:3336)
09-19 14:59:01.184: I/dalvikvm(1675):   at android.view.View.<init>(View.java:3273)
09-19 14:59:01.184: I/dalvikvm(1675):   at android.view.ViewGroup.<init>(ViewGroup.java:421)
09-19 14:59:01.184: I/dalvikvm(1675):   at android.widget.RelativeLayout.<init>(RelativeLayout.java:184)
09-19 14:59:01.184: I/dalvikvm(1675):   at java.lang.reflect.Constructor.constructNative(Native Method)
09-19 14:59:01.184: I/dalvikvm(1675):   at java.lang.reflect.Constructor.newInstance(Constructor.java:417)
09-19 14:59:01.184: I/dalvikvm(1675):   at android.view.LayoutInflater.createView(LayoutInflater.java:587)
09-19 14:59:01.184: I/dalvikvm(1675):   at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:56)
09-19 14:59:01.184: I/dalvikvm(1675):   at android.view.LayoutInflater.onCreateView(LayoutInflater.java:660)
09-19 14:59:01.184: I/dalvikvm(1675):   at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:685)
09-19 14:59:01.184: I/dalvikvm(1675):   at android.view.LayoutInflater.inflate(LayoutInflater.java:466)
09-19 14:59:01.184: I/dalvikvm(1675):   at android.view.LayoutInflater.inflate(LayoutInflater.java:396)
09-19 14:59:01.184: I/dalvikvm(1675):   at android.view.LayoutInflater.inflate(LayoutInflater.java:352)
09-19 14:59:01.184: I/dalvikvm(1675):   at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:256)
09-19 14:59:01.184: I/dalvikvm(1675):   at android.app.Activity.setContentView(Activity.java:1867)
09-19 14:59:01.184: I/dalvikvm(1675):   at com.androidsleepmachine.gamble.Ocean.onCreate(Ocean.java:23)
09-19 14:59:01.184: I/dalvikvm(1675):   at android.app.Activity.performCreate(Activity.java:5008)
09-19 14:59:01.184: I/dalvikvm(1675):   at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
09-19 14:59:01.184: I/dalvikvm(1675):   at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023)
09-19 14:59:01.184: I/dalvikvm(1675):   at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
09-19 14:59:01.184: I/dalvikvm(1675):   at android.app.ActivityThread.access$600(ActivityThread.java:130)
09-19 14:59:01.184: I/dalvikvm(1675):   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
09-19 14:59:01.184: I/dalvikvm(1675):   at android.os.Handler.dispatchMessage(Handler.java:99)
09-19 14:59:01.184: I/dalvikvm(1675):   at android.os.Looper.loop(Looper.java:137)
09-19 14:59:01.184: I/dalvikvm(1675):   at android.app.ActivityThread.main(ActivityThread.java:4745)
09-19 14:59:01.184: I/dalvikvm(1675):   at java.lang.reflect.Method.invokeNative(Native Method)
09-19 14:59:01.184: I/dalvikvm(1675):   at java.lang.reflect.Method.invoke(Method.java:511)
09-19 14:59:01.184: I/dalvikvm(1675):   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
09-19 14:59:01.184: I/dalvikvm(1675):   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
09-19 14:59:01.184: I/dalvikvm(1675):   at dalvik.system.NativeStart.main(Native Method)
09-19 14:59:01.204: A/libc(1675): Fatal signal 11 (SIGSEGV) at 0x00000000 (code=1), thread 1675 (pmachine.gamble)

清单

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.androidsleepmachine.gamble"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk
    android:minSdkVersion="16"
    android:targetSdkVersion="18" />

<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name="com.androidsleepmachine.gamble.Home"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activity android:name="com.androidsleepmachine.gamble.Ship" />
     <activity android:name="com.androidsleepmachine.gamble.OceanThunder" />
    <activity android:name="com.androidsleepmachine.gamble.Ocean" />

</application>

</manifest>
4

3 回答 3

0

检查你是否更新了你的“清单”,这是很常见的问题。我们的大脑忙于代码,以至于我们经常忘记更新清单。

于 2013-09-18T22:51:43.673 回答
0

代码魔术是对的。您需要调用释放。

protected void onStop(){
    if (this.mediaPlayer != null){
        super.onStop();
        this.mediaPlayer.stop();
        this.mediaPlayer.release();  
    }

那应该这样做。

于 2013-09-18T23:13:53.523 回答
0

问题大概就在这里

    protected void onStop()
  {
    if (this.mediaPlayer != null)
      this.mediaPlayer.stop();
      super.onStop();
  }

我相信你应该来mediaPlayer.release()这里打电话。我MediaPlayer在这一点上的经验是有限的,但我相信打电话stop()是不够的。您需要释放资源。如果这不起作用,那么您需要发布完整的 logcat,因为如果它崩溃了,那么您的 logcat 会比您提供的更多。

这也可能在onPause().

从评论更新

 protected void onStop()
  {
    if (this.mediaPlayer != null)
      this.mediaPlayer.stop();
      mediaPlayer.release();   // release your resources
      super.onStop();
  }

onPause()但正如我所说,这可能比 in 更安全onStop()。当用户按下后退按钮时,这将起作用,但如果其他东西进入前台,则不起作用。

于 2013-09-18T23:04:08.953 回答