как получить разрешение на захват экрана MediaProjectionManager только один раз, а не каждый раз?

public class MainActivity extends AppCompatActivity {

private static final String TAG = "MainActivity";
private static final int REQUEST_CODE = 1234;
private int mScreenDensity;
private MediaProjectionManager mProjectionManager;
private static final int DISPLAY_WIDTH = 720;
private static final int DISPLAY_HEIGHT = 1280;
private MediaProjection mMediaProjection;
private VirtualDisplay mVirtualDisplay;
private ToggleButton mToggleButton;
private MediaRecorder mMediaRecorder;
private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
private static final int REQUEST_PERMISSIONS = 10;

static {
    ORIENTATIONS.append(Surface.ROTATION_0, 90);
    ORIENTATIONS.append(Surface.ROTATION_90, 0);
    ORIENTATIONS.append(Surface.ROTATION_180, 270);
    ORIENTATIONS.append(Surface.ROTATION_270, 180);
}

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


    DisplayMetrics metrics = new DisplayMetrics();
    getWindowManager().getDefaultDisplay().getMetrics(metrics);
    mScreenDensity = metrics.densityDpi;


    mProjectionManager = (MediaProjectionManager) getSystemService
            (Context.MEDIA_PROJECTION_SERVICE);

    mToggleButton = (ToggleButton) findViewById(R.id.toggle);
    mToggleButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (ContextCompat.checkSelfPermission(MainActivity.this,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE) + ContextCompat
                    .checkSelfPermission(MainActivity.this,
                            Manifest.permission.RECORD_AUDIO)
                    != PackageManager.PERMISSION_GRANTED) {
                if (ActivityCompat.shouldShowRequestPermissionRationale
                        (MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) ||
                        ActivityCompat.shouldShowRequestPermissionRationale
                                (MainActivity.this, Manifest.permission.RECORD_AUDIO)) {
                    mToggleButton.setChecked(false);
                    Snackbar.make(findViewById(android.R.id.content), R.string.label_permissions,
                            Snackbar.LENGTH_INDEFINITE).setAction("ENABLE",
                            new View.OnClickListener() {
                                @Override
                                public void onClick(View v) {
                                    ActivityCompat.requestPermissions(MainActivity.this,
                                            new String[]{Manifest.permission
                                                    .WRITE_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO},
                                            REQUEST_PERMISSIONS);
                                }
                            }).show();
                } else {
                    ActivityCompat.requestPermissions(MainActivity.this,
                            new String[]{Manifest.permission
                                    .WRITE_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO},
                            REQUEST_PERMISSIONS);
                }
            } else {
                onToggleScreenShare(v);
            }
        }
    });
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {

    Log.d(TAG, " requestCode " + requestCode + " resultCode " + requestCode);

    if (REQUEST_CODE == requestCode) {
        if (resultCode == RESULT_OK) {
            mMediaProjection = mProjectionManager.getMediaProjection(resultCode, data);
            startRecording(); // defined below
        } else {
            Log.d(TAG, "Persmission denied");
        }
    }
}

private static final String VIDEO_MIME_TYPE = "video/avc";
private static final int VIDEO_WIDTH = 720;
private static final int VIDEO_HEIGHT = 1280;
// …
private boolean mMuxerStarted = false;
private Surface mInputSurface;
private MediaMuxer mMuxer;
private MediaCodec mVideoEncoder;
private MediaCodec.BufferInfo mVideoBufferInfo;
private int mTrackIndex = -1;

private final Handler mDrainHandler = new Handler(Looper.getMainLooper());
private Runnable mDrainEncoderRunnable = new Runnable() {
    @Override
    public void run() {
        drainEncoder();
    }
};

private void startRecording() {

    DisplayManager dm = (DisplayManager) getSystemService(Context.DISPLAY_SERVICE);
    Display defaultDisplay = dm.getDisplay(Display.DEFAULT_DISPLAY);
    if (defaultDisplay == null) {
        throw new RuntimeException("No display found.");
    }
    prepareVideoEncoder();

    try {
        mMuxer = new MediaMuxer(Environment.getExternalStoragePublicDirectory(Environment
                .DIRECTORY_DOWNLOADS) + "/video.mp4", MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
    } catch (IOException ioe) {
        throw new RuntimeException("MediaMuxer creation failed", ioe);
    }

    // Get the display size and density.
    DisplayMetrics metrics = getResources().getDisplayMetrics();
    int screenWidth = metrics.widthPixels;
    int screenHeight = metrics.heightPixels;
    int screenDensity = metrics.densityDpi;

    // Start the video input.
    mMediaProjection.createVirtualDisplay("Recording Display", screenWidth,
            screenHeight, screenDensity, 0 /* flags */, mInputSurface,
            null /* callback */, null /* handler */);

    // Start the encoders
    drainEncoder();
}

private void prepareVideoEncoder() {

    mVideoBufferInfo = new MediaCodec.BufferInfo();
    MediaFormat format = MediaFormat.createVideoFormat(VIDEO_MIME_TYPE, VIDEO_WIDTH, VIDEO_HEIGHT);
    int frameRate = 15; // 30 fps

    // Set some required properties. The media codec may fail if these aren't defined.
    format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
    //format.setInteger(MediaFormat.KEY_SAMPLE_RATE, 8000);
    format.setInteger(MediaFormat.KEY_BIT_RATE, 6000000); // 6Mbps
    format.setInteger(MediaFormat.KEY_FRAME_RATE, frameRate);
    //format.setInteger(MediaFormat.KEY_CAPTURE_RATE, frameRate);
    // format.setInteger(MediaFormat.KEY_REPEAT_PREVIOUS_FRAME_AFTER, 1000000 / frameRate);
    //format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1);
    format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 10); // 1 seconds between I-frames

    // Create a MediaCodec encoder and configure it. Get a Surface we can use for recording into.
    try {
        mVideoEncoder = MediaCodec.createEncoderByType(VIDEO_MIME_TYPE);
        mVideoEncoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
        mInputSurface = mVideoEncoder.createInputSurface();
        mVideoEncoder.start();
    } catch (IOException e) {
        releaseEncoders();
    }
}

private void releaseEncoders() {


    mDrainHandler.removeCallbacks(mDrainEncoderRunnable);
    if (mMuxer != null) {
        if (mMuxerStarted) {
            mMuxer.stop();
        }
        mMuxer.release();
        mMuxer = null;
        mMuxerStarted = false;
    }
    if (mVideoEncoder != null) {
        mVideoEncoder.stop();
        mVideoEncoder.release();
        mVideoEncoder = null;
    }
    if (mInputSurface != null) {
        mInputSurface.release();
        mInputSurface = null;
    }
    if (mMediaProjection != null) {
        mMediaProjection.stop();
        mMediaProjection = null;
    }
    mVideoBufferInfo = null;
    //mDrainEncoderRunnable = null;
    mTrackIndex = -1;
}

private boolean drainEncoder() {
    mDrainHandler.removeCallbacks(mDrainEncoderRunnable);
    while (true) {
        int bufferIndex = mVideoEncoder.dequeueOutputBuffer(mVideoBufferInfo, 0);

        if (bufferIndex == MediaCodec.INFO_TRY_AGAIN_LATER) {
            // nothing available yet
            break;
        } else if (bufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
            // should happen before receiving buffers, and should only happen once
            if (mTrackIndex >= 0) {
                throw new RuntimeException("format changed twice");
            }
            mTrackIndex = mMuxer.addTrack(mVideoEncoder.getOutputFormat());
            if (!mMuxerStarted && mTrackIndex >= 0) {
                mMuxer.start();
                mMuxerStarted = true;
            }
        } else if (bufferIndex < 0) {
            // not sure what's going on, ignore it
        } else {
            ByteBuffer encodedData = mVideoEncoder.getOutputBuffer(bufferIndex);
            if (encodedData == null) {
                throw new RuntimeException("couldn't fetch buffer at index " + bufferIndex);
            }

            if ((mVideoBufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
                mVideoBufferInfo.size = 0;
            }

            if (mVideoBufferInfo.size != 0) {
                if (mMuxerStarted) {
                    encodedData.position(mVideoBufferInfo.offset);
                    encodedData.limit(mVideoBufferInfo.offset + mVideoBufferInfo.size);
                    mMuxer.writeSampleData(mTrackIndex, encodedData, mVideoBufferInfo);
                } else {
                    // muxer not started
                }
            }

            mVideoEncoder.releaseOutputBuffer(bufferIndex, false);

            if ((mVideoBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
                break;
            }
        }
        Log.d(TAG, "Recording");
    }

    mDrainHandler.postDelayed(mDrainEncoderRunnable, 10);

    return false;
}


public void onToggleScreenShare(View view) {
    if (((ToggleButton) view).isChecked()) {
        if (mMediaProjection == null) {
            startActivityForResult(mProjectionManager.createScreenCaptureIntent(), REQUEST_CODE);
        } else {
            startRecording();
        }
    } else {
        releaseEncoders();
    }
}

}

startActivityForResult(mProjectionManager.createScreenCaptureIntent(), REQUEST_CODE);

Эта строка кода запрашивает разрешение на захват экрана. Каждый раз, когда мой код вызывает это, он показывает диалоговое окно для разрешения. Но если я нажму «Больше не показывать», он не будет запрашивать разрешение, а предоставит разрешение в фоновом режиме. Как я могу получить разрешение только один раз и предоставить все время, не выбирая больше не показывать ?? Полный код приведен здесь


person Md. Sulayman    schedule 07.02.2017    source источник
comment
опубликуйте полный код, пожалуйста.   -  person tahsinRupam    schedule 07.02.2017
comment
Рупам, редактируй коре диси   -  person Md. Sulayman    schedule 07.02.2017
comment
Хорошо, дара дехтеси   -  person tahsinRupam    schedule 07.02.2017
comment
mMediaProjection пустой пакет кено? разрешение предоставить кора хой най тай ?   -  person tahsinRupam    schedule 07.02.2017
comment
разрешение предоставляется на дыру null paabe . Somossa holo prottek bar запись korte gele разрешение req kore. Кинту не показывай te dile ar chai na. Программа Ami chacchi поможет вам управлять кортом. Библиотека с исходным кодом, mProjectionManager.createScreenCaptureIntent(), а также частная активность, связанная с тем, что вы можете использовать AlertDialog, чтобы запустить кору или защиту.   -  person Md. Sulayman    schedule 07.02.2017
comment
Не показывай снова, т.к. временное решение может быть лучше, т.е. лучше. eita - stackoverflow.com/a/33892817/7235049 дехте парос   -  person tahsinRupam    schedule 07.02.2017
comment
Получил решение. Необходимо сохранить ссылку Intent и resultCode из onActivityResult() для дальнейшего использования. И возьмите мою медиапроекцию этим намерением для будущего использования   -  person Md. Sulayman    schedule 11.02.2017


Ответы (1)


public void onToggleScreenShare(View view) {
if (((ToggleButton) view).isChecked()) {
    if (mMediaProjection == null) {
        startActivityForResult(mProjectionManager.createScreenCaptureIntent(), REQUEST_CODE);
    } else {
        startRecording();
    }
} else {
    releaseEncoders();
}
}

В этом методе метод startActivityForResult() запрашивает разрешение на захват экрана. Если предоставить разрешение или отказать в нем, вызов передачи кода onActivityResultMethod()

    @Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {

Log.d(TAG, " requestCode " + requestCode + " resultCode " + requestCode);

if (REQUEST_CODE == requestCode) {
    if (resultCode == RESULT_OK) {
        mMediaProjection = mProjectionManager.getMediaProjection(resultCode, data);
        startRecording(); // defined below
    } else {
        Log.d(TAG, "Persmission denied");
    }
}
}

В этом методе мы получаем данные Intent и resultCode. Чтобы в дальнейшем использовать MediaProjectionManager без запроса непрерывного разрешения, мы должны сохранить ссылку на Intent и значение resultCode и использовать mediaProjectionManager через эту строку кода.

mMediaProjection = mProjectionManager.getMediaProjection(saveResult, savedIntent);

Таким образом, он не будет запрашивать разрешение снова, поскольку разрешение уже предоставлено.

person Md. Sulayman    schedule 11.02.2017
comment
Это работает? Как вы могли бы сохранить Intent в SharedPreferenses и восстановить? Я пробую prefs.pusString(key,intent.toUri(0)); и восстановить намерение Intent = Intent.parseUri(uriStr, 0); Но когда я запускаю mediaprojection с этим намерением, mediaprojection == null. - person Tim Kruichkov; 18.05.2018
comment
Не сохраняйте его в SharedPreference. Создайте частную переменную типа Intent в своей деятельности, назначьте ссылку на намерение для этой переменной и используйте ее. - person Md. Sulayman; 18.05.2018
comment
Вы можете попытаться сохранить намерение в Singleton и попробовать использовать его в других действиях. Хотя этого я не пробовал. моя потребность была удовлетворена этим подходом - person Md. Sulayman; 18.05.2018
comment
Сохранение в приватной переменной не будет работать при перезагрузке телефона. - person Rougher; 03.07.2019
comment
@TimKruichkov, вы нашли решение для сохранения данных о намерениях в SharedPreferenses той же проблеме, что и я, пожалуйста, помогите - person Sagar; 30.07.2019