add wizard for sending FDroid to another device via WiFi/QR

This is a little helper to direct people to get a new device to download
FDroid from another device that already has it.  It first prompts them to
join the same wifi network, and offers a QR Code to associate to the same
wifi.  The next step is a QR Code for getting the URL to the local repo.
The index.html on that local repo includes a download link for FDroid and
a repo link to the local repo.

refs  https://dev.guardianproject.info/issues/3204
This commit is contained in:
Hans-Christoph Steiner 2014-05-02 20:51:23 -04:00
parent 17c42e4bd0
commit 94dc2d019f
7 changed files with 252 additions and 1 deletions

@ -182,6 +182,8 @@
<activity
android:name=".NfcNotEnabledActivity"
android:noHistory="true" />
<activity android:name=".views.QrWizardDownloadActivity" />
<activity android:name=".views.QrWizardWifiNetworkActivity" />
<activity
android:name=".views.LocalRepoActivity"
android:configChanges="orientation|keyboardHidden|screenSize"

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/qrWizardInstructions"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="@string/wifi_network" />
<TextView
android:id="@+id/qrWifiNetworkName"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginLeft="15dp"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textStyle="bold"
android:typeface="monospace" />
</LinearLayout>
<ImageView
android:id="@+id/qrWizardImage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:contentDescription="@string/qr_code" />
<Button
android:id="@+id/qrNextButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/next" />
</LinearLayout>

@ -5,7 +5,12 @@
android:id="@+id/menu_setup_repo"
android:icon="@android:drawable/ic_input_add"
android:showAsAction="ifRoom|withText"
android:title="Setup Repo"/>
android:title="@string/setup_repo"/>
<item
android:id="@+id/menu_send_fdroid_via_wifi"
android:icon="@android:drawable/arrow_up_float"
android:showAsAction="never"
android:title="@string/send_fdroid_via_wifi"/>
<item
android:id="@+id/menu_settings"
android:icon="@android:drawable/ic_menu_preferences"

@ -154,6 +154,7 @@
<string name="local_repos_title">Local FDroid Repos</string>
<string name="local_repos_scanning">Discovering local FDroid repos&#8230;</string>
<string name="local_repo_running">Your local FDroid repo is accessible.</string>
<string name="setup_repo">Setup Local Repo</string>
<string name="touch_to_configure_local_repo">Touch to setup your local repo.</string>
<string name="updating">Updating&#8230;</string>
<string name="deleting_repo">Deleting current repo&#8230;</string>
@ -167,7 +168,12 @@
<string name="enable_wifi">Enable WiFi</string>
<string name="enabling_wifi">Enabling WiFi&#8230;</string>
<string name="same_wifi_instructions">To connect to other people\'s devices, make sure both devices are on the same WiFi network. Then either type the URL above into F-Droid, or scan this QR Code:</string>
<string name="qr_code">QR Code</string>
<string name="next">Next</string>
<string name="qr_content_description">QR Code of repo URL</string>
<string name="qr_wizard_wifi_network_instructions">Scan this QR Code to connect to the same WiFi network as this device.</string>
<string name="qr_wizard_download_instructions">Scan this QR Code to connect to the website for getting started.</string>
<string name="send_fdroid_via_wifi">Send FDroid via WiFi&#8230;</string>
<!--
status_download takes four parameters:

@ -112,6 +112,9 @@ public class LocalRepoActivity extends Activity {
packages[1] = "com.android.bluetooth";
new UpdateAsyncTask(this, packages).execute();
return true;
case R.id.menu_send_fdroid_via_wifi:
startActivity(new Intent(this, QrWizardWifiNetworkActivity.class));
return true;
case R.id.menu_settings:
startActivityForResult(new Intent(this, PreferencesActivity.class), SET_IP_ADDRESS);
return true;

@ -0,0 +1,82 @@
package org.fdroid.fdroid.views;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import org.fdroid.fdroid.FDroidApp;
import org.fdroid.fdroid.QrGenAsyncTask;
import org.fdroid.fdroid.R;
import org.fdroid.fdroid.net.WifiStateChangeService;
public class QrWizardDownloadActivity extends Activity {
private static final String TAG = "QrWizardDownloadActivity";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.qr_wizard_activity);
TextView instructions = (TextView) findViewById(R.id.qrWizardInstructions);
instructions.setText(R.string.qr_wizard_download_instructions);
Button next = (Button) findViewById(R.id.qrNextButton);
next.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
setResult(RESULT_OK);
finish();
}
});
}
@Override
public void onResume() {
super.onResume();
resetNetworkInfo();
LocalBroadcastManager.getInstance(this).registerReceiver(onWifiChange,
new IntentFilter(WifiStateChangeService.BROADCAST));
}
@Override
public void onPause() {
super.onPause();
LocalBroadcastManager.getInstance(this).unregisterReceiver(onWifiChange);
}
private BroadcastReceiver onWifiChange = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent i) {
Log.i(TAG, "onWifiChange.onReceive()");
resetNetworkInfo();
}
};
private void resetNetworkInfo() {
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
String qrString = "";
if (prefs.getBoolean("use_https", false))
qrString += "https";
else
qrString += "http";
qrString += "://" + FDroidApp.ipAddressString;
qrString += ":" + FDroidApp.port;
new QrGenAsyncTask(this, R.id.qrWizardImage).execute(qrString);
Log.i(TAG, "qr: " + qrString);
TextView wifiNetworkName = (TextView) findViewById(R.id.qrWifiNetworkName);
wifiNetworkName.setText(qrString.replaceFirst("http://", ""));
}
}

@ -0,0 +1,110 @@
package org.fdroid.fdroid.views;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import org.fdroid.fdroid.FDroidApp;
import org.fdroid.fdroid.QrGenAsyncTask;
import org.fdroid.fdroid.R;
import org.fdroid.fdroid.net.WifiStateChangeService;
public class QrWizardWifiNetworkActivity extends Activity {
private static final String TAG = "QrWizardWifiNetworkActivity";
private WifiManager wifiManager;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
wifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
wifiManager.setWifiEnabled(true);
FDroidApp.startLocalRepoService(this);
setContentView(R.layout.qr_wizard_activity);
TextView instructions = (TextView) findViewById(R.id.qrWizardInstructions);
instructions.setText(R.string.qr_wizard_wifi_network_instructions);
Button next = (Button) findViewById(R.id.qrNextButton);
next.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(getBaseContext(), QrWizardDownloadActivity.class);
startActivityForResult(intent, 0);
finish();
}
});
}
@Override
public void onResume() {
super.onResume();
resetNetworkInfo();
LocalBroadcastManager.getInstance(this).registerReceiver(onWifiChange,
new IntentFilter(WifiStateChangeService.BROADCAST));
}
@Override
public void onPause() {
super.onPause();
LocalBroadcastManager.getInstance(this).unregisterReceiver(onWifiChange);
}
private BroadcastReceiver onWifiChange = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent i) {
Log.i(TAG, "onWifiChange.onReceive()");
resetNetworkInfo();
}
};
private void resetNetworkInfo() {
int wifiState = wifiManager.getWifiState();
if (wifiState == WifiManager.WIFI_STATE_ENABLED) {
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
// http://zxing.appspot.com/generator/
// WIFI:S:openwireless.org;; // no pw
// WIFI:S:openwireless.org;T:WPA;;
// WIFI:S:openwireless.org;T:WEP;;
// WIFI:S:openwireless.org;H:true;; // hidden
// WIFI:S:openwireless.org;T:WPA;H:true;; // all
String qrString = "WIFI:S:";
qrString += wifiInfo.getSSID();
// TODO get encryption state (none, WEP, WPA)
/*
* WifiConfiguration wc = null; for (WifiConfiguration i :
* wifiManager.getConfiguredNetworks()) { if (i.status ==
* WifiConfiguration.Status.CURRENT) { wc = i; break; } } if (wc !=
* null)
*/
if (wifiInfo.getHiddenSSID())
qrString += ";H:true";
qrString += ";;";
new QrGenAsyncTask(this, R.id.qrWizardImage).execute(qrString);
Log.i(TAG, "qr: " + qrString);
TextView wifiNetworkName = (TextView) findViewById(R.id.qrWifiNetworkName);
wifiNetworkName.setText(wifiInfo.getSSID());
Log.i(TAG, "wifi network name: " + wifiInfo.getSSID());
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// this wizard is done, clear this Activity from the history
if (resultCode == RESULT_OK)
finish();
}
}