I use CameraX API for handle camera in my application, and I added SeekBar to control zoom camera, but it not working well when I seek to 0 it was zoom out then I seek to 100 it zoom to maximum amount, so what I need to do, zoom 0 - 100 zooming smoothly
Current Preview
CameraActivity.java
public class CameraActivity extends AppCompatActivity {
private Executor executor = Executors.newSingleThreadExecutor();
private int REQUEST_CODE_PERMISSIONS = 1001;
public static final int REQUEST_CAPTURE_IMAGE = 1002;
private final String[] REQUIRED_PERMISSIONS = new String[]{"android.permission.CAMERA", "android.permission.WRITE_EXTERNAL_STORAGE"};
private PreviewView mPreviewView;
private FloatingActionButton captureImage;
private VerticalSeekBar seekBar;
private Camera camera;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera);
mPreviewView = findViewById(R.id.camera);
captureImage = findViewById(R.id.capture);
seekBar = findViewById(R.id.seekBar);
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
camera.getCameraControl().setLinearZoom((float) (progress/100));
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
if(allPermissionsGranted()){
startCamera(); //start camera if permission has been granted by user
} else{
ActivityCompat.requestPermissions(this, REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS);
}
}
private void startCamera() {
final ListenableFuture<ProcessCameraProvider> cameraProviderFuture = ProcessCameraProvider.getInstance(this);
cameraProviderFuture.addListener(new Runnable() {
#Override
public void run() {
try {
ProcessCameraProvider cameraProvider = cameraProviderFuture.get();
bindPreview(cameraProvider);
} catch (ExecutionException | InterruptedException e) {
// No errors need to be handled for this Future.
// This should never be reached.
}
}
}, ContextCompat.getMainExecutor(this));
}
void bindPreview(#NonNull ProcessCameraProvider cameraProvider) {
Preview preview = new Preview.Builder()
.build();
CameraSelector cameraSelector = new CameraSelector.Builder()
.requireLensFacing(CameraSelector.LENS_FACING_BACK)
.build();
ImageAnalysis imageAnalysis = new ImageAnalysis.Builder()
.build();
ImageCapture.Builder builder = new ImageCapture.Builder();
//Vendor-Extensions (The CameraX extensions dependency in build.gradle)
HdrImageCaptureExtender hdrImageCaptureExtender = HdrImageCaptureExtender.create(builder);
// Query if extension is available (optional).
if (hdrImageCaptureExtender.isExtensionAvailable(cameraSelector)) {
// Enable the extension if available.
hdrImageCaptureExtender.enableExtension(cameraSelector);
}
final ImageCapture imageCapture = builder
.setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
.build();
preview.setSurfaceProvider(mPreviewView.getSurfaceProvider());
camera = cameraProvider.bindToLifecycle(this, cameraSelector, preview, imageAnalysis, imageCapture);
camera.getCameraControl().setZoomRatio(0.1f);
captureImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String path = getIntent().getStringExtra("path");
File file = null;
if(path != null){
file = new File(path, getIntent().getStringExtra("fileName"));
} else {
SimpleDateFormat mDateFormat = new SimpleDateFormat("yyyyMMddHHmmss", Locale.US);
file = new File(getBatchDirectoryName(), mDateFormat.format(new Date()) + ".jpg");
}
ImageCapture.Metadata metadata = new ImageCapture.Metadata();
if(Session.getLocation() != null) {
metadata.setLocation(Session.getLocation());
}
ImageCapture.OutputFileOptions outputFileOptions = new ImageCapture.OutputFileOptions.Builder(file).setMetadata(metadata).build();
File finalFile = file;
imageCapture.takePicture(outputFileOptions, executor, new ImageCapture.OnImageSavedCallback () {
#Override
public void onImageSaved(#NonNull ImageCapture.OutputFileResults outputFileResults) {
Intent intent=new Intent();
intent.putExtra("path", finalFile.getPath());
setResult(RESULT_OK, intent);
finish();
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(CameraActivity.this, "Image Saved successfully", Toast.LENGTH_SHORT).show();
}
});
}
#Override
public void onError(#NonNull ImageCaptureException error) {
error.printStackTrace();
}
});
}
});
}
public String getBatchDirectoryName() {
String app_folder_path = "";
app_folder_path = Environment.getExternalStorageDirectory().toString() + "/images";
File dir = new File(app_folder_path);
if (!dir.exists() && !dir.mkdirs()) {
}
return app_folder_path;
}
private boolean allPermissionsGranted(){
for(String permission : REQUIRED_PERMISSIONS){
if(ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED){
return false;
}
}
return true;
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if(requestCode == REQUEST_CODE_PERMISSIONS){
if(allPermissionsGranted()){
startCamera();
} else{
Toast.makeText(this, "Permissions not granted by the user.", Toast.LENGTH_SHORT).show();
this.finish();
}
}
}
}
You are casting the value incorrectly. So instead:
camera.getCameraControl().setLinearZoom((float) (progress/100));
do:
camera.getCameraControl().setLinearZoom((float) progress/seekBar.getMax());
Related
Im quite new to Android and I'm looking to find a way how to access the wide angle camera. I know how to list all my cameras on a certain device and I know how to see which camera I'm opening. I need to know how to set my camera to open the wide angle one. Thanks in advance ! I also read everything in android developers but there is nothing mentioning about the wide angle camera. And this is how I'm opening/activating my camera.
public class CameraActivity extends AppCompatActivity {
private static final String TAG = "cam";
private String lastImageUri;
private ListenableFuture<ProcessCameraProvider> cameraProviderListenableFuture;
private ImageCapture imageCapture;
private PreviewView previewView;
private PermissionManager permissionManager;
private final String[] permissions = {Manifest.permission.CAMERA,
Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE};
private Uri fileUri;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera);
Button buttonCameraSelectToDeleteImage = (Button) findViewById(R.id.buttonDeleteImage);
Button button = (Button) findViewById(R.id.buttonMain);
previewView = findViewById(R.id.previewView);
permissionManager = PermissionManager.getInstance(CameraActivity.this);
cameraProviderListenableFuture = ProcessCameraProvider.getInstance(getApplicationContext());
cameraProviderListenableFuture.addListener(() -> {
try {
ProcessCameraProvider cameraProvider = cameraProviderListenableFuture.get();
startCameraX(cameraProvider);
} catch (ExecutionException | InterruptedException e) {
e.printStackTrace();
}
}, getExecutor());
Button buttonCameraSelectToMakeAndSavePhoto = (Button) findViewById(R.id.buttonCameraSelectToMakeAndSavePhoto);
buttonCameraSelectToMakeAndSavePhoto.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (!permissionManager.checkPermissions(permissions)) {
permissionManager.askPermission(CameraActivity.this, permissions, 100);
} else {
capturePhoto();
}
}
});
buttonCameraSelectToDeleteImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
CommonPropertiesArray.arrayOfUriStrings.remove(lastImageUri);
}
});
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(CameraActivity.this, AddInternActivity.class);
startActivity(intent);
}
});
// Context context = CameraActivity.this;
// CameraManager manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
// try {
// String[] cameraIds = manager.getCameraIdList();
// Log.d("cameraIds", Arrays.toString(cameraIds));
// } catch (CameraAccessException e) {
// e.printStackTrace();
// }
}
private Executor getExecutor() {
return ContextCompat.getMainExecutor(this);
}
private void startCameraX(ProcessCameraProvider cameraProvider) {
cameraProvider.unbindAll();
// Camera Selector use case
CameraSelector cameraSelector = new CameraSelector.Builder()
.requireLensFacing(CameraSelector.LENS_FACING_BACK)
.build();
// Preview use case
Preview preview = new Preview.Builder().build();
preview.setSurfaceProvider(previewView.getSurfaceProvider());
// Image capture use case
imageCapture = new ImageCapture.Builder()
.setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
.build();
cameraProvider.bindToLifecycle((LifecycleOwner) this, cameraSelector, preview, imageCapture);
}
private void capturePhoto() {
long timeStamp = System.currentTimeMillis();
ContentValues contentValues = new ContentValues();
contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, timeStamp);
contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg");
imageCapture.takePicture(
new ImageCapture.OutputFileOptions.Builder(
getContentResolver(),
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
contentValues
).build(),
getExecutor(),
new ImageCapture.OnImageSavedCallback() {
#Override
public void onImageSaved(#NonNull ImageCapture.OutputFileResults outputFileResults) {
if (CommonPropertiesArray.arrayOfUriStrings.size() < 3) {
fileUri = (outputFileResults.getSavedUri());
lastImageUri = String.valueOf(fileUri);
CommonPropertiesArray.arrayOfUriStrings.add(lastImageUri);
Toast.makeText(CameraActivity.this, "Photo has been save successfully", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(CameraActivity.this, "You can make max 3 picture", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onError(#NonNull ImageCaptureException exception) {
Toast.makeText(CameraActivity.this, "Error saving photo: " + exception.getMessage(), Toast.LENGTH_SHORT).show();
}
}
);
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == 100) {
permissionManager.handlePermissionResult(CameraActivity.this, 100, permissions,
grantResults);
}
}
I have almost a week figuring out how should I have one instance of exoplayer in background.
I want to use this instance in a playerview and in notification as well. Problem I am facing now, the player plays well, after a time it pauses (to release resource I guess), but when i click play it plays again, when i click other oudio, I get two audio playing at same time.
Here are my codes.
------------------------ BACKGROUND SERVICE --------------------------------------
public class BackgroundPlayingService extends Service {
public static PlayerNotificationManager playerNotificationManager;
public static ExoPlayer exoPlayer;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (this.exoPlayer == null){
createPlayer();
}
/////////////////THIS WAS ADDED LATER
return START_STICKY;
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onDestroy() {
super.onDestroy();
exoPlayer.pause();
exoPlayer = null;
playerNotificationManager.setPlayer(null);
}
private void createPlayer(){
exoPlayer = new ExoPlayer.Builder(this).build();
MediaItem mediaItem;
try {
mediaItem = MediaItem.fromUri(Uri.parse(DataUtility.playingUrl));
}catch (Exception e){
mediaItem = MediaItem.fromUri(Uri.parse("https://server13.mp3quran.net/husr/062.mp3"));
}
exoPlayer.setMediaItem(mediaItem);
exoPlayer.prepare();
exoPlayer.addListener(new Player.Listener() {
#Override
public void onPlaybackStateChanged(int playbackState) {
Player.Listener.super.onPlaybackStateChanged(playbackState);
try {
if (ThePlayingActivity.dialog.isShowing()){
ThePlayingActivity.dialog.dismiss();}
}catch (Exception ignore){
}
if (playbackState==Player.STATE_READY){
try {
ThePlayingActivity.downloadBtn.setVisibility(View.VISIBLE);
showNotification();
}catch (Exception ignore){
}
}
if (playbackState == Player.STATE_BUFFERING) {
try {
ThePlayingActivity.myProgress.setVisibility(View.VISIBLE);
}catch (Exception e){
}
} else {
try {
ThePlayingActivity.myProgress.setVisibility(View.GONE);
}catch (Exception e){
}
}
}
#Override
public void onIsLoadingChanged(boolean isLoading) {
Player.Listener.super.onIsLoadingChanged(isLoading);
}
#Override
public void onPlayerError(PlaybackException error) {
Player.Listener.super.onPlayerError(error);
try {
if (ThePlayingActivity.dialog.isShowing()){
ThePlayingActivity.dialog.dismiss();
}
playerNotificationManager.setPlayer(null);
}catch (Exception ignore){
}
}
});
exoPlayer.play();
try {
ThePlayingActivity.myPlayerView.setPlayer(exoPlayer);
}catch (Exception e){
Log.d("background", "createPlayer: set player to view"+e.getLocalizedMessage());
}
}
public static void setNewPlayeData(){
MediaItem mediaItem = MediaItem.fromUri(Uri.parse(DataUtility.playingUrl));
exoPlayer.setMediaItem(mediaItem);
exoPlayer.prepare();
ThePlayingActivity.myPlayerView.setPlayer(exoPlayer);
try {
ThePlayingActivity.myPlayerView.setPlayer(exoPlayer);
}catch (Exception e){
Log.d("background", "createPlayer: set player to view"+e.getLocalizedMessage());
}
}
public void showNotification() {
playerNotificationManager = new PlayerNotificationManager.Builder(this, 151,
this.getResources().getString(R.string.app_name))
.setChannelNameResourceId(R.string.app_name)
.setChannelImportance(IMPORTANCE_HIGH)
.setMediaDescriptionAdapter(new PlayerNotificationManager.MediaDescriptionAdapter() {
#Override
public CharSequence getCurrentContentTitle(Player player) {
return player.getCurrentMediaItem().mediaMetadata.displayTitle;
}
#Nullable
#Override
public PendingIntent createCurrentContentIntent(Player player) {
return null;
}
#Nullable
#Override
public CharSequence getCurrentContentText(Player player) {
return Objects.requireNonNull(player.getCurrentMediaItem()).mediaMetadata.artist;
}
#Nullable
#Override
public Bitmap getCurrentLargeIcon(Player player, PlayerNotificationManager.BitmapCallback callback) {
return null;
}
}).setNotificationListener(new PlayerNotificationManager.NotificationListener() {
#Override
public void onNotificationCancelled(int notificationId, boolean dismissedByUser) {
}
#Override
public void onNotificationPosted(int notificationId, Notification notification, boolean ongoing) {
PlayerNotificationManager.NotificationListener.super.onNotificationPosted(notificationId, notification, ongoing);
}
})
.build();
playerNotificationManager.setUseStopAction(false);
try {
playerNotificationManager.setPlayer(exoPlayer);
}catch (Exception e){
}
}
}
-----------------------HERE IS THE ACTIVITY WITH PLAYER ----------------------------------
public class ThePlayingActivity extends AppCompatActivity {
private static final int PERMISION_STORAGE_CODE = 100;
private ProgressBar downloadingProgress;
public static ProgressBar myProgress;
public static Dialog dialog;
private ConstraintLayout layoutForSnack;
long downloadId;
private PowerManager powerManager;
private PowerManager.WakeLock wakeLock;
String myurl;
public static PlayerControlView myPlayerView;
private TextView currentPlaying, downloadingTv;
public static Button downloadBtn;
private String thePlayingSura;
private final BroadcastReceiver onDownloadComplete = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID,-1);
if (downloadId == id){
downloadingProgress.setVisibility(View.GONE);
downloadingTv.setVisibility(View.GONE);
downloadBtn.setText("DOWNLOADED");
downloadBtn.setBackgroundColor(Color.TRANSPARENT);
downloadBtn.setTextColor(Color.BLACK);
downloadBtn.setClickable(false);
Toast.makeText(context, "DOWNLOAD COMPLETED", Toast.LENGTH_SHORT).show();
}
}
};
#SuppressLint("SetTextI18n")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_the_playing);
myPlayerView = findViewById(R.id.playerView);
Intent dataIntent = getIntent();
myurl = dataIntent.getStringExtra("theUrl");
if (BackgroundPlayingService.exoPlayer == null){
startService();}else{
BackgroundPlayingService.setNewPlayeData();
myPlayerView.setPlayer(BackgroundPlayingService.exoPlayer);
}
keepActivityAlive();
registerReceiver(onDownloadComplete,new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
downloadingProgress = findViewById(R.id.downloadProgress);
downloadingTv = findViewById(R.id.downloadingWaitTv);
currentPlaying = findViewById(R.id.currentPlaying);
downloadBtn = findViewById(R.id.downloadbtn);
downloadBtn.setVisibility(View.GONE);
myProgress = findViewById(R.id.progressBar2);
myProgress.setVisibility(View.GONE);
layoutForSnack = findViewById(R.id.constraintLayout);
downloadingProgress.setVisibility(View.GONE);
downloadingTv.setVisibility(View.GONE);
thePlayingSura = dataIntent.getStringExtra("sendSuraName");
currentPlaying.setText(thePlayingSura+" - " + DataUtility.theKariName);
/////////////end of ids
showLoadingDialog();
/////////////////download
downloadBtn.setOnClickListener(view -> {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED){
//todo ask permission
String permissions[] = {Manifest.permission.WRITE_EXTERNAL_STORAGE};
requestPermissions(permissions,PERMISION_STORAGE_CODE);
}else{
downloadStaffs();
}
}else {
//TODO DOWNLOAD
downloadStaffs();
}
});
/////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
}
#Override
public void onBackPressed() {
super.onBackPressed();
//todo fire service (may be)
}
private void showLoadingDialog() {
dialog = new Dialog(ThePlayingActivity.this);
dialog.setContentView(R.layout.dialog_loading_quran);
dialog.setCancelable(false);
dialog.show();
}
private void showSnackBar() {
Snackbar snackbar = Snackbar.make(layoutForSnack, "THERE WAS ON ERROR, CHECK YOUR INTERNET CONNECTION", Snackbar.LENGTH_INDEFINITE);
snackbar.setAction("RETRY", view -> {
});
snackbar.setActionTextColor(Color.YELLOW);
snackbar.show();
}
#Override
protected void onStop() {
super.onStop();
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode){
case PERMISION_STORAGE_CODE:{
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
// we have permission
//todo Download
downloadStaffs();
}else{
Toast.makeText(ThePlayingActivity.this , "PERMISSION DENIED... CAN NOT DOWNLOAD", Toast.LENGTH_SHORT).show();
}
}
}
}
#Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(onDownloadComplete);
try {
if (wakeLock.isHeld()){
wakeLock.release();}
}catch (Exception ignore){
}
}
private void downloadStaffs(){
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(DataUtility.playingUrl));
request.setDescription("Download File");
request.setTitle(thePlayingSura);
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, thePlayingSura+" - "+ DataUtility.theKariName+".mp3");
final DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
final long downloadId = manager.enqueue(request);
this.downloadId = downloadId;
final ProgressBar mProgressBar = (ProgressBar) findViewById(R.id.downloadProgress);
downloadingTv.setVisibility(View.VISIBLE);
mProgressBar.setVisibility(View.VISIBLE);
new Thread(new Runnable() {
#SuppressLint("Range")
#Override
public void run() {
boolean downloading = true;
while (downloading) {
DownloadManager.Query q = new DownloadManager.Query();
q.setFilterById(downloadId);
Cursor cursor = manager.query(q);
cursor.moveToFirst();
#SuppressLint("Range") int bytes_downloaded = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
#SuppressLint("Range") int bytes_total = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
if (cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_SUCCESSFUL) {
downloading = false;
}
final double dl_progress = (int) ((bytes_downloaded * 100l) / bytes_total);
runOnUiThread(new Runnable() {
#Override
public void run() {
mProgressBar.setProgress((int) dl_progress);
}
});
Log.d("MESSAGES", statusMessage(cursor));
cursor.close();
}
}
}).start();
}
#SuppressLint("Range")
private String statusMessage(Cursor c) {
String msg = "???";
switch (c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS))) {
case DownloadManager.STATUS_FAILED:
msg = "Download failed!";
break;
case DownloadManager.STATUS_PAUSED:
msg = "Download paused!";
break;
case DownloadManager.STATUS_PENDING:
msg = "Download pending!";
break;
case DownloadManager.STATUS_RUNNING:
msg = "Download in progress!";
break;
case DownloadManager.STATUS_SUCCESSFUL:
msg = "Download complete!";
break;
default:
msg = "Download is nowhere in sight";
break;
}
return (msg);
}
}
private void keepActivityAlive(){
powerManager = (PowerManager) this.getSystemService(Context.POWER_SERVICE);
wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,"QuranAudio:WakeLock");
}
private void startService(){
Intent i = new Intent(this, BackgroundPlayingService.class);
startService(i);
}
}
I figured it out.
I had to keep most of my business inside in onStartCommand
public class BackgroundPlayingService extends Service {
public static final String TAG = "bck_service";
public static ExoPlayer player;
public static PlayerNotificationManager playerNotificationManager;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
String url = DataUtility.playingUrl;
if (url==null){
url = "https://server8.mp3quran.net/afs/Rewayat-AlDorai-A-n-Al-Kisa-ai/025.mp3";
}
if (player == null){
player = createPlayerIfNull();
MediaItem mediaItem = MediaItem.fromUri(Uri.parse(url));
player.setMediaItem(mediaItem);
player.prepare();
player.addListener(new Player.Listener() {
#Override
public void onEvents(Player player, Player.Events events) {
}
#Override
public void onPlaybackStateChanged(int playbackState) {
Player.Listener.super.onPlaybackStateChanged(playbackState);
try {
if (ThePlayingActivity.dialog.isShowing()){
ThePlayingActivity.dialog.dismiss();}
}catch (Exception ignore){
}
if (playbackState==Player.STATE_READY){
try {
ThePlayingActivity.downloadBtn.setVisibility(View.VISIBLE);
showNotification();
}catch (Exception ignore){
}
}
if (playbackState == Player.STATE_BUFFERING) {
try {
ThePlayingActivity.myProgress.setVisibility(View.VISIBLE);
}catch (Exception e){
}
} else {
try {
ThePlayingActivity.myProgress.setVisibility(View.GONE);
}catch (Exception e){
}
}
}
#Override
public void onIsLoadingChanged(boolean isLoading) {
Player.Listener.super.onIsLoadingChanged(isLoading);
}
#Override
public void onPlayerError(PlaybackException error) {
Player.Listener.super.onPlayerError(error);
try {
if (ThePlayingActivity.dialog.isShowing()){
ThePlayingActivity.dialog.dismiss();}
}catch (Exception ignore){
}
}
});
player.play();
try {
ThePlayingActivity.myPlayerView.setPlayer(player);
}catch (Exception ignore){}
}
//notification
createNotificationChannel();
Intent i = new Intent(this,BackgroundPlayingService.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,0,i,0);
Notification notification = new NotificationCompat.Builder(this,"myChannelId")
.setContentTitle("QURAN IS PLAYING")
.setContentText("This means that Qur-an app is open. You can close it from app exit menu")
.setSmallIcon(androidx.core.R.drawable.notification_icon_background)
.setContentIntent(pendingIntent)
.build();
startForeground(1,notification);
return START_STICKY;
}
public ExoPlayer createPlayerIfNull() {
if (player == null) {
player = new ExoPlayer.Builder(BackgroundPlayingService.this).build();
ThePlayingActivity.myProgress.setVisibility(View.VISIBLE);
try {
ThePlayingActivity.dialog.show();
}catch (Exception e){
Log.d(TAG, "createPlayerIfNull: ");
}
}
return player;
}
private void createNotificationChannel(){
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
NotificationChannel channel = new NotificationChannel("myChannelId","qur-anAudiChannel", NotificationManager.IMPORTANCE_LOW);
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(channel);
}
}
#Override
public void onDestroy() {
super.onDestroy();
player.stop();
player = null;
stopForeground(true);
}
public void showNotification() {
playerNotificationManager = new PlayerNotificationManager.Builder(this, 151,
this.getResources().getString(R.string.app_name))
.setChannelNameResourceId(R.string.app_name)
.setChannelImportance(IMPORTANCE_HIGH)
.setMediaDescriptionAdapter(new PlayerNotificationManager.MediaDescriptionAdapter() {
#Override
public CharSequence getCurrentContentTitle(Player player) {
return player.getCurrentMediaItem().mediaMetadata.displayTitle;
}
#Nullable
#Override
public PendingIntent createCurrentContentIntent(Player player) {
return null;
}
#Nullable
#Override
public CharSequence getCurrentContentText(Player player) {
return Objects.requireNonNull(player.getCurrentMediaItem()).mediaMetadata.artist;
}
#Nullable
#Override
public Bitmap getCurrentLargeIcon(Player player, PlayerNotificationManager.BitmapCallback callback) {
return null;
}
}).setNotificationListener(new PlayerNotificationManager.NotificationListener() {
#Override
public void onNotificationCancelled(int notificationId, boolean dismissedByUser) {
}
#Override
public void onNotificationPosted(int notificationId, Notification notification, boolean ongoing) {
PlayerNotificationManager.NotificationListener.super.onNotificationPosted(notificationId, notification, ongoing);
}
})
.build();
playerNotificationManager.setUseStopAction(false);
try {
playerNotificationManager.setPlayer(player);
}catch (Exception e){
}}
}
-------------------- player view activity ------------------------------------
public class ThePlayingActivity extends AppCompatActivity {
private static final int PERMISION_STORAGE_CODE = 100;
private ProgressBar downloadingProgress;
public static ProgressBar myProgress;
public static Dialog dialog;
private ConstraintLayout layoutForSnack;
long downloadId;
private PowerManager powerManager;
private PowerManager.WakeLock wakeLock;
String myurl;
public static PlayerControlView myPlayerView;
private TextView currentPlaying, downloadingTv;
public static Button downloadBtn;
private String thePlayingSura;
private BroadcastReceiver onDownloadComplete = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
if (downloadId == id) {
downloadingProgress.setVisibility(View.GONE);
downloadingTv.setVisibility(View.GONE);
downloadBtn.setText("DOWNLOADED");
downloadBtn.setBackgroundColor(Color.TRANSPARENT);
downloadBtn.setTextColor(Color.BLACK);
downloadBtn.setClickable(false);
Toast.makeText(context, "DOWNLOAD COMPLETED", Toast.LENGTH_SHORT).show();
}
}
};
#SuppressLint("StaticFieldLeak")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_the_playing);
myPlayerView = findViewById(R.id.playerView);
Intent dataIntent = getIntent();
myurl = dataIntent.getStringExtra("theUrl");
Intent backgroundPlayIntent = new Intent(ThePlayingActivity.this,BackgroundPlayingService.class);
try {
stopService(backgroundPlayIntent);
}catch (Exception e){}
if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){
startForegroundService(backgroundPlayIntent);
}else{
startService(backgroundPlayIntent);
}
keepActivityAlive();
registerReceiver(onDownloadComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
downloadingProgress = findViewById(R.id.downloadProgress);
downloadingTv = findViewById(R.id.downloadingWaitTv);
currentPlaying = findViewById(R.id.currentPlaying);
downloadBtn = findViewById(R.id.downloadbtn);
downloadBtn.setVisibility(View.GONE);
myProgress = findViewById(R.id.progressBar2);
myProgress.setVisibility(View.VISIBLE);
layoutForSnack = findViewById(R.id.constraintLayout);
downloadingProgress.setVisibility(View.GONE);
downloadingTv.setVisibility(View.GONE);
thePlayingSura = dataIntent.getStringExtra("sendSuraName");
currentPlaying.setText(thePlayingSura + " - " + DataUtility.theKariName);
/////////////end of ids
showLoadingDialog();
/////////////////download
downloadBtn.setOnClickListener(view -> {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED) {
String permissions[] = {Manifest.permission.WRITE_EXTERNAL_STORAGE};
requestPermissions(permissions, PERMISION_STORAGE_CODE);
} else {
downloadStaffs();
}
} else {
downloadStaffs();
}
});
}
private void showLoadingDialog() {
dialog = new Dialog(ThePlayingActivity.this);
dialog.setContentView(R.layout.dialog_loading_quran);
dialog.setCancelable(false);
dialog.show();
}
public void showSnackBar() {
Snackbar snackbar = Snackbar.make(layoutForSnack, "THERE WAS ON ERROR, CHECK YOUR INTERNET CONNECTION", Snackbar.LENGTH_INDEFINITE);
snackbar.setAction("RETRY", view -> {
//todo retry player
});
snackbar.setActionTextColor(Color.YELLOW);
snackbar.show();
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case PERMISION_STORAGE_CODE: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// we have permission
downloadStaffs();
} else {
Toast.makeText(ThePlayingActivity.this, "PERMISSION DENIED... CAN NOT DOWNLOAD", Toast.LENGTH_SHORT).show();
}
}
}
}
#Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(onDownloadComplete);
try {
if (wakeLock.isHeld()) {
wakeLock.release();
}
} catch (Exception ignore) {
}
}
private void downloadStaffs() {
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(DataUtility.playingUrl));
request.setDescription("Download File");
request.setTitle(thePlayingSura);
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, thePlayingSura + " - " + DataUtility.theKariName + ".mp3");
final DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
final long downloadId = manager.enqueue(request);
this.downloadId = downloadId;
final ProgressBar mProgressBar = (ProgressBar) findViewById(R.id.downloadProgress);
downloadingTv.setVisibility(View.VISIBLE);
mProgressBar.setVisibility(View.VISIBLE);
new Thread(new Runnable() {
#SuppressLint("Range")
#Override
public void run() {
boolean downloading = true;
while (downloading) {
DownloadManager.Query q = new DownloadManager.Query();
q.setFilterById(downloadId);
Cursor cursor = manager.query(q);
cursor.moveToFirst();
#SuppressLint("Range") int bytes_downloaded = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
#SuppressLint("Range") int bytes_total = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
if (cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_SUCCESSFUL) {
downloading = false;
}
final double dl_progress = (int) ((bytes_downloaded * 100l) / bytes_total);
runOnUiThread(new Runnable() {
#Override
public void run() {
mProgressBar.setProgress((int) dl_progress);
}
});
Log.d("MESSAGES", statusMessage(cursor));
cursor.close();
}
}
}).start();
}
#SuppressLint("Range")
private String statusMessage(Cursor c) {
String msg = "???";
switch (c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS))) {
case DownloadManager.STATUS_FAILED:
msg = "Download failed!";
break;
case DownloadManager.STATUS_PAUSED:
msg = "Download paused!";
break;
case DownloadManager.STATUS_PENDING:
msg = "Download pending!";
break;
case DownloadManager.STATUS_RUNNING:
msg = "Download in progress!";
break;
case DownloadManager.STATUS_SUCCESSFUL:
msg = "Download complete!";
break;
default:
msg = "Download is nowhere in sight";
break;
}
return (msg);
}
private void keepActivityAlive() {
powerManager = (PowerManager) this.getSystemService(Context.POWER_SERVICE);
wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "QuranAudio:WakeLock");
}
private void startService() {
Intent i = new Intent(this, BackgroundPlayingService.class);
startService(i);
}}
--------------------- extra --------------------------------------
I also had to create other service to remove notification when the
user kill app by clearing app from recent apps.
here is it
MyAppService extends Service {
#Override
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
Intent i = new Intent(MyAppService.this,BackgroundPlayingService.class);
try {
BackgroundPlayingService.playerNotificationManager.setPlayer(null);
stopService(i);
}catch (Exception ignore){}
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}}
-------------------- WARNING ----------------------------------
I don't take this as a best approach, but it gave me a quick solution while waiting for a better approach.
I will pot the app link here when it's available in playstore.
I have an application for recording a screen, it does not work on android version 10. As I understand it, this is due to privacy changes in force in Android 10. Now for any application using MediaProjection api, must specify an attribute android:foregroundServiceType= in the service tag under the manifest, but my application uses MediaProjection in the fragment, not the service. Is it possible to make MediaProjection work from a fragment, or do I need to redo it?
Sorry for my bad english
Here is a mistake
Caused by java.lang.SecurityException
Media projections require a foreground service of type ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION
com.example.screen_recording.screens.main_record.MainFragment.onActivityResult (MainFragment.java:321)
Here is the snippet code
public class MainFragment extends Fragment {
SharedPreferences p;
TimerViewModel model;
private static final int REQUEST_CODE = 1000;
private static final int REQUEST_PERMISSION = 1001;
private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
private boolean isRecord = false;
private boolean isPause = false;
private boolean isNightTheme = false;
private String videoUri = "";
private MediaProjectionManager mediaProjectionManager;
private MediaProjection mediaProjection;
private VirtualDisplay virtualDisplay;
private MediaProjectionCallBack mediaProjectionCallBack;
private MediaRecorder mediaRecorder;
private int mScreenDensity;
private static int DISPLAY_WIDTH;
private static int DISPLAY_HEIGHT;
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);
}
//View
private CardView rootLayout;
private VideoView videoView;
private ToggleButton toggleButton;
private TextView textViewTimer;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_main, container, false);
p = PreferenceManager.getDefaultSharedPreferences(getActivity());
isNightTheme = p.getBoolean("isNightTheme", false);
DisplayMetrics metrics = new DisplayMetrics();
getActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics);
mScreenDensity = metrics.densityDpi;
DISPLAY_WIDTH = metrics.widthPixels;
DISPLAY_HEIGHT = metrics.heightPixels;
mediaRecorder = new MediaRecorder();
mediaProjectionManager = (MediaProjectionManager) getActivity().getSystemService(Context.MEDIA_PROJECTION_SERVICE);
// View
videoView = view.findViewById(R.id.videoView);
rootLayout = view.findViewById(R.id.cardView);
toggleButton = view.findViewById(R.id.toggleButton);
textViewTimer = view.findViewById(R.id.textViewTimer);
// ViewModal
model = new ViewModelProvider(getActivity()).get(TimerViewModel.class);
textViewTimer.setText(model.timeState);
if (isNightTheme) {
rootLayout.setBackgroundResource(R.color.colorBlack);
textViewTimer.setTextColor(Color.WHITE);
}
// Event
//Record Toggle Start and Stop
toggleButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)
+ ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.RECORD_AUDIO)
!= PackageManager.PERMISSION_GRANTED) {
errorRecordAction();
if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)
|| ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), Manifest.permission.RECORD_AUDIO)) {
errorRecordAction();
Snackbar.make(rootLayout, "Разрешения", Snackbar.LENGTH_INDEFINITE)
.setAction("Включить", new View.OnClickListener() {
#Override
public void onClick(View v) {
ActivityCompat.requestPermissions(getActivity(),
new String[]{
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.RECORD_AUDIO
}, REQUEST_PERMISSION);
}
}).show();
} else {
ActivityCompat.requestPermissions(getActivity(),
new String[]{
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.RECORD_AUDIO
}, REQUEST_PERMISSION);
}
} else {
toggleScreenShare(toggleButton);
}
}
});
return view;
}
private void toggleScreenShare(View v) {
if (((ToggleButton) v).isChecked()) {
int quality = p.getInt("quality", 480);
boolean micro = p.getBoolean("micro", false);
int fps = p.getInt("FPS", 15);
initRecorder(quality, micro, fps);
recorderScreen();
isRecord = true;
p.edit().putBoolean("isRecord", isRecord).apply();
} else {
mediaRecorder.stop();
mediaRecorder.reset();
stopRecordScreen();
videoView.setVisibility(View.VISIBLE);
videoView.setVideoURI(Uri.parse(videoUri));
videoView.start();
isRecord = false;
p.edit().putBoolean("isRecord", isRecord).apply();
getActivity().stopService(new Intent(getContext(), TimerService.class));
}
}
private BroadcastReceiver uiUpdated = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
textViewTimer.setText(intent.getStringExtra("countdown"));
model.timeState = intent.getStringExtra("countdown");
}
};
private void recorderScreen() {
if (mediaProjection == null) {
startActivityForResult(mediaProjectionManager.createScreenCaptureIntent(), REQUEST_CODE);
return;
}
virtualDisplay = createVirtualDisplay();
mediaRecorder.start();
}
private VirtualDisplay createVirtualDisplay() {
return mediaProjection.createVirtualDisplay("MainFragment", DISPLAY_WIDTH, DISPLAY_HEIGHT, mScreenDensity,
DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
mediaRecorder.getSurface(), null, null);
}
private void initRecorder(int QUALITY, boolean isMicro, int fps) {
try {
if (isMicro) {
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
}
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
if (isMicro) {
mediaRecorder.setAudioSamplingRate(44100);
mediaRecorder.setAudioEncodingBitRate(16 * 44100);
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
}
videoUri = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)
+ new StringBuilder("/FreeRecord_").append(new SimpleDateFormat("dd-MM-yyyy-hh-mm-ss")
.format(new Date())).append(".mp4").toString();
mediaRecorder.setOutputFile(videoUri);
mediaRecorder.setVideoSize(DISPLAY_WIDTH, DISPLAY_HEIGHT);
mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mediaRecorder.setVideoEncodingBitRate(40000);
mediaRecorder.setCaptureRate(fps);
mediaRecorder.setVideoFrameRate(fps);
int rotation = getActivity().getWindowManager().getDefaultDisplay().getRotation();
int orientation = ORIENTATIONS.get(rotation + 90);
mediaRecorder.setOrientationHint(orientation);
mediaRecorder.prepare();
} catch (IOException e) {
e.printStackTrace();
}
}
#RequiresApi(api = Build.VERSION_CODES.O)
#Override
public void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode != REQUEST_CODE) {
Toast.makeText(getActivity(), "Unk error", Toast.LENGTH_SHORT).show();
errorRecordAction();
return;
}
if (resultCode != Activity.RESULT_OK) {
Log.i("Разрешения", "Я зашел");
Toast.makeText(getActivity(), "Доступ запрещен", Toast.LENGTH_SHORT).show();
errorRecordAction();
return;
}
mediaProjectionCallBack = new MediaProjectionCallBack();
if (data != null) {
mediaProjection = mediaProjectionManager.getMediaProjection(resultCode, data);
mediaProjection.registerCallback(mediaProjectionCallBack, null);
virtualDisplay = createVirtualDisplay();
mediaRecorder.start();
} else {
Toast.makeText(getActivity(), "Не удалось запустить запись", Toast.LENGTH_SHORT).show();
Log.i("dataActivity", "data = null");
}
getActivity().startService(new Intent(getContext(), TimerService.class));
getActivity().registerReceiver(uiUpdated, new IntentFilter("COUNTDOWN_UPDATED"));
}
private class MediaProjectionCallBack extends MediaProjection.Callback {
#Override
public void onStop() {
if (toggleButton.isChecked()) {
errorRecordAction();
mediaRecorder.stop();
mediaRecorder.reset();
}
mediaProjection = null;
stopRecordScreen();
super.onStop();
}
}
private void stopRecordScreen() {
if (virtualDisplay == null) {
return;
}
virtualDisplay.release();
destroyMediaProject();
}
private void destroyMediaProject() {
if (mediaProjection != null) {
mediaProjection.unregisterCallback(mediaProjectionCallBack);
mediaProjection.stop();
mediaProjection = null;
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case REQUEST_PERMISSION: {
if ((grantResults.length > 0) && (grantResults[0] + grantResults[1] == PackageManager.PERMISSION_GRANTED)) {
toggleScreenShare(toggleButton);
} else {
errorRecordAction();
Snackbar.make(rootLayout, "Права доступа", Snackbar.LENGTH_INDEFINITE)
.setAction("Включить", new View.OnClickListener() {
#Override
public void onClick(View v) {
ActivityCompat.requestPermissions(getActivity(),
new String[]{
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.RECORD_AUDIO
}, REQUEST_PERMISSION);
}
}).show();
}
return;
}
}
}
private void errorRecordAction() {
getActivity().stopService(new Intent(getContext(), TimerService.class));
isRecord = false;
toggleButton.setChecked(false);
mediaRecorder.reset();
}
}
You should use a foreground service inside the fragment to capture the screen.
Find below links for how to use the foreground service to capture the screen.
How to take a Screenshot from a background-service class using MediaProjection API?
am writing a body measurement app. I have been able to create the camera and it stores the image. I want to use the captured image in another activity where i called the method 'bodyMeasurement'
I really need help in achieving this. Further corrections are also welcomed. Thanks
Here is my Camera Activity;
CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
#Override
public void onOpened(#NonNull CameraDevice camera) {
cameraDevice = camera;
createCameraPreview();
}
#Override
public void onDisconnected(#NonNull CameraDevice cameraDevice) {
cameraDevice.close();
}
#Override
public void onError(#NonNull CameraDevice cameraDevice, int i) {
cameraDevice.close();
cameraDevice=null;
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textureView = (TextureView)findViewById(R.id.textureView);
//From Java 1.4 , you can use keyword 'assert' to check expression true or false
assert textureView != null;
textureView.setSurfaceTextureListener(textureListener);
btnCapture = (ImageButton)findViewById(R.id.btnCapture);
/* Dexter.withActivity(this)
.withPermissions(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.CAMERA)
.withListener(new MultiplePermissionsListener() {
#Override
public void onPermissionsChecked(MultiplePermissionsReport report) {
if (!report.areAllPermissionsGranted()) {
Toast.makeText(MainActivity.this, "You need to grant all permission to use this app features", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onPermissionRationaleShouldBeShown(List<PermissionRequest> permissions, PermissionToken token) {
}
})
.check();*/
btnCapture.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
takePicture();
}
});
}
private void takePicture() {
if(cameraDevice == null)
return;
CameraManager manager = (CameraManager)getSystemService(Context.CAMERA_SERVICE);
try{
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraDevice.getId());
Size[] jpegSizes = null;
if(characteristics != null)
jpegSizes = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)
.getOutputSizes(ImageFormat.JPEG);
//Capture image with custom size
int width = 4608;
int height = 3456;
if(jpegSizes != null && jpegSizes.length > 0)
{
width = jpegSizes[0].getWidth();
height = jpegSizes[0].getHeight();
}
final ImageReader reader = ImageReader.newInstance(width,height,ImageFormat.JPEG,1);
List<Surface> outputSurface = new ArrayList<>(2);
outputSurface.add(reader.getSurface());
outputSurface.add(new Surface(textureView.getSurfaceTexture()));
final CaptureRequest.Builder captureBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
captureBuilder.addTarget(reader.getSurface());
captureBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
//Check orientation base on device
int rotation = getWindowManager().getDefaultDisplay().getRotation();
captureBuilder.set(CaptureRequest.JPEG_ORIENTATION,ORIENTATIONS.get(rotation));
file = new File(Environment.getExternalStorageDirectory()+"/"+ ".CnatraSamp"+".jpg");
ImageReader.OnImageAvailableListener readerListener = new ImageReader.OnImageAvailableListener() {
#Override
public void onImageAvailable(ImageReader imageReader) {
Image image = null;
try{
image = reader.acquireLatestImage();
ByteBuffer buffer = image.getPlanes()[0].getBuffer();
byte[] bytes = new byte[buffer.capacity()];
buffer.get(bytes);
save(bytes);
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
finally {
{
if(image != null)
image.close();
}
}
}
private void save(byte[] bytes) throws IOException {
OutputStream outputStream = null;
try{
outputStream = new FileOutputStream(file);
outputStream.write(bytes);
}finally {
if(outputStream != null)
outputStream.close();
}
}
};
reader.setOnImageAvailableListener(readerListener,mBackgroundHandler);
final CameraCaptureSession.CaptureCallback captureListener = new CameraCaptureSession.CaptureCallback() {
#Override
public void onCaptureCompleted(#NonNull CameraCaptureSession session, #NonNull CaptureRequest request, #NonNull TotalCaptureResult result) {
super.onCaptureCompleted(session, request, result);
Toast.makeText(MainActivity.this, "Saved "+file, Toast.LENGTH_SHORT).show();
finish();
Intent i = new Intent(MainActivity.this,BlankActivity.class);
startActivity(i);
finish();
}
};
cameraDevice.createCaptureSession(outputSurface, new CameraCaptureSession.StateCallback() {
#Override
public void onConfigured(#NonNull CameraCaptureSession cameraCaptureSession) {
try{
cameraCaptureSession.capture(captureBuilder.build(),captureListener,mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
#Override
public void onConfigureFailed(#NonNull CameraCaptureSession cameraCaptureSession) {
}
},mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void createCameraPreview() {
try{
SurfaceTexture texture = textureView.getSurfaceTexture();
assert texture != null;
texture.setDefaultBufferSize(imageDimension.getWidth(),imageDimension.getHeight());
Surface surface = new Surface(texture);
captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
captureRequestBuilder.addTarget(surface);
cameraDevice.createCaptureSession(Arrays.asList(surface), new CameraCaptureSession.StateCallback() {
#Override
public void onConfigured(#NonNull CameraCaptureSession cameraCaptureSession) {
if(cameraDevice == null)
return;
cameraCaptureSessions = cameraCaptureSession;
updatePreview();
}
#Override
public void onConfigureFailed(#NonNull CameraCaptureSession cameraCaptureSession) {
Toast.makeText(MainActivity.this, "Changed", Toast.LENGTH_SHORT).show();
}
},null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void updatePreview() {
if(cameraDevice == null)
Toast.makeText(this, "Error", Toast.LENGTH_SHORT).show();
captureRequestBuilder.set(CaptureRequest.CONTROL_MODE,CaptureRequest.CONTROL_MODE_AUTO);
try{
cameraCaptureSessions.setRepeatingRequest(captureRequestBuilder.build(),null,mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void openCamera() {
CameraManager manager = (CameraManager)getSystemService(Context.CAMERA_SERVICE);
try{
cameraId = manager.getCameraIdList()[1];
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
assert map != null;
imageDimension = map.getOutputSizes(SurfaceTexture.class)[1];
//Check realtime permission if run higher API 23
if(ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED)
{
ActivityCompat.requestPermissions(this,new String[]{
Manifest.permission.CAMERA,
Manifest.permission.WRITE_EXTERNAL_STORAGE
},REQUEST_CAMERA_PERMISSION);
return;
}
manager.openCamera(cameraId,stateCallback,null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
TextureView.SurfaceTextureListener textureListener = new TextureView.SurfaceTextureListener() {
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i1) {
openCamera();
}
#Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i1) {
}
#Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
return false;
}
#Override
public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
}
};
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if(requestCode == REQUEST_CAMERA_PERMISSION)
{
if(grantResults[0] != PackageManager.PERMISSION_GRANTED)
{
Toast.makeText(this, "You can't use camera without permission", Toast.LENGTH_SHORT).show();
finish();
}
}
}
#Override
protected void onResume() {
super.onResume();
startBackgroundThread();
if(textureView.isAvailable())
openCamera();
else
textureView.setSurfaceTextureListener(textureListener);
}
#Override
protected void onPause() {
stopBackgroundThread();
super.onPause();
}
private void stopBackgroundThread() {
mBackgroundThread.quitSafely();
try{
mBackgroundThread.join();
mBackgroundThread= null;
mBackgroundHandler = null;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void startBackgroundThread() {
mBackgroundThread = new HandlerThread("Camera Background");
mBackgroundThread.start();
mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
}
the activity i need the image;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_blank);
height = findViewById(R.id.height);
cancel = findViewById(R.id.cancel);
btnctn = findViewById(R.id.continuebtn);
cmIn = findViewById(R.id.cmIn);
height.setInputType(InputType.TYPE_CLASS_NUMBER |
InputType.TYPE_NUMBER_FLAG_DECIMAL |
InputType.TYPE_NUMBER_FLAG_SIGNED);
btnctn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (height.getText().toString().trim().isEmpty()){
Toast.makeText(BlankActivity.this,"Please input your height..",Toast.LENGTH_LONG).show();
}else {
final ProgressDialog progressDialog = new ProgressDialog(BlankActivity.this);
progressDialog.setMessage("Getting Your Measurement");
progressDialog.setTitle("Please wait!");
progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progressDialog.show(); // Display Progress Dialog
progressDialog.setCancelable(false);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
Intent i = new Intent(BlankActivity.this, SettingsActivity.class);
startActivity(i);
progressDialog.dismiss();
}
},5000);
}
//place measurement object
bodyMeasurement();
}
});
cancel.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
BlankActivity.this.finish();
Intent i = new Intent(BlankActivity.this, HomeActivity.class);
startActivity(i);
finish();
}
});
cmIn.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(isChecked){
num = Double.parseDouble(String.valueOf(height.getText()));
in = 0.3937 * num;
String r = String.valueOf(in);
height.setText(r);
}else {
num = Double.parseDouble(String.valueOf(height.getText()));
cm = num / 0.3937;
String r = String.valueOf(cm);
height.setText(r);
}
}
});
}
private void bodyMeasurement() {
}
}
As mentioned in the comment, you can get the absolute path from the saved image and pass it through an intent to the Activity that it needs it.
To achieve this, you might want to convert your image file to a BitMap first, which will give you the actual path of the image (sometimes .getAbsolutePath() method returns a wrong file path, so it is a better solution to convert your image to a bitmap first).
This can be achieved:
String filePath = file.getPath();
Bitmap imgBitmap = BitmapFactory.decodeFile(filePath);
Then to obtain the real path of the image you saved you need to
1) Obtain the Uri of the created Bitmap:
public Uri getUri(Context context, Bitmap imgBitmap) {
ByteArrayOutputStream bOutputStream = new ByteArrayOutputStream();
String path = MediaStore.Images.Media.insertImage(context.getContentResolver(),
imgBitmap, "Title", null);
return Uri.parse(path);
}
2) Fetch the real path from Uri:
public String getRealPath(Uri uri) {
String [] proj={MediaStore.Images.Media.DATA};
Cursor cursor = getContentResolver().query(uri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
String path = cursor.getString(column_index);
cursor.close();
return path;
}
In your first activity you can pass the path of your image through an intent to the other activity, then fetch it and display it/etc.
Intent intent = new Intent(context,OtherActivity.class);
intent.putExtra("PATH",path);
startActivity(intent);
Receive the data you passed:
Intent intent = getIntent();
String path = intent.getStringExtra("PATH");
//convert the path to image/bitmap and display the image
You can also pass the entire Bitmap to the Activity you need it, but I strongly recommend that you don't, because it will use a lot of memory.
I'm aware that this question has been asked before but all of the answers I have looked at have failed to give me the answer (most probably because some of them I can't understand but also because there are a lot of different solutions it seems and I can't see the wood for the trees).
I'm hoping that by providing my code that someone will be able to point me in the right direction.
Here is my class used to take the picture:
public class CameraPhotoActivity extends AppCompatActivity {
private Button btnCapture;
private TextureView textureView;
// to check the state orientation of the output image
private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
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);
}
private String cameraId;
private CameraDevice cameraDevice;
private CameraCaptureSession cameraCaptureSessions;
private CaptureRequest.Builder captureRequestBuilder;
private Size imageDimension;
private ImageReader imageReader;
// save to file
private File file;
private static final int REQUEST_CAMERA_PERMISSION = 200;
private boolean mFlashSupported;
private Handler mBackgroundHandler;
private HandlerThread mBackgroundThread;
CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
#Override
public void onOpened(#NonNull CameraDevice camera) {
cameraDevice = camera;
createCameraPreview();
}
#Override
public void onDisconnected(#NonNull CameraDevice cameraDevice) {
cameraDevice.close();
}
#Override
public void onError(#NonNull CameraDevice cameraDevice, int i) {
cameraDevice.close();
cameraDevice = null;
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera_photo);
textureView = (TextureView) findViewById(R.id.textureView);
assert textureView != null;
textureView.setSurfaceTextureListener(textureListener);
btnCapture = (Button) findViewById(R.id.btnCapture);
btnCapture.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
takePicture();
}
});
}
private void takePicture() {
if (cameraDevice == null)
return;
CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
try {
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraDevice.getId());
Size[] jpegSizes = null;
if (characteristics != null)
jpegSizes = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)
.getOutputSizes(ImageFormat.JPEG);
// capture the image with custom size
int width = 640;
int height = 480;
if (jpegSizes != null && jpegSizes.length > 0) {
width = jpegSizes[0].getWidth();
height = jpegSizes[0].getHeight();
}
final ImageReader reader = ImageReader.newInstance(width, height, ImageFormat.JPEG, 1);
List<Surface> outputSurface = new ArrayList<>(2);
outputSurface.add(reader.getSurface());
outputSurface.add(new Surface(textureView.getSurfaceTexture()));
final CaptureRequest.Builder captureBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
captureBuilder.addTarget(reader.getSurface());
captureBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
// check the orientation on the device
int rotation = getWindowManager().getDefaultDisplay().getRotation();
captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation));
file = new File(Environment.getExternalStorageDirectory() + "/" + UUID.randomUUID().toString()
+ ".jpg");
ImageReader.OnImageAvailableListener readerListener = new ImageReader.OnImageAvailableListener() {
#Override
public void onImageAvailable(ImageReader imageReader) {
Image image = null;
try {
image = reader.acquireLatestImage();
ByteBuffer buffer = image.getPlanes()[0].getBuffer();
byte[] bytes = new byte[buffer.capacity()];
buffer.get(bytes);
save(bytes);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
{
if (image != null)
image.close();
}
}
}
private void save(byte[] bytes) throws IOException {
OutputStream outputStream = null;
try {
outputStream = new FileOutputStream(file);
outputStream.write(bytes);
} finally {
if (outputStream != null)
outputStream.close();
}
}
};
reader.setOnImageAvailableListener(readerListener, mBackgroundHandler);
final CameraCaptureSession.CaptureCallback captureListener = new CameraCaptureSession.CaptureCallback() {
#Override
public void onCaptureCompleted(#NonNull CameraCaptureSession session, #NonNull CaptureRequest request, #NonNull TotalCaptureResult result) {
super.onCaptureCompleted(session, request, result);
Toast.makeText(CameraPhotoActivity.this, "Saved " + file, Toast.LENGTH_SHORT).show();
createCameraPreview();
}
};
cameraDevice.createCaptureSession(outputSurface, new CameraCaptureSession.StateCallback() {
#Override
public void onConfigured(#NonNull CameraCaptureSession cameraCaptureSession) {
try {
cameraCaptureSession.capture(captureBuilder.build(), captureListener, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
#Override
public void onConfigureFailed(#NonNull CameraCaptureSession cameraCaptureSession) {
}
}, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void createCameraPreview() {
try {
SurfaceTexture texture = textureView.getSurfaceTexture();
assert texture != null;
texture.setDefaultBufferSize(imageDimension.getWidth(), imageDimension.getHeight());
Surface surface = new Surface(texture);
captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
captureRequestBuilder.addTarget(surface);
cameraDevice.createCaptureSession(Arrays.asList(surface), new CameraCaptureSession.StateCallback() {
#Override
public void onConfigured(#NonNull CameraCaptureSession cameraCaptureSession) {
if (cameraDevice == null)
return;
cameraCaptureSessions = cameraCaptureSession;
updatePreview();
}
#Override
public void onConfigureFailed(#NonNull CameraCaptureSession cameraCaptureSession) {
Toast.makeText(CameraPhotoActivity.this, "Changed", Toast.LENGTH_SHORT).show();
}
}, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void updatePreview() {
if (cameraDevice == null)
Toast.makeText(this, "Error", Toast.LENGTH_SHORT).show();
captureRequestBuilder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO);
try {
cameraCaptureSessions.setRepeatingRequest(captureRequestBuilder.build(), null, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void openCamera() {
CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
try {
cameraId = manager.getCameraIdList()[0];
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
assert map != null;
imageDimension = map.getOutputSizes(SurfaceTexture.class)[0];
// check realtime permission if run higher than API 23
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{
Manifest.permission.CAMERA,
Manifest.permission.WRITE_EXTERNAL_STORAGE
}, REQUEST_CAMERA_PERMISSION);
return;
}
manager.openCamera(cameraId, stateCallback, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
TextureView.SurfaceTextureListener textureListener = new TextureView.SurfaceTextureListener() {
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i1) {
openCamera();
}
#Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i1) {
}
#Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
return false;
}
#Override
public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
}
};
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if (requestCode == REQUEST_CAMERA_PERMISSION) {
if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "You can't use the camera without permission", Toast.LENGTH_SHORT).show();
finish();
}
}
}
#Override
protected void onResume() {
super.onResume();
startBackgroundThread();
if (textureView.isAvailable())
openCamera();
else
textureView.setSurfaceTextureListener(textureListener);
}
#Override
protected void onPause() {
stopBackgroundThread();
super.onPause();
}
private void stopBackgroundThread() {
mBackgroundThread.quitSafely();
try {
mBackgroundThread.join();
mBackgroundThread = null;
mBackgroundHandler = null;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void startBackgroundThread() {
mBackgroundThread = new HandlerThread("Camera Background");
mBackgroundThread.start();
mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
}
}
I have tried adding the following but, if it's correct, I can't seem to put it in the correct place:
MediaScannerConnection.scanFile(this, new String[]{file.toString()}, null,
new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
Log.i("External Storage", "Scanned" + path + ":");
Log.i("External Storage", "-> uri=" + uri);
}
});
Thanks for any help. Much appreciated.
This means "context". You need to place the code within the activity class, once the image has been fetched from the camera. Also call connect before calling scanFile. You can try below code.
MediaScannerConnection.scanFile(CameraPhotoActivity.this, new String[]{file.toString()}, null,
new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
Log.i("External Storage", "Scanned" + path + ":");
Log.i("External Storage", "-> uri=" + uri);
}
});