I have java desktop application where I have file upload and view feature.
Here is my code for opening a file
public static boolean open(File file) {
OSDetector osdetector = new OSDetector();
try {
if (osdetector.isWindows()) {
Runtime.getRuntime().exec(new String[]{"rundll32", "url.dll,FileProtocolHandler",
file.getAbsolutePath()});
return true;
} else if (osdetector.isLinux() || osdetector.isMac()) {
Runtime.getRuntime().exec(new String[]{"/usr/bin/open",
file.getAbsolutePath()});
return true;
} else // Unknown OS, try with desktop
if (Desktop.isDesktopSupported()) {
Desktop.getDesktop().open(file);
return true;
} else {
return false;
}
} catch (Exception e) {
e.printStackTrace(System.err);
return false;
}
}
This is perfectly working in MAC OS but when I am running in windows 7 PC it won't open files.
Following are the error messages;
Adobe reader error: "There was an error opening this document. This file is already open or in use by another application"
Windows Photo viewer error message: "Windows photo viewer can't open this picture because the picture is being edited in another program"
Paint error message: "A sharing violation occurred while accessing ....."
Please help
Thank You
Windows can't cope with the idea of two programs using a file at once, presumably due to its DOS single-user origins. Make sure that when you save the file, you close it before you call your open() method.
Related
Running my Java application with this code:
if (Desktop.isDesktopSupported())
{
Desktop d = Desktop.getDesktop();
try
{
d.browse(new URI("someurl")); // someurl is just an example, I am opening real url
}
catch (IOException | URISyntaxException e)
{
logger.warn(ExceptionUtils.getStackTrace(e));
}
}
results in application not responding (probably deadlock) on Manjaro Linux KDE. While it works with no problem on Windows, I do not want to check for OS in my application and allow it just for Windows. I have not tried other platforms yet.
What i use:
Adoptium JDK 11
Manjaro kernel 5.10.83-1-MANJARO 64bit
KDE Plasma 5.23.4
Qt 5.15.2
Detailed deadlock location:
Desktop class:
public void browse(URI uri) throws IOException {
checkAWTPermission();
checkExec();
checkActionSupport(Action.BROWSE);
Objects.requireNonNull(uri);
peer.browse(uri); // <- goes here
}
Deadlock happens in XDesktopPeer class that implements DesktopPeer interface (peer) on method gnome_url_show(...):
private void launch(URI uri) throws IOException {
byte[] uriByteArray = ( uri.toString() + '\0' ).getBytes();
boolean result = false;
XToolkit.awtLock();
try {
if (!nativeLibraryLoaded) {
throw new IOException("Failed to load native libraries.");
}
result = gnome_url_show(uriByteArray); // <- deadlock / app not responding here
} finally {
XToolkit.awtUnlock();
}
if (!result) {
throw new IOException("Failed to show URI:" + uri);
}
}
So... is Desktop#browse supported on Linux platform just for Gnome desktop?
I am guessing this, because of that method name.
If yes, can I make a check for deadlock around my code, so I prevent this in my app? rather than checking for OS and distros?
There are already several questions on SO about that issue:
Desktop.getDesktop().browse Hangs
Desktop and desktop.browse are supported, but browse still hangs
Desktop browse does not work in java for Ubuntu
There is also this discussion:
https://bugs.launchpad.net/ubuntu/+source/openjdk-8/+bug/1574879
where someone says:
gnome_url_show is actually in libgnome-2-0 package
So, if the package is missing, Desktop.browse() will fail. There are 2 solutions to fix that.
Solution 1
Install the libgnome package.
Solution 2
Execute xdg-open to open the URL, e.g.:
Runtime.getRuntime().exec(new String[]{"xdg-open", someurl});
I've finished an app and have been attempting to have that app log some data in a text file. I have a few questions about creating files and file paths with Android Studio. I'm not well versed in the editor so perhaps my questions are simple. I'm logging the data in an activity that extends MainActivity, declared as LoggerActivity.
public class LoggerActvitivty extends MainActivity{
public boolean bNewUser = true;
public String sFileName;
public void writeToFile(HashMap hmSaleToSave) {
if (bNewUser) {
System.out.println(hmSaleToSave);
sFileName = Environment.DIRECTORY_DOWNLOADS + "/Sales-" + LocalDateTime.now() + ".txt";
try {
if(!Files.exists(Paths.get(sFileName))) {
Files.createFile(Paths.get(sFileName));
Files.write(Paths.get(sFileName), sFileName.getBytes(StandardCharsets.UTF_8));
}
System.out.println("FILE WRITE EXECUTED");
System.out.println("Location" + sFileName);
} catch (IOException e) {
e.printStackTrace();
}
} else {
}
}
}
Nothing crash's, but I believe I'm providing a null directory resulting in this logcat error
W/System.err: java.nio.file.NoSuchFileException: Download/Sales-2021-08-16T07:44:36.321.txt
I would like the logs to go to my tablets download directory. My first question is should I be using a different method to get my directory rather than through Enviornment.DIRECTORY_DOWNLOADS? Additionally if the path doesn't exist Files.createFile(....) should create the path too? Or does that just create the file at the specified path (sFileName)?
I am trying to write a text file to internal storage of my android application. But it is not possible for me to see if the file is generated or not.
My text file is stored in the following path:
data/data/"MyApplcationPackageName"/files/MyFile.txt
Permission : drwxrwx-x
I have tried the following things -
1) Using device file explorer:
Device file explorer does not open my application package. it gives following error if I try to open it.
Device File Explorer
2) Terminal:
I have also tried opening it using adb in the terminal. But when I try to open files inside my application package it says permission denied.
adb terminal
Please let me know how I can open my text file for debugging. Thanks in advance.
public static void StoreDB() {
if(isExternalStorageWritable() && checkPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
File file = getFinalDir();
try {
FileOutputStream fos = new FileOutputStream(file);
fos.write("something".getBytes());
fos.close();
ToastUtil.showToast(Resource.getAppContext(),"File Saved");
} catch (IOException e) {
Log.e("StoreDB", "Exception");
e.printStackTrace();
}
}
}
public static boolean isExternalStorageWritable() {
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
Log.d("External storage", "Writable");
return true;
}
Log.d("External storage", "Not Writable");
return false;
}
public static boolean checkPermission(String Permission){
int check = ContextCompat.checkSelfPermission(Resource.getAppContext(),Permission);
boolean Perm = (check == PackageManager.PERMISSION_GRANTED);
Log.d("Check Permission", "Result: " + Perm);
return Perm;
}
private static File getFinalDir() {
return createDirIfNotExist(Environment.getExternalStorageDirectory().getPath() + "/Co_Ordinate.txt/");
}
public static File createDirIfNotExist(String path) {
File dir = new File(path);
if (!dir.exists()) {
dir.mkdirs();
}
return dir;
}
Now I am trying to put the file in external storage. Above code always gives IO exception.
You need to root your phone to view those files. Or you can do it on an emulator by using the Device File Explorer.
EDIT: Or just use an unprotected file path. This will create the directory. After that you just need to save the .txt file to that directory.
private static File getFinalDir() {
return createDirIfNotExist(Environment.getExternalStorageDirectory().getPath() + "/MyAppName/");
}
public static File createDirIfNotExist(String path) {
File dir = new File(path);
if (!dir.exists()) {
dir.mkdirs();
}
return dir;
}
You can do this with Emulator. Run your app in emulator and go to Android Device monitor
Choose device, go to File Explorer menu and search your text file in data folder
My Java app will detect file extension and open it in Windows using wordpad, like this :
public static Process Display_File(String File_Path)
{
String Command,Program,Suffix=File_Path.toLowerCase();
Process process=null;
if (Suffix.endsWith("txt") || Suffix.endsWith("json")) Program="C:\\Program Files (x86)\\Windows NT\\Accessories\\word_pad.exe ";
Command=Program+"\""+File_Path+"\"";
try { process=Runtime.getRuntime().exec(Command); }
catch (Exception e) { e.printStackTrace(); }
return process;
}
But it won't work on Mac, I know there is TextEdit.app on Mac, so how to change the above code to run it on Mac ?
After the change, it looks like this :
public static Process Display_File_On_Mac(String File_Path)
{
String Command,Program,Suffix=File_Path.toLowerCase();
Process process=null;
if (Suffix.endsWith("txt") || Suffix.endsWith("json")) Program="/Applications/TextEdit.app ";
Command=Program+"\""+File_Path+"\"";
try { process=Runtime.getRuntime().exec(Command); }
catch (Exception e) { e.printStackTrace(); }
return process;
}
But I got this error :
java.io.IOException: Cannot run program "/Applications/TextEdit.app": error=13, Permission denied
How to fix it ?
Starting macOS Catalina system applications moved to /System/Applicatyions folder: https://support.apple.com/HT210650
So, new path to TextEdit is /System/Applications/TextEdit.app/Contents/MacOS/TextEdit
On El-capitan, giving the below path worked for me:
Program="open /Applications/TextEdit.app/Contents/MacOS/TextEdit";
You can Navigate into the TextEdit.app folder from a terminal window and make sure you have the executable in the right place before trying it out.
Also, you need to change the setting of command like this:
Command = Program+ " "+File_Path;
I'm creating a Java application using Netbeans. From the 'Help' Menu item, I'm required to open a PDF file. When I run the application via Netbeans, the document opens, but on opening via the jar file, it isn't opening. Is there anything that can be done?
m_aboutItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Runtime rt = Runtime.getRuntime();
URL link2=getClass().getResource("/newpkg/Documentation.pdf");
String link=link2.toString();
link=link.substring(6);
System.out.println(link);
System.out.println(link2);
String link3="E:/new/build/classes/newpkg/Documentation.pdf";
try {
Process proc = rt.exec("rundll32.exe url.dll,FileProtocolHandler " + link3);
} catch (IOException ex) {
Logger.getLogger(Menubar1.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
The two outputs are as follows:
E:/new/build/classes/newpkg/Documentation.pdf
file:/E:/new/build/classes/newpkg/Documentation.pdf
Consider the above code snippet. On printing 'link',we can see that it is exactly same as the hard coded 'link3'. On using the hard coded 'link3' , the PDF file gets opened from jar application. But when we use link, though it is exactly same as 'link3', the PDF doesn't open.
This is most likely related to the incorrect PDF resource loading. In the IDE you have the PDF file either as part of the project structure or with a directly specified relative path. When a packaged application is running it does not see the resource.
EDIT:
Your code reveals the problem as I have described. The following method could be used to properly identify resource path.
public static URL getURL(final String pathAndFileName) {
return Thread.currentThread().getContextClassLoader().getResource(pathAndFileName);
}
Pls refer to this question, which might provide additional information.
Try out this:
m_aboutItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (Desktop.isDesktopSupported()) {
Desktop desktop = Desktop.getDesktop();
URL link2=Menubar1.class.getResource("/newpkg/Documentation.pdf");
String link=link2.toString();
link=link.substring(6);
System.out.println(link);
File file=new File(link);
System.out.println(file);
try {
desktop.open(file);
} catch (IOException ex) {
Logger.getLogger(Menubar1.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
});