在模拟器中运行时出现内存泄漏错误

时间:2017-11-04 04:12:27

标签: android memory-leaks

我正在尝试制作小型音板。我收到内存泄漏错误,应用程序崩溃。谁能告诉我,我的代码是否有问题或效率低下。我有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(); 
    }

}

1 个答案:

答案 0 :(得分:0)

Sound课程中,您正在mParent中持有对活动的引用,并且您永远不会通过将其设置为null来让活动进行,因此活动永远不会被垃圾回收

老实说,您似乎已经尝试将所有活动代码提取到另一个类中,以制作一种类型的模板&#39;但没有得到Android生命周期的影响。