4

に関連する大きな問題に直面していActivityます。私のシナリオは次のとおりです。

アクティビティ A を開始し、ボタンをクリックして、ギャラリーから画像を選択し、onActivityResultを呼び出しstartActivity(B)ました。

アクティビティ B で、A で選択した画像が表示されていListViewます。

呼び出したボタンをクリックするstartActivityforResult(Recorder class)と、カスタム ビデオ レコーダー アクティビティである新しいアクティビティが開かれました。

アクティビティレコーダーで停止ボタンをクリックするmediaRecorderと停止し、ビデオをリリースして保存し、その後setResult再びアクティビティBに移動しonActivityResult()ます。しかし、ここに問題があります:

ここで見つけた2つの異なるケース:

  1. 1 つ目は、Recorder クラスを Landscape として宣言したときです。

    ここで Recorder クラスの停止ボタンをクリックすると、画面が真っ暗になり、数秒後にアクティビティ A が開始されます。

  2. 2 つ目は、Recorder クラスの向きを縦モードに変更したときです。

    ここで Recorder クラスのアクティビティ B の停止ボタンをクリックすると (黒い画面は表示されません)、数秒後に再びアクティビティ A が開始されます。

ここで私が観察したもう1つのこと:

  • アクティビティ B で置き換えstartActivityForResult()startActivity()アクティビティ B を示すレコーダー アクティビティ i から再度呼び出しstartActivity(B)ましたが、数秒後に同じアクティビティ B が再び開始された後、何か新しいことが起こります。
  • これは、クラスMediaRecorderのすべてのメディア レコーダー コードにコメントしたときに問題がなかったからだと確信しています。Recorder

私の Code of Recorder クラスは次のとおりです。

public class Recorder extends Activity implements SurfaceHolder.Callback{

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mediaRecorder = new MediaRecorder();
        setContentView(R.layout.recorde);
        initMediaRecorder();

        timer = new Timer();
        TimerTask timerTask = new TimerTask() {
            @Override
            public void run() {
                if(counter<=10)
                    counter++;
                //Android UI get Updated continouly
                else {
                    // If condition full filled the timer will stop here
                    mediaRecorder.stop();
                    mediaRecorder.reset();
                    mediaRecorder.release();
                    timer.cancel();
                    Recorder.this.finish();
                    Intent i = new Intent(Recorder.this,B.class);
                    setResult(Activity.RESULT_OK, i.putExtra("returnedVideo", strPath));
                }
            } 
        };
        timer.schedule(timerTask, 1000, 1000);

        SurfaceView myVideoView = (SurfaceView)findViewById(R.id.videoview);
        surfaceHolder = myVideoView.getHolder();
        surfaceHolder.addCallback(this);
        surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

        myButton = (Button)findViewById(R.id.mybutton);
        myButton.setOnClickListener(myButtonOnClickListener);
    }

    private Button.OnClickListener myButtonOnClickListener
    = new Button.OnClickListener(){

        public void onClick(View arg0) {
            // TODO Auto-generated method stub
            mediaRecorder.stop();
            mediaRecorder.reset();
            mediaRecorder.release();
            timer.cancel();
            Recorder.this.finish();

            Intent i = new Intent(Recorder.this,B.class);
            setResult(Activity.RESULT_OK, i.putExtra("returnedVideo", strPath));
        }};

        public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
            // TODO Auto-generated method stub

        }
        public void surfaceCreated(SurfaceHolder arg0) {
            // TODO Auto-generated method stub
            prepareMediaRecorder();
        }
        public void surfaceDestroyed(SurfaceHolder arg0) {
            // TODO Auto-generated method stub

            mediaRecorder.stop();
            mediaRecorder.release();
            //Recorder.this.finish();
        }

        @Override
        public void onBackPressed() {
            // TODO Auto-generated method stub
            super.onBackPressed();

            mediaRecorder.stop();
            mediaRecorder.release();
        }

        private void initMediaRecorder(){
            Random genraotr = new Random();
            int n = 10000;
            n = genraotr.nextInt(n);            

            mediaRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
            mediaRecorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT);
            CamcorderProfile camcorderProfile_HQ = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);
            mediaRecorder.setProfile(camcorderProfile_HQ);
            mediaRecorder.setOutputFile("/sdcard/my_video"+n+".mp4");
            strPath = "/sdcard/my_video"+n+".mp4";
            mediaRecorder.setMaxDuration(10000); // Set max duration 10 sec.
            mediaRecorder.setMaxFileSize(5000000); // Set max file size 5M
        }

        private void prepareMediaRecorder(){
            mediaRecorder.setPreviewDisplay(surfaceHolder.getSurface());
            try {
                mediaRecorder.prepare();
                mediaRecorder.start();
            } catch (IllegalStateException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
}
4

2 に答える 2

1

Activityインスタンスの状態を保存および復元するコードが表示されません。Androidは、別のアクティビティを一番上に置くとアクティビティを破棄して再作成する場合があります。また、デバイスの向きを変えるとアクティビティを再開します。あなたはこれらの2つのケースで正確に問題を抱えているようです。

その後、Androidはアクティビティを再開しようとしますが、状態を保存して再開することで支援する必要があります。デフォルトではあまり復元されません。特に、独自のフィールドはnull値を取得するだけです。

onSavedInstanceStateを実装し、プログラムが動作し続けるために重要な可能性のある提供されたバンドル(マップ)に入れます。次に、onCreateパラメーターsavedInstanceStateがnullでないかどうかを確認し、nullでない場合は、このバンドルから重要と思われるものを復元します。また、onRestoreInstanceStateを実装します。

これが問題を示すコードです。これは、String型の状態変数を1つ持つ単純なアプリケーションです。プログラムを起動し、デバイスの向きを縦向きから横向きに変えてみてください。メッセージテキストは「私の状態はnullでしたが、13c140ff7e6に復元されました」のように変更されます。したがって、create()が2回呼び出された場合、状態フィールドはnullになり、渡されたバンドルから復元する必要があります。同時に、静的フィールドの値は保持される可能性が高く(場合によってはなくなる可能性もあります)、これはアプリケーションの完全なコールドリスタートではないことを示します。これは、単純な方向転換によって、そのようなことを認識していないアプリがクラッシュする可能性があることを説明している可能性があります。結果を得るために別のアクティビティを開始すると、同様の効果が生じる可能性があります。このコードは、問題を解決する方法も示しています。

package com.example.state;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends Activity {

String myState;

static String staticString;

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    TextView sv = (TextView) findViewById(R.id.main);

    if (savedInstanceState != null) {
        String state = savedInstanceState.getString("myState");
        sv.setText("My state was " + myState + " but now restored to "
                + state+", static "+staticString);
        myState = state;
    } else {
        String state = Long.toHexString(System.currentTimeMillis());
        sv.setText("My state: " + myState + ", cold start, now set to "+state);
        myState = state;
        staticString = state;
    }
}

protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    myState = savedInstanceState.getString("myState");
}

protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putString("myState", myState);
}
}

レイアウト付き

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

    <TextView
        android:id="@+id/main"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
     />

</RelativeLayout>
于 2013-01-06T11:30:47.833 に答える
1

あなたのレコーダークラスに問題があるようです。このコードを使用して一度試してみてください:

public class AndroidVideoCapture extends Activity{

    private Camera myCamera;
    private MyCameraSurfaceView myCameraSurfaceView;
    private MediaRecorder mediaRecorder;

    Button myButton;
    SurfaceHolder surfaceHolder;
    boolean recording;  
    public static String strPath;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        recording = false;

        setContentView(R.layout.main);

        //Get Camera for preview
        myCamera = getCameraInstance();
        if(myCamera == null){
            Toast.makeText(AndroidVideoCapture.this, 
                    "Fail to get Camera", 
                    Toast.LENGTH_LONG).show();
        }

        myCameraSurfaceView = new MyCameraSurfaceView(this, myCamera);
        FrameLayout myCameraPreview = (FrameLayout)findViewById(R.id.videoview);
        myCameraPreview.addView(myCameraSurfaceView);

        myButton = (Button)findViewById(R.id.mybutton);
        myButton.setOnClickListener(myButtonOnClickListener);
    }

    Button.OnClickListener myButtonOnClickListener
    = new Button.OnClickListener(){

        public void onClick(View v) {
            // TODO Auto-generated method stub
            if(recording){
                // stop recording and release camera
                mediaRecorder.stop();  // stop the recording
                releaseMediaRecorder(); // release the MediaRecorder object
                Intent i = new Intent(AndroidVideoCapture.this,TakeAnotherPhoto.class);
                i.putExtra("returnedVideo", strPath);
                setResult(Activity.RESULT_OK, i);

                //Exit after saved
                finish();
            }else{

                //Release Camera before MediaRecorder start
                releaseCamera();

                if(!prepareMediaRecorder()){
                    Toast.makeText(AndroidVideoCapture.this, 
                            "Fail in prepareMediaRecorder()!\n - Ended -", 
                            Toast.LENGTH_LONG).show();
                    finish();
                }

                mediaRecorder.start();
                recording = true;
                myButton.setText("STOP");
            }
        }};

    private Camera getCameraInstance(){
        // TODO Auto-generated method stub
        Camera c = null;
        try {
            c = Camera.open(); // attempt to get a Camera instance
        }
        catch (Exception e){
            // Camera is not available (in use or does not exist)
        }
        return c; // returns null if camera is unavailable
    }

    private boolean prepareMediaRecorder(){

        Random genraotr = new Random();
        int n = 10000;
        n = genraotr.nextInt(n);    

        myCamera = getCameraInstance();
        mediaRecorder = new MediaRecorder();

        myCamera.unlock();
        mediaRecorder.setCamera(myCamera);

        mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
        mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);

        mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));

        mediaRecorder.setOutputFile("/sdcard/auction_video"+n+".mp4");
        strPath = "/sdcard/auction_video"+n+".mp4";
        mediaRecorder.setMaxDuration(10000); // Set max duration 10 sec.
        mediaRecorder.setMaxFileSize(5000000); // Set max file size 5M

        mediaRecorder.setPreviewDisplay(myCameraSurfaceView.getHolder().getSurface());

        try {
            mediaRecorder.prepare();
        } catch (IllegalStateException e) {
            releaseMediaRecorder();
            return false;
        } catch (IOException e) {
            releaseMediaRecorder();
            return false;
        }
        return true;

    }

    protected void onPause() {
        super.onPause();
        releaseMediaRecorder();       // if you are using MediaRecorder, release it first
        releaseCamera();              // release the camera immediately on pause event
    }

    private void releaseMediaRecorder(){
        if (mediaRecorder != null) {
            mediaRecorder.reset();   // clear recorder configuration
            mediaRecorder.release(); // release the recorder object
            mediaRecorder = null;
            myCamera.lock();           // lock camera for later use
        }
    }

    private void releaseCamera(){
        if (myCamera != null){
            myCamera.release();        // release the camera for other applications
            myCamera = null;
        }
    }

    public class MyCameraSurfaceView extends SurfaceView implements SurfaceHolder.Callback{

        private SurfaceHolder mHolder;
        private Camera mCamera;

        public MyCameraSurfaceView(Context context, Camera camera) {
            super(context);
            mCamera = camera;

            // Install a SurfaceHolder.Callback so we get notified when the
            // underlying surface is created and destroyed.
            mHolder = getHolder();
            mHolder.addCallback(this);
            // deprecated setting, but required on Android versions prior to 3.0
            mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        }

        public void surfaceChanged(SurfaceHolder holder, int format, int weight,
                int height) {
            // If your preview can change or rotate, take care of those events here.
            // Make sure to stop the preview before resizing or reformatting it.

            if (mHolder.getSurface() == null){
              // preview surface does not exist
              return;
            }

            // stop preview before making changes
            try {
                mCamera.stopPreview();
            } catch (Exception e){
              // ignore: tried to stop a non-existent preview
            }

            // make any resize, rotate or reformatting changes here

            // start preview with new settings
            try {
                mCamera.setPreviewDisplay(mHolder);
                mCamera.startPreview();

            } catch (Exception e){
            }
        }

        public void surfaceCreated(SurfaceHolder holder) {
            // TODO Auto-generated method stub
            // The Surface has been created, now tell the camera where to draw the preview.
            try {
                mCamera.setPreviewDisplay(holder);
                mCamera.startPreview();
            } catch (IOException e) {
            }
        }

        public void surfaceDestroyed(SurfaceHolder holder) {
            // TODO Auto-generated method stub

        }
    }

    @Override
    public void onBackPressed() {
        // TODO Auto-generated method stub
        super.onBackPressed();

        mediaRecorder.stop();  // stop the recording
        releaseMediaRecorder(); // release the MediaRecorder object               
        //Exit after saved
        finish();
    }

//  public void showMessage(String title, String message, final Context context){
//      try
//      {
//          AlertDialog.Builder alt_bld = new AlertDialog.Builder(context);
//          alt_bld.setTitle(title);
//          alt_bld.setMessage(message);
//          alt_bld.setCancelable(false);
//          alt_bld.setNeutralButton("OK", new DialogInterface.OnClickListener() {
//
//              public void onClick(DialogInterface dialog, int which) {
//                  // TODO Auto-generated method stub
//                  dialog.dismiss();
//                  
//                  Intent i = new Intent(AndroidVideoCapture.this,TakeAnotherPhoto.class);
//                  i.putExtra("returnedVideo", strPath);
//                  setResult(Activity.RESULT_OK, i);
//              }
//          });
//          alt_bld.show();
//      }
//      catch (Exception e) {
//          // TODO: handle exception
//      }
//  }
}

それが機能するかどうかを教えてください。

ありがとう

于 2013-01-08T08:53:15.827 に答える