summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Joey Hess <joey@kitenet.net>2013-05-31 21:28:37 -0400
committerGravatar Joey Hess <joey@kitenet.net>2013-05-31 21:30:21 -0400
commit03da93e798950fa10d5ab8ecf6e18fb3b02b1d9b (patch)
tree816518d430ca0afd6f76845274707c5bc543e1b8
parent2b990dc0149e20a3a0949f898f5950670da57c64 (diff)
Android: Work around Android devices where the `am` command doesn't work.
-rw-r--r--Command/WebApp.hs43
-rw-r--r--Utility/WebApp.hs1
-rw-r--r--debian/changelog2
-rw-r--r--doc/bugs/Android_app_permission_denial_on_startup.mdwn2
-rw-r--r--doc/bugs/warning_-_WebApp_crashed:___60__file_descriptor_15__62__:_hPutStr:_illegal_operation___40__handle_is_closed__41___on_Android.mdwn3
-rw-r--r--standalone/android/Makefile2
-rwxr-xr-xstandalone/android/runshell21
-rw-r--r--standalone/android/term.patch126
8 files changed, 166 insertions, 34 deletions
diff --git a/Command/WebApp.hs b/Command/WebApp.hs
index 0a8c62be8..3a4a0e73f 100644
--- a/Command/WebApp.hs
+++ b/Command/WebApp.hs
@@ -20,6 +20,7 @@ import Assistant.Install
import Annex.Environment
import Utility.WebApp
import Utility.Daemon (checkDaemon)
+import Utility.Env
import Init
import qualified Git
import qualified Git.Config
@@ -32,7 +33,7 @@ import Control.Concurrent
import Control.Concurrent.STM
import System.Process (env, std_out, std_err)
import Network.Socket (HostName)
-import System.Environment
+import System.Environment (getArgs)
def :: [Command]
def = [ withOptions [listenOption] $
@@ -158,25 +159,21 @@ firstRun listenhost = do
openBrowser :: Maybe FilePath -> FilePath -> String -> Maybe Handle -> Maybe Handle -> IO ()
#ifndef __ANDROID__
-openBrowser mcmd htmlshim _realurl outh errh = do
+openBrowser mcmd htmlshim _realurl outh errh = runbrowser
#else
openBrowser mcmd htmlshim realurl outh errh = do
{- The Android app has a menu item that opens this file. -}
- writeFile "/sdcard/git-annex.home/.git-annex-url" realurl
-#endif
- hPutStrLn (fromMaybe stdout outh) $ "Launching web browser on " ++ url
- hFlush stdout
- environ <- cleanEnvironment
- (_, _, _, pid) <- createProcess p
- { env = environ
- , std_out = maybe Inherit UseHandle outh
- , std_err = maybe Inherit UseHandle errh
- }
- exitcode <- waitForProcess pid
- unless (exitcode == ExitSuccess) $ do
- hPutStrLn (fromMaybe stderr errh) "failed to start web browser"
-#ifdef __ANDROID__
- hPutStrLn (fromMaybe stderr errh) "To open the WebApp, go to the menu and select \"Open WebApp\""
+ writeFile "/sdcard/git-annex.home/.git-annex-url" url
+ {- Android's `am` command does not work reliably across the
+ - wide range of Android devices. Intead, FIFO should be set to
+ - the filename of a fifo that we can write the URL to. -}
+ v <- getEnv "FIFO"
+ case v of
+ Nothing -> runbrowser
+ Just f -> void $ forkIO $ do
+ fd <- openFd f WriteOnly Nothing defaultFileFlags
+ void $ fdWrite fd url
+ closeFd fd
#endif
where
p = case mcmd of
@@ -190,6 +187,18 @@ openBrowser mcmd htmlshim realurl outh errh = do
#else
url = fileUrl htmlshim
#endif
+ runbrowser = do
+ hPutStrLn (fromMaybe stdout outh) $ "Launching web browser on " ++ url
+ hFlush stdout
+ environ <- cleanEnvironment
+ (_, _, _, pid) <- createProcess p
+ { env = environ
+ , std_out = maybe Inherit UseHandle outh
+ , std_err = maybe Inherit UseHandle errh
+ }
+ exitcode <- waitForProcess pid
+ unless (exitcode == ExitSuccess) $ do
+ hPutStrLn (fromMaybe stderr errh) "failed to start web browser"
{- web.browser is a generic git config setting for a web browser program -}
webBrowser :: Git.Repo -> Maybe FilePath
diff --git a/Utility/WebApp.hs b/Utility/WebApp.hs
index 762819b2f..4c112bbe6 100644
--- a/Utility/WebApp.hs
+++ b/Utility/WebApp.hs
@@ -49,6 +49,7 @@ browserProc :: String -> CreateProcess
browserProc url = proc "open" [url]
#else
#ifdef __ANDROID__
+-- Warning: The `am` command does not work very reliably on Android.
browserProc url = proc "am"
["start", "-a", "android.intent.action.VIEW", "-d", url]
#else
diff --git a/debian/changelog b/debian/changelog
index 3d4f30378..a6f3ded84 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -20,7 +20,7 @@ git-annex (4.20130522) UNRELEASED; urgency=low
* sync: Fix double merge conflict resolution handling.
* XMPP: Fix a file descriptor leak.
* Android: Added an "Open WebApp" item to the terminal's menu.
- Should work for Android devices that cannot auto-open the webapp on start.
+ * Android: Work around Android devices where the `am` command doesn't work.
* Can now restart certain long-running git processes if they crash, and
continue working.
diff --git a/doc/bugs/Android_app_permission_denial_on_startup.mdwn b/doc/bugs/Android_app_permission_denial_on_startup.mdwn
index e60f01450..689d7a748 100644
--- a/doc/bugs/Android_app_permission_denial_on_startup.mdwn
+++ b/doc/bugs/Android_app_permission_denial_on_startup.mdwn
@@ -14,3 +14,5 @@ Just downloaded the .apk (Friday May 3rd). Android 4.2.2 on Google/LG Nexus 4
See this [screenshot](https://docs.google.com/file/d/0B8tqeaAn45VORU1ET1ZpTWxLTjQ/edit?usp=sharing).
Feel free to ping me on IRC if you need additional info or want to test a fix.
+
+> [[done]]; now comprehensively fixed. --[[Joey]]
diff --git a/doc/bugs/warning_-_WebApp_crashed:___60__file_descriptor_15__62__:_hPutStr:_illegal_operation___40__handle_is_closed__41___on_Android.mdwn b/doc/bugs/warning_-_WebApp_crashed:___60__file_descriptor_15__62__:_hPutStr:_illegal_operation___40__handle_is_closed__41___on_Android.mdwn
index 02b05f4a1..afdf6b270 100644
--- a/doc/bugs/warning_-_WebApp_crashed:___60__file_descriptor_15__62__:_hPutStr:_illegal_operation___40__handle_is_closed__41___on_Android.mdwn
+++ b/doc/bugs/warning_-_WebApp_crashed:___60__file_descriptor_15__62__:_hPutStr:_illegal_operation___40__handle_is_closed__41___on_Android.mdwn
@@ -19,3 +19,6 @@ Git annex still syncs with `box.com` even if the warning is showing.
I'm using a Nexus 4 (4.2.2)
I didn't find `daemon.log`.
+
+> [[done]]; the android app no longer uses `am`, so no longer needs to
+> display a message when `am` fails. --[[Joey]]
diff --git a/standalone/android/Makefile b/standalone/android/Makefile
index 85457a719..50d32f3e8 100644
--- a/standalone/android/Makefile
+++ b/standalone/android/Makefile
@@ -11,7 +11,7 @@ PATH:=$(ANDROID_CROSS_COMPILER):$(PATH)
export ANDROID_SDK_ROOT?=$(HOME)/tmp/adt-bundle-linux-x86/sdk
export ANDROID_NDK_ROOT?=$(HOME)/tmp/android-ndk-r8d
-# Where to store the $(GIT_ANNEX_ANDROID_SOURCETREE)s to utilities. This
+# Where to store the source tree used to build utilities. This
# directory will be created by `make source`.
GIT_ANNEX_ANDROID_SOURCETREE?=$(HOME)/tmp/android-sourcetree
diff --git a/standalone/android/runshell b/standalone/android/runshell
index 5e461f062..ef6744494 100755
--- a/standalone/android/runshell
+++ b/standalone/android/runshell
@@ -116,12 +116,17 @@ run () {
fi
}
-if ! prep; then
- $cmd echo "prep failed. Please report a bug."
- read line
-fi
-if ! install; then
- $cmd echo "install failed. Please report a bug."
- read line
+if $cmd test -n "$MKFIFO"; then
+ # because java is insane
+ $cmd mkfifo "$MKFIFO"
+else
+ if ! prep; then
+ $cmd echo "prep failed. Please report a bug."
+ read line
+ fi
+ if ! install; then
+ $cmd echo "install failed. Please report a bug."
+ read line
+ fi
+ run
fi
-run
diff --git a/standalone/android/term.patch b/standalone/android/term.patch
index 05a40e567..b83c30e98 100644
--- a/standalone/android/term.patch
+++ b/standalone/android/term.patch
@@ -390,21 +390,65 @@ index f1464e9..b06ec9a 100644
<string name="special_keys">Special keys</string>
<string name="toggle_soft_keyboard">Toggle soft keyboard</string>
+diff --git a/src/jackpal/androidterm/ShellTermSession.java b/src/jackpal/androidterm/ShellTermSession.java
+index 501e7ab..0b43513 100644
+--- a/src/jackpal/androidterm/ShellTermSession.java
++++ b/src/jackpal/androidterm/ShellTermSession.java
+@@ -80,12 +80,12 @@ public class ShellTermSession extends TermSession {
+ }
+ };
+
+- public ShellTermSession(TermSettings settings, String initialCommand) {
++ public ShellTermSession(TermSettings settings, String initialCommand, String webAppFifo) {
+ super();
+
+ updatePrefs(settings);
+
+- initializeSession();
++ initializeSession(webAppFifo);
+ mInitialCommand = initialCommand;
+
+ mWatcherThread = new Thread() {
+@@ -106,7 +106,7 @@ public class ShellTermSession extends TermSession {
+ setDefaultUTF8Mode(settings.defaultToUTF8Mode());
+ }
+
+- private void initializeSession() {
++ private void initializeSession(String webAppFifo) {
+ TermSettings settings = mSettings;
+
+ int[] processId = new int[1];
+@@ -128,9 +128,10 @@ public class ShellTermSession extends TermSession {
+ if (settings.verifyPath()) {
+ path = checkPath(path);
+ }
+- String[] env = new String[2];
++ String[] env = new String[3];
+ env[0] = "TERM=" + settings.getTermType();
+ env[1] = "PATH=" + path;
++ env[2] = "FIFO=" + webAppFifo;
+
+ createSubprocess(processId, settings.getShell(), env);
+ mProcId = processId[0];
diff --git a/src/jackpal/androidterm/Term.java b/src/jackpal/androidterm/Term.java
-index 8a3a4ac..af8d1ad 100644
+index 8a3a4ac..824025d 100644
--- a/src/jackpal/androidterm/Term.java
+++ b/src/jackpal/androidterm/Term.java
-@@ -21,6 +21,9 @@ import java.text.Collator;
+@@ -20,6 +20,13 @@ import java.io.UnsupportedEncodingException;
+ import java.text.Collator;
import java.util.Arrays;
import java.util.Locale;
-
++import java.lang.Process;
++import java.lang.ProcessBuilder;
++import java.util.Map;
++
+import java.io.FileReader;
+import java.io.BufferedReader;
-+
++import java.io.File;
+
import android.app.Activity;
import android.app.AlertDialog;
- import android.content.ActivityNotFoundException;
-@@ -59,6 +62,11 @@ import android.view.inputmethod.InputMethodManager;
+@@ -59,6 +66,11 @@ import android.view.inputmethod.InputMethodManager;
import android.widget.TextView;
import android.widget.Toast;
@@ -416,7 +460,75 @@ index 8a3a4ac..af8d1ad 100644
import jackpal.androidterm.emulatorview.ColorScheme;
import jackpal.androidterm.emulatorview.EmulatorView;
import jackpal.androidterm.emulatorview.TermSession;
-@@ -911,31 +919,15 @@ public class Term extends Activity implements UpdateCallback {
+@@ -107,6 +119,9 @@ public class Term extends Activity implements UpdateCallback {
+ public static final String EXTRA_WINDOW_ID = "jackpal.androidterm.window_id";
+ private int onResumeSelectWindow = -1;
+
++ public static String appDir;
++ public static String webAppFifo;
++
+ private PowerManager.WakeLock mWakeLock;
+ private WifiManager.WifiLock mWifiLock;
+ // Available on API 12 and later
+@@ -257,6 +272,48 @@ public class Term extends Activity implements UpdateCallback {
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
++
++ try {
++ appDir = getApplicationContext().getPackageManager().getPackageInfo(getPackageName(), 0).applicationInfo.dataDir;
++ } catch (Exception e) {
++ appDir = "/data/data/ga.androidterm";
++ }
++ webAppFifo = appDir + "/fifo";
++
++ /* webapp url opening thread */
++ new Thread() {
++ @Override
++ public void run() {
++ try {
++ /* First, set up the fifo that urls to open will be
++ * read from. This is complicated by java not being
++ * able to mkfifo. */
++ File f = new File (webAppFifo);
++ if (! f.exists()) {
++ ProcessBuilder pb = new ProcessBuilder(appDir + "/lib/lib.start.so");
++ Map<String, String> env = pb.environment();
++ env.put("MKFIFO", webAppFifo);
++ Process p = pb.start();
++ p.waitFor();
++ }
++
++ /* Reading from the fifo blocks until a url is written
++ * to it. */
++ BufferedReader buf = new BufferedReader(new FileReader(webAppFifo));
++ while (true) {
++ String s = buf.readLine();
++ try {
++ Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(s));
++ startActivity(intent);
++ } catch (Exception e) {
++ }
++
++ }
++ } catch (Exception e) {
++ }
++ }
++ }.start();
++
+ Log.e(TermDebug.LOG_TAG, "onCreate");
+ mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
+ mSettings = new TermSettings(getResources(), mPrefs);
+@@ -427,7 +484,7 @@ public class Term extends Activity implements UpdateCallback {
+ }
+
+ protected static TermSession createTermSession(Context context, TermSettings settings, String initialCommand) {
+- ShellTermSession session = new ShellTermSession(settings, initialCommand);
++ ShellTermSession session = new ShellTermSession(settings, initialCommand, webAppFifo);
+ // XXX We should really be able to fetch this from within TermSession
+ session.setProcessExitMessage(context.getString(R.string.process_exit_message));
+
+@@ -911,31 +968,15 @@ public class Term extends Activity implements UpdateCallback {
}
private void doEmailTranscript() {