Android: Work around Android devices where the am command doesn't work.

This commit is contained in:
Joey Hess 2013-05-31 21:28:37 -04:00
parent b325524b0f
commit a48d340abd
8 changed files with 166 additions and 34 deletions

View file

@ -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

View file

@ -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

2
debian/changelog vendored
View file

@ -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.

View file

@ -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]]

View file

@ -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]]

View file

@ -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

View file

@ -116,12 +116,17 @@ run () {
fi
}
if ! prep; then
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
fi
if ! install; then
$cmd echo "install failed. Please report a bug."
read line
fi
run
fi
run

View file

@ -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() {