Android - openFileInput() NullPointerException [duplicate] - java

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 3 years ago.
I'm trying to generate a code as string in my android application and save it to a text file. When you press a Share button, the code should be read from the text file and be copied to the clipboard.
I guess I'm not understanding something about acivity/context.
Of course I read in the documentation about it, but I can't figure out the problem. Hope you guys could help me!
FileSystem.java
package com.niclasjaksch.shoppinglist;
import android.content.Context;
import androidx.appcompat.app.AppCompatActivity;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
class FileSystem extends AppCompatActivity {
static String filename = "shoppinglist_code.txt";
void Create() {
try {
FileOutputStream fOut = openFileOutput(filename, Context.MODE_PRIVATE);
String str = Utility.randomString(10);
fOut.write(str.getBytes());
fOut.close();
} catch (IOException e) {
e.printStackTrace();
}
}
String Read() {
String result = "";
try {
FileInputStream fin = openFileInput(filename);
int c;
while( (c = fin.read()) != -1){
result += c;
}
fin.close();
} catch (Exception e) {
System.out.println("An error occurred.");
e.printStackTrace();
}
return result;
}
void Clear() {
try {
File dir = getFilesDir();
File file = new File(dir, filename);
file.delete();
} catch (Exception e) {
System.out.println("An error occurred.");
e.printStackTrace();
}
}
}
Share.java
package com.niclasjaksch.shoppinglist;
import android.content.ClipData;
import androidx.appcompat.app.AppCompatActivity;
class Share extends AppCompatActivity {
android.content.ClipboardManager clipboardManager = null;
FileSystem fs = new FileSystem();
void Share() {
String code = fs.Read();
if(code == "" || code == null) {
fs.Create();
code = fs.Read();
}
ClipData clipData = ClipData.newPlainText("Source Text", code);
clipboardManager.setPrimaryClip(clipData);
}
}
MainActivity.java
...
Share share = new Share();
...
#Override
public boolean onOptionsItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.item_share:
share.Share();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
Getting a NullPointerException in this line:
FileOutputStream fOut = openFileOutput(filename, Context.MODE_PRIVATE);

Only create subclasses of AppCompatActivity for actual UI work, where you will start that activity using startActivity() or startActivityForResult().
Move those methods to a real activity, such as MainActivity, and get rid of the Share and FileSystem classes.

First things first, you shouldn't extend AppCompatActivity for FileSystem and Share.
What's happening is that the openFileOutput is taking the FileSystem object (this) as it's context. When in reality it wouldn't count as a separate activity.
You could either do as CommonWare suggest and remove the classes FileSystem and Share, and move their functions to the MainActivity. Or you could explicitly pass the context from the MainActivity.

Related

JFileChooser showSaveDialog not working sometimes

I'm using Netbeans 7.2 on OS X 10.9. The JFileChooser.showSaveDialog() fails on certain occasions. Before I call the showSaveDialog, I call showOpenDialog to open an .srt file. The show dialog fails only when I open certain files esp. from /Volumes/.. on a mounted device. Here's the code:
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFileChooser;
import javax.swing.filechooser.FileNameExtensionFilter;
import org.apache.commons.io.FilenameUtils;
public class FileSaver extends JFileChooser {
private int result;
private File subFile;
private File save;
private File filename;
private String rectifiedSub;
private FileNameExtensionFilter filter;
public FileSaver(File subFile, String rectifiedSub) {
this.subFile = subFile;
this.rectifiedSub = rectifiedSub;
filename = new File(System.getProperty("user.home"));
filter = new FileNameExtensionFilter("Subtitle Files (*.srt)", "srt");
}
public void createAndShowGUI() {
System.out.println("6");
this.setDialogTitle("Select destination");
System.out.println("6");
this.setCurrentDirectory(filename);
System.out.println("6");
this.setSelectedFile(new File(subFile.getName()));
System.out.println("6");
this.setFileFilter(filter);
System.out.println("6");
result = this.showSaveDialog(this);
System.out.println("6");
if(result == JFileChooser.APPROVE_OPTION) {
save = fixExtension(this.getSelectedFile());
write(save);
}
this.setVisible(true);
}
public void write(File save) {
FileWriter fw = null;
try {
fw = new FileWriter(save);
fw.write(rectifiedSub);
} catch (IOException ex) {
Logger.getLogger(FileSaver.class.getName()).log(Level.SEVERE, null, ex);
} finally {
try {
fw.close();
} catch (IOException ex) {
Logger.getLogger(FileSaver.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
public File fixExtension(File file) {
if(!FilenameUtils.getExtension(file.getName()).equalsIgnoreCase(".srt"))
file = new File(file.getParentFile(), FilenameUtils.getBaseName(file.getName()).concat(".srt"));
return file;
}
}
Output:
6
6
6
6
6
It stops at the 6 before the line result = this.shhowSaveDialog(this);. The program freezes after that and the save dialog doesn't show up. It works perfectly fine on some files. Somebody tell me whats happening ?
Git: https://github.com/Jimmy-666/Subzero.git

Couldn't append the text onto a Google Drive File

I am trying to append text to a text file on the Google Drive. But when I write, it whole file is overwritten. Why can't I just add the text in the end of the file?
DriveFile file = Drive.DriveApi.getFile(mGoogleApiClient, id);
file.open(mGoogleApiClient, DriveFile.MODE_WRITE_ONLY, null).setResultCallback(new ResultCallback<DriveApi.DriveContentsResult>() {
#Override
public void onResult(DriveApi.DriveContentsResult driveContentsResult) {
msg.Log("ContentsOpenedCallBack");
if (!driveContentsResult.getStatus().isSuccess()) {
Log.i("Tag", "On Connected Error");
return;
}
final DriveContents driveContents = driveContentsResult.getDriveContents();
try {
msg.Log("onWrite");
OutputStream outputStream = driveContents.getOutputStream();
Writer writer = new OutputStreamWriter(outputStream);
writer.append(et.getText().toString());
writer.close();
driveContents.commit(mGoogleApiClient, null);
} catch (IOException e) {
e.printStackTrace();
}
}
});
Finally I've found the answer to append the text on the drive document.
DriveContents contents = driveContentsResult.getDriveContents();
try {
String input = et.getText().toString();
ParcelFileDescriptor parcelFileDescriptor = contents.getParcelFileDescriptor();
FileInputStream fileInputStream = new FileInputStream(parcelFileDescriptor
.getFileDescriptor());
// Read to the end of the file.
fileInputStream.read(new byte[fileInputStream.available()]);
// Append to the file.
FileOutputStream fileOutputStream = new FileOutputStream(parcelFileDescriptor
.getFileDescriptor());
Writer writer = new OutputStreamWriter(fileOutputStream);
writer.write("\n"+input);
writer.close();
driveContentsResult.getDriveContents().commit(mGoogleApiClient, null);
} catch (IOException e) {
e.printStackTrace();
}
SO
The reason is that commit's default resolution strategy is to overwrite existing files. Check the API docs and see if there is a way to append changes.
For anyone facing this problem in 2017 :
Google has some methods to append data Here's a link!
Though copying the method from google didn't worked entirely for me , so here is the class which would append data : ( Please note this is a modified version of this code link )
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.preference.PreferenceManager;
import android.util.Log;
import com.google.android.gms.common.api.Result;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.drive.Drive;
import com.google.android.gms.drive.DriveApi.DriveContentsResult;
import com.google.android.gms.drive.DriveApi.DriveIdResult;
import com.google.android.gms.drive.DriveContents;
import com.google.android.gms.drive.DriveFile;
import com.google.android.gms.drive.DriveId;
/**
* An activity to illustrate how to edit contents of a Drive file.
*/
public class EditContentsActivity extends BaseDemoActivity {
private static final String TAG = "EditContentsActivity";
#Override
public void onConnected(Bundle connectionHint) {
super.onConnected(connectionHint);
final ResultCallback<DriveIdResult> idCallback = new ResultCallback<DriveIdResult>() {
#Override
public void onResult(DriveIdResult result) {
if (!result.getStatus().isSuccess()) {
showMessage("Cannot find DriveId. Are you authorized to view this file?");
return;
}
DriveId driveId = result.getDriveId();
DriveFile file = driveId.asDriveFile();
new EditContentsAsyncTask(EditContentsActivity.this).execute(file);
}
};
SharedPreferences sp= PreferenceManager.getDefaultSharedPreferences(EditContentsActivity.this);
Drive.DriveApi.fetchDriveId(getGoogleApiClient(), EXISTING_FILE_ID)
.setResultCallback(idCallback);
}
public class EditContentsAsyncTask extends ApiClientAsyncTask<DriveFile, Void, Boolean> {
public EditContentsAsyncTask(Context context) {
super(context);
}
#Override
protected Boolean doInBackgroundConnected(DriveFile... args) {
DriveFile file = args[0];
SharedPreferences sp=PreferenceManager.getDefaultSharedPreferences(EditContentsActivity.this);
System.out.println("0"+sp.getString("drive_id","1"));
DriveContentsResult driveContentsResult=file.open(getGoogleApiClient(), DriveFile.MODE_READ_WRITE, null).await();
System.out.println("1");
if (!driveContentsResult.getStatus().isSuccess()) {
return false;
}
DriveContents driveContents = driveContentsResult.getDriveContents();
try {
System.out.println("2");
ParcelFileDescriptor parcelFileDescriptor = driveContents.getParcelFileDescriptor();
FileInputStream fileInputStream = new FileInputStream(parcelFileDescriptor
.getFileDescriptor());
// Read to the end of the file.
fileInputStream.read(new byte[fileInputStream.available()]);
System.out.println("3");
// Append to the file.
FileOutputStream fileOutputStream = new FileOutputStream(parcelFileDescriptor
.getFileDescriptor());
Writer writer = new OutputStreamWriter(fileOutputStream);
writer.write("hello world");
writer.close();
System.out.println("4");
driveContents.commit(getGoogleApiClient(), null).await();
return true;
} catch (IOException e) {
e.printStackTrace();
}
return false;
};
#Override
protected void onPostExecute(Boolean result) {
if (!result) {
showMessage("Error while editing contents");
return;
}
showMessage("Successfully edited contents");
}
}
}
Existing_File_id is the resource id. Here is one link if you need resource id a link

Calling Java Method from Javascript in Android Project - PhoneGap

I have the following Java Class
package com.phonegap.plugins.video;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import org.json.JSONArray;
import org.json.JSONException;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import org.apache.cordova.api.CallbackContext;
import org.apache.cordova.api.CordovaPlugin;
import org.apache.cordova.api.PluginResult;
public class VideoPlayer extends CordovaPlugin {
private static final String YOU_TUBE = "youtube.com";
private static final String ASSETS = "file:///android_asset/";
#Override
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) {
PluginResult.Status status = PluginResult.Status.OK;
String result = "";
//this.greatMethod();
try {
if (action.equals("playVideo")) {
playVideo(args.getString(0));
}
else {
status = PluginResult.Status.INVALID_ACTION;
}
callbackContext.sendPluginResult(new PluginResult(status, result));
} catch (JSONException e) {
callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION));
} catch (IOException e) {
callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.IO_EXCEPTION));
}
return true;
}
private void playVideo(String url) throws IOException {
if (url.contains("bit.ly/") || url.contains("goo.gl/") || url.contains("tinyurl.com/") || url.contains("youtu.be/")) {
//support for google / bitly / tinyurl / youtube shortens
URLConnection con = new URL(url).openConnection();
con.connect();
InputStream is = con.getInputStream();
//new redirected url
url = con.getURL().toString();
is.close();
}
// Create URI
Uri uri = Uri.parse(url);
Intent intent = null;
// Check to see if someone is trying to play a YouTube page.
if (url.contains(YOU_TUBE)) {
// If we don't do it this way you don't have the option for youtube
uri = Uri.parse("vnd.youtube:" + uri.getQueryParameter("v"));
if (isYouTubeInstalled()) {
intent = new Intent(Intent.ACTION_VIEW, uri);
} else {
intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("market://details?id=com.google.android.youtube"));
}
} else if(url.contains(ASSETS)) {
// get file path in assets folder
String filepath = url.replace(ASSETS, "");
// get actual filename from path as command to write to internal storage doesn't like folders
String filename = filepath.substring(filepath.lastIndexOf("/")+1, filepath.length());
// Don't copy the file if it already exists
File fp = new File(this.cordova.getActivity().getFilesDir() + "/" + filename);
if (!fp.exists()) {
this.copy(filepath, filename);
}
// change uri to be to the new file in internal storage
uri = Uri.parse("file://" + this.cordova.getActivity().getFilesDir() + "/" + filename);
//return uri; /*NEED TO RETUNRN THE URI TO THE CALLED TO GIVE THEMENEW LOCATION OF THE FILE CREATED BY THIS CLASS*/
// Display video player
intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(uri, "video/mp4");
} else {
// Display video player
intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(uri, "video/mp4");
}
this.cordova.getActivity().startActivity(intent);
}
private void copy(String fileFrom, String fileTo) throws IOException {
// get file to be copied from assets
InputStream in = this.cordova.getActivity().getAssets().open(fileFrom);
// get file where copied too, in internal storage.
// must be MODE_WORLD_READABLE or Android can't play it
FileOutputStream out = this.cordova.getActivity().openFileOutput(fileTo, Context.MODE_WORLD_READABLE);
// Transfer bytes from in to out
byte[] buf = new byte[8192];
int len;
while ((len = in.read(buf)) > 0)
out.write(buf, 0, len);
in.close();
out.flush();
out.close();
}
private boolean isYouTubeInstalled() {
PackageManager pm = this.cordova.getActivity().getPackageManager();
try {
pm.getPackageInfo("com.google.android.youtube", PackageManager.GET_ACTIVITIES);
return true;
} catch (PackageManager.NameNotFoundException e) {
return false;
}
}
public String greatMethod(){
System.out.println("Great Method return");
return "great";
}
}
I have following in my config.xml file
<plugin name="VideoPlayer" value="com.phonegap.plugins.video.VideoPlayer"/>
I want to call say the 'greatMethod' from the javascript file. how do I do that. calling the play method like following works but calling other methods do not work and the play method is not even in the given class.
WORKS:
window.plugins.videoPlayer.play("file:///android_asset/www/videos/myVideo.mp4")
DOES NOT WORK:
alert(window.plugins.videoPlayer.greatMethod());
Any help will be much appreciated.
Have you add greatMethod method into JavaScript PhoneGap object?
Just like following JavaScript code
var videoPlayer=function(){};
videoPlayer.prototype.greatMethod = function(params, success, fail){
return PhoneGap.exec(
function(args){
success(args);
},
function(args){
fail(args);
},
'VideoPlayer',
'greatMethod'
);
};
PhoneGap.addConstructor(function() {
PhoneGap.addPlugin('videoPlayer', new videoPlayer());
});

Android External File Inconsistently Appearing

I'm using an IntentService to append single NMEA strings to a log file stored in the external public storage on an Android device, but I'm getting inconsistent behavior.
First off the log file does not appear when the device is connected for USB debugging. I read that many Android devices cannot write to external storage when connected via USB, but even when it is run disconnected from USB, it may take several times of turning it on and off and rerunning the applications before the log file appears in the file system. If I do not clear the log, I still have to restart the phone before it will begin appending to the file again.
How can I get the file to appear consistently everytime?
import android.app.IntentService;
import android.content.Intent;
public class LogFileService extends IntentService {
DebugLog debug = new DebugLog("LogFileService");
public static final String GPS_STR = "GPS_STR";
public static final String FILE_PATH = "FILE_PATH";
public static final String FILE_NAME = "gps_data.txt";
public LogFileService() {
super("LogFileService");
}
#Override
protected void onHandleIntent(Intent intent) {
debug.log("Handling intent");
String data = intent.getStringExtra(GPS_STR);
debug.log("Writing " + data);
GpsLogFile logFile = new GpsLogFile(FILE_NAME);
logFile.open();
logFile.write(data);
logFile.close();
}
#Override
public void onCreate() {
super.onCreate();
debug.log("Created");
}
}
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import android.content.Context;
import android.os.Environment;
public class GpsLogFile {
DebugLog debug = new DebugLog("LogFile");
private File filePath = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DOWNLOADS
);
private File logFile = null;
private String fileName = null;
private PrintWriter fileOut = null;
public GpsLogFile(String name) {
fileName = name;
}
public void open() {
try {
filePath.mkdirs();
if (!isExternalMediaAvailable()) {
throw new IOException("External media not available.");
}
logFile = new File(filePath, fileName);
//logFile.mkdirs();
if (!logFile.exists()) {
logFile.createNewFile();
}
fileOut = new PrintWriter(
new FileOutputStream(logFile.getAbsolutePath(), true)
);
} catch (IOException e) {
debug.log("Unable to open file.");
debug.log(e.getMessage());
}
}
public void write(String data) {
debug.log("Writing to " + logFile.getAbsolutePath() + " " + data);
try {
fileOut.write(data);
//fileOut.newLine();
checkPrintWriterError(fileOut);
fileOut.flush();
} catch (IOException e) {
debug.log("Unable to write");
debug.log(e.getMessage());
}
}
public void close() {
if (null != fileOut) {
try {
fileOut.close();
checkPrintWriterError(fileOut);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private void checkPrintWriterError(PrintWriter writer) throws IOException {
if (true == writer.checkError()) {
throw new IOException("Print writer error.");
}
}
}

Writing Console Output to File in Java

So I was wondering if it was possible to write all the console output to a separate file outside of Java? I know about the Printwriter and Filewriter method. However, in my experience those would work if I was using them all within one method, but I don't think I can do that with the code I have right now. Below is what I have...
Java Code
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
public class XMLTagParser extends DefaultHandler
{
private int i;
public XMLTagParser()
{
traverse(new File("C:/Documents and Settings/user/workspace/Intern Project/Proposals/Converted Proposals/Extracted Items"));
}
private static final class SaxHandler extends DefaultHandler
{
private StringBuffer buffer;
private String heading;
private boolean inHeading;
public void startElement(String uri, String localName, String qName, Attributes attrs)
{
if ("w:pStyle".equals(qName))
{
String val = attrs.getValue("w:val");
if (val.contains("Heading"))
{
if (isHeading(val))
{
System.out.println(val);
inHeading = true;
}
}
}
if("w:t".equals(qName))
{
if (inHeading == true)
{
buffer = new StringBuffer();
}
}
}
public void characters(char buff[], int offset, int length) throws SAXException
{
String s = new String(buff, offset, length);
if(buffer != null)
{
buffer.append(s);
heading = heading += s;
}
}
public void endElement(String uri, String localName, String qName)
{
buffer = null;
//if the qName is "w:p" and it is in the heading, print out the heading and then reset
if ("w:p".equals(qName) && inHeading == true)
{
System.out.println(heading);
heading = "";
inHeading = false;
}
}
// method to verify whether element is an actual heading
private static boolean isHeading(String heading)
{
String headingNumber = heading.substring(7,8);
String headingName = heading.substring(0,7);
if (headingName.equals("Heading"))
{
if (headingNumber.equals("1")
|| headingNumber.equals("2")
|| headingNumber.equals("3")
|| headingNumber.equals("4")
|| headingNumber.equals("5")
|| headingNumber.equals("6"))
{
return true;
}
}
return false;
}
}
/*private void writeFile(File file)
{
try
{
PrintWriter out = new PrintWriter(new FileWriter(file + "/" + i++));
out.close();
}
catch (IOException e)
{
e.printStackTrace(System.out);
}
}*/
private void traverse(File directory)
{
//Get all files in directory
File[] files = directory.listFiles();
for (File file : files)
{
if (file.getName().equals("document.xml"))
{
try
{
// creates and returns new instance of SAX-implementation:
SAXParserFactory factory = SAXParserFactory.newInstance();
// create SAX-parser...
SAXParser parser = factory.newSAXParser();
// prints out the current working proposal, traversing up the directory structure
System.out.println(file.getParentFile().getParentFile().getName());
// .. define our handler:
SaxHandler handler = new SaxHandler();
// and parse:
parser.parse(file.getAbsolutePath(), handler);
try
{
// instantiates new printwriter which writes out to a file
PrintWriter out = new PrintWriter(new FileWriter(file.getParentFile().getParentFile() + "/" + i++ + ".txt"));
out.close();
}
catch (IOException e)
{
e.printStackTrace(System.out);
}
}
catch (Exception ex)
{
ex.printStackTrace(System.out);
}
}
else if (file.isDirectory())
{
//It's a directory so (recursively) traverse it
traverse(file);
}
}
}
}
So I've instantiated the printwriter in there, but obviously it's no good if I have nothing to write to it. So I'm not really sure how I can get what's printing out the console to be written to that file. Any ideas? Thanks in advance.
If you really want to you can redirect System.out to any PrintStream like this:
PrintStream stream = new PrintStream("filename.txt");
System.setOut(stream);
If you get into rolling your own file logger you'll spend more time dealing with io issues, rolling files, file sizes, ect. You should use log4j instead! It will handle things like this and make your logging more flexible. It's pretty much the standard for java logging.
The System.out is basically an OutputStream; which by default points to the console. Instead, you could just create a new FileOutputStream instance pointing to the file of your choice, and identify this stream by setting it through System.setOut. That will do it for you, throughout the life-cycle of the program/application. Check this link for a complete code.
Instead of using System.out, you could use a FileWriter, write to it and flush it. It is unclear, why you increment i in your code. I guess you want to write everything to just one file.
Also, it looks like you never write to the Writer that you initialize.
You could keep using System.out, and redirect it using ">" to the file when you invoke the application. You can still retain stderr for direct console output.
Or do you mean something else when you write "outside java"?

Categories

Resources