Any way to unzip file on react-native - react-native

Managed to download .zip file to my filesystem on mobile phone. But after a while realised I can't find a way how to unzip that file. As I tried with:
https://github.com/plrthink/react-native-zip-archive
https://github.com/remobile/react-native-zip
First one dies immidiately after requiring, getting error "Cannot read property 'unzip' of undefined" (followed instructions carefully)
And the second one dies because it's dependant on codrova port to react native which also doesn't work.
Any suggestions or way to solve these problems?
Using react-native 0.35, testing on Note4 with android 5.1.1.

I did manage in the end solve my problem:
using react-native-zip-archive
the solution was to change code inside:
RNZipArchiveModule.java file which is inside module
The changes that needed to be applied are written in this comment:
https://github.com/plrthink/react-native-zip-archive/issues/14#issuecomment-261712319
So credits to hujiudeyang for solving problem.

go to this direction :
node_modules\react-native-zip-archive\android\src\main\java\com\rnziparchive\RNZipArchiveModule.java
and replace this codes instead of unzip method
public static void customUnzip(File zipFile, File targetDirectory) throws IOException {
ZipInputStream zis = new ZipInputStream(
new BufferedInputStream(new FileInputStream(zipFile)));
try {
ZipEntry ze;
int count;
byte[] buffer = new byte[8192];
while ((ze = zis.getNextEntry()) != null) {
File file = new File(targetDirectory, ze.getName());
File dir = ze.isDirectory() ? file : file.getParentFile();
if (!dir.isDirectory() && !dir.mkdirs())
throw new FileNotFoundException("Failed to ensure directory: " +
dir.getAbsolutePath());
if (ze.isDirectory())
continue;
FileOutputStream fout = new FileOutputStream(file);
try {
while ((count = zis.read(buffer)) != -1)
fout.write(buffer, 0, count);
} finally {
fout.close();
}
/* if time should be restored as well
long time = ze.getTime();
if (time > 0)
file.setLastModified(time);
*/
}
} finally {
zis.close();
}
}
//**************************
#ReactMethod
public void unzip(final String zipFilePath, final String destDirectory, final String charset, final Promise promise) {
new Thread(new Runnable() {
#Override
public void run() {
try {
customUnzip(new File(zipFilePath ) , new File(destDirectory));
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}

Related

Is it possible to cancel a call to speakTextAsync?

I'm using the javascript SDK of Microsoft Speech Synthesizer and calling speakTextAsync to convert text to speech.
This works perfectly, but sometimes the text is long and I want to be able to cancel in the middle, but I cannot find any way to do this. The documentation doesn't seem to indicate any way to cancel. The name speakTextAsync suggests that it returns a Task that could be cancelled, but in fact the method returns undefined, and I can't find any other way to do this. How can this be done?
Seems there is no way to stop it when it is speaking. But actually,as a workaround, you can just download the audio file and play the file yourself so that you can control everything. try the code below:
import com.microsoft.cognitiveservices.speech.*;
import com.microsoft.cognitiveservices.speech.audio.AudioConfig;
import java.nio.file.*;
import java.io.*;
import javax.sound.sampled.*;
public class TextToSpeech {
public static void main(String[] args) {
try {
String speechSubscriptionKey = "key";
String serviceRegion = "location";
String audioTempPath = "d://test.wav"; //temp file location
SpeechConfig config = SpeechConfig.fromSubscription(speechSubscriptionKey, serviceRegion);
AudioConfig streamConfig = AudioConfig.fromWavFileOutput(audioTempPath);
SpeechSynthesizer synth = new SpeechSynthesizer(config, streamConfig);
String filePath = "....//test2.txt"; // .txt file for test with long text
Path path = Paths.get(filePath);
String text = Files.readString(path);
synth.SpeakText(text);
Thread thread = new Thread(new Speaker(audioTempPath));
thread.start();
System.out.println("play audio for 8s...");
Thread.sleep(8000);
System.out.println("stop play audio");
thread.stop();
} catch (Exception ex) {
System.out.println("Unexpected exception: " + ex);
assert (false);
System.exit(1);
}
}
}
class Speaker implements Runnable {
private String path;
public String getText(String path) {
return this.path;
}
public Speaker(String path) {
this.path = path;
}
public void run() {
try {
File file = new File(path);
AudioInputStream stream;
AudioFormat format;
DataLine.Info info;
Clip clip;
stream = AudioSystem.getAudioInputStream(file);
format = stream.getFormat();
info = new DataLine.Info(Clip.class, format);
clip = (Clip) AudioSystem.getLine(info);
clip.open(stream);
clip.start();
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}

Read resource file from inside SonarQube Plugin

I am developing a plugin using org.sonarsource.sonarqube:sonar-plugin-api:6.3. I am trying to access a file in my resource folder. The reading works fine in unit testing, but when it is deployed as a jar into sonarqube, it couldn't locate the file.
For example, I have the file Something.txt in src/main/resources. Then, I have the following code
private static final String FILENAME = "Something.txt";
String template = FileUtils.readFile(FILENAME);
where FileUtils.readFile would look like
public String readFile(String filePath) {
try {
return readAsStream(filePath);
} catch (IOException ioException) {
LOGGER.error("Error reading file {}, {}", filePath, ioException.getMessage());
return null;
}
}
private String readAsStream(String filePath) throws IOException {
try (InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(filePath)) {
if (inputStream == null) {
throw new IOException(filePath + " is not found");
} else {
return IOUtils.toString(inputStream, StandardCharsets.UTF_8);
}
}
}
This question is similar with reading a resource file from within a jar. I also have tried with /Something.txt and Something.txt, both does not work.If I put the file Something.txt in the classes folder in sonarqube installation folder, the code will work.
Try this:
File file = new File(getClass().getResource("/Something.txt").toURI());
BufferredReader reader = new BufferedReader(new FileReader(file));
String something = IOUtils.toString(reader);
Your should not use getContextClassLoader(). see Short answer: never use the context class loader!

Osmdroid - from offline folder

I am using OSMdroid to display both online and offline data in my app. The offline data are stored in a .zip file with the required structure.
Is it possible to have these offline tiles stored in a directory (extracted .zip file with the same structure)?
Could somebody please tell me how could I achive this?
Thank you.
I am sorry. I should try more before asking. But I am leaving this question here, somebody could find it useful.
Solution:
New MapTileFileProvider. I called it MapTileFileFolderProvider, it is a lightly modified MapTileFileArchiveProvider. It is using folders instead of archives. The modifications are not perfect, it is a "hot solution" that needs someone more experienced in Java/Android to make it properly.
Benefits from loading Tiles from folders:
Faster loading of tiles (I know, I won't recognize the difference).
Easier updates focused only on changed tiles not whole map plans.
Application can download tiles when is in "online mode" and then use the downloaded Tiles offline.
MapTileFileFolderProvider - only modifications
public class MapTileFileArchiveProvider extends MapTileFileStorageProviderBase
public class MapTileFileFolderProvider extends MapTileFileStorageProviderBase {
private final boolean mSpecificFoldersProvided;
private final ArrayList<String> mFolders = new ArrayList<String>();
private final AtomicReference<ITileSource> mTileSource = new AtomicReference<ITileSource>();
...
}
public MapTileFileArchiveProvider(...)
public MapTileFileFolderProvider(final IRegisterReceiver pRegisterReceiver,
final ITileSource pTileSource,
final String[] pFolders) {
super(pRegisterReceiver, NUMBER_OF_TILE_FILESYSTEM_THREADS,
TILE_FILESYSTEM_MAXIMUM_QUEUE_SIZE);
setTileSource(pTileSource);
if (pFolders == null) {
mSpecificFoldersProvided = false;
findFolders();
} else {
mSpecificFoldersProvided = true;
for (int i = pFolders.length - 1; i >= 0; i--) {
mFolders.add(pFolders[i]);
}
}
}
findArchiveFiles()
private void findFolders() {
mFolders.clear();
if (!getSdCardAvailable()) {
return;
}
String baseDirPath = Environment.getExternalStorageDirectory().toString()+"/ctu_navigator"; // TODO get from Config
File dir=new File(baseDirPath);
final File[] files = dir.listFiles();
if (files != null) {
String fileName;
for (File file : files) {
if (file.isDirectory()) {
fileName = baseDirPath + '/' + file.getName();
mFolders.add(fileName);
Utils.log(PlanTileProviderFactory.class, "Added map source: " + fileName);
}
}
}
}
#Override
protected String getName() {
return "Folders Provider";
}
#Override
protected String getThreadGroupName() {
return "folder";
}
protected class TileLoader extends MapTileModuleProviderBase.TileLoader {
#Override
public Drawable loadTile(final MapTileRequestState pState) {
ITileSource tileSource = mTileSource.get();
if (tileSource == null) {
return null;
}
final MapTile pTile = pState.getMapTile();
// if there's no sdcard then don't do anything
if (!getSdCardAvailable()) {
Utils.log("No sdcard - do nothing for tile: " + pTile);
return null;
}
InputStream inputStream = null;
try {
inputStream = getInputStream(pTile, tileSource);
if (inputStream != null) {
Utils.log("Use tile from folder: " + pTile);
final Drawable drawable = tileSource.getDrawable(inputStream);
return drawable;
}
} catch (final Throwable e) {
Utils.log("Error loading tile");
Utils.logError(getClass(), (Exception) e);
} finally {
if (inputStream != null) {
StreamUtils.closeStream(inputStream);
}
}
return null;
}
private synchronized InputStream getInputStream(final MapTile pTile, final ITileSource tileSource) {
for (final String folder : mFolders) {
final String path = folder + '/' + tileSource.getTileRelativeFilenameString(pTile);
File mapTileFile = new File(path);
InputStream in = null;
try {
in = new BufferedInputStream(new FileInputStream(mapTileFile));
} catch (IOException e) {
//Utils.log("Tile " + pTile + " not found in " + path);
}
if (in != null) {
Utils.log("Found tile " + pTile + " in " + path);
return in;
}
}
Utils.log("Tile " + pTile + " not found.");
return null;
}
}
Well, as far as I understand what you are trying to get... this is more or less what the standard XYTileSource is already doing.
So if you simply use a ready-to-use tile source like this one:
map.setTileSource(TileSourceFactory.MAPNIK);
you will see downloaded tiles files stored in /sdcard/osmdroid/tiles/Mapnik/
The main difference is that it adds a ".tile" extension at the end of each tile file (probably to prevent tools like Android gallery to index all those images).
If you have a ZIP file with tiles ready to use, you could extract them in this directory, and add .tile extension to each tile (355.png => 355.png.tile)
And TileSourceFactory.MAPNIK will be able to use them.

Error: file doesn't exist

Now am working on a project where I need to create a folder in sdcard which am able to do. Also I need to hide/unhide it according to need. The code is working fine on emulator but not in device this is my code what went wrong ?
public class FolderCreate extends MIDlet {
private Form form;
private Display display;
FileConnection fc;
String path;
public void startApp() {
form = new Form("Hello World");
String msg = "Hello World!!!!!!!";
form.append(msg);
display = Display.getDisplay(this);
display.setCurrent(form);
System.out.println("WWWW");
try {
path = System.getProperty("fileconn.dir.memorycard");
System.out.println("Path : "+path+"/sample");
fc = (FileConnection)Connector.open(path+"/ABCD/");
if(!fc.exists())
{
fc.mkdir();
System.out.println("directory created");
}
} catch (IOException e) {
// TODO Auto-generated catch block
//System.out.println("ERROR "+e.getMessage());
Alert alert = new Alert("Alert");
alert.setString(e.getMessage());
display.setCurrent(alert);
}
try
{
//fc = (FileConnection)Connector.open(path+"/sample/");
if(fc.isHidden())
{
fc.setHidden(false);
}
else{
fc.setHidden(true);
}
fc.close();
}
catch (Exception e)
{
Alert alert = new Alert("Alert2");
alert.setString(e.toString());
display.setCurrent(alert);
}
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
System.out.println("Destroyed");
notifyDestroyed();
}
}
The error am getting is: java.io.IOException: file does not exist
Check if path starts with "file://". If not, add the suffix.
path = System.getProperty("fileconn.dir.memorycard");
if (path != null && !path.startsWith("file://")) {
path = "file://" + path;
}
I think you are doing mistake at following line,
path = System.getProperty("fileconn.dir.memorycard");
When you are working with phone and SD-Card you should use e: drive for referring to SD Card as follows,
path = file:///e:/<folder-name>/

org.apache.commons.io.FileCleaningTracker does not delete temp files unless explicitly calling System.gc()?

I am working on a upload image feature for my web app, and am having a strange issue with the "FileCleaningTracker" from apache commons fileupload. I have a ImageUploadService with a instance variable FileCleaningTracker, then I have a upload method that creates an instance of DiskFileItemFactory and then references the FileCleaningTracker, after the upload method completes successfully, I set the FileCleaningTracker of DiskFileItemFactory to null, so i would expect the DiskFileItemFactory to be garbage collected and then the underlying subclass of PhantomReference in FileCleaningTracker will be notified hence delete the temp file the DiskFileItemFactory created.
But that does not happen until I null the DiskFileItemFactory and call System.gc() (only nulling the DiskFileItemFactory does not help) at the end of the upload method. THis seems very strange to me. Here is my code :
#Override
public void upload(final HttpServletRequest request) {
ValidateUtils.checkNotNull(request, "upload request");
final File tmp = new File(this.tempFolder);
if (!tmp.exists()) {
tmp.mkdir();
}
DiskFileItemFactory fileItemFactory = new DiskFileItemFactory(this.sizeThreshold, tmp);
fileItemFactory.setFileCleaningTracker(this.fileCleaningTracker);
ServletFileUpload uploadHandler = new ServletFileUpload(fileItemFactory);
List items;
try {
items = uploadHandler.parseRequest(request);
} catch (final FileUploadException e) {
throw new ImageUploadServiceException("Error parsing the http servlet request for image upload.", e);
}
final Iterator it = items.iterator();
while (it.hasNext()) {
final DiskFileItem item = (DiskFileItem) it.next();
if (item.isFormField()) {
// log message
} else {
final String fileName = item.getName();
final File destination = this.createFileForUpload(fileName, this.uploadFolder);
FileChannel outChannel;
try {
outChannel = new FileOutputStream(destination).getChannel();
} catch (final FileNotFoundException e) {
throw new ImageUploadServiceException(e);
}
FileChannel inChannel = null;
try {
inChannel = new FileInputStream(item.getStoreLocation()).getChannel();
outChannel.transferFrom(inChannel, 0, item.getSize());
} catch (final IOException e) {
throw new ImageUploadServiceException(String.format("Error uploading image to '%s/%s'.", this.uploadFolder, destination.getName()), e);
} finally {
IOUtils.closeChannel(inChannel);
IOUtils.closeChannel(outChannel);
}
}
}
fileItemFactory.setFileCleaningTracker(null);
}
The above code causes every upload creates a file in the temp folder but does not remove it at the end by the "fileCleaningTracker", possibly because the DiskFileItemFactory instance is not garbage collected(I've failed to see why it shouldn't have) or it has been GCed but not notified by the PhantomReference in fileCleaningTracker(how reliable is PhantomReference?)
I waited 10 minutes and the files are still there, so it should't be because the GC has not run. and there are no exceptions.
Now if I add the following code, the temp files are removed every time after the upload:
fileItemFactory = null;
System.gc();
This looks very strange to me as I would expect the fileItemFactory be GCed without an explict call to System.gc().
Any input will be appreciated.
Thank you.
I have the same problem. The temporary files are never removed even after the server shutdown: GC process had not been started so FileCleaningTracker had no chance to get tracked files to delete from ReferenceQueue and all the files remain on the hard drive.
Due to specific behavior of my application I have to clean up after each upload (files might be very big). Instead of using standard org.apache.commons.io.FileCleaningTracker I am feeling lucky to override this class with my own implementation:
/**
* Cleaning tracker to clean files after each upload with special method invocation.
* Not thread safe and must be used with 1 factory = 1 thread policy.
*/
public class DeleteFilesOnEndUploadCleaningTracker extends FileCleaningTracker {
private List<String> filesToDelete = new ArrayList();
public void deleteTemporaryFiles() {
for (String file : filesToDelete) {
new File(file).delete();
}
filesToDelete.clear();
}
#Override
public synchronized void exitWhenFinished() {
deleteTemporaryFiles();
}
#Override
public int getTrackCount() {
return filesToDelete.size();
}
#Override
public void track(File file, Object marker) {
filesToDelete.add(file.getAbsolutePath());
}
#Override
public void track(File file, Object marker, FileDeleteStrategy deleteStrategy) {
filesToDelete.add(file.getAbsolutePath());
}
#Override
public void track(String path, Object marker) {
filesToDelete.add(path);
}
#Override
public void track(String path, Object marker, FileDeleteStrategy deleteStrategy) {
filesToDelete.add(path);
}
}
If this the right case for you just inject the instance of the class above into your DiskFileItemFactory:
DeleteFilesOnEndUploadCleaningTracker tracker = new DeleteFilesOnEndUploadCleaningTracker();
fileItemFactory.setFileCleaningTracker(tracker);
And don't forget to invoke the cleaning method after your work with uploaded items is done:
tracker.deleteTemporaryFiles();
Forgot to mention: I use commons-fileupload version 1.2.2 and commons-io version 1.3.2.