Merge branch 'android_branch' into android_groups

This commit is contained in:
Eric House 2012-11-26 07:41:20 -08:00
commit a39cc44d56
8 changed files with 179 additions and 59 deletions

View file

@ -115,15 +115,22 @@
</intent-filter> </intent-filter>
</receiver> </receiver>
<activity android:name="DispatchNotify" <activity android:name="DispatchNotify">
>
<intent-filter> <intent-filter>
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<action android:name="android.intent.action.EDIT" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="newxwgame"/> <data android:scheme="newxwgame"/>
</intent-filter> </intent-filter>
<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="http"
android:host="eehouse.org" android:pathPrefix="/and" />
</intent-filter>
</activity> </activity>
<!-- downloading dicts --> <!-- downloading dicts -->

View file

@ -105,7 +105,7 @@
<!-- <string name="default_host">10.0.2.2</string> --> <!-- <string name="default_host">10.0.2.2</string> -->
<string name="dict_url">http://eehouse.org/and_wordlists</string> <string name="dict_url">http://eehouse.org/and_wordlists</string>
<string name="game_url_pathf">//%1$s/newgame.php</string> <string name="game_url_pathf">//%1$s/and</string>
<string name="expl_update_url">Update checks URL</string> <string name="expl_update_url">Update checks URL</string>
<string name="default_update_url">http://eehouse.org/xw4/info.py</string> <string name="default_update_url">http://eehouse.org/xw4/info.py</string>

View file

@ -21,31 +21,43 @@
package org.eehouse.android.xw4; package org.eehouse.android.xw4;
import android.app.Activity; import android.app.Activity;
import android.os.Bundle;
import android.os.AsyncTask;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.Window; import android.view.Window;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import android.widget.TextView; import android.widget.TextView;
import java.io.InputStream;
import java.io.File; import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URI; import java.net.URI;
import junit.framework.Assert; import junit.framework.Assert;
public class DictImportActivity extends XWActivity { public class DictImportActivity extends XWActivity {
public static final String APK_EXTRA = "APK";
private class DownloadFilesTask extends AsyncTask<Uri, Integer, Long> { private class DownloadFilesTask extends AsyncTask<Uri, Integer, Long> {
private String m_saved = null; private String m_saved = null;
private boolean m_isApp = false;
private File m_appFile = null;
public DownloadFilesTask( boolean isApp )
{
super();
m_isApp = isApp;
}
@Override @Override
protected Long doInBackground( Uri... uris ) protected Long doInBackground( Uri... uris )
{ {
m_saved = null; m_saved = null;
m_appFile = null;
int count = uris.length; int count = uris.length;
Assert.assertTrue( 1 == count ); Assert.assertTrue( 1 == count );
long totalSize = 0;
for ( int ii = 0; ii < count; ii++ ) { for ( int ii = 0; ii < count; ii++ ) {
Uri uri = uris[ii]; Uri uri = uris[ii];
DbgUtils.logf( "trying %s", uri ); DbgUtils.logf( "trying %s", uri );
@ -55,7 +67,12 @@ public class DictImportActivity extends XWActivity {
uri.getSchemeSpecificPart(), uri.getSchemeSpecificPart(),
uri.getFragment() ); uri.getFragment() );
InputStream is = jUri.toURL().openStream(); InputStream is = jUri.toURL().openStream();
m_saved = saveDict( is, uri.getPath() ); String name = basename( uri.getPath() );
if ( m_isApp ) {
m_appFile = saveToDownloads( is, name );
} else {
m_saved = saveDict( is, name );
}
is.close(); is.close();
} catch ( java.net.URISyntaxException use ) { } catch ( java.net.URISyntaxException use ) {
DbgUtils.loge( use ); DbgUtils.loge( use );
@ -65,7 +82,7 @@ public class DictImportActivity extends XWActivity {
DbgUtils.loge( ioe ); DbgUtils.loge( ioe );
} }
} }
return totalSize; return new Long(0);
} }
@Override @Override
@ -77,6 +94,10 @@ public class DictImportActivity extends XWActivity {
XWPrefs.getDefaultLoc( DictImportActivity.this ); XWPrefs.getDefaultLoc( DictImportActivity.this );
DictLangCache.inval( DictImportActivity.this, m_saved, DictLangCache.inval( DictImportActivity.this, m_saved,
loc, true ); loc, true );
} else if ( null != m_appFile ) {
// launch the installer
Intent intent = Utils.makeInstallIntent( m_appFile );
startActivity( intent );
} }
finish(); finish();
} }
@ -86,6 +107,7 @@ public class DictImportActivity extends XWActivity {
protected void onCreate( Bundle savedInstanceState ) protected void onCreate( Bundle savedInstanceState )
{ {
super.onCreate( savedInstanceState ); super.onCreate( savedInstanceState );
DownloadFilesTask dft = null;
requestWindowFeature( Window.FEATURE_LEFT_ICON ); requestWindowFeature( Window.FEATURE_LEFT_ICON );
setContentView( R.layout.import_dict ); setContentView( R.layout.import_dict );
@ -96,27 +118,60 @@ public class DictImportActivity extends XWActivity {
Intent intent = getIntent(); Intent intent = getIntent();
Uri uri = intent.getData(); Uri uri = intent.getData();
if ( null != uri) { if ( null == uri ) {
if ( null != intent.getType() String url = intent.getStringExtra( APK_EXTRA );
&& intent.getType().equals( "application/x-xwordsdict" ) ) { if ( null != url ) {
DbgUtils.logf( "based on MIME type" ); dft = new DownloadFilesTask( true );
new DownloadFilesTask().execute( uri ); uri = Uri.parse(url);
} else if ( uri.toString().endsWith( XWConstants.DICT_EXTN ) ) { }
String txt = getString( R.string.downloading_dictf, } else if ( null != intent.getType()
basename( uri.getPath()) ); && intent.getType().equals( "application/x-xwordsdict" ) ) {
TextView view = (TextView)findViewById( R.id.dwnld_message ); dft = new DownloadFilesTask( false );
view.setText( txt ); } else if ( uri.toString().endsWith( XWConstants.DICT_EXTN ) ) {
new DownloadFilesTask().execute( uri ); String txt = getString( R.string.downloading_dictf,
} else { basename( uri.getPath()) );
DbgUtils.logf( "bogus intent: %s/%s", intent.getType(), uri ); TextView view = (TextView)findViewById( R.id.dwnld_message );
finish(); view.setText( txt );
} dft = new DownloadFilesTask( false );
}
if ( null == dft ) {
finish();
} else {
dft.execute( uri );
} }
} }
private String saveDict( InputStream inputStream, String path ) private File saveToDownloads( InputStream is, String name )
{
boolean success = false;
File appFile = new File( DictUtils.getDownloadDir( this ), name );
Assert.assertNotNull( appFile );
byte[] buf = new byte[1024*4];
try {
FileOutputStream fos = new FileOutputStream( appFile );
int nRead;
while ( 0 <= (nRead = is.read( buf, 0, buf.length )) ) {
fos.write( buf, 0, nRead );
}
fos.close();
success = true;
} catch ( java.io.FileNotFoundException fnf ) {
DbgUtils.loge( fnf );
} catch ( java.io.IOException ioe ) {
DbgUtils.loge( ioe );
}
if ( !success ) {
appFile.delete();
appFile = null;
}
return appFile;
}
private String saveDict( InputStream inputStream, String name )
{ {
String name = basename( path );
DictUtils.DictLoc loc = XWPrefs.getDefaultLoc( this ); DictUtils.DictLoc loc = XWPrefs.getDefaultLoc( this );
if ( !DictUtils.saveDict( this, inputStream, name, loc ) ) { if ( !DictUtils.saveDict( this, inputStream, name, loc ) ) {
name = null; name = null;

View file

@ -566,7 +566,7 @@ public class DictUtils {
return null != getDownloadDir( context ); return null != getDownloadDir( context );
} }
private static File getDownloadDir( Context context ) public static File getDownloadDir( Context context )
{ {
File result = null; File result = null;
if ( haveWriteableSD() ) { if ( haveWriteableSD() ) {

View file

@ -66,36 +66,41 @@ public class DispatchNotify extends Activity {
} }
} else if ( null != data ) { // relay invite redirected URL case } else if ( null != data ) { // relay invite redirected URL case
NetLaunchInfo nli = new NetLaunchInfo( data ); NetLaunchInfo nli = new NetLaunchInfo( data );
long rowid = DBUtils.getRowIDForOpen( this, nli ); if ( null != nli && nli.isValid() ) {
if ( DBUtils.ROWID_NOTFOUND == rowid ) { long rowid = DBUtils.getRowIDForOpen( this, nli );
boolean haveDict; if ( DBUtils.ROWID_NOTFOUND == rowid ) {
if ( null == nli.dict ) { // can only test for language support boolean haveDict;
haveDict = if ( null == nli.dict ) { // can only test for language support
0 < DictLangCache.getHaveLang( this, nli.lang ).length; haveDict =
} else { 0 < DictLangCache.getHaveLang( this,
haveDict = DictLangCache.haveDict( this, nli.lang, nli.dict ); nli.lang ).length;
} } else {
if ( haveDict ) { haveDict =
if ( !tryHandle( data ) ) { DictLangCache.haveDict( this, nli.lang, nli.dict );
mustLaunch = true; }
if ( haveDict ) {
if ( !tryHandle( data ) ) {
mustLaunch = true;
}
} else {
Intent intent =
MultiService.makeMissingDictIntent( this, nli );
intent.putExtra( MultiService.OWNER,
MultiService.OWNER_RELAY );
// do we have gameID?
MultiService.
postMissingDictNotification( this, intent,
nli.inviteID
.hashCode() );
} }
} else { } else {
Intent intent = MultiService.makeMissingDictIntent( this, DbgUtils.logf( "DispatchNotify: dropping duplicate invite" );
nli ); GameSummary summary = DBUtils.getSummary( this, rowid );
intent.putExtra( MultiService.OWNER, if ( null != summary ) {
MultiService.OWNER_RELAY ); gameID = summary.gameID;
// do we have gameID? if ( !tryHandle( gameID ) ) {
MultiService. mustLaunch = true;
postMissingDictNotification( this, intent, }
nli.inviteID.hashCode() );
}
} else {
DbgUtils.logf( "DispatchNotify: dropping duplicate invite" );
GameSummary summary = DBUtils.getSummary( this, rowid );
if ( null != summary ) {
gameID = summary.gameID;
if ( !tryHandle( gameID ) ) {
mustLaunch = true;
} }
} }
} }

View file

@ -29,6 +29,7 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.net.Uri; import android.net.Uri;
import android.os.SystemClock; import android.os.SystemClock;
import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -174,11 +175,33 @@ public class UpdateCheckReceiver extends BroadcastReceiver {
if ( jobj.has( k_APP ) ) { if ( jobj.has( k_APP ) ) {
JSONObject app = jobj.getJSONObject( k_APP ); JSONObject app = jobj.getJSONObject( k_APP );
if ( app.has( k_URL ) ) { if ( app.has( k_URL ) ) {
String url = app.getString( k_URL );
ApplicationInfo ai = pm.getApplicationInfo( packageName, 0); ApplicationInfo ai = pm.getApplicationInfo( packageName, 0);
String label = pm.getApplicationLabel( ai ).toString(); String label = pm.getApplicationLabel( ai ).toString();
Intent intent =
new Intent( Intent.ACTION_VIEW, Uri.parse(url) ); // If there's a download dir AND an installer
// app, handle this ourselves. Otherwise just
// launch the browser
boolean useBrowser;
File downloads = DictUtils.getDownloadDir( context );
if ( null == downloads ) {
useBrowser = true;
} else {
File tmp = new File( downloads,
"xx" + XWConstants.APK_EXTN );
useBrowser = !Utils.canInstall( context, tmp );
}
Intent intent;
String url = app.getString( k_URL );
if ( useBrowser ) {
intent = new Intent( Intent.ACTION_VIEW,
Uri.parse(url) );
} else {
intent = new Intent( context,
DictImportActivity.class );
intent.putExtra( DictImportActivity.APK_EXTRA, url );
}
String title = String title =
Utils.format( context, R.string.new_app_availf, label ); Utils.format( context, R.string.new_app_availf, label );
String body = context.getString( R.string.new_app_avail ); String body = context.getString( R.string.new_app_avail );

View file

@ -32,6 +32,8 @@ import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences.Editor; import android.content.SharedPreferences.Editor;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.database.Cursor; import android.database.Cursor;
import android.net.Uri; import android.net.Uri;
@ -43,8 +45,10 @@ import android.widget.CheckBox;
import android.widget.EditText; import android.widget.EditText;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import java.io.File;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Random; import java.util.Random;
import junit.framework.Assert; import junit.framework.Assert;
@ -419,6 +423,29 @@ public class Utils {
return null == s_appVersion? 0 : s_appVersion; return null == s_appVersion? 0 : s_appVersion;
} }
public static Intent makeInstallIntent( File file )
{
Uri uri = Uri.parse( "file:/" + file.getPath() );
Intent intent = new Intent( Intent.ACTION_VIEW );
intent.setDataAndType( uri, XWConstants.APK_TYPE );
intent.addFlags( Intent.FLAG_ACTIVITY_NEW_TASK );
return intent;
}
// Return whether there's an app installed that can install
public static boolean canInstall( Context context, File path )
{
boolean result = false;
PackageManager pm = context.getPackageManager();
Intent intent = makeInstallIntent( path );
List<ResolveInfo> doers =
pm.queryIntentActivities( intent,
PackageManager.MATCH_DEFAULT_ONLY );
result = 0 < doers.size();
DbgUtils.logf( "canInstall()=>%b", result );
return result;
}
private static void setFirstBootStatics( Context context ) private static void setFirstBootStatics( Context context )
{ {
int thisVersion = getAppVersion( context ); int thisVersion = getAppVersion( context );

View file

@ -23,4 +23,7 @@ package org.eehouse.android.xw4;
public interface XWConstants { public interface XWConstants {
public static final String GAME_EXTN = ".xwg"; public static final String GAME_EXTN = ".xwg";
public static final String DICT_EXTN = ".xwd"; public static final String DICT_EXTN = ".xwd";
public static final String APK_EXTN = ".apk";
public static final String APK_TYPE =
"application/vnd.android.package-archive";
} }