Force close when writing to SD card (android) - android

I have an app that backs up data to the sd card. When the SD card is inserted, it works perfectly fine and will backup the data. When the SD card is not present, I programed it to create an alert that tells the user that the SD card wasnt found.
The problem I'm having is that if somebody tries to export data for the first time without an SD card present, it will force close. However, if they backup a set of data first and then have no SD card later when they try to backup more data, an alert message appears just how I want.
Somebody help please! Heres my code (modified from a tutorial):
InputStream myInput;
try {
myInput = new FileInputStream("/data/data/com.android.footprint/databases/MY_DATABASE");
File directory = new File("/sdcard/Footprint");
if (!directory.exists())
{
directory.mkdirs();
}
OutputStream myOutput = new FileOutputStream(directory.getPath()+ "/MY_DATABASE.backup");
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer))>0)
{
myOutput.write(buffer, 0, length);
}
myOutput.flush();
myOutput.close();
myInput.close();
alertDialog2 = new AlertDialog.Builder(
settings.this).create();
alertDialog2.setTitle("Export Complete");
alertDialog2.setMessage("Data Backup successful");
alertDialog2.setButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
alertDialog2.dismiss();
}
});
alertDialog2.show();
} catch (FileNotFoundException e) {
alertDialog2.dismiss();
alertDialog3 = new AlertDialog.Builder(
settings.this).create();
alertDialog3.setIcon(R.drawable.delete);
alertDialog3.setTitle("Export Failed");
alertDialog3.setMessage("Make sure SD card is inserted and unmounted");
alertDialog3.setButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
alertDialog3.dismiss();
}
});
alertDialog3.show();
} catch (IOException e) {
alertDialog2.dismiss();
alertDialog3 = new AlertDialog.Builder(
settings.this).create();
alertDialog3.setIcon(R.drawable.delete);
alertDialog3.setTitle("Export Failed");
alertDialog3.setMessage("Make sure SD card is inserted and unmounted");
alertDialog3.setButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
alertDialog3.dismiss();
}
});
alertDialog3.show();
} catch (Exception e) {
alertDialog2.dismiss();
alertDialog3 = new AlertDialog.Builder(
settings.this).create();
alertDialog3.setIcon(R.drawable.delete);
alertDialog3.setTitle("Export Failed");
alertDialog3.setMessage("Make sure SD card is inserted and unmounted");
alertDialog3.setButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
alertDialog3.dismiss();
}
});
alertDialog3.show();
}

use this code for check SD card:
public static boolean isSdPresent() {
return android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED);
}
I found this on this link. Hope this helps..

Not sure if that is your problem but it would be a good idea to review the way you're checking if the SD Card is present. Here's how I handled it in one of my most recent application:
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
// Everything is fine, write away !
} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
// Card is in read mode, cannot write
Log.e("FileManager", "SD Card is in READ ONLY mode, impossible to write files.");
} else {
// Impossible to access SD Card
Log.e("FileManager", "Having trouble with SD card, can't write nor read from it.");
}
Also, may I suggest you get your path from the static method found in the Environement Class like so:
File root = Environment.getExternalStorageDirectory();
File directory = new File(root + "/Footprint");
Hope this helps you solve your problem!

Related

How to take screenshot of dialog in Android programmatically?

I have Android application which interacts with Web Server. When data is sent from phone to server, there is a bit of work with data (10-20 secs) and after that I get result back to phone. And i display that result in dialog with 2 choices. One choice is "OK" and it means that user is fine with result and dismiss the dialog. The other choice makes a screenshot of that results. And when I press this button I don't get picture of dialog, i get picture of layout which is behind that dialog.
My code behind this is
//this method is called on onPostExecute of async task
public void recieveResult (final Activity act,String result){
new AlertDialog.Builder(act)
.setTitle("Data - status")
.setMessage(result)
.setNegativeButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
})
.setPositiveButton("Save picture", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Bitmap bitmap = takeScreenshot(act);
saveBitmap(bitmap,act);
Toast.makeText(act,"Saved",Toast.LENGTH_LONG).show();
dialog.dismiss();
}
})
.show();
}
public Bitmap takeScreenshot(Activity act) {
View rootView = act.findViewById(android.R.id.content).getRootView();
rootView.setDrawingCacheEnabled(true);
return rootView.getDrawingCache();
}
public void saveBitmap(Bitmap bitmap,Activity act) {
String timeStamp = new SimpleDateFormat("MMyyyydd_HHmmss").format(new Date());
String imageFileName = "/screenshot_"+timeStamp+"_.png";
File storage = Environment.getExternalStoragePublicDirectory("Screens");
if (!storage.exists())
{
Toast.makeText(act, "Directory made", Toast.LENGTH_LONG).show();
storage.mkdirs();
}
File imagePath = new File(storage.getPath() + imageFileName);
FileOutputStream fos;
try {
fos = new FileOutputStream(imagePath);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.flush();
fos.close();
} catch (FileNotFoundException e) {
Log.e("GREC", e.getMessage(), e);
} catch (IOException e) {
Log.e("GREC", e.getMessage(), e);
}
}
My result of picture is just screen without dialog. How to get picture of dialog in it?
Try obtaining the Windows's decor view
then get its drawing cache bitmap as you implemented.
Dialog has it's own window ( different form activity's window ), you can use dialog.getWindow() method to get dialog's window.
so here is the screenshot code:
private AlertDialog dialog;
public void showDialog(View view) {
dialog = new AlertDialog.Builder(this)
.setTitle("Titel")
.setMessage("some content")
.setPositiveButton("Screenshot", (d, which) -> {
Bitmap bitmap = screenshot(dialog);
// you can save the bitmap or display in an ImageView
}).create();
dialog.show();
}
private Bitmap screenshot(Dialog dialog) {
Window window = dialog.getWindow();
View decorView = window.getDecorView();
Bitmap bitmap = Bitmap.createBitmap(decorView.getWidth(), decorView.getHeight(), Bitmap.Config.ARGB_8888);
decorView.draw(new Canvas(bitmap));
return bitmap;
}
try this code
String picId=String.valueOf(nu);
String myfile="meter"+picId+".jpeg";
BitmapDrawable bitmapDrawable = null;
Toast.makeText(getActivity(),"success full store image gallery",Toast.LENGTH_SHORT).show();
Date now = new Date();
android.text.format.DateFormat.format("yyyy-MM-dd_hh:mm:ss", now);
try {
File dir_image = new File(Environment.getExternalStorageDirectory()+//<---
File.separator+"SoundMeter"); //23-1-16 //<---
dir_image.mkdirs();
// image naming and path to include sd card appending name you choose for file
// String mPath = Environment.getExternalStorageDirectory().toString() + "/" + now + ".jpg";
// create bitmap screen capture
View v1 = surfaceView.getRootView();
v1.setDrawingCacheEnabled(true);
Bitmap bitmap = Bitmap.createBitmap(v1.getDrawingCache());
/* bitmapDrawable = new BitmapDrawable(bitmap);*/
v1.setDrawingCacheEnabled(false);
// File imageFile = new File(mPath); //file path 23-1-16
File imageFile = new File(dir_image,myfile);
FileOutputStream outputStream = new FileOutputStream(imageFile);
int quality = 100;
bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outputStream);
outputStream.flush();
outputStream.close();
openScreenshot(imageFile);
} catch (Throwable e) {
// Several error may come out with file handling or OOM
e.printStackTrace();
}
btnCaptured1.setVisibility(View.VISIBLE);
btnCaptured.setVisibility(View.VISIBLE);
//btnCaptured.setBackgroundDrawable(bitmapDrawable);
}
});
}
else
{
Toast.makeText(getActivity().getApplicationContext(), "No Connection", Toast.LENGTH_LONG).show();
}

Save data from edit Text within custom alertdialog to excel file with apache poi

This question might have been asked several times (about returning value from alert dialog) but i just couldn't get this thing to work (the flow in android application was fine but it just couldn't save the data to the excel files), I've tried several methods posted in SO but still no luck and in a deep frustration atm.
I have some suspicion though. I think it's because i accessed both etOne and etTwo from within the inner class that makes it somewhat unreadable?
The snippet of my code:
AlertDialog.Builder alertDialog = new AlertDialog.Builder(getActivity());
alertDialog.setTitle("Enter the data below");
LayoutInflater inflater = getActivity().getLayoutInflater();
View dialog = inflater.inflate(R.layout.alertdialog, null);
//I think the problem comes from here?
final EditText etOne = (EditText) dialog.findViewById(R.id.etOne);
final EditText etTwo = (EditText) dialog.findViewById(R.id.etTwo);
//----------------------------------------------------------------
alertDialog.setView(dialog)
// Add action buttons
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int id) {
// Save One and Two to excel file
try {
FileInputStream file;
HSSFWorkbook workbook;
file = new FileInputStream(new File(fileName));
workbook = new HSSFWorkbook(file);
HSSFSheet sheet2 = workbook.getSheetAt(2);
int row;
Cell cell;
row = ((KaryawanActivity) getActivity()).position;
cell = sheet2.getRow(row).getCell(1);
cell.setCellValue(etOne.getText().toString());
cell = sheet2.getRow(row).getCell(2);
cell.setCellValue(etTwo.getText().toString());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
//Open Semasa Activity
Intent intent = new Intent(getActivity().getBaseContext(), SemasaActivity.class);
intent.putExtra("filepath", fileName);
intent.putExtra("evaluator", evaluator);
intent.putExtra(THEME, theme);
intent.putExtra("KaryawanNo", KaryawanNo);
intent.putExtra("KaryawanPos", ((KaryawanActivity) getActivity()).position);
startActivity(intent);
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
}
});
alertDialog.show();
Thanks in advance.
Ah forget it, it's my own mistake anyway. I forgot to set the write the workbook of course it'll never save. My bad -_-
For those who need it, the complete code goes this way, and accessing the EditText from within inner class is doable (although i doubt this is a good way of doing it).
AlertDialog.Builder alertDialog = new AlertDialog.Builder(getActivity());
alertDialog.setTitle("Enter the data below");
LayoutInflater inflater = getActivity().getLayoutInflater();
View dialog = inflater.inflate(R.layout.alertdialog, null);
//I think the problem comes from here?
final EditText etOne = (EditText) dialog.findViewById(R.id.etOne);
final EditText etTwo = (EditText) dialog.findViewById(R.id.etTwo);
//----------------------------------------------------------------
alertDialog.setView(dialog)
// Add action buttons
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int id) {
// Save One and Two to excel file
try {
FileInputStream file;
HSSFWorkbook workbook;
file = new FileInputStream(new File(fileName));
workbook = new HSSFWorkbook(file);
HSSFSheet sheet2 = workbook.getSheetAt(2);
int row;
Cell cell;
row = ((KaryawanActivity) getActivity()).position;
cell = sheet2.getRow(row).getCell(1);
cell.setCellValue(etOne.getText().toString());
cell = sheet2.getRow(row).getCell(2);
cell.setCellValue(etTwo.getText().toString());
file.close();
FileOutputStream outFile = new FileOutputStream(new File(fileName));
workbook.write(outFile);
outFile.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
//Open Semasa Activity
Intent intent = new Intent(getActivity().getBaseContext(), SemasaActivity.class);
intent.putExtra("filepath", fileName);
intent.putExtra("evaluator", evaluator);
intent.putExtra(THEME, theme);
intent.putExtra("KaryawanNo", KaryawanNo);
intent.putExtra("KaryawanPos", ((KaryawanActivity) getActivity()).position);
startActivity(intent);
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
}
});
alertDialog.show();

recovery data from internal storage

I wrote an Android app. Export as signed APK sent via mail installed to device.- not at Market.
At runtime it will save they data to internal storage with similar code:
FileOutputStream fos = openFileOutput(FILENAME, Context.MODE_PRIVATE);
fos.write(string.getBytes());
fos.close();
As I know - correct me if I am wrong - it is saved to /data/data/com.mycompany.myapp/FILENAME
Because it is saved with MODE_PRIVATE I am not sure if any other app from Market or mine can see it save it. Maybe if I create an app with the same signature?
The phone it is not rooted. I have tryed many backup, copy with app and ADB shell.
App didn't saved my file, adb shell gave permission denied.
Is there any solution with programming or not to get that file?
I wrote a little code part to test it:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends Activity {
private EditText tfData;
private Button btSave, btLoad;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tfData = (EditText) findViewById(R.id.tfData);
btSave = (Button) findViewById(R.id.btSave);
btLoad = (Button) findViewById(R.id.btLoad);
btSave.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
doSave();
}
});
btLoad.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
doLoad();
}
});
tfData.setText("Some secret data");
boolean btLoadVisible = false; // TODO change this value for the second build!
if (!btLoadVisible) {
btLoad.setVisibility(View.GONE);
}
else{
btSave.setVisibility(View.INVISIBLE);
}
}
private static final String FILENAME = "private.dat";
private void doSave() {
String text = null;
if (tfData.getText() == null) {
Toast.makeText(this, "Please enter a string!", Toast.LENGTH_SHORT).show();
return;
}
text = tfData.getText().toString();
if (text == null || text.length() == 0) {
Toast.makeText(this, "Please enter a string!!!", Toast.LENGTH_SHORT).show();
}
FileOutputStream fos = null;
try {
fos = openFileOutput(FILENAME, Context.MODE_PRIVATE);
fos.write(text.getBytes("UTF-8"));
fos.close();
fos = null;
new AlertDialog.Builder(this).setTitle("Saved").setMessage("Your data is saved:\n" + text+"\nChange the build to recover it!")
.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
}).show();
} catch (Exception e) {
Log.e("doSave", "Can't save ...", e);
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
// I don't care:
e.printStackTrace();
}
}
}
}
private void doLoad() {
FileInputStream fis = null;
try {
fis = openFileInput(FILENAME);
} catch (FileNotFoundException e) {
e.printStackTrace();
new AlertDialog.Builder(this)
.setTitle("FileNotFoundException")
.setMessage(
"The file with data can't be found. Or it wasn't saved at all or you have uninstalled the old app or... who knows.\nI can't recover the data, it is lost permanenty!!!")
.setPositiveButton("I am sad", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
}).show();
return; // I don't like return from catch...
}
if (fis != null) {
try {
int size = fis.available();// not the best, but now I hope is possible to read 10-30 bytes without blocking
byte[] buff = new byte[size];
int readCount = fis.read(buff);
if (readCount != size) {
Toast.makeText(this, "Dammit can't read : " + size + " bytes, only " + readCount + ". Restart app, than phone? ", Toast.LENGTH_SHORT)
.show();
}
String text = new String(buff, "UTF-8");
tfData.setText(text);
new AlertDialog.Builder(this).setTitle("Loaded").setMessage("Your data is recovered:\n" + text)
.setPositiveButton("I am happy", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
}).show();
} catch (IOException e) {
Log.e("doLoad", "Can't load ...", e);
new AlertDialog.Builder(this).setTitle("IOException").setMessage("There is some error while reading the data:\n" + e.getMessage())
.setPositiveButton("I am sad", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
}).show();
}
}
}
}
Clean, build, export as signed apk: eg InternalMemoryReader_save.apk
save the keystore!!!
change the boolean btLoadVisible = false to boolean btLoadVisible = true .
export apk WITH THE SAME KEYSTORE! but diff name, eg InternalMemoryReader_load.apk - but can be a _datasaver _factoryservice whatever. This usually it is not given to the user.
Install the first apk and do a save.
do not uninstall the apk
lets propose you are blaming of data loss, can't open it ...and once in a mail you will receive the _load.apk from the support service. Install it without remove the old apk. It has the same package name, same signature, just diff file name.
I was able to load the data. It can be send via mail or processed there, the hardest part is done.
Conclusion:
If you are the app developer and if you have the keystore and able to sign a modified apk than you will have access to that internal, private file.
I hope I am helping somebody else to to recover his app data and not waste so much time.
If you know better solution, please let me know!

AlertDailogBox in android,saving file

In my application on clicking on button i'm showing alert dailog box to get file name.and getting name from user for a file.and saving it.
but what is happening is, after clicking on button alert dailog box is gets infront of screen and before that its try to save file.but its trying to save file befor user enters the name for file thats why file name is null in saving file.how to call use alert box so that i can get name from user and then save the file using that name.plase help me.
public void savebitmap(Bitmap bitmap)
{
str++;
AlertDialog.Builder alert = new AlertDialog.Builder(Work.this);
alert.setMessage("File name :");
input = new EditText(Work.this);
input.setLayoutParams(new LayoutParams(100,50));
alert.setView(input);
alert.setNeutralButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
NameValue = input.getText().toString();
System.out.println(" file name.---"+NameValue);
}
});
alert.show();
System.out.println("file is..."+NameValue);
try
{
System.out.println("in bitmap save...");
File fn=new File("/sdcard/"+" filename4"+".png");
FileOutputStream out=new FileOutputStream(fn);
System.out.println(",,,,,,,,,,,,,,,"+out);
Toast.makeText(getApplicationContext(), "In Save",Toast.LENGTH_SHORT).show();
bitmap.compress(Bitmap.CompressFormat.JPEG, 90,out);
out.flush();
out.close();
Toast.makeText(getApplicationContext(), "File is Saved in "+fn, Toast.LENGTH_SHORT).show();
}
catch(Exception e){
e.printStackTrace();
}
}
you will to move all file saving code inside onClick event of Button or wrap all code inside a method and then call it on Button click as :
public void savebitmap(Bitmap bitmap){
//....your code here
alert.setNeutralButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
NameValue = input.getText().toString();
System.out.println(" file name.---"+NameValue);
// put your code here to save file on Ok button click
saveFileOnSdCard(NameValue);
}
});
alert.show();
}
private void saveFileOnSdCard(String str_filename){
// move yor file saving code here..
}
You need to take input first then when user press OK on that you need to create file. So you need to write code in side onClick.
Try this,
public void savebitmap(Bitmap bitmap)
{
str++;
AlertDialog.Builder alert = new AlertDialog.Builder(Work.this);
alert.setMessage("File name :");
input = new EditText(Work.this);
input.setLayoutParams(new LayoutParams(100,50));
alert.setView(input);
alert.setNeutralButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
NameValue = input.getText().toString();
System.out.println(" file name.---"+NameValue);
try
{
System.out.println("in bitmap save...");
File fn=new File("/sdcard/"+" filename4"+".png");
FileOutputStream out=new FileOutputStream(fn);
System.out.println(",,,,,,,,,,,,,,,"+out);
Toast.makeText(getApplicationContext(), "In Save",Toast.LENGTH_SHORT).show();
bitmap.compress(Bitmap.CompressFormat.JPEG, 90,out);
out.flush();
out.close();
}
catch(Exception e){
e.printStackTrace();
}
}
});
alert.show();
System.out.println("file is..."+NameValue);
}

View data tables odf database in external device

The only way to get and visualize the data table of my database inside external devices is by atribution of privilege of superuser privilege in external device? Don't exist another way that allow visualize the data tables as in emulator?
I make this question because this way of superuser privilege not inspire me security.
Thanks for your attention (PS: Sorry by mistakes, but english is not my mother language :) )
You can add functionality to export the database file from the internal read-only app storage to the SD-Card by simply letting your app copy the file.
Then use whatever ways you have to get it from there. Works on any device and no root required.
private void exportDb() {
File database = getDatabasePath("myDb.db");
File sdCard = new File(Environment.getExternalStorageDirectory(), "myDb.db");
if (copy(database, sdCard)) {
Toast.makeText(this, "Get db from " + sdCard.getPath(), Toast.LENGTH_LONG).show();
} else {
Toast.makeText(this, "Copying the db failed", Toast.LENGTH_LONG).show();
}
}
private static boolean copy(File src, File target) {
// try creating necessary directories
target.mkdirs();
boolean success = false;
FileOutputStream out = null;
FileInputStream in = null;
try {
out = new FileOutputStream(target);
in = new FileInputStream(src);
byte[] buffer = new byte[8 * 1024];
int read;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
success = true;
} catch (FileNotFoundException e) {
// maybe log
} catch (IOException e) {
// maybe log
} finally {
close(in);
close(out);
}
if (!success) {
// try to delete failed attempts
target.delete();
}
return success;
}
private static void close(final Closeable closeMe) {
if (closeMe != null)
try {
closeMe.close();
} catch (IOException ignored) {
// ignored
}
}

Categories

Resources