mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-02-17 09:34:08 +01:00
Merge branch 'android_branch' into android_groups
This commit is contained in:
commit
a39cc44d56
8 changed files with 179 additions and 59 deletions
xwords4/android/XWords4
|
@ -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 -->
|
||||||
|
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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() ) {
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
|
@ -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";
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue