Background:
I am using three fragments and one activity in my application. Two fragments use recyclerViews and the other uses an expandableListView.
Problem:
I am trying to properly program the onPause(), onResume(), onStop(), and onRestart() methods to save the state of my application when the home, back, or switch views buttons are pressed.
To save the state of the program and load it when it comes back I have created the save() and load() methods in my one and only activity.
//from the end of onCreate
load();
}
#Override
protected void onStart() {
super.onStart();
mRef = new Firebase("https://sure-7856d.firebaseio.com/");
}
#Override
protected void onStop(){
super.onStop();
save();
}
#Override
protected void onPause(){
super.onPause();
save();
}
#Override
protected void onResume(){
super.onResume();
load();
}
#Override
protected void onRestart(){
super.onRestart();
load();
}
In the save method I get the adapters from my 2 recyclerViews and my expandableListView`s ArrayList that keeps track of which checkboxes are checked.
After that I put them each into a temporary Arraylist then I add each of those ArrayLists to a single arraylist that will be saved to the file.
private void save(){
//saved_data = new File("saved_data");
/*try {
if(saved_data.exists()==false){
//saved_data.createNewFile();
saved_data.setWritable(true);
}
} catch (IOException e) {
e.printStackTrace();
}*/
File myFile;
try{
myFile = new File(getFilesDir().getAbsolutePath(), "dir/save_data.bin");
myFile.mkdirs();
myFile.createNewFile();
FILENAME = myFile.getName();
}catch (IOException e){
e.printStackTrace();
}
OneFragment f20 = (OneFragment) frags.get(0);
TwoFragment f21 = (TwoFragment) frags.get(1);
ThreeFragment f22 = (ThreeFragment) frags.get(2);
ArrayList saveTasks = f20.adapter.getList();
ArrayList saveReqs = f21.adapter.getList();
ArrayList saveMap = new ArrayList<String>();
if(f22.listAdapter!=null) {
if (f22.listAdapter.getExport() != null) {
saveMap = f22.listAdapter.getExport();
}
}
ArrayList results = new ArrayList();
results.add(saveTasks);
results.add(saveReqs);
results.add(saveMap);
ObjectOutputStream oos1 = null;
FileOutputStream fos1 = null;
try {
fos1 = openFileOutput(FILENAME, Context.MODE_PRIVATE);
oos1 = new ObjectOutputStream(fos1);
oos1.writeObject(results);
oos1.close();
fos1.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(oos1 != null){
try {
oos1.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
In the load code I get the object from the file and update the adapters to their previous state.
private void load(){
//saved_data = new File("saved_data");
ArrayList results = new ArrayList();
FileInputStream fis = null;
ObjectInputStream ois = null;
if(FILENAME==null){
return;
}
try {
fis = new FileInputStream(FILENAME);
ois = new ObjectInputStream(fis);
}catch (FileNotFoundException e) {
e.printStackTrace();
return;
}catch (IOException e) {
e.printStackTrace();
}
try {
while (true) {
results = (ArrayList)(ois.readObject());
}
} catch (OptionalDataException e) {
if (!e.eof) try {
throw e;
} catch (OptionalDataException e1) {
e1.printStackTrace();
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
ois.close();
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
for(int i = 0; i < results.size();i++){
if(i == 0){
frags.set(0,results.get(i));
}
else if(i == 1){
frags.set(1,results.get(i));
}
else if(i == 2){
frags.set(2,results.get(i));
}
else{
}
}
}
When I press the square button at the bottom of the emulator and go back to it one of a few things happen
It crashes saying the file could not be found
W/System.err: Caused by: android.system.ErrnoException: open failed: ENOENT (No such file or directory)
And this error points to the load method as the point of failure specifically
FileInputStream fis = null;
When I hit the triangle button nothing happens in logcat, everything is gone upon returning, and the app loses its functions of adding strings to lists on both recyclerViews and displaying both lists in the expandableListView.
Hitting the center circle button and going back to the app is fine nothing breaks.
Since Im getting a file not found error I think that the file isnt getting written
I have searched Stack for a solution and I am new to File IO and fragments, so I have no idea where to go from here.
Related
I am busy developing a APP On Android Studio using the Flutter framework, that functions as follows,
The user can press press a button and it will take a picture without opening the camera view.
I have a MethodChannel between my Dart/Flutter and Android.Java ,I am able to press the button and the app takes a pic and saves it to gallery.
The issue I am having is that it closes the app afterwards with no error.
Could you please have a look at my code and see if you can help me.
MainActivity.Java
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
new MethodChannel(getFlutterView(), CHANNEL).setMethodCallHandler(
new MethodCallHandler() {
#Override
public void onMethodCall(MethodCall call, Result result) {
if(call.method.equals("test"))
{
StartCameraFrontCamera();
}
else {
result.notImplemented();
}
}
});
}
public void StartCameraFrontCamera()
{
File directory = new File(Environment.getExternalStorageDirectory() + "/PicturesTest/");
if (!directory.exists()) {
directory.mkdir();
}
try {
ReleaseCamera();
mCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT);
} catch (Exception e) {
Log.e(getString(R.string.app_name), "failed to open Camera");
e.printStackTrace();
}
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPictureFormat(ImageFormat.JPEG);
mCamera.setParameters(parameters);
SurfaceView mview = new SurfaceView(this);
SurfaceTexture surfaceTexture = new SurfaceTexture(0);
imageName = "fontcamera.jpg";
try{
//mCamera.setPreviewDisplay(mview.getHolder());
mCamera.setPreviewTexture(surfaceTexture);
//mCamera.setPreviewDisplay(null);
mCamera.startPreview();
mCamera.takePicture(null,null,photoCallback);
//mCamera.stopPreview();
}catch(IOException e) {
e.printStackTrace();
}
}
Camera.PictureCallback photoCallback=new Camera.PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
try {
String root = Environment.getExternalStorageDirectory().toString();
File myDir = new File(root + "/PicturesTest");
File file = new File (myDir, "image1.jpg");
FileOutputStream out = new FileOutputStream(file);
out.write(data);
out.flush();
out.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e)
{
e.printStackTrace();
}
finish();
}
};
I need my app to save the HashMaps when the app close and restore it's information that are stored on the 3 HashMaps and one ArrayList.
If I remove the two lines with the >> my app is working fine but the data is not stored anywhere so you have to register every time.
Although when I add these lines even if you register you are not able to login which is very odd. Another important thing is that no exception is thrown.
A very important thing my HashMap and ArrayList are in separate classes as static field in order to be accessible by all objects and activities
This method is the main activity from where my app starts.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
btnLogin=findViewById(R.id.buttonLogin);
btnRegister=findViewById(R.id.buttonRegister);
presenter=new LoginPresenter(this,getApplicationContext());
>>presenter.loadDataToDB();
btnLogin.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
User curUser=presenter.login();
if(curUser!=null){
Intent intent=new Intent(Login_activity.this,
curUser.getUserType());
intent.putExtra("User",curUser.getMail());
startActivity(intent);
>>presenter.saveDataToDB();
finish();
}
}
});
The methods from the LoginPresenter Class are the following
public void loadDataToDB(){
try {
EventManagersDB.loadAllManagers((HashMap<EventManager, String>)
readArrayListFromSD(context, EVENTMANAGERDB));
UsersDB.loadFromFile((HashMap<User, String>)
readArrayListFromSD(context, USERSDB));
ParentsDB.loadFromFile((HashMap<Parent, String>)
readArrayListFromSD(context, PARENTSDB));
EventsDB.setAllEvents((ArrayList<Event>)
readArrayListFromSD(context, EVENTSDB));
}catch (Exception e){
e.printStackTrace();
}
}
public void saveDataToDB(){
saveDataToSD(context,EVENTSDB, EventsDB.getAllEvents());
saveDataToSD(context,USERSDB,UsersDB.getAllUsers());
saveDataToSD(context,PARENTSDB, ParentsDB.getParents());
saveDataToSD(context,EVENTMANAGERDB,EventManagersDB.getAllEventManagers());
}
private void saveDataToSD(Context mContext, String filename, Object list){
try {
FileOutputStream fos = mContext.openFileOutput(filename + ".dat"
, mContext.MODE_PRIVATE);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(list);
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
private Object readArrayListFromSD(Context mContext,String filename){
try {
FileInputStream fis = mContext.openFileInput(filename + ".dat");
ObjectInputStream ois = new ObjectInputStream(fis);
Object obj= ois.readObject();
fis.close();
return obj;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
so I'm implementing like music playlist app, my audios are uploaded to Parse.com as mp3 , I want to retrieve those audios ..
final Button btn = (Button) v.findViewById(R.id.button);
final ParseFile fileObject = object.getParseFile("music");
if (fileObject != null) {
fileObject.getDataInBackground(new GetDataCallback() {
#Override
public void done(byte[] bytes, com.parse.ParseException e) {
final String audioFileURL = fileObject.getUrl();
mediaPlayer = new MediaPlayer();
mediaPlayer.reset();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
btn.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
try {
mediaPlayer.setDataSource(audioFileURL);
mediaPlayer.prepare();
mediaPlayer.start();
} catch (IllegalArgumentException e1) {
e1.printStackTrace();
}//end catch
catch (IOException e1) {
e1.printStackTrace();
}
}//end on click
}//end listener
);
}//end done
});//end get data
}//end if
this is how I retrieve music from Parse.com but this is taking so much time specially that I have a list of audios .. I want a way to download group of the audios in the background .. so when I click the button, the music play so fast .. any help would be greatly appreciated.
I have no time right now to understand why your code doesn't work, but you can take my sample app on github (committed just now), you should solve your problem...if not, let me know. Please, take note of the README.md
https://github.com/fullwipe/ParseAudioFileExample
Hope it helps...
Edit This is the essential part of my repository. Record and save:
String outputFile = Environment.getExternalStorageDirectory().
getAbsolutePath() + "/rumor.mp3";
myRecorder = new MediaRecorder();
myRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
myRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
myRecorder.setAudioEncoder(MediaRecorder.OutputFormat.AMR_NB);
myRecorder.setOutputFile(outputFile);
Then, start recording...
try {
myRecorder.prepare();
myRecorder.start();
} catch (IllegalStateException e) {
// start:it is called before prepare()
// prepare: it is called after start() or before setOutputFormat()
e.printStackTrace();
} catch (IOException e) {
// prepare() fails
e.printStackTrace();
}
When you stop recording, save it on Parse.com in this way:
FileInputStream fileInputStream = null;
File fileObj = new File(outputFile);
byte[] data = new byte[(int) fileObj.length()];
try {
//convert file into array of bytes
fileInputStream = new FileInputStream(fileObj);
fileInputStream.read(data);
fileInputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
ParseFile parseAudioFile = new ParseFile("audiofile.mp3", data);
parseAudioFile.saveInBackground();
ParseObject parseObject = new ParseObject("AudioFileClass");
parseObject.put("audiofile", parseAudioFile);
parseObject.saveInBackground(new SaveCallback() {
public void done(ParseException e) {
if (e == null) {
Toast.makeText(getApplicationContext(),"Audio file saved successfully", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getApplicationContext(),"Error: audio file not saved", Toast.LENGTH_SHORT).show();
}
}
});
Retrieve and play from Parse.com is very simple, I have used a ParseQueryAdapter. This is the part where you get the mp3 file and play it:
ParseFile descr = object.getParseFile("audiofile");
if (descr != null) {
String audioFileURL = descr.getUrl();
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
mediaPlayer.setDataSource(audioFileURL);
mediaPlayer.prepare();
mediaPlayer.start();
}
...
...
I am using the MP4ParserMergeAudioVideo to add a new audio to an MP4 file. The library had said to use .wav file, if i keep a .wav file in the directory and give the name of the audiofile as example.m4a, I get a file not found exception. So I changed the file to a .m4a audio file. The code is given below.
findViewById(R.id.append).setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
String root = Environment.getExternalStorageDirectory().toString();
Log.e("",""+root);
String audio = root + "/download/"+"mymovieaudio.m4a";
String video = root + "/download/"+"My_Movie.mp4";
String output = root + "/download/ouput.mp4";
mux(video, audio, output);
}
});
The mux function is like this
public boolean mux(String videoFile, String audioFile, String outputFile) {
Movie video;
try {
video = new MovieCreator().build(videoFile);
} catch (RuntimeException e) {
e.printStackTrace();
return false;
} catch (IOException e) {
e.printStackTrace();
return false;
}
Movie audio;
try {
audio = new MovieCreator().build(audioFile);
} catch (IOException e) {
e.printStackTrace();
return false;
} catch (NullPointerException e) {
e.printStackTrace();
return false;
}
Track audioTrack = audio.getTracks().get(0);
video.addTrack(audioTrack);
Container out = new DefaultMp4Builder().build(video);
FileOutputStream fos;
try {
fos = new FileOutputStream(outputFile);
} catch (FileNotFoundException e) {
e.printStackTrace();
return false;
}
BufferedWritableFileByteChannel byteBufferByteChannel = new BufferedWritableFileByteChannel(fos);
try {
out.writeContainer(byteBufferByteChannel);
byteBufferByteChannel.close();
fos.close();
} catch (IOException e) {
e.printStackTrace();
return false;
}
return true;
}
I successfully get the output.mp4 file in my download directory of my device. The problem is that it does not have any audio. Please help. Thanks in advance.
I want my program to download many images (around 500) from the internet and store them in my external storage. Currently when I download a single image, it shows a progressBar and downloads the image properly. However when I am trying to replicate w/ two images, it gives the Toast for "Download complete" for both images being downloaded, however no progressBar for either image is shown and only the first image is properly downloaded.
Here is the code for my onCreate method for activity.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Remove Title bar
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
//force portrait orientation. (No landscape orientation).
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
setContentView(R.layout.activity_quran);
//Instantiate ProgressDialog (Used for downloading quran pages).
myProgressDialog = new ProgressDialog(QuranActivity.this);
myProgressDialog.setMessage("Downloading Quran");
myProgressDialog.setIndeterminate(true);
myProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
myProgressDialog.setCancelable(true);
//execute when the downloader must be fired.
final DownloadTask downloadTask = new DownloadTask(QuranActivity.this);
DownloadTask second = new DownloadTask(getApplicationContext());
myHTTPURL = "https://ia601608.us.archive.org/BookReader/BookReaderImages.php?zip=/10/items/05Quran15LineWhitePageWithVioletBorderWww.Momeen.blogspot.com/05%20Quran%2015%20Line%20[White%20page%20with%20Violet%20border]%20-%20www.Momeen.blogspot.com_jp2.zip&file=05%20Quran%2015%20Line%20[White%20page%20with%20Violet%20border]%20-%20www.Momeen.blogspot.com_jp2/05%20Quran%2015%20Line%20[White%20page%20with%20Violet%20border]%20-%20www.Momeen.blogspot.com_0001.jp2&scale=1&rotate=0";
myHTTPURL2 = "https://ia601608.us.archive.org/BookReader/BookReaderImages.php?zip=/10/items/05Quran15LineWhitePageWithVioletBorderWww.Momeen.blogspot.com/05%20Quran%2015%20Line%20[White%20page%20with%20Violet%20border]%20-%20www.Momeen.blogspot.com_jp2.zip&file=05%20Quran%2015%20Line%20[White%20page%20with%20Violet%20border]%20-%20www.Momeen.blogspot.com_jp2/05%20Quran%2015%20Line%20[White%20page%20with%20Violet%20border]%20-%20www.Momeen.blogspot.com_0002.jp2&scale=1&rotate=0";
//First check if the file has already been created. (Only need to download 1ce, or
//in the case where the user deleted the files, we reinstall them again).
if (isExternalStorageWritable()) {
File makeDirectory = getQuranStorageDir(QuranActivity.this, "Quran_Pages");
for (int i = 0; i < 2; i++) {
Bundle myBundle = new Bundle();
myBundle.putInt("i", i);
if (i == 0) {
downloadTask.execute(myHTTPURL);
try {
downloadTask.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
myProgressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
#Override
public void onCancel(DialogInterface dialog) {
downloadTask.cancel(true);
}
});
} else {
/*if (downloadTask.getStatus() == AsyncTask.Status.FINISHED) {
downloadTask.execute(myHTTPURL2);
} else if (downloadTask.getStatus() == AsyncTask.Status.RUNNING) {
try {
downloadTask.execute(myHTTPURL2).wait(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
} */
second.execute(myHTTPURL2);
try {
second.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
// downloadTask.execute(myHTTPURL2);
}
}
}
and this is the code for my AsynTask Class.
#TargetApi(Build.VERSION_CODES.FROYO)
private class DownloadTask extends AsyncTask {
private Context context;
private PowerManager.WakeLock myWakeLock;
public DownloadTask(Context context) {
this.context = context;
}
#Override
protected String doInBackground(String... sUrl) {
InputStream input = null;
OutputStream output = null;
HttpURLConnection connection = null;
try {
URL url = new URL(sUrl[0]);
connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("GET");
connection.connect();
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
return "Server returned HTTP " + connection.getResponseCode()
+ " " + connection.getResponseMessage();
}
//Display download percentage.
int fileLength = connection.getContentLength();
//create folder to place the downloaded file in.
// File Path:E:\Android\data\com.syedabdullah.syed.quran_memorization_application
// \files\Quran Memorization Application\Quran_Pictures
//So first create a root folder Quran Memorization Application then inside that
//folder we create another folder named Quran Pictures.
/* File rootFolder = new File(getExternalFilesDir("Quran Memorization Application"),
"Quran_Pages"); */
//Here we insert inside the Quran_Pictures folder the quran_pages.
//String myFileName = "quran_01.jpg";
Bundle y = new Bundle();
int retrievePos = y.getInt("i");
String quranFilePageName = "_" + retrievePos + ".jpg";
// String fileName = "justwork.jpg";
File sup = new File(getExternalFilesDir("Quran Memorization Application"), "Quran_Pages");
File myFile = new File(sup, quranFilePageName);
myFile.createNewFile();
//downlaod the file.
input = connection.getInputStream();
output = new FileOutputStream(myFile);
byte data[] = new byte[4096];
long total = 0;
int count;
while ((count = input.read(data)) != -1) {
//allow cancel with back button.
if (isCancelled()) {
input.close();
return null;
}
total += count;
//publish the progress.
if (fileLength > 0) {
publishProgress((int) (total * 100 / fileLength));
}
output.write(data, 0, count);
}
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
intent.setData(Uri.fromFile(myFile));
QuranActivity.this.sendBroadcast(intent);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (output != null) {
output.close();
}
if (input != null) {
input.close();
}
} catch (IOException e) {
e.printStackTrace();
}
if (connection != null) {
connection.disconnect();
}
}
return null;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
//Take CPU lock to prevent CPU from going off if the user presses the power button.
//during download.
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
myWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, getClass().getName());
myWakeLock.acquire();
myProgressDialog.show();
}
#Override
protected void onProgressUpdate(Integer... progress) {
super.onProgressUpdate(progress);
//If we get here length is known, so setIndertimante to false.
myProgressDialog.setIndeterminate(false);
myProgressDialog.setMax(100);
myProgressDialog.setProgress(progress[0]);
}
#Override
protected void onPostExecute(String result) {
myWakeLock.release();
myProgressDialog.dismiss();
if (result != null) {
Toast.makeText(context, "Download error: " + result, Toast.LENGTH_LONG).show();
} else {
Toast.makeText(context, "Download Complete", Toast.LENGTH_SHORT).show();
}
}
} }
I was hoping to have a for loop that would create hundreds of downloadTasks and download all the images I need, and then I would call the get method. However in order for that to work, I first need too know why when I try for 2 images only the first one gets downloaded and why no progressbar shows up. Also if possible if I could get a hint as to how I can make my progressBar update for all the images and not be designed for just 1. Thanks in advance. (Note all URLs are currect.)
Thank you so much! figured out that my loops were suppose to go inside doInBackground. Also to anyone else having a similar issue. To download multiple files and display a decent progressBar, here is a very great tutorial: http://theopentutorials.com/tutorials/android/dialog/android-download-multiple-files-showing-progress-bar/