📜 ⬆️ ⬇️

How to send email from an Android device from a Unity application without writing a single line of Java code

Often, developers add to the application the ability to send an email to a friend with a link to the application. Usually it is possible to do it by regular means of the final OS When porting our application to Android, I had to spend some time to add this functionality. The last time I worked with the Java language 5 years ago, and I did not want to go into the wilds of writing an Android plug-in for Unity, installing Eclipse, building a jar-file, setting up AndroidManifest.xml, and so on. I managed to do it in C # without writing a single line of Java code (except for in the comments). I want to share with you how I did it so that you do not waste your time. In this case, the method specified in the article can be used to call any Java code.


Simple option


There is a very simple option. If the text of the letter is small, does not contain html-codes, then you can use the mailto URI scheme:
string url = string.Format("mailto:{0}?subject={1}&body={2}", to, WWW.EscapeURL(subject), WWW.EscapeURL(body)); Application.OpenURL(url); 

Those. a special link is created and opened using the Unity Application.OpenURL function. Not all mail programs adequately perceive such a link, especially if there are gaps in the text. Therefore you have to use WWW.EscapeURL .
What to do if you want to send a letter containing links, images, etc.?

HTML option


This can be done using the built-in mail program Android. To do this, write the following Java code:
 intent = new Intent(Intent.ACTION_SEND); if (isHTML) intent.setType("text/html"); else intent.setType("message/rfc822"); intent.putExtra(Intent.EXTRA_SUBJECT, subject); if (isHTML) intent.putExtra(Intent.EXTRA_TEXT, Html.fromHtml(body)); else intent.putExtra(Intent.EXTRA_TEXT, body); startActivity(intent); 

It can be found in numerous online examples. On Habré there was an article about how to do this on Andoird . If you're interested in what this code does, read it.

Next, to call this code from Unity, you need to build a jar file, call a Java function from a C # script, and so on. But you can do without all of this. We will help the Unity support classes AndroidJavaClass and AndroidJavaObject . These are very useful tools. With their help, you can access any Java class and any Java object, respectively, as well as create Java objects, gain access to class methods, static methods and data, and so on.
')
I rewrote it in C # using the above classes:
 /// <summary> /// Sends mail using default mail application. /// </summary> private static void SendMail(string subject, string body, bool isHTML) { using (var intentClass = new AndroidJavaClass("android.content.Intent")) { // intent = new Intent(Intent.ACTION_SEND); using (var intentObject = new AndroidJavaObject("android.content.Intent", intentClass.GetStatic<string>("ACTION_SEND"))) { // Setting text type if (isHTML) // intent.setType("text/html"); intentObject.Call<AndroidJavaObject>("setType", "text/html"); else // intent.setType("message/rfc822"); intentObject.Call<AndroidJavaObject>("setType", "message/rfc822"); // intent.putExtra(Intent.EXTRA_SUBJECT, subject); intentObject.Call<AndroidJavaObject>("putExtra", intentClass.GetStatic<string>("EXTRA_SUBJECT"), subject); // Setting body if (isHTML) { // intent.putExtra(Intent.EXTRA_TEXT, Html.fromHtml(body)); using (var html = new AndroidJavaClass("android.text.Html")) { var htmlBody = html.CallStatic<AndroidJavaObject>("fromHtml", body); intentObject.Call<AndroidJavaObject>("putExtra", intentClass.GetStatic<string>("EXTRA_TEXT"), htmlBody); } } else { // intent.putExtra(Intent.EXTRA_TEXT, body); intentObject.Call<AndroidJavaObject>("putExtra", intentClass.GetStatic<string>("EXTRA_TEXT"), body); } // startActivity(intent); using (var unity = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) { using (var currentActivity = unity.GetStatic<AndroidJavaObject>("currentActivity")) { currentActivity.Call("startActivity", intentObject); } } } } } 

The intentClass variable provides access to the android.content.Intent Java class, which I used to access constants like Intent.EXTRA_TEXT using the GetStatic function:
 intentClass.GetStatic<string>("EXTRA_TEXT") 

The variable intentObject is a link to the created object of the Java class android.content.Intent . As you can see, creating a Java class object is very easy:
 var intentObject = new AndroidJavaObject("android.content.Intent", intentClass.GetStatic<string>("ACTION_SEND")) 

The first parameter of the class constructor AndroidJavaObject is the name of the Java class, the remaining parameters are the parameters of the constructor of the Java class itself.

Do not confuse AndroidJavaObject with AndroidJavaClass , use each for its intended purpose. These classes are so similar visually ( AndroidJavaClass is even inherited from AndroidJavaObject ) that in one place I used AndroidJavaClass instead of AndroidJavaObject and did not notice it. Sadly, it took time to fix this little detail.

The using directive is used to timely "release" Java objects. This is well written in Best practice when using Java plugins with Unity .
Access to the class methods is done through the Call function, while if the method returns a result, then a generalized version of the function is used to specify the type of the returned result:
 intentObject.Call<AndroidJavaObject>("putExtra", intentClass.GetStatic<string>("EXTRA_TEXT"), body); 

Do not forget about this: even if you do not need a return result, you must still specify the type of result, otherwise you will receive an incorrect method signature and it will not be found, or, even worse, you will reluctantly call a similar method (if it exists) that does not return result, and do not immediately notice the error.

At the end, we get the current context ( currentActivity and be it) and initiate sending using the created intentObject object:
 using (var unity = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) { using (var currentActivity = unity.GetStatic<AndroidJavaObject>("currentActivity")) { currentActivity.Call("startActivity", intentObject); } } 

That's all.
Similarly, you can rewrite almost any Java code. I recommend this method if the code is small and you don’t want to write a plugin. Otherwise, of course, a very cumbersome code is obtained, incomprehensible to an ignorant person.

Ready to listen to questions and suggestions;)

Perhaps someone will be interested to read my previous articles:


Good luck to you in your development!

Source: https://habr.com/ru/post/175509/


All Articles