• Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
Question by DoctorWhy · May 08, 2017 at 10:48 PM · androidfiledataexternalintent

Convert Android URI to a file path Unity can read

I have an external app sending me a URI of a .zip file I need to access. Here is my attempt to convert the uri:

 AndroidJavaClass UnityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
 AndroidJavaObject currentActivity = UnityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
 
 AndroidJavaObject intent = currentActivity.Call<AndroidJavaObject>("getIntent");
 AndroidJavaObject data = intent.Call<AndroidJavaObject>("getData");
 
 AndroidJavaObject fileObject = new AndroidJavaObject("java.io.File", data);
 Debug.Log(fileObject.Call<string>("getPath"));

I am getting the uri correctly. But the constructor for the File class is getting this error:

 UnityEngine.AndroidJavaException: java.lang.NoSuchMethodError: no non-static method "Ljava/io/File;.<init>(Landroid.net.Uri$HierarchicalUri;)V"
 05-08 16:26:54.997 30011 30026 I Unity   : java.lang.NoSuchMethodError: no non-static method "Ljava/io/File;.<init>(Landroid.net.Uri$HierarchicalUri;)V"

How do I pass the uri to the java File class so I can get the proper path to the zip file?

Thanks for the help!

Comment
liortal

People who like this

1 Show 4
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Guy-Corbett · May 30, 2017 at 08:19 PM 0
Share

Have you had any luck with this? I'm encountering a similar problem.

avatar image DoctorWhy Guy-Corbett · May 30, 2017 at 08:29 PM 0
Share

There are 2 different URI classes. One for java, one for android. The File class uses the java uri, while I was passing it an android uri.

The only way I could figure out how to get the file from the android uri is with an InputStream. But the function was very slow in Unity because it had to be called a bunch of times to get all the bytes. I ended up writing a Java plugin that grabs all the bytes from the file and passes the byte array to Unity.

avatar image Guy-Corbett · May 31, 2017 at 07:18 PM 0
Share

So I found a way to work around this. What I'm doing is using the URI to read the file as an input stream. By doing that you can read the file byte by byte, or wrap the input reader in something more sophisticated extract strings. In the absolute laziest case you could read all the bytes to memory, write them out to a known file location and then read that file as you normally would. That code would look something like this;

 AndroidJavaClass unityPlayerClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
 AndroidJavaObject activityObject = unityPlayerClass.GetStatic<AndroidJavaObject>("currentActivity");
 AndroidJavaObject intent = activityObject.Call<AndroidJavaObject>("getIntent");
 AndroidJavaObject intentURI = intent.Call<AndroidJavaObject>("getData");
 AndroidJavaObject contentResolver = activityObject.Call<AndroidJavaObject>("getContentResolver");
 AndroidJavaObject inputStream = contentResolver.Call<AndroidJavaObject>("openInputStream", intentURI);
 List<byte> bytes = new List<byte>();
 int nextByte = inputStream.Call<int>("read");
 while (nextByte != -1)
 {
     bytes.Add((byte)nextByte);
     nextByte = inputStream.Call<int>("read");
 }
 
 inputStream.Call("close");
 
 File.WriteAllBytes(myKnownPath, bytes.ToArray());
 MyFileReadingFunction(myKnownPath);

avatar image Guy-Corbett Guy-Corbett · May 31, 2017 at 07:19 PM 0
Share

Damn, just saw your reply where you said you ended up doing the same thing!... until it was too slow for you. I'll leave this up here though, in case it's useful for anyone.

2 Replies

· Add your reply
  • Sort: 
avatar image

Answer by liortal · Jun 05, 2017 at 06:48 AM

Your original code is fine, but this is a limitation with how JNI finds and invokes methods from C# (well, technically from C++, but Mono is using the same infrastructure).

See the following (related) question on Stack overflow.

The problem is you're trying to find a method that has a signature that is different than the actual File class constructor, and so it fails.

The easiest solution you can do is create a simple plugin (fancy name for a small .jar containing helper methods), then call these Java helper methods from your C# code to achieve what you want.

Comment

People who like this

0 Show 0 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image

Answer by Guy-Corbett · Jun 05, 2017 at 05:21 PM

So found a way to do this without writing a plugin or resorting to reading byte by byte. Seems to run pretty fast. Here's the function I've written which copies the whole of any file given with the intent to another location;

         private void ImportFromIntent(string importPath)
         {
             try
             {
                 // Get the current activity
                 AndroidJavaClass unityPlayerClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
                 AndroidJavaObject activityObject = unityPlayerClass.GetStatic<AndroidJavaObject>("currentActivity");
 
                 // Get the current intent
                 AndroidJavaObject intent = activityObject.Call<AndroidJavaObject>("getIntent");
 
                 // Get the intent data using AndroidJNI.CallObjectMethod so we can check for null
                 IntPtr method_getData = AndroidJNIHelper.GetMethodID(intent.GetRawClass(), "getData", "()Ljava/lang/Object;");
                 IntPtr getDataResult = AndroidJNI.CallObjectMethod(intent.GetRawObject(), method_getData, AndroidJNIHelper.CreateJNIArgArray(new object[0]));
                 if (getDataResult.ToInt32() != 0)
                 {
                     // Now actually get the data. We should be able to get it from the result of AndroidJNI.CallObjectMethod, but I don't now how so just call again
                     AndroidJavaObject intentURI = intent.Call<AndroidJavaObject>("getData");
 
                     // Open the URI as an input channel
                     AndroidJavaObject contentResolver = activityObject.Call<AndroidJavaObject>("getContentResolver");
                     AndroidJavaObject inputStream = contentResolver.Call<AndroidJavaObject>("openInputStream", intentURI);
                     AndroidJavaObject inputChannel = inputStream.Call<AndroidJavaObject>("getChannel");
 
                     // Open an output channel
                     AndroidJavaObject outputStream = new AndroidJavaObject("java.io.FileOutputStream", importPath);
                     AndroidJavaObject outputChannel = outputStream.Call<AndroidJavaObject>("getChannel");
 
                     // Copy the file
                     long bytesTransfered = 0;
                     long bytesTotal = inputChannel.Call<long>("size");
                     while (bytesTransfered < bytesTotal)
                     {
                         bytesTransfered += inputChannel.Call<long>("transferTo", bytesTransfered, bytesTotal, outputChannel);
                     }
 
                     // Close the streams
                     inputStream.Call("close");
                     outputStream.Call("close");
                 }
             }
             catch (System.Exception ex)
             {
                 // Handle error
             }
         }
Comment

People who like this

0 Show 0 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Welcome to Unity Answers

If you’re new to Unity Answers, please check our User Guide to help you navigate through our website and refer to our FAQ for more information.

Before posting, make sure to check out our Knowledge Base for commonly asked Unity questions.

Check our Moderator Guidelines if you’re a new moderator and want to work together in an effort to improve Unity Answers and support our users.

Follow this Question

Answers Answers and Comments

127 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Open another app with intent url on Android 1 Answer

External Saves for android games 1 Answer

Which platforms support the "file://" protocol in the WWW class? 2 Answers

Allow … to access photos, media, and files on your device? 2 Answers

How to Save PNG in android...? 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges