Null Pointer Exception when writing to a File - Android Studio - java

My app crashes every time I go to send the data gathered by the sensor. The error I am given is as follows:
06-20 14:50:00.784 22983-22983/com.example.adam.proj2 E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.NullPointerException
at com.example.adam.proj2.SensorActivity.onClick(SensorActivity.java:124)
at android.view.View.performClick(View.java:3549)
at android.view.View$PerformClick.run(View.java:14393)
at android.os.Handler.handleCallback(Handler.java:605)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:4944)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
at dalvik.system.NativeStart.main(Native Method)
Here is the code for gathering the sensor data:
public void onSensorChanged(SensorEvent event) {
float x = event.values[0];
ArrayList<Float> enrolAcc = new ArrayList<>();
ArrayList<Float> authAcc = new ArrayList<>();
TextView textEnrol = (TextView) findViewById(R.id.textView);
if (choice == 1) {
mPreviousAcc = mCurrentAcc;
mCurrentAcc = (float) Math.sqrt((double) (x * x));
float delta = mCurrentAcc - mPreviousAcc;
mDiffAcc = mDiffAcc * 0.9f + delta;
if (enrolAcc.size() < 100) {
enrolAcc.add(x);
} else {
enrolAcc.remove(0);
enrolAcc.add(x);
}
walkData = enrolAcc.toString();
textEnrol.setText(walkData);
}
Here is the code for writing to the file (this happens onClick of a button):
public void onClick(View v) {
switch (v.getId()) {
case R.id.enrolBtn:
choice = 1;
Toast.makeText(this, "Enrolment Mode Selected", Toast.LENGTH_SHORT).show();
break;
case R.id.authBtn:
choice = 2;
Toast.makeText(this, "Authentication Service Starting", Toast.LENGTH_SHORT).show();
break;
case R.id.sendBtn:
choice = 3;
String baseDir = android.os.Environment.getExternalStorageDirectory().getAbsolutePath();
String fileName = "Walk Data.csv";
String filePath = baseDir + File.separator + fileName;
File f = new File(filePath);
FileOutputStream out = null;
try {
out = new FileOutputStream(f);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
try {
out.write(walkData.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
android.net.Uri u1 = Uri.fromFile(f);
Intent sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_STREAM, u1);
sendIntent.setType("text/html");
startActivity(sendIntent);
break;
}
}
From what I can see the exception is generated by the out.write method?
The array list holding the sensor values is stored in the walkData string so that the string can be then written in the csv file stored on the external device storage. I would like the data to be in CSV format.
I am stumped and cannot figure out how to prevent this, any help would be much appreciated.

You get the error because you are trying to write to a READ ONLY file.
The line out = new FileOutputStream(f) throws an exception:
java.io.FileNotFoundException: /storage/sdcard/Walk Data.csv: open failed: EROFS (Read-only file system), but you actually ignore it, so out = NULL and then you get the other exception.
Move your file to a place where you can write to it -
String fileName = "Walk Data.csv";
String baseDir = getFilesDir() + "/" + fileName;
File f = new File(baseDir);

Look at the code:
try {
out = new FileOutputStream(f);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
try {
out.write(walkData.getBytes());
The exception is thrown at the last line. So, what could possibly be wrong at that line?
out could be null. out will be null if the file is not found, since you catch that exception and pretend nothing wrong happened at the line before, leaving out as null. You shouldn't try to use outif you just failed to initialize it. The try block should ensclose all the lines using out, and not just the line initializing it.
walkDatacould also be null. But since we don't know where it comes from, we can't say. Use your debugger to know which is null. And whatever the answer is, fix your exception handling code. It should look like
FileOutputStream out = null;
try {
out = new FileOutputStream(f);
out.write(walkData.getBytes());
android.net.Uri u1 = Uri.fromFile(f);
Intent sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_STREAM, u1);
sendIntent.setType("text/html");
startActivity(sendIntent);
} catch (IOException e) {
// TODO signal the error to the user. Printing a stack trace is not enough
}
finally {
if (out != null) {
try {
out.close();
} catch (IOException e) {
// TODO signal the error to the user. Printing a stack trace is not enough
}
}
}

Related

Show array of URI as GIF Android using AnimationDrawble

So I basically have a List of URIs, each has a .jpeg file, and I want to show this list like a GIF file (not necessesary to make a gif, only to display).
So after a research I found the AnimationDrawble object, converted each URI into Drawable and added it as a frame to AnimationDrawable.
This is my code:
AnimationDrawable ad = new AnimationDrawable();
Drawable[] dr = new Drawable[position+1];
ProgressItem pi;
try {
for (int i = 0; i <= position; i++) {
pi = progress.get(i);
try {
dr[i] = drawableFromUrl(pi.getImage());
} catch (IOException ios) {
Toast.makeText(activity, ios.getMessage(), Toast.LENGTH_SHORT).show();
}
}
}
catch(Exception ex)
{
Toast.makeText(activity, ex.getMessage(), Toast.LENGTH_SHORT).show();
}
Intent i = new Intent(activity,ProgressImage.class);
DataWraper.setItems(dr);
drawableFromUrl:
public Drawable drawableFromUrl(String url) throws IOException {
Bitmap x;
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
MyDownloadTask mdt = new MyDownloadTask();
try{
mdt.execute(connection);
}
catch(Exception ex)
{
Toast.makeText(activity, ex.getMessage(), Toast.LENGTH_SHORT).show();
}
InputStream input = mdt.getInputStream();
x = BitmapFactory.decodeStream(input);
return new BitmapDrawable(x);
}
The implementation part:
Glide.with(this)
.load(ad)
.into(progressImage);
When I'm trying to Glide the AnimationDrawble into the ImageView I get the following exception:
java.lang.IllegalArgumentException: Unknown type class android.graphics.drawable.AnimationDrawable.
This made me hesistate the way I'm trying to pull this off. Should this be this complicated?
If this is the right way, what am I doing wrong? maybe there's another way of doing so? I'd love to get some details. Thanks in advance!
https://github.com/koral--/android-gif-drawable
Not sure if you're open to any 3rd party libraries, but i used this one for gifs before and it worked quite well for me

Error when trying to share an image

So I take a screenshot of my activity, then save it to "screenshot.png". When trying to share it via, let's say, Whatsapp, I get an error: "could not send image". Same with gmail, pushbullet and basically all other apps. Therefore, I conclude that the file somehow exists, but it is either empty, or messed up... I don't know, honestly.
Here's the code:
Taking the activity screenshot:
public Bitmap takeScreenshot() {
View rootView = findViewById(android.R.id.content).getRootView();
rootView.setDrawingCacheEnabled(true);
return rootView.getDrawingCache();
}
Saving the screenshot:
public void saveBitmap(Bitmap bitmap) {
FileOutputStream fos;
String filePath = getApplicationContext().getFilesDir().getPath().toString() + "/screenshot.png";
File f = new File(filePath);
try {
fos = new FileOutputStream(f);
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);
}
}
And finally, the sharing itself:
if (id == R.id.action_share){
Bitmap bitmap = takeScreenshot();
saveBitmap(bitmap);
Intent share = new Intent(Intent.ACTION_SEND);
share.setType("image/png");
share.putExtra(Intent.EXTRA_STREAM, Uri.parse("screenshot.png"));
startActivity(Intent.createChooser(share, "Teilen via"));
}
Where is my error? I don't get any errors in logcat, but I am unable to share the "screenshot".
Firstly, you should use :
share.putExtra(Intent.EXTRA_STREAM. Uri.fromFile(new File(getApplicationContext().getFilesDir().getPath().toString() + "/screenshot.png"));
But you would then get "Permission denied for the attachment" and you possibly would try but with no luck :(
share.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
So probably the best way to deal with this issue is to store the captured screenshot in media library and send the file from there.
public void share() {
String filePath=getApplicationContext().getFilesDir().getPath().toString() + "/screenshot.png";
String path;
try {
path = Images.Media.insertImage(getContentResolver(), filePath, "title", null);
Uri screenshotUri = Uri.parse(path);
Intent share = new Intent(Intent.ACTION_SEND);
share.setType("image/png");
share.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
share.putExtra(Intent.EXTRA_STREAM, screenshotUri);
startActivity(Intent.createChooser(share, "Teilen via"));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
Hope it would help!

Unable to write a txt file to SD card on Android KitKat

I keep trying to write to the SD card in my java code but whenever i check my card the folder and file isnt there; i know that for KitKat you have to use .getExternalFilesDir but so far nothing is working.
my current code:
String DataIn = PhoneNumber + "," + dataLong + "," + dataLat;
File storageDirectory = new File (this.getExternalFilesDir(null), "location.txt");
if(!storageDirectory.exists()) {
try {
storageDirectory.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
String Directory = storageDirectory.toString();
try
{
FileOutputStream fout = new FileOutputStream(storageDirectory, true);
OutputStreamWriter myoutwriter = new OutputStreamWriter(fout);
myoutwriter.write(DataIn);
myoutwriter.close();
Toast.makeText(getBaseContext(),"Saved", Toast.LENGTH_SHORT).show();
}
catch (Exception e)
{
Toast.makeText(getBaseContext(), e.getMessage(), Toast.LENGTH_SHORT).show();
}
Try this:
File storageDirectory = new File(Environment.getExternalStorageDirectory(), "location.txt");
Make sure you have this permission in your manifest:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

No Such Method Exception button error (XML onClick) [duplicate]

This question already has an answer here:
Which is the best way to add a button?
(1 answer)
Closed 8 years ago.
I'm trying to program a button to first create a file them send it using an email provider but i keep getting this error in the logcat:
Caused by: java.lang.NoSuchMethodException: clickedUpdate [class android.view.View]
I'm sure that im getting something truly trivial wrong but i can't seem to find what it is, i've browsed other questions but they don't apply to my case. By the way this code is place above the onCreate method and inside a regular activity.
java:
public void clickedUpdate(Context cn, View view)
{
TextView dLong = (TextView) findViewById (R.id.textLong);
TextView dLat = (TextView) findViewById (R.id.textLat);
String dataLat = dLat.getText().toString();
String dataLong = dLong.getText().toString();
boolean UpdateResume;
if(!(dataLat.equals("") && !(dataLong.equals(""))))
{
UpdateResume = true;
}
else
{
UpdateResume = false;
}
TelephonyManager telephonemanager =(TelephonyManager)cn.getSystemService(Context.TELEPHONY_SERVICE);
String PhoneNumber = telephonemanager.getLine1Number();
File DataDir = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+File.separator+"Android/LocationData");
if(!DataDir.exists())
{
try
{
DataDir.mkdir();
}
catch (Exception e)
{
e.printStackTrace();
}
}
File Data = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+File.separator+"BlogData" + File.separator+"Locationer.txt");
if(!Data.exists()) {
try {
Data.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
while (UpdateResume = true)
{
if (Data.exists())
{
try
{
FileWriter fileWriter = new FileWriter(Data);
BufferedWriter bfWriter = new BufferedWriter(fileWriter);
bfWriter.write(PhoneNumber + "," + dataLat + "," + dataLong);
bfWriter.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
break;
}
}
Intent emailintent = new Intent(Intent.ACTION_SEND);
emailintent.setType("text/plain");
emailintent.putExtra(Intent.EXTRA_EMAIL, new String[]{"xxxxxxxxx#xxxxxxxx.com"});
emailintent.putExtra(Intent.EXTRA_SUBJECT, "Data");
emailintent.putExtra(Intent.EXTRA_TEXT, "Hello World!");
File root = Environment.getExternalStorageDirectory();
String DataAttachment = "Android/LocationData/Locationer.txt";
File filer = new File(root, DataAttachment);
if (!filer.exists() || filer.canRead())
{
return;
}
Uri uri = Uri.fromFile(filer);
emailintent.putExtra(Intent.EXTRA_STREAM, uri);
startActivity(Intent.createChooser(emailintent, "Choose an Email provider"));
}
xml
<Button
android:id="#+id/updatebtn"
android:onClick="clickedUpdate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="#+id/contactbtn"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:background="#drawable/buttonsettings"
android:paddingBottom="80dp"
android:text="#string/updatenow"
android:textColor="#ffffff"
android:textSize="18sp" />
Method signature should be exactly this:
public void clickedUpdate(View view)
And given that you've add another parameter (Context), Android isn't able to find correct method via reflection. Remove it and your code should work.
Your clickedUpdate method can only have the View parameter. If you absolutely need to use the Context variable variable you passed in, you can make it an instance variable in the activity.

Android: Ringtone is being saved, but not set as the Active/Default ringtone

I'm working on an Android application that allows users to long-click on a button to save a sound as a ringtone. I am using the code below to do so. The code currently works to save the file in the list of ringtones to be used, however it does not automatically set the sound as the default ringtone. I have searched all around and not had much luck finding a clear guide on saving a sound as the default/active ringtone.
As of now, the user can long-click the button, then go into the Menu > Sounds > Phone Ringtone menu and select from the list, but that seems a bit inconvenient when I know that it is possible to have it simply set as the active ringtone straight away.
Any insight as to what I am missing? Much appreciated!
public boolean saveas(int ressound){
byte[] buffer=null;
InputStream fIn = getBaseContext().getResources().openRawResource(ressound);
int size=0;
try {
size = fIn.available();
buffer = new byte[size];
fIn.read(buffer);
fIn.close();
} catch (IOException e) {
// TODO Auto-generated catch block
return false;
}
String path="/sdcard/media/audio/ringtones/";
String filename="ADTone"+".ogg";
boolean exists = (new File(path)).exists();
if (!exists){new File(path).mkdirs();}
FileOutputStream save;
try {
save = new FileOutputStream(path+filename);
save.write(buffer);
save.flush();
save.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
return false;
} catch (IOException e) {
// TODO Auto-generated catch block
return false;
}
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://"+path+filename)));
File k = new File(path, filename);
ContentValues values = new ContentValues();
values.put(MediaStore.MediaColumns.DATA, k.getAbsolutePath());
values.put(MediaStore.MediaColumns.TITLE, "AD Ringtone");
values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/ogg");
values.put(MediaStore.Audio.Media.ARTIST, "adtone ");
values.put(MediaStore.Audio.Media.IS_RINGTONE, true);
values.put(MediaStore.Audio.Media.IS_NOTIFICATION, true);
values.put(MediaStore.Audio.Media.IS_ALARM, true);
values.put(MediaStore.Audio.Media.IS_MUSIC, false);
//Insert it into the database
this.getContentResolver().insert(MediaStore.Audio.Media.getContentUriForPath(k.getAbsolutePath()), values);
return true;
}
Not sure if you figured this one out, but I just did recently. Replace your Insert Database line with this:
Uri uri = MediaStore.Audio.Media.getContentUriForPath(k.getAbsolutePath());
getContentResolver().delete(uri, MediaStore.MediaColumns.DATA + "=\"" + k.getAbsolutePath() + "\"", null);
Uri newUri = getContentResolver().insert(uri, values);
RingtoneManager.setActualDefaultRingtoneUri(
YOURACTIVITYNAME.this,
RingtoneManager.TYPE_RINGTONE,
newUri
);

Categories