Enable opening mailto URLs under Android
* doc/emacs/android.texi (Android Startup): Mention how mailto URLs are treated by the emacsclient wrapper. * java/AndroidManifest.xml.in: Register `mailto' scheme filters for EmacsOpenActivity. * java/org/gnu/emacs/EmacsOpenActivity.java (startEmacsClient): Extract code that starts Emacs when it isn't already running, and take a list of arguments rather than a single file name. (onCreate): If the scheme is `mailto', escape the URI and call `message-mailto'.
This commit is contained in:
parent
9db3fbd369
commit
d71b9673a0
3 changed files with 73 additions and 23 deletions
|
@ -158,6 +158,13 @@ opened.
|
|||
@command{emacsclient} wrapper as a program capable of opening
|
||||
``org-protocol'' links (@pxref{Protocols,,,org, The Org Manual}).
|
||||
|
||||
@cindex ``mailto'' links, android
|
||||
Furthermore, the wrapper is also registered as a program capable of
|
||||
sending mail to @code{mailto} URIs; when it is invoked to open such a
|
||||
URL, it calls the function @code{message-mailto} with that URI as its
|
||||
first argument. This feature does not function when the Emacs server
|
||||
is not already running.
|
||||
|
||||
@node Android File System
|
||||
@section What Files Emacs Can Access on Android
|
||||
@cindex /assets directory, android
|
||||
|
|
|
@ -122,6 +122,21 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. -->
|
|||
<category android:name="android.intent.category.BROWSABLE"/>
|
||||
<data android:scheme="org-protocol"/>
|
||||
</intent-filter>
|
||||
|
||||
<!-- And also mailto links. -->
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<category android:name="android.intent.category.BROWSABLE"/>
|
||||
<data android:scheme="mailto"/>
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SENDTO"/>
|
||||
<data android:scheme="mailto"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity android:name="org.gnu.emacs.EmacsMultitaskActivity"
|
||||
|
|
|
@ -342,8 +342,14 @@ private class EmacsClientThread extends Thread
|
|||
});
|
||||
}
|
||||
|
||||
/* Start `emacsclient' with the provided list of ARGUMENTS, after
|
||||
ARGUMENTS[0] is replaced with the name of the emacsclient binary.
|
||||
|
||||
Create a new thread to await its completion, subsequently
|
||||
reporting any errors that arise to the user. */
|
||||
|
||||
public void
|
||||
startEmacsClient (String fileName)
|
||||
startEmacsClient (String[] arguments)
|
||||
{
|
||||
String libDir;
|
||||
ProcessBuilder builder;
|
||||
|
@ -352,23 +358,10 @@ private class EmacsClientThread extends Thread
|
|||
File file;
|
||||
Intent intent;
|
||||
|
||||
/* If the Emacs service is not running, then start Emacs and make
|
||||
it open this file. */
|
||||
|
||||
if (EmacsService.SERVICE == null)
|
||||
{
|
||||
fileToOpen = fileName;
|
||||
intent = new Intent (EmacsOpenActivity.this,
|
||||
EmacsActivity.class);
|
||||
finish ();
|
||||
startActivity (intent);
|
||||
return;
|
||||
}
|
||||
|
||||
libDir = EmacsService.getLibraryDirectory (this);
|
||||
builder = new ProcessBuilder (libDir + "/libemacsclient.so",
|
||||
fileName, "--reuse-frame",
|
||||
"--timeout=10", "--no-wait");
|
||||
arguments[0] = libDir + "/libemacsclient.so";
|
||||
|
||||
builder = new ProcessBuilder (arguments);
|
||||
|
||||
/* Redirection is unfortunately not possible in Android 7 and
|
||||
earlier. */
|
||||
|
@ -413,7 +406,7 @@ private class EmacsClientThread extends Thread
|
|||
ContentResolver resolver;
|
||||
ParcelFileDescriptor fd;
|
||||
byte[] names;
|
||||
String errorBlurb;
|
||||
String errorBlurb, scheme;
|
||||
|
||||
super.onCreate (savedInstanceState);
|
||||
|
||||
|
@ -431,7 +424,8 @@ private class EmacsClientThread extends Thread
|
|||
|
||||
if (action.equals ("android.intent.action.VIEW")
|
||||
|| action.equals ("android.intent.action.EDIT")
|
||||
|| action.equals ("android.intent.action.PICK"))
|
||||
|| action.equals ("android.intent.action.PICK")
|
||||
|| action.equals ("android.intent.action.SENDTO"))
|
||||
{
|
||||
/* Obtain the URI of the action. */
|
||||
uri = intent.getData ();
|
||||
|
@ -442,15 +436,35 @@ private class EmacsClientThread extends Thread
|
|||
return;
|
||||
}
|
||||
|
||||
scheme = uri.getScheme ();
|
||||
|
||||
/* If URL is a mailto URI, call `message-mailto' much the same
|
||||
way emacsclient-mail.desktop does. */
|
||||
|
||||
if (scheme.equals ("mailto"))
|
||||
{
|
||||
/* Escape the special characters $ and " before enclosing
|
||||
the string within the `message-mailto' wrapper. */
|
||||
fileName = uri.toString ();
|
||||
fileName.replace ("\"", "\\\"").replace ("$", "\\$");
|
||||
fileName = "(message-mailto \"" + fileName + "\")";
|
||||
|
||||
/* Execute emacsclient in order to execute this code. */
|
||||
currentActivity = this;
|
||||
startEmacsClient (new String[] { "--timeout=10", "--no-wait",
|
||||
"--eval", fileName, });
|
||||
return;
|
||||
}
|
||||
|
||||
/* Now, try to get the file name. */
|
||||
|
||||
if (uri.getScheme ().equals ("file"))
|
||||
if (scheme.equals ("file"))
|
||||
fileName = uri.getPath ();
|
||||
else
|
||||
{
|
||||
fileName = null;
|
||||
|
||||
if (uri.getScheme ().equals ("content"))
|
||||
if (scheme.equals ("content"))
|
||||
{
|
||||
/* This is one of the annoying Android ``content''
|
||||
URIs. Most of the time, there is actually an
|
||||
|
@ -501,7 +515,7 @@ private class EmacsClientThread extends Thread
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (uri.getScheme ().equals ("org-protocol"))
|
||||
else if (scheme.equals ("org-protocol"))
|
||||
/* URL is an org-protocol:// link, which is meant to be
|
||||
directly relayed to emacsclient. */
|
||||
fileName = uri.toString ();
|
||||
|
@ -516,11 +530,25 @@ else if (uri.getScheme ().equals ("org-protocol"))
|
|||
}
|
||||
}
|
||||
|
||||
/* If the Emacs service is not running, then start Emacs and make
|
||||
it open this file. */
|
||||
|
||||
if (EmacsService.SERVICE == null)
|
||||
{
|
||||
fileToOpen = fileName;
|
||||
intent = new Intent (EmacsOpenActivity.this,
|
||||
EmacsActivity.class);
|
||||
finish ();
|
||||
startActivity (intent);
|
||||
return;
|
||||
}
|
||||
|
||||
/* And start emacsclient. Set `currentActivity' to this now.
|
||||
Presumably, it will shortly become capable of displaying
|
||||
dialogs. */
|
||||
currentActivity = this;
|
||||
startEmacsClient (fileName);
|
||||
startEmacsClient (new String[] { "--timeout=10", "--no-wait",
|
||||
"--reuse-frame", fileName, });
|
||||
}
|
||||
else
|
||||
finish ();
|
||||
|
|
Loading…
Add table
Reference in a new issue