我正在尝试制作小型音板。我收到内存泄漏错误,应用程序崩溃。谁能告诉我,我的代码是否有问题或效率低下。我有10个类似Activity1的活动。有什么办法可以让代码更高效,更快捷。我不确定代码的哪一部分导致内存泄漏错误
Sound.java
public class Sound
implements OnClickListener,OnCreateContextMenuListener, OnMenuItemClickListener{
static final private int MENU_RINGTONE = Menu.FIRST;
static final private int MENU_NOTIFICATION = MENU_RINGTONE + 1;
static final private int MENU_MUSIC = MENU_NOTIFICATION + 1;
static final private int MENU_SET = MENU_MUSIC + 1;
private Activity mParent;
private int mResourceId;
private String mName;
private int mButtonID;
private static Player mPlayer;
public static Player getPlayer() { return mPlayer; }
public static void setPlayer(Player value) {
mPlayer = value;
}
private static boolean mDoSet;
public static boolean getmDoSet() { return mDoSet; }
public static void setmDoSet(boolean value) { mDoSet = value; }
enum Action {Ringtone, Notification, Music};
private boolean doSet;
private Action mAction;
Sound(Activity Parent, int RawResId, int ButtonID, String Name){
mParent = Parent;
mResourceId = RawResId;
mName = Name;
mButtonID = ButtonID;
}
public void Initialize() {
mParent.findViewById(mButtonID).setOnClickListener(this);
mParent.findViewById(mButtonID).setOnCreateContextMenuListener(this);
}
@Override
public void onClick(View v) {
if (mPlayer != null){
mPlayer.play(mParent.getBaseContext(), mResourceId);
}
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
mParent.onCreateContextMenu(menu, v, menuInfo);
menu.setHeaderTitle("Context Menu");
menu.add(0, MENU_RINGTONE, 0, R.string.SaveRingtone).setOnMenuItemClickListener(this);
menu.add(0, MENU_NOTIFICATION, 0, R.string.SaveNotification).setOnMenuItemClickListener(this);
menu.add(0, MENU_MUSIC, 0, R.string.SaveMusic).setOnMenuItemClickListener(this);
}
@Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId())
{
case MENU_RINGTONE:
mAction = Action.Ringtone;
break;
case MENU_NOTIFICATION:
mAction = Action.Notification;
break;
case MENU_MUSIC:
mAction = Action.Music;
break;
}
String name = mName.toLowerCase().replace(' ', '_');
return SaveSound(mParent,name, mName, mResourceId);
}
public boolean SaveSound(Activity Parent, String filename, String Title, int ressound) {
byte[] buffer = null;
InputStream fIn = Parent.getBaseContext().getResources().openRawResource(ressound);
int size = 0;
try {
size = fIn.available();
buffer = new byte[size];
fIn.read(buffer);
fIn.close();
} catch (IOException e) {
// TODO Auto-generated catch block
return false;
}
String path1 = android.os.Environment.getExternalStorageDirectory().getPath() + "/media/audio/ringtones/";
String path2 = android.os.Environment.getExternalStorageDirectory().getPath() + "/media/audio/notifications/";
boolean saved = false;
switch (mAction){
case Ringtone:
saved = save(Parent, filename, Title, buffer,path1);
case Notification:
saved = save(Parent, filename, Title, buffer, path2);
case Music:
};
if (saved) {
return true;
} else {
return false;
}
}
public boolean save(Activity Parent, String filename, String Title,
byte[] buffer, String path) {
boolean exists = (new File(path)).exists();
if (!exists){new File(path).mkdirs();}
FileOutputStream save;
try {
save = new FileOutputStream(path+filename);
save.write(buffer);
save.flush();
save.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
return false;
} catch (IOException e) {
// TODO Auto-generated catch block
return false;
}
Parent.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://"+path+filename)));
File k = new File(path, filename);
ContentValues values = new ContentValues();
values.put(MediaStore.MediaColumns.DATA, k.getAbsolutePath());
values.put(MediaStore.MediaColumns.TITLE, Title);
values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/ogg");
values.put(MediaStore.Audio.Media.ARTIST, " ");
values.put(MediaStore.Audio.Media.IS_RINGTONE, true);
values.put(MediaStore.Audio.Media.IS_NOTIFICATION, true);
values.put(MediaStore.Audio.Media.IS_ALARM, true);
values.put(MediaStore.Audio.Media.IS_MUSIC, true);
//Insert it into the database
Uri uri = MediaStore.Audio.Media.getContentUriForPath(k.getAbsolutePath());
Uri newUri = Parent.getContentResolver().insert(uri, values);
// set the ringtone
if (doSet == true && mAction == Action.Ringtone
|| mAction == Action.Notification) {
int type = RingtoneManager.TYPE_RINGTONE;
switch (mAction) {
case Ringtone:
type = RingtoneManager.TYPE_RINGTONE;
break;
case Notification:
type = RingtoneManager.TYPE_NOTIFICATION;
}
RingtoneManager.setActualDefaultRingtoneUri(mParent, type, newUri);
}
return true;
}
}
Player.java
public class Player {
private MediaPlayer mp;
public Player(){
mp = new MediaPlayer();
}
public void play(Context c, int r) {
if (mp==null)
return;
if (mp.isPlaying()){
mp.stop();
mp.release();
}else{
mp = MediaPlayer.create(c, r);
mp.start();
}
}
public void stop() {
if (mp==null)
return;
if (mp.isPlaying()){
mp.stop();
mp.release();
}
}
}
Activity1.java
public class Activity1
extends Activity {
private Player p;
Sound Sounds[] = {
new Sound(this, R.raw.baboon, R.id.Animal1, "")
, new Sound(this, R.raw.baligator, R.id.Animal2, "")
, new Sound(this, R.raw.bat, R.id.Animal3, "")
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.animals);
p = new Player();
Sound.setPlayer(p);
for (int i = 0; i < Sounds.length; i++) {
Sounds[i].Initialize();
}
}
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
return true;
}
@Override
public void onBackPressed() {
super.onBackPressed();
p.stop();
}
@Override
protected void onPause()
{
super.onPause();
p.stop();
}
}
答案 0 :(得分:0)
在Sound
课程中,您正在mParent
中持有对活动的引用,并且您永远不会通过将其设置为null
来让活动进行,因此活动永远不会被垃圾回收
老实说,您似乎已经尝试将所有活动代码提取到另一个类中,以制作一种类型的模板&#39;但没有得到Android生命周期的影响。