Dropbox now have an apsolutely new API, which is absolutely differ from the old one (it's interesting why), but there's no ANY actual examples in the internet, so I've found only some code in their examples. Here is it:
// Download the file.
try (OutputStream outputStream = new FileOutputStream (file)) {
mDbxClient.files ()
.download (metadata.getPathLower (), metadata.getRev ())
.download (outputStream);
}
I need to download file from remote folder to the local one, so I need to use this path for example:
.download ("Backups/backup.ab", "/storage/sdcard/Folder/backup.ab")
I've tried it, but get a error
IllegalArgumentException: String 'rev' does not match pattern'
Do you know, what it can be, and metadata.getPathLower () and metadata.getRev () methods are using for? I've learned, that metadata var gets from the first argv from execute (), but what this functions do?
Thanks a lot!
Not sure if if works for android. I have posted the following method just in case someone is looking for a C# .net solution.
private async Task Download(DropboxClient dbx, string folder, string file, string localFilePath)
{
using (var response = await dbx.Files.DownloadAsync(folder + "/" + file))
{
using (var fileStream = File.Create(localFilePath))
{
(await response.GetContentAsStreamAsync()).CopyTo(fileStream);
}
}
}
Parameter example:
file = "YourFileName.pdf";
folder = "/YourDropboxFolderName";
localFilePath = #"C:\Users\YourUserName\YourFileName.pdf";
The Dropbox API v2 Java SDK's download method takes these two parameters:
String path
String rev
Per the download method documentation there, the first is the remote path of the file in Dropbox you want to download, and the second is the identifier for the revision of the file you want. The second parameter is not the local path where you want to save the file, as it appears you're supplying in your code. Instead, you save the file content using the .download (outputStream); portion of the sample code you posted, e.g., as also shown in this sample code.
Also, as stated in the documentation, the second parameter is deprecated and should no longer be used. You can just use the version of the download method that only takes the one parameter. The code for using it is otherwise the same as the sample.
For reference, in the sample, the metadata object is an instance of FileMetadata. You can find more information on the getPathLower and getRev methods in the documentation as well.
Related
I'm using Xamarin, C# and Monogame and I'm taking a fully-working Desktop game and porting it over to Android.
My problem is that I have this "Content folder" that you would always use in the Desktop version of the app. But I cannot access it or any other folder through the code directly using Android.
basicShader = new Effect(game1.GraphicsDevice,System.IO.File.ReadAllBytes("Content/TextureShader.mgfxo"));
This works just fine in the Desktop app but throws System.IO.DirectoryNotFoundException:'Could not find a part of the path "/Content/TextureShader.mgfxo".' on Android.
I'd like to mention that I already had the code and the project working perfectly when it was a desktop program. I also have a private class-level variable string[] list_of_files and in the constructor, I had the line list_of_files = Directory.GetFiles("./Content","*.txt");
This is for saving and loading player data. It may have been rudimentary but I had a fully functioning program that saved and loaded data on my computer. I am transitioning this program to be an Android app and this is the only part of the project that isn't working. When I run the code as it was originally written, I get "System.IO.DirectoryNotFoundException: 'Could not find a part of the path '/Content'.' ".
I've tried playing around with trying to read the contents of different folders.
I've messed around with different paths, including the Resources folder instead.
I added <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> to my manifest.
I know that I'm trying to access internal storage, not external, so I also tried <uses-permission android:name="android.permission.READ_INTERNAL_STORAGE" /> just to see if that might work.
Nothing works.
In another stack overflow post, a guy commented:
For the people who are facing NullPointerException - you are trying to access the files in the app's internal storage which are private sorry you can't do that. –
coderpc
Jun 23, 2017 at 16:00
I cannot imagine why this would be true. Why would a programmer not be able to write a program that can access it's own internal storage? That makes no sense to me. Obviously my app needs to be able to read and write it's own internal storage! And if this is true, then how else can I save persistent data on my phone? I don't want a database or a shared thingamabobber that uses key-value pairs, I have a self-made system that works as a text file and I want to continue to use it. I refuse to believe that an Android app can't keep track of a simple .txt file in one of it's own folders, that's just too hard for me to imagine. It can't be true.
I wanted to ask the commenter about his comment but Stack Overflow wouldn't let me because I don't have over 50xp.
Just like CommonsWare sayed, you can use the Intent.ActionOpenDocument to get the uri of the file. Such as
static readonly int READ_REQUEST_CODE = 1337;
Intent intent = new Intent(Intent.ActionOpenDocument);
intent.AddCategory(Intent.CategoryOpenable);
intent.SetType("*/*");
StartActivityForResult(intent, READ_REQUEST_CODE);
And override the OnActivityResult method:
if (requestCode == READ_REQUEST_CODE && resultCode == Result.Ok)
{
// The document selected by the user won't be returned in the intent.
// Instead, a URI to that document will be contained in the return intent
// provided to this method as a parameter. Pull that uri using "resultData.getData()"
if (data != null)
{
Android.Net.Uri uri = data.Data;
DocumentFile documentFile = DocumentFile.FromSingleUri(this.ApplicationContext,uri);
// Then you can operate the file with input and output stream
}
}
More information please check the simple on the github:
https://github.com/xamarin/monodroid-samples/blob/main/StorageClient/StorageClientFragment.cs
In addition, if you can ensure the file's path. You can use the StreamWriter and the StreamReader to write and read the file. Such as:
using (StreamWriter sw = new StreamWriter(path))
{
sw.WriteLine(content);
}
Furthermore, you can try to create the content folder and the txt file in the Android with the following code.
var filename1 = Android.App.Application.Context.GetExternalFilesDir(System.DateTime.Now.ToString("Content")).AbsolutePath;
var filename = System.IO.Path.Combine(filename1, "xxx.txt");
using (System.IO.FileStream os = new System.IO.FileStream(filename, System.IO.FileMode.Create))
{
}
The folder and the files created by this way belongs to the app and you can access it easily.
You can read the official document about the storage in the Android.
Link : https://developer.android.com/training/data-storage/shared/documents-files
I am using unity 2019.2.14f1 and visual studio 2019.I also tried with ICSharpCode.SharpZipLib but can't find any solution.I am trying with the code from the code which is available in the following url:
Unzip a memorystream (Contains the zip file) and get the files
Thanks in advance.
You can download files in Unity using UnityWebRequest.Get. Note that using it like in the example shown on that page, you're going to want to make sure you know how to use Unity's Coroutines.
Also, instead of downloadHandler.text you're going to want to use downloadHandler.data to get the downloaded data as bytes you can put into a stream.
Once you've got those you can use the appropriate libraries or standard library calls to unzip your files.
To download a file from a URL you can use system.net
WebClient client = new WebClient();
client.DownloadFile("http://whateverlinkyouhave.zip", #"C:\whateverlinkyouhave.zip")
Everyone's answer is correct, especially using UnityWebRequest. One of things you must do is to turn the byte[] data to zip file. And then use some Unzip library.
Example implementation
using System;
using UnityEngine.Networking;
private IEnumerator DownloadZipFile(string url)
{
using (UnityWebRequest www = UnityWebRequest.Get(url))
{
yield return www.Send();
if (www.isNetworkError || www.isHttpError)
{
Debug.Log(www.error);
}
else
{
string savePath = string savePath = string.Format("{0}/{1}.zip", Application.persistentDataPath, "zip_file_name");
System.IO.File.WriteAllBytes(savePath, www.downloadHandler.data);
}
}
}
Hope it helps.
Im currently trying to save some values in a text file in Processing Android (APDE). I want to later use this in another context, so it's important to use a complete file path. From Processing documentation for loadStrings():
... Alternatively, the file maybe be loaded from anywhere on the local
computer using an absolute path (something that starts with / on Unix
and Linux, or a drive letter on Windows)
So it must be possible.
I already searched for a answer, but never found something for Processing.
So my code is:
String[] saveData;
int score;
void setup(){
saveData=loadStrings("/storage/emulated/0/dataP/hi.txt");
score=parseInt(saveData[0]);
fullScreen();
frameRate(60);
noStroke();
noSmooth();
textAlign(CENTER);
textSize(height/20);
}
void draw(){
background(0);
fill(255) ;
text(score, width/2,height/2);
}
void mousePressed(){
score--;
saveData[0]=str(score);
println(saveData[0]);
saveStrings("/storage/emulated/0/hi.txt" ,saveData);
}
and I get the following error:
java.lang.IllegalArgumentException: File
/storage/emulated/0/dataP/hi.txt contains a path separator
I believe the confusion stems from the fact that loadStrings() method works differently for Java mode and Android mode. In Java mode, it is definitely possible to give loadStrings() an absolute Path with included separators, but in Android mode, loadStrings() will only work if you only specify a name without any separator (assumes by default to be looking into the data folder). Therefore, having any separator inside loadStrings() will throw the error.
One simple workaround you can try is to first create a separate path variable:
String path = "/storage/emulated/0/dataP/hi.txt";
And then give that as parameter to the loadStrings() method:
saveData = loadStrings(path);
If you were to use an SD card for storage, for example, you could do something like:
String SDCARD = Environment.getExternalStorageDirectory().getAbsolutePath();
File file = new File(SDCARD + File.separator + "mytext.txt");
String[] s = loadStrings(file.getPath());
As explained in the link in the comment I posted, loadStrings() and saveStrings() does not take absolute path as argument. What it means is that it can only access files with path "name.txt" and not "folder/name.txt". You have to do it using a FileInputStream and FileOutputStream if you must use absolute path. There are many examples of both these files on StackOverflow.
I have some level definitions in xml format (with .txt extension) inside (without any subfolders) my project's rescources folder
I for more scalability, I have a plain text file naming all these level definition XMLs
I read that file using
TextAsset WorldList = (TextAsset)Resources.Load("WorldList");
And then I load the needed world:
TextAsset TA = (TextAsset)Resources.Load(/*"LevelDefs/" +*/ Worlds[worldToload]);
xps.parseXml(TA.text);
loadLevel(levelToLoad);
(you see that I have moved these rescources out of subfolder to reduce the chance of them not loading)
worldToload here is the index number of that world
program works fine on windows but nothing loads on my android test device.
I seem to have problems debugging on device so I only guess something went wrong in loading phase.
any suggestions?
From Unity Documentation:
Most assets in Unity are combined into the project when it is built.
However, it is sometimes useful to place files into the normal
filesystem on the target machine to make them accessible via a
pathname. An example of this is the deployment of a movie file on iOS
devices; the original movie file must be available from a location in
the filesystem to be played by the PlayMovie function.
Any files placed in a folder called StreamingAssets in a Unity project
will be copied verbatim to a particular folder on the target machine.
You can retrieve the folder using the Application.streamingAssetsPath
property. It’s always best to use Application.streamingAssetsPath to
get the location of the StreamingAssets folder, it will always point
to the correct location on the platform where the application is
running.
So below snippet should work:
// Put your file to "YOUR_UNITY_PROJ/Assets/StreamingAssets"
// example: "YOUR_UNITY_PROJ/Assets/StreamingAssets/Your.xml"
if (Application.platform == RuntimePlatform.Android)
{
// Android
string oriPath = System.IO.Path.Combine(Application.streamingAssetsPath, "Your.xml");
// Android only use WWW to read file
WWW reader = new WWW(oriPath);
while ( ! reader.isDone) {}
realPath = Application.persistentDataPath + "/Your"; // no extension ".xml"
var contents = System.IO.File.ReadAll(realPath);
}
else // e.g. iOS
{
dbPath = System.IO.Path.Combine(Application.streamingAssetsPath, "Your.xml");
}
Thanks to David I have resolved this problem.
for more precision I add some small details:
1-As David points out in his answer (and as stated in unity documentations), we should use StreamingAssets if we want to have the same folder structure. One should use Application.streamingAssetsPathto retrieve the path.
However, files are still in the apk package in android's case, so they should be accessed using unity android's www class.
a good practice here is to create a method to read the file (even mandatory if you are going to read more than one file)
here is one such method:
private IEnumerator LoadDataFromResources(string v)
{
WWW fileInfo = new WWW(v);
yield return fileInfo;
if (string.IsNullOrEmpty(fileInfo.error))
{
fileContents = fileInfo.text;
}
else
fileContents = fileInfo.error;
}
This is a coroutine, and to use it we need to call it using
yield return StartCoroutine(LoadDataFromResources(path + "/fileName.ext"));
Yet another remark: we can not write into this file or modify it as it's still inside the apk package.
all you guys who know things I don't :-)
I've run into this problem that may not be actually a problem, only a revelation that I don't know what I'm doing. AGAIN!
I'm uploading a JPEG with some description and indexable keywords. Works like a charm. But I can't figure out how to add/modify meta data later, without creating another instance of the file. So, when I add a picture of my dog with description "dog", I end up with what I wanted. But if I try to modify the metadata by either using:
gooFl = drvSvc.files().insert(meta).execute();
or
gooFl = drvSvc.files().insert(meta,null).execute();
I end up with a new file (of the same name) on GOOGLE Drive.
See the code snippet below:
File meta = new File();
meta.setTitle("PicOfMyDog.jpg");
meta.setMimeType("image/jpeg");
meta.setParents(Arrays.asList(new ParentReference().setId(ymID)));
File gooFl = null;
if (bNewJPG == true) {
meta.setDescription("dog");
meta.setIndexableText(new IndexableText().setText("dog"));
gooFl = drvSvc.files().insert(meta,
new FileContent("image/jpeg", new java.io.File(fullPath("PicOfMyDog.jpg"))))
.execute();
} else {
meta.setDescription("dick");
meta.setIndexableText(new IndexableText().setText("dick"));
// gooFl = drvSvc.files().insert(meta).execute();
gooFl = drvSvc.files().insert(meta,null).execute();
}
if (gooFl != null)
Log.d("atn", "success " + gooFl.getTitle());
It is the "else" branch I'm asking about. First file one has meatadata "dog", second "dick".
So, what's the solution. Do I delete the previous instance (and how)? Is there another syntax / method I don't know about?
thank you, sean
If you need to modify the metadata, use files.patch.
drvSvc.files().patch(id, meta).execute();
In cases you need both modify the metadata and the file contents, use files.update.
drvSvc.files().update(id, meta, content).execute();
Insertions make POST requests that always create a new resource.
You need to use Files.Patch if you want to update only Metadata. files().insert always creates a new file.
A full list of File commands and what operations you need to use can be found in the API Reference