I am executing split video Ffmpeg command on Android and it creates output_%d files to SD card (external storage)
Once command is executed and finished, files are not appearing immediately until I open Gallery App
I tried running media scanner for newly created directory but I see that directory is empty and has no files available immediately.
What do you mean by "not appearing immediately ?
1/ With a file explorer ?
This issue is due to the use of the MTP protocol. You have to do a rescan of the files using the MediaScannerConnection class.
Using a media scan app from google play help if you don't want to reboot or develop something.
2/ from java ?
You could try to list all files of the folder and then do a media scanner on each files (instead of doing it on the directory).
Context ctx = <your_context>;
File directory = new File("<your_path>");
File[] files = directory.listFiles();
for (int i = 0; i < files.length; i++)
{
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
intent.setData(Uri.fromFile(files[i]));
context.sendBroadcast(intent);
}
If you need the result immediately when the scan is finished, you'll need MediaScannerConnectionClient
private static final class Client implements MediaScannerConnectionClient
{ private final String path;
private final String mimeType;
public MediaScannerConnection connection;
public Client(String path, String mimeType)
{ this.path = path;
this.mimeType = mimeType;
}
#Override
public void onMediaScannerConnected()
{ connection.scanFile(path, mimeType);
}
#Override
public void onScanCompleted(String path, Uri uri)
{ connection.disconnect();
}
};
public static void scanFile(Context context, String path, String mimeType)
{ Client client = new Client(path, mimeType);
MediaScannerConnection connection = new MediaScannerConnection(context, client);
client.connection = connection;
connection.connect();
}
Ideally, this should be done in the ffmpeg splitter app.
Try this...
I am using this
You are using the Full sample Code Sample Here record Video , Spilt image and take output l
You try the command of FFmpeg as you want if you need any help let me know
public class FrontCameraPreviewActivity extends AppCompatActivity implements CameraController.CameraRecordListener, FFMpegVideoGenerator.VideoGeneratorListener {
public final static String TAG = "FrontCameraPreviewAct";
private final static int CAMERA_PERMISSION_REQUEST_CODE = 50;
private FrontCameraSurfaceView mPreview;
private FrameLayout mPreviewFrame;
private FloatingActionButton fab;
private Animation hideCameraFab;
private CameraController mCameraController;
private ProgressBar mPbProcessing;
SweetAlertDialog progressDialog;
int mCount;
View mView;
ImageView btn_record_image;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_front_camera_preview);
mView=(View)findViewById(R.id.mView);
btn_record_image=(ImageView) findViewById(R.id.btn_record_image);
mView.setVisibility(View.GONE);
fab = (FloatingActionButton) findViewById(R.id.btn_record);
btn_record_image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
btn_record_image.setVisibility(View.GONE);
mCameraController.record();
mCount=0;
mView.setBackgroundColor(ContextCompat.getColor(FrontCameraPreviewActivity.this,R.color.white));
mView.setVisibility(View.VISIBLE);
new CountDownTimer(Constants.VIDEO_DURATION, 100) {
public void onTick(long millisUntilFinished) {
mCount++;
if(mCount%2 == 0)
{
mView.setVisibility(View.VISIBLE);
}
else
{
mView.setVisibility(View.GONE);
}
// mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
//here you can have your logic to set text to edittext
}
public void onFinish() {
mView.setVisibility(View.GONE);
}
}.start();
}
});
progressDialog = new SweetAlertDialog(FrontCameraPreviewActivity.this, SweetAlertDialog.PROGRESS_TYPE);
mPbProcessing = (ProgressBar) findViewById(R.id.pb_processing);
mPreviewFrame = (FrameLayout) findViewById(R.id.fl_camera_preview);
View decorView = getWindow().getDecorView();
// Hide the status bar.
decorView.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_FULLSCREEN |
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
);
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case CAMERA_PERMISSION_REQUEST_CODE: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
this.initCamera();
} else {
// TODO : display an error view
}
}
}
}
#Override
protected void onResume() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED&&
ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA,Manifest.permission.WRITE_EXTERNAL_STORAGE}, CAMERA_PERMISSION_REQUEST_CODE);
} else {
initCamera();
}
super.onResume();
}
#Override
protected void onPause() {
super.onPause();
if (mCameraController != null) {
mCameraController.release();
mCameraController = null;
}
}
private void initCamera() {
if (mCameraController == null) {
mCameraController = new CameraController(this);
mCameraController.setCameraRecordListener(this);
if (mCameraController.getCamera() == null) {
Toast.makeText(this, R.string.camera_not_available, Toast.LENGTH_SHORT).show();
// TODO : display an error view
} else if (mPreview == null) {
mPreview = new FrontCameraSurfaceView(this, mCameraController.getCamera(), CameraController.getFrontCameraInfo());
mPreviewFrame.addView(mPreview);
} else {
// handle the onResume after background properly
mPreview.setCamera(mCameraController.getCamera());
}
} else {
mCameraController.getCamera();
}
}
#Override
public void onCameraRecordSuccess(final File file) {
this.runOnUiThread(new Runnable() {
#Override
public void run() {
fab.setVisibility(View.GONE);
btn_record_image.setVisibility(View.GONE);
mCameraController.release();
mPreviewFrame.removeAllViews();
mCameraController = null;
mPbProcessing.setVisibility(View.GONE);
progressDialog.getProgressHelper().setBarColor(ContextCompat.getColor(FrontCameraPreviewActivity.this, R.color.darkbutton));
progressDialog.setTitleText("Processing...");
progressDialog.setCancelable(false);
progressDialog.show();
}
});
new Thread(new Runnable() {
#Override
public void run() {
Log.d(TAG, "start");
FFMpegVideoGenerator generator = new FFMpegVideoGenerator(FrontCameraPreviewActivity.this.getApplication());
generator.setVideoGeneratorListener(FrontCameraPreviewActivity.this);
generator.convert(file);
}
}).start();
}
#Override
public void onCameraRecordFailure() {
this.runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(FrontCameraPreviewActivity.this, R.string.camera_not_available, Toast.LENGTH_SHORT).show();
}
});
}
#Override
public void onVideoGenerated(String message, File generatedFile) {
progressDialog.dismiss();
Intent intent = new Intent(FrontCameraPreviewActivity.this, VideoPreviewActivity.class);
intent.putExtra(VideoPreviewActivity.VIDEO_PATH, generatedFile.getAbsolutePath());
startActivity(intent);
recreate();
}
#Override
public void onVideoGeneratedError(String message) {
Log.e(TAG, message);
}
}
Split Images of Video and Other Functionality
FFMpegVideoGenerator.java
import android.content.Context;
import android.util.Log;
import com.github.hiteshsondhi88.libffmpeg.ExecuteBinaryResponseHandler;
import com.github.hiteshsondhi88.libffmpeg.FFmpeg;
import com.github.hiteshsondhi88.libffmpeg.LoadBinaryResponseHandler;
import com.github.hiteshsondhi88.libffmpeg.exceptions.FFmpegCommandAlreadyRunningException;
import com.github.hiteshsondhi88.libffmpeg.exceptions.FFmpegNotSupportedException;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.lang.ref.WeakReference;
import java.util.Arrays;
import java.util.Locale;
import wc.arjs.boomerang.controllers.VideoGenerator;
import wc.arjs.boomerang.utils.FileUtils;
import wc.arjs.boomerang.Constants;
public class FFMpegVideoGenerator extends Thread implements VideoGenerator {
private static final String TAG = "VideoGenerator";
private static final String TEMP_IMG_DIR = "imgs";
private static final String METADATA_PREFIX = "met_";
private static final String CROP_PREFIX = "crop_";
private WeakReference<VideoGeneratorListener> mWeakListener;
private String mWorkingDir;
private String mFinalOutputDir;
private FFmpeg mFFmpeg;
public FFMpegVideoGenerator(Context ctx) {
mFFmpeg = FFmpeg.getInstance(ctx);
mWorkingDir = ctx.getCacheDir() + File.separator + TMP_DIR;
mFinalOutputDir = ctx.getCacheDir() + File.separator + OUTPUT_DIR;
}
#Override
public void setVideoGeneratorListener(VideoGeneratorListener listener) {
mWeakListener = new WeakReference<>(listener);
}
#Override
public void convert(final File inputFile) {
FileUtils.createDirIfNeeded(mWorkingDir);
FileUtils.createDirIfNeeded(mFinalOutputDir);
try {
mFFmpeg.loadBinary(new LoadBinaryResponseHandler() {
#Override
public void onSuccess() {
fixMetaData(inputFile);
}
});
} catch (FFmpegNotSupportedException e) {
Log.e(TAG, "not supported");
}
}
private void fixMetaData(final File inputFile) {
Log.d(TAG, "fixeMetaData");
String c = "-y -i " + inputFile.getAbsolutePath() + " -metadata:s:v rotate=90 -codec copy "
+ mWorkingDir + File.separator + METADATA_PREFIX + inputFile.getName();
String[] cmd = c.split(" ");
try {
mFFmpeg.execute(cmd, new ExecuteBinaryResponseHandler() {
#Override
public void onFailure(String message) {
Log.e(TAG, message);
dispatchError(message);
}
#Override
public void onSuccess(String message) {
Log.d(TAG, message);
File generated = new File(mWorkingDir +
File.separator + METADATA_PREFIX + inputFile.getName());
cropVideo(generated);
}
});
} catch (FFmpegCommandAlreadyRunningException e) {
dispatchError(e.getMessage());
}
}
private void cropVideo(final File inputFile) {
String c = "-y -i " + inputFile.getAbsolutePath() + " -vf crop=" +
Constants.VIDEO_ASPECT_RATIO + "*in_h:in_h -preset ultrafast " +
mWorkingDir + File.separator + CROP_PREFIX + inputFile.getName();
String[] cmd = c.split(" ");
try {
mFFmpeg.execute(cmd, new ExecuteBinaryResponseHandler() {
#Override
public void onFailure(String message) {
Log.e(TAG, message);
dispatchError(message);
}
#Override
public void onSuccess(String message) {
Log.d(TAG, message);
File generated = new File(mWorkingDir +
File.separator + CROP_PREFIX + inputFile.getName());
splitIntoImages(generated);
}
});
} catch (FFmpegCommandAlreadyRunningException e) {
dispatchError(e.getMessage());
}
}
private void splitIntoImages(final File inputFile) {
Log.d(TAG, "splitIntoImages");
final File tempImgsDir = new File(mWorkingDir + File.separator + TEMP_IMG_DIR);
if (tempImgsDir.exists()) {
FileUtils.deleteDirectory(tempImgsDir);
}
tempImgsDir.mkdir();
String c = "-y -i " + inputFile.getAbsolutePath() +
" -strict experimental -r 30 -qscale 1 -f image2 -vcodec mjpeg " +
tempImgsDir.getAbsolutePath() + File.separator + "%03d.jpg";
String[] cmd = c.split(" ");
try {
mFFmpeg.execute(cmd, new ExecuteBinaryResponseHandler() {
#Override
public void onFailure(String message) {
Log.e(TAG, message);
dispatchError(message);
}
#Override
public void onSuccess(String message) {
Log.d(TAG, message);
reverseImagesOrder(tempImgsDir);
assembleVideo(tempImgsDir);
}
});
} catch (FFmpegCommandAlreadyRunningException e) {
dispatchError(e.getMessage());
}
}
private void reverseImagesOrder(final File inputDirectory) {
File[] files = inputDirectory.listFiles();
Arrays.sort(files);
int nbImages = files.length;
if (nbImages <= 2) {
dispatchError("Not enough images generated");
}
// start from before the last image and duplicate all the images in reverse order
for (int i = nbImages - 2; i > 0; i--) {
File img = files[i];
if (img.exists()) {
String copiedImg = inputDirectory.getAbsolutePath() + File.separator +
String.format(Locale.ENGLISH, "%03d", 2 * nbImages - i - 1) + ".jpg";
Log.d(TAG, copiedImg);
FileUtils.copyAndRenameInDirectory(img.getAbsolutePath(), copiedImg);
} else {
Log.e(TAG, "file not found : " + img.getAbsolutePath());
}
}
}
private void assembleVideo(final File inputDirectory) {
Log.d(TAG, "assembleVideo");
File containingFolder = new File(mFinalOutputDir);
final File assembledVideo = new File(containingFolder.getAbsolutePath() + File.separator + FINAL_VIDEO_NAME);
String[] cmdCreateMP4 = {
"-framerate",
"6",
"-i",
inputDirectory.getAbsolutePath() + File.separator +
"%03d.jpg",
"-c:v",
"libx264",
"-profile:v",
"high",
"-crf",
"20",
"-pix_fmt",
"yuv420p",
assembledVideo.getAbsolutePath()};
String c = "-framerate 70 -y -f image2 -loop 1 -i " + inputDirectory.getAbsolutePath() + File.separator +
"%03d.jpg -r 30 -vcodec mpeg4 -b:v 2100k -t 4 " +
assembledVideo.getAbsolutePath();
String[] cmd = c.split(" ");
try {
mFFmpeg.execute(cmd, new ExecuteBinaryResponseHandler() {
#Override
public void onFailure(String message) {
Log.e(TAG, message);
dispatchError(message);
}
#Override
public void onSuccess(String message) {
Log.d(TAG, message);
dispatchSuccess(message, assembledVideo);
/*String root = Environment.getExternalStorageDirectory().toString();
File myDir = new File(root + "/boomerang/unsafe");
myDir.mkdirs();
String fname = "VID_"+ System.currentTimeMillis() +".mp4";
File file = new File (myDir, fname);
if (file.exists ())
file.delete ();
try {
InputStream in = new FileInputStream(assembledVideo.getAbsolutePath());
OutputStream out = new FileOutputStream(file);
// Copy the bits from instream to outstream
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
in.close();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
File myDir1 = new File(root + "/boomerang/");
String fname1 = "VID_"+ System.currentTimeMillis() +".mp4";
File file1= new File (myDir1, fname1);
*/
// concatenate(file.getAbsolutePath(),file.getAbsolutePath(),file1.getAbsolutePath());
}
});
} catch (FFmpegCommandAlreadyRunningException e) {
dispatchError(e.getMessage());
}
}
private static String generateList(String[] inputs) {
File list;
Writer writer = null;
try {
list = File.createTempFile("ffmpeg-list", ".txt");
writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(list)));
for (String input: inputs) {
writer.write("file '" + input + "'\n");
Log.d(TAG, "Writing to list file: file '" + input + "'");
}
} catch (IOException e) {
e.printStackTrace();
return "/";
} finally {
try {
if (writer != null)
writer.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
Log.d(TAG, "Wrote list file to " + list.getAbsolutePath());
return list.getAbsolutePath();
}
public void concatenate(String inputFile1, String inputFile2, final String outputFile) {
Log.d(TAG, "Concatenating " + inputFile1 + " and " + inputFile2 + " to " + outputFile);
String list = generateList(new String[] {inputFile1, inputFile2});
/* String c = "ffmpeg -i "+inputFile1+" -qscale:v 1 intermediate1.mpg ffmpeg -i "+inputFile2+" -qscale:v 1 intermediate2.mpg cat intermediate1.mpg intermediate2.mpg > intermediate_all.mpg ffmpeg -i intermediate_all.mpg -qscale:v 2 "+
outputFile;
*/
/* new String[] {
"ffmpeg",
"-f",
"concat",
"-i",
list,
"-c",
"copy",
outputFile
}*/
String c = "ffmpeg -i "+inputFile1+" -filter_complex [0]reverse[r];[0][r]concat,loop=5:250,setpts=N/25/TB " +
outputFile;
String[] cmd = c.split(" ");
try {
mFFmpeg.execute(cmd, new ExecuteBinaryResponseHandler() {
#Override
public void onFailure(String message) {
Log.e(TAG, message);
//dispatchError(message);
}
#Override
public void onSuccess(String message) {
Log.d("#Success", "Ho gaya");
dispatchSuccess(message, new File(outputFile));
}
});
} catch (FFmpegCommandAlreadyRunningException e) {
//dispatchError(e.getMessage());
}
/*
Videokit vk = new Videokit();
vk.run(new String[] {
"ffmpeg",
"-f",
"concat",
"-i",
list,
"-c",
"copy",
outputFile
});
*/
}
private void dispatchSuccess(String message, File file) {
if (mWeakListener != null && mWeakListener.get() != null) {
mWeakListener.get().onVideoGenerated(message, file);
}
}
private void dispatchError(String message) {
if (mWeakListener != null && mWeakListener.get() != null) {
mWeakListener.get().onVideoGeneratedError(message);
}
}
}
You can take the split image on this path which is cache temporary (android/data/....) save you change the path also as you want, makedirs and save the images in which you want to save
tempImgsDir.getAbsolutePath() + File.separator + "%03d.jpg"
Cameracontroller
import android.content.Context;
import android.hardware.Camera;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.os.FileObserver;
import android.util.Log;
import java.io.File;
import java.io.IOException;
import wc.arjs.boomerang.Constants;
/**
* Created by Sylvain on 26/11/2016.
*/
public class CameraController {
private final static String TAG = "CameraController";
public interface CameraRecordListener {
void onCameraRecordSuccess(File file);
void onCameraRecordFailure();
}
private CameraRecordListener mCameraRecordListener;
private Camera mCamera;
private MediaRecorder mMediaRecorder;
private boolean isRecording;
private Context mContext;
private static Camera GetFrontCameraInstance() {
Camera c = null;
int cameraId = GetFrontCameraId();
try {
c = Camera.open(cameraId);
} catch (Exception e) {
e.printStackTrace();
}
return c; // returns null if camera is unavailable
}
private static int GetFrontCameraId() {
Camera.CameraInfo info = new Camera.CameraInfo();
int count = Camera.getNumberOfCameras();
for (int i = 0; i < count; i++) {
Camera.getCameraInfo(i, info);
if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
return i;
}
}
return -1;
}
public static Camera.CameraInfo getFrontCameraInfo(){
Camera.CameraInfo info = new Camera.CameraInfo();
int count = Camera.getNumberOfCameras();
for (int i = 0; i < count; i++) {
Camera.getCameraInfo(i, info);
if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
return info;
}
}
return info;
}
public CameraController(Context ctx){
this.mContext = ctx;
mCamera = GetFrontCameraInstance();
Camera.Parameters params = mCamera.getParameters();
params.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO);
/* params.setExposureCompensation(params.getMaxExposureCompensation());
if(params.isAutoExposureLockSupported()) {
params.setAutoExposureLock(false);
}*/
params.setRecordingHint(true);
mCamera.setParameters(params);
isRecording = false;
}
public void setCameraRecordListener(CameraRecordListener cameraRecordListener){
this.mCameraRecordListener = cameraRecordListener;
}
class RecordedFileObserver extends FileObserver {
private File output;
public RecordedFileObserver(File output, int mask) {
super(output.getAbsolutePath(), mask);
this.output = output;
}
public void onEvent(int event, String path) {
if(event == FileObserver.CLOSE_WRITE){
if(mCameraRecordListener!=null){
mCameraRecordListener.onCameraRecordSuccess(output);
}
}
}
}
public void record(){
final File output = getOutputMediaFile();
if (prepareVideoRecorder(output)) {
// Camera is available and unlocked, MediaRecorder is prepared,
// now you can start recording
mMediaRecorder.setOnInfoListener(new MediaRecorder.OnInfoListener() {
#Override
public void onInfo(MediaRecorder mr, int what, int extra) {
if(what==MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED){
if (isRecording) {
RecordedFileObserver fb = new RecordedFileObserver(output, FileObserver.CLOSE_WRITE);
fb.startWatching();
// stop recording and release camera
mMediaRecorder.stop(); // stop the recording
releaseMediaRecorder(); // release the MediaRecorder object
mCamera.lock(); // take camera access back from MediaRecorder
isRecording = false;
}
}else{
if(mCameraRecordListener!=null){
mCameraRecordListener.onCameraRecordFailure();
}
}
}
});
mMediaRecorder.start();
isRecording = true;
} else {
releaseMediaRecorder();
if(mCameraRecordListener!=null){
mCameraRecordListener.onCameraRecordFailure();
}
}
}
public void release(){
this.releaseMediaRecorder();
this.releaseCamera();
}
private boolean prepareVideoRecorder(File output) {
mMediaRecorder = new MediaRecorder();
// store the quality profile required
CamcorderProfile profile = CamcorderProfile.get(CameraController.GetFrontCameraId(), CamcorderProfile.QUALITY_480P);
// Step 1: Unlock and set camera to MediaRecorder
mCamera.unlock();
mMediaRecorder.setCamera(mCamera);
// Step 2: Set sources
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
// Step 3: Set a CamcorderProfile (requires API Level 8 or higher)
mMediaRecorder.setOutputFormat(profile.fileFormat);
mMediaRecorder.setVideoEncoder(profile.videoCodec);
mMediaRecorder.setVideoEncodingBitRate(profile.videoBitRate);
mMediaRecorder.setVideoFrameRate(profile.videoFrameRate);
mMediaRecorder.setVideoSize(profile.videoFrameWidth, profile.videoFrameHeight);
mMediaRecorder.setVideoSize(640, 480);
// recorder.setVideoSize(640, 480);
// recorder.setVideoFrameRate(16); //might be auto-determined due to lighting
// recorder.setVideoEncodingBitRate(3000000);
// recorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);// MPEG_4_SP
// recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
// Step 4: Set output file
mMediaRecorder.setOutputFile(output.toString());
// Set the duration
mMediaRecorder.setMaxDuration(Constants.VIDEO_DURATION);
// Step 6: Prepare configured MediaRecorder
try {
mMediaRecorder.prepare();
} catch (IllegalStateException e) {
Log.d(TAG, "IllegalStateException preparing MediaRecorder: " + e.getMessage());
releaseMediaRecorder();
return false;
} catch (IOException e) {
Log.d(TAG, "IOException preparing MediaRecorder: " + e.getMessage());
releaseMediaRecorder();
return false;
}
return true;
}
private void releaseCamera() {
if (mCamera != null) {
mCamera.release(); // release the camera for other applications
mCamera = null;
}
}
private void releaseMediaRecorder() {
if (mMediaRecorder != null) {
mMediaRecorder.reset(); // clear recorder configuration
mMediaRecorder.release(); // release the recorder object
mMediaRecorder = null;
mCamera.lock(); // lock camera for later use
}
}
private File getOutputMediaFile() {
return new File(mContext.getFilesDir().getPath() + File.separator + Constants.VIDEO_TEMP_NAME);
}
public Camera getCamera() {
return mCamera;
}
}
Constantstake
public class Constants {
public final static double VIDEO_ASPECT_RATIO = 0.6; // 1:5
public final static int VIDEO_DURATION = 2000;
public final static String VIDEO_TEMP_NAME = "VID_TEMP.mp4";
}
I am trying to intercept ANR (Application Not Responding) in android devices. I am implementing FileObserver on /data/anr/traces.txt file and capture the logs.
I am able to read this file in Samsung Galaxy J7(Android 6.0.1) but not on other devices ex: Nexus 4 (Android 5) and Moto G5 plus (Android 7).
I want FileObserver to read traces.txt on all devices. Any help will be appreciated.
Following is my code:
public class MainActivity extends AppCompatActivity {
private FileObserver fileObs;
private File anrFile = new File("/data/anr/traces.txt");
private File newFile;
int count=0;
long epochTimeCurrent=0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(Build.VERSION.SDK_INT >= 23){
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.INTERNET,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE},
100);
}
fileObs = new FileObserver("/data/anr") {
#Override
public void onEvent(int i, #Nullable String s) {
if(i == FileObserver.CLOSE_WRITE) {
if (anrFile.exists()) {
System.out.println("ANR file available");
//boolean read = anrFile.canRead();
if (count == 0) {
//Log.i("ANRTest", "Traces.text is available ? "+read);
epochTimeCurrent = System.currentTimeMillis();
Log.e("ANRTest", "System time in epoch : "+epochTimeCurrent);
readContent(anrFile);
} else if(count > 0) {
//Log.i("ANRTest", "Count increased : "+count);
}
}
else {
System.out.println("ANR file not available");
}
}
}
};
fileObs.startWatching();
//code to simulate ANR
final RelativeLayout cont = findViewById(R.id.container);
Button btn = findViewById(R.id.btn_anr);
final TextView textView = new TextView(this);
textView.setText("ANR");
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
System.out.println("Devtest : Inside onclick");
while (true) {
cont.addView(textView);
cont.removeView(textView);
}
//throw new ArrayIndexOutOfBoundsException();
//throw new RuntimeException("This is a crash");
}
});
}
public void readContent(File file) {
BufferedReader br = null;
FileReader fileReader;
String strLine = "";
try {
fileReader = new FileReader(file);
int pid = android.os.Process.myPid();
br = new BufferedReader(fileReader);
while( (strLine = br.readLine()) != null){
semusi.logger.Log.info(strLine);
//semusi.logger.Log.info("Hello there !");
//System.out.println(strLine);
if(strLine.contains("pid "+pid) && count==0) {
System.out.println("File content is : "+strLine);
long logTime = calcSubstring(strLine);
//semusi.logger.Log.info(strLine);
System.out.println("Log print time : "+logTime);
//1512364990000 and 1512364990670
if(logTime > epochTimeCurrent) {
//semusi.logger.Log.info(strLine);
if(strLine.contains("-- end")) {
}
}
count++;
}
}
fileReader.close();
br.close();
} catch (FileNotFoundException e) {
System.err.println("Unable to find the file: fileName");
} catch (IOException e) {
System.err.println("Unable to read the file: fileName");
}
}
public long calcSubstring(String rawStr) {
if(rawStr.contains("at")){
int index = rawStr.indexOf("2017");
//System.out.println("Index of 2017 is : "+index);
String dateSubs = rawStr.substring(index,index+19);
//System.out.println("Time substring : "+dateSubs);
//2017-12-04 10:42:28
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
Date gmt = null;
try {
gmt = formatter.parse(dateSubs);
} catch (ParseException e) {
e.printStackTrace();
}
long millisecondsSinceEpoch0 = gmt.getTime();
String asString = formatter.format(gmt);
System.out.println("Date after formatting : "+asString);
return millisecondsSinceEpoch0;
}
return 0;
}
}
I am new to android, I tried a lot codes, but can't get the path.
but using below code, I got the path of the External Sdcard, but could'nt access the External Sdcard directory.
public static List<StorageInfo> getStorageList() {
List<StorageInfo> list = new ArrayList<StorageInfo>();
String def_path = Environment.getExternalStorageDirectory().getPath();
boolean def_path_internal = !Environment.isExternalStorageRemovable();
String def_path_state = Environment.getExternalStorageState();
boolean def_path_available = def_path_state.equals(Environment.MEDIA_MOUNTED)
|| def_path_state.equals(Environment.MEDIA_MOUNTED_READ_ONLY);
boolean def_path_readonly = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED_READ_ONLY);
BufferedReader buf_reader = null;
try {
HashSet<String> paths = new HashSet<String>();
buf_reader = new BufferedReader(new FileReader("/proc/mounts"));
String line;
int cur_display_number = 1;
while ((line = buf_reader.readLine()) != null) { if (line.contains("vfat") || line.contains("/mnt")) {
StringTokenizer tokens = new StringTokenizer(line, " ");
String unused = tokens.nextToken(); //device
String mount_point = tokens.nextToken(); //mount point
if (paths.contains(mount_point)) {
continue;
}
unused = tokens.nextToken(); //file system
List<String> flags = Arrays.asList(tokens.nextToken().split(",")); //flags
boolean readonly = flags.contains("ro");
if (mount_point.equals(def_path)) {
paths.add(def_path);
list.add(0, new StorageInfo(def_path, def_path_internal, readonly, -1));
} else if (line.contains("/dev/block/vold")) {
if (!line.contains("/mnt/secure")
&& !line.contains("/mnt/asec")
&& !line.contains("/mnt/obb")
&& !line.contains("/dev/mapper")
&& !line.contains("tmpfs")) {
paths.add(mount_point);
list.add(new StorageInfo(mount_point, false, readonly, cur_display_number++));
}
}
}
}
if (!paths.contains(def_path) && def_path_available) {
list.add(0, new StorageInfo(def_path, def_path_internal, def_path_readonly, -1));
}
} catch (FileNotFoundException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (buf_reader != null) {
try {
buf_reader.close();
} catch (IOException ex) {} }
}
return list;
}
How can i access the Sd card directory.
From android 23+ you need to gain user permission to write to the phones external storage. Do this by adding the following to your manifest:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
If this does not give you access to the SD card then you may need to ask for permission at runtime before trying to access the card. Here is an example:
public void checkPermissions() {
String[] tmp = {"WRITE_EXTERNAL_STORAGE"};
for (String s : tmp) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!hasPermissionInManifest(getBaseContext(), s)) {
if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
}
}
}
}
}
You need permissions to access other sensors in the phone and camera which can be done in a similar way. You can get the path to the external storage like this:
Environment.getExternalStorageDirectory().toString();
I'm doing an Android application which needs to list out all installed applications with cache size & app user data size. Now I want to clear the data (both cache & User data) of all installed applications. Below is my tried code.
Its not clearing data. When I go to Settings -> Applications -> Manage Applications -> Your Application -> Size is still showing as data & Cache. How could I remove those unused data for all installed applications. Thanks.
My code:
...
public static void trimCache(Context context) {
try {
File dir = context.getCacheDir();
if (dir != null && dir.isDirectory()) {
deleteDir(dir);
}
} catch (Exception e) {
// TODO: handle exception
}
}
public void clearApplicationData() {
File cache = getCacheDir();
File appDir = new File(cache.getParent());
if (appDir.exists()) {
String[] children = appDir.list();
for (String s : children) {
// if (!s.equals("lib")) {
deleteDir(new File(appDir, s));
Log.i("TAG", "**************** File /data/data/APP_PACKAGE/" + s + " DELETED *******************");
// }
}
}
}
public static boolean deleteDir(File dir) {
if (dir != null && dir.isDirectory()) {
String[] children = dir.list();
for (int i = 0; i < children.length; i++) {
boolean success = deleteDir(new File(dir, children[i]));
if (!success) {
return false;
}
}
}
// The directory is now empty so delete it
return dir.delete();
}
private void showProgress(String message) {
pd = new ProgressDialog(this);
pd.setIcon(R.drawable.ic_launcher);
pd.setTitle("Please Wait...");
pd.setMessage(message);
pd.setCancelable(false);
pd.show();
}
long packageSize = 0, size = 0;
AppDetails cAppDetails;
public ArrayList<PackageInfoStruct> res;
private void getpackageSize() {
PACK_SIZE.clear();
DATA_SIZE.clear();
CACHE_SIZE.clear();
mPack = null;
mData = null;
mCache = null;
cAppDetails = new AppDetails(this);
res = cAppDetails.getPackages();
if (res == null)
return;
for (int m = 0; m < res.size(); m++) {
PackageManager pm = getPackageManager();
Method getPackageSizeInfo;
try {
getPackageSizeInfo = pm.getClass().getMethod(
"getPackageSizeInfo", String.class,
IPackageStatsObserver.class);
getPackageSizeInfo.invoke(pm, res.get(m).pname,
new cachePackState());
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
handle.sendEmptyMessage(ALL_PACAGE_SIZE_COMPLETED);
Log.v("Total Cache Size", " " + packageSize);
}
private Handler handle = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case FETCH_PACKAGE_SIZE_COMPLETED:
if (packageSize > 0)
size = (packageSize / 1024000);
lbl_cache_size.setText("Cache Size : " + size + " MB");
break;
case ALL_PACAGE_SIZE_COMPLETED:
MySimpleArrayAdapter adapter = new MySimpleArrayAdapter(
CacheList.this, mPack, mData, mCache);
lv.setAdapter(adapter);
if (null != pd)
if (pd.isShowing())
pd.dismiss();
break;
default:
break;
}
}
};
private class cachePackState extends IPackageStatsObserver.Stub {
#Override
public void onGetStatsCompleted(PackageStats pStats, boolean succeeded)
throws RemoteException {
Log.d("Package Size", pStats.packageName + "");
Log.i("Cache Size", pStats.cacheSize + "");
Log.w("Data Size", pStats.dataSize + "");
packageSize = packageSize + pStats.cacheSize;
Log.v("Total Cache Size", " " + packageSize);
PACK_SIZE.add(pStats.packageName);
DATA_SIZE.add(String.valueOf(pStats.dataSize / 1024000));
CACHE_SIZE.add(String.valueOf(pStats.cacheSize / 1024000));
mPack = PACK_SIZE.toArray(new String[PACK_SIZE.size()]);
mData = DATA_SIZE.toArray(new String[DATA_SIZE.size()]);
mCache = CACHE_SIZE.toArray(new String[CACHE_SIZE.size()]);
handle.sendEmptyMessage(FETCH_PACKAGE_SIZE_COMPLETED);
}
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_get_cacheSize:
size = 0;
packageSize = 0;
showProgress("Calculating Cache Size..!!!");
/**
* You can also use async task
* */
new Thread(new Runnable() {
#Override
public void run() {
getpackageSize();
}
}).start();
break;
case R.id.btn_clear_cache:
clearApplicationData();// Clear User Data
trimCache(CacheList.this);// Clear Cache Data
Toast.makeText(getApplicationContext(), "Successfully Cleared",
Toast.LENGTH_SHORT).show();
}
}
I want to set on button click events backup my applications data on SD-Card.
This is my code :
shv.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
Toast.makeText(SecondActivity.this, "backup Button press",Toast.LENGTH_LONG).show();
boolean rc = MyDatabaseTools.backup();
System.out.println(rc);
if(rc==true)
{
Toast.makeText(SecondActivity.this, "backup Successfully",Toast.LENGTH_LONG).show();
}
else
{
Toast.makeText(SecondActivity.this, "backup error",Toast.LENGTH_LONG).show();
}
}
});
I proceed like this :
public class MyDatabaseTools {
private String appName = "";
private String packageName = "";
public static boolean backup() {
boolean rc = false;
boolean writeable = isSDCardWriteable();
if (writeable) {
File file = new File(Environment.getDataDirectory() + "/data/<com.example.judgedetail>/databases/ado.db");
File fileBackupDir = new File(Environment.getExternalStorageDirectory(), "ADOBOOK" + "/backup");
if (!fileBackupDir.exists()) {
fileBackupDir.mkdirs();
}
if (file.exists()) {
File fileBackup = new File(fileBackupDir, "ado.db");
try {
fileBackup.createNewFile();
/*Files.copyFile(file, fileBackup);*/ //got error here dis line not work
rc = true;
} catch (IOException ioException) {
//
} catch (Exception exception) {
//
}
}
}
return rc;
}
private static boolean isSDCardWriteable() {
boolean rc = false;
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
rc = true;
}
return rc;
}
public MyDatabaseTools(final Context context, final String appName) {
this.appName = appName;
packageName = context.getPackageName();
}
}
Files.copyFile(file, fileBackup);
This line got error.
How shall I solve this ?
Please help.
Try this:
public void writeToSD() throws IOException {
File f=new File("/data/data/com.YourPackageName/databases/DBName");
FileInputStream fis=null;
FileOutputStream fos=null;
try{
fis=new FileInputStream(f);
fos=new FileOutputStream("/mnt/sdcard/dump.db");
while(true){
int i=fis.read();
if(i!=-1){
fos.write(i);
}
else{
break;
}
}
fos.flush();
}
catch(Exception e){
e.printStackTrace();
}
finally{
try{
fos.close();
fis.close();
}
catch(IOException ioe){
System.out.println(ioe);
}
}
}
I don't know where you copied that code from, but either you or the poster missed something. Files.copyFile() is no existing Android API function, and I guess that's what you describe as the line being not working.
You'll have to copy your file using another method, I'd suggest one like this:
https://stackoverflow.com/a/9293885/1691231