Compare commits
37 Commits
android-cl
...
android-0.
Author | SHA1 | Date | |
---|---|---|---|
41d1200df7 | |||
c9a62fba9a | |||
c9598fa831 | |||
9965c31b2d | |||
43de6425b2 | |||
b98cdf3e0b | |||
26c11ebaed | |||
c9c3de1d04 | |||
9b29b56982 | |||
8956fd7ce0 | |||
f1f94ea3e0 | |||
94b433aead | |||
5623d54114 | |||
9133a2f848 | |||
70324c3ecc | |||
5613d21324 | |||
9036bf3f6b | |||
94991d2df3 | |||
76f23946f0 | |||
862e856913 | |||
cf3de34cb6 | |||
81de79c725 | |||
228b6f1baa | |||
8e395cfd4e | |||
6d6123df9b | |||
321a49156c | |||
e8a47e17fb | |||
9df27ea168 | |||
cb6b7c4f48 | |||
ca623e6b18 | |||
8b6e02136e | |||
6a0493a578 | |||
bf2a437a82 | |||
ac949e3f5e | |||
7483251393 | |||
d690b7d861 | |||
829695d690 |
12
TODO
12
TODO
@ -9,10 +9,9 @@
|
||||
- Disable uPnP when on cell networks
|
||||
<zzz> spewing UPnP out into cell networks is a waste of time at best and a security risk at worst, but you really want it for wifi
|
||||
- Display release notes directly on new router version
|
||||
- Text content
|
||||
- Move help content from release notes to help page
|
||||
- Rewrite release notes to be release-specific
|
||||
- Fill out help page
|
||||
- Fill out help pages
|
||||
- Proper browser configuration page
|
||||
- Rewrite release notes to be release-specific
|
||||
- Fix release notes UI, either make back button use clear or add buttons
|
||||
- NetDB tablet view fixes
|
||||
- Refresh detail fragment when changing tab
|
||||
@ -20,10 +19,13 @@
|
||||
- Create nav history when viewing RI from LS
|
||||
- Include GeoIP db for country info
|
||||
- Maybe change router-off mechanic for various pages? Enable as they become available?
|
||||
- Add "copy (error) log" option
|
||||
|
||||
# Medium-term
|
||||
|
||||
- Network profiles
|
||||
- User selects profile in settings
|
||||
- Change network participation etc. based on profile
|
||||
- Also look at connection type: Connectivity.isConnectionFast()
|
||||
- Expose log level overrides
|
||||
- Improve graphs
|
||||
- Show time on bottom axis
|
||||
|
@ -37,15 +37,15 @@ android {
|
||||
dependencies {
|
||||
compile project(':routerjars')
|
||||
compile project(':client')
|
||||
compile 'com.android.support:support-v4:19.1.0'
|
||||
compile 'com.android.support:appcompat-v7:19.1.0'
|
||||
compile files('libs/androidplot-core-0.6.0.jar')
|
||||
compile 'com.android.support:support-v4:20.0.0'
|
||||
compile 'com.android.support:appcompat-v7:20.0.0'
|
||||
compile files('libs/androidplot-core-0.6.1.jar')
|
||||
}
|
||||
|
||||
dependencyVerification {
|
||||
verify = [
|
||||
'com.android.support:support-v4:3f40fa7b3a4ead01ce15dce9453b061646e7fe2e7c51cb75ca01ee1e77037f3f',
|
||||
'com.android.support:appcompat-v7:9df7637c5219202ddbbbf0924c2d5a9e6d64379166795a89d8f75d1e3f3372df',
|
||||
'com.android.support:support-v4:81f2b1c2c94efd5a4ec7fcd97b6cdcd00e87a933905c5c86103c7319eb024572',
|
||||
'com.android.support:appcompat-v7:736f576ab0b68d27bdf18b1e7931566e6d8254b73965175313e87f8866b91547',
|
||||
]
|
||||
}
|
||||
|
||||
|
Binary file not shown.
BIN
app/libs/androidplot-core-0.6.1.jar
Normal file
BIN
app/libs/androidplot-core-0.6.1.jar
Normal file
Binary file not shown.
@ -2,8 +2,8 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="net.i2p.android.router"
|
||||
android:installLocation="auto"
|
||||
android:versionCode="4745219"
|
||||
android:versionName="0.9.14.1-rc3">
|
||||
android:versionCode="4745222"
|
||||
android:versionName="0.9.15.1">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
@ -15,7 +15,7 @@
|
||||
<application
|
||||
android:icon="@drawable/ic_launcher_itoopie"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/Theme.AppCompat">
|
||||
android:theme="@style/I2PAndroid">
|
||||
<service
|
||||
android:name=".service.RouterService"
|
||||
android:icon="@drawable/ic_launcher_itoopie"
|
||||
@ -52,7 +52,7 @@
|
||||
android:value="net.i2p.android.router.MainActivity" />
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".HelpActivity"
|
||||
android:name="net.i2p.android.help.HelpActivity"
|
||||
android:label="Help"
|
||||
android:parentActivityName=".MainActivity">
|
||||
<meta-data
|
||||
@ -62,10 +62,10 @@
|
||||
<activity
|
||||
android:name=".LicenseActivity"
|
||||
android:label="I2P License Information"
|
||||
android:parentActivityName=".HelpActivity">
|
||||
android:parentActivityName="net.i2p.android.help.HelpActivity">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value="net.i2p.android.router.HelpActivity" />
|
||||
android:value="net.i2p.android.help.HelpActivity" />
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".web.WebActivity"
|
||||
|
156
app/src/main/java/net/i2p/android/help/HelpActivity.java
Normal file
156
app/src/main/java/net/i2p/android/help/HelpActivity.java
Normal file
@ -0,0 +1,156 @@
|
||||
package net.i2p.android.help;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentTransaction;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.app.ActionBarActivity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ScrollView;
|
||||
import android.widget.SpinnerAdapter;
|
||||
import android.widget.TextView;
|
||||
|
||||
import net.i2p.android.router.LicenseActivity;
|
||||
import net.i2p.android.router.R;
|
||||
import net.i2p.android.router.dialog.TextResourceDialog;
|
||||
|
||||
import org.sufficientlysecure.htmltextview.HtmlTextView;
|
||||
|
||||
public class HelpActivity extends ActionBarActivity {
|
||||
public static final String CATEGORY = "help_category";
|
||||
public static final int CAT_MAIN = 0;
|
||||
public static final int CAT_CONFIGURE_BROWSER = 1;
|
||||
public static final int CAT_ADDRESSBOOK = 2;
|
||||
public static final int CAT_I2PTUNNEL = 3;
|
||||
|
||||
/**
|
||||
* Whether or not the activity is in two-pane mode, i.e. running on a tablet
|
||||
* device.
|
||||
*/
|
||||
private boolean mTwoPane;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_help);
|
||||
|
||||
final ActionBar actionBar = getSupportActionBar();
|
||||
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
|
||||
|
||||
SpinnerAdapter spinnerAdapter = ArrayAdapter.createFromResource(this,
|
||||
R.array.help_categories, android.R.layout.simple_spinner_dropdown_item);
|
||||
|
||||
ActionBar.OnNavigationListener navigationListener = new ActionBar.OnNavigationListener() {
|
||||
@Override
|
||||
public boolean onNavigationItemSelected(int i, long l) {
|
||||
showCategory(i);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
actionBar.setListNavigationCallbacks(spinnerAdapter, navigationListener);
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
int category = getIntent().getIntExtra(CATEGORY, CAT_MAIN);
|
||||
// TODO remove when addressbook and I2PTunnel help added
|
||||
if (category > CAT_CONFIGURE_BROWSER)
|
||||
category = CAT_MAIN;
|
||||
actionBar.setSelectedNavigationItem(category);
|
||||
showCategory(category);
|
||||
}
|
||||
|
||||
if (findViewById(R.id.detail_fragment) != null) {
|
||||
// The detail container view will be present only in the
|
||||
// large-screen layouts (res/values-large and
|
||||
// res/values-sw600dp). If this view is present, then the
|
||||
// activity should be in two-pane mode.
|
||||
mTwoPane = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void showCategory(int category) {
|
||||
Fragment f;
|
||||
switch (category) {
|
||||
case CAT_CONFIGURE_BROWSER:
|
||||
//f = new BrowserConfigFragment();
|
||||
f = HelpHtmlFragment.newInstance(R.raw.help_configure_browser);
|
||||
break;
|
||||
|
||||
case CAT_ADDRESSBOOK:
|
||||
f = HelpHtmlFragment.newInstance(R.raw.help_addressbook);
|
||||
break;
|
||||
|
||||
case CAT_I2PTUNNEL:
|
||||
f = HelpHtmlFragment.newInstance(R.raw.help_i2ptunnel);
|
||||
break;
|
||||
|
||||
case CAT_MAIN:
|
||||
default:
|
||||
f = HelpHtmlFragment.newInstance(R.raw.help_main);
|
||||
break;
|
||||
}
|
||||
|
||||
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
|
||||
ft.replace(R.id.main_fragment, f);
|
||||
if (mTwoPane)
|
||||
ft.remove(getSupportFragmentManager().findFragmentById(R.id.detail_fragment));
|
||||
ft.commit();
|
||||
}
|
||||
|
||||
public static class HelpHtmlFragment extends Fragment {
|
||||
public static final String ARG_HTML_FILE = "htmlFile";
|
||||
|
||||
static HelpHtmlFragment newInstance(int htmlFile) {
|
||||
HelpHtmlFragment f = new HelpHtmlFragment();
|
||||
Bundle args = new Bundle();
|
||||
args.putInt(ARG_HTML_FILE, htmlFile);
|
||||
f.setArguments(args);
|
||||
return f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
ScrollView scroller = new ScrollView(getActivity());
|
||||
HtmlTextView text = new HtmlTextView(getActivity());
|
||||
scroller.addView(text);
|
||||
int padH = getResources().getDimensionPixelOffset(R.dimen.activity_horizontal_margin);
|
||||
int padV = getResources().getDimensionPixelOffset(R.dimen.activity_vertical_margin);
|
||||
text.setPadding(padH, padV, padH, padV);
|
||||
text.setHtmlFromRawResource(getActivity(), getArguments().getInt(ARG_HTML_FILE), true);
|
||||
return scroller;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.activity_help_actions, menu);
|
||||
return super.onCreateOptionsMenu(menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.menu_help_licenses:
|
||||
Intent lic = new Intent(HelpActivity.this, LicenseActivity.class);
|
||||
startActivity(lic);
|
||||
return true;
|
||||
case R.id.menu_help_release_notes:
|
||||
TextResourceDialog dialog = new TextResourceDialog();
|
||||
Bundle args = new Bundle();
|
||||
args.putString(TextResourceDialog.TEXT_DIALOG_TITLE,
|
||||
getResources().getString(R.string.label_release_notes));
|
||||
args.putInt(TextResourceDialog.TEXT_RESOURCE_ID, R.raw.releasenotes_txt);
|
||||
dialog.setArguments(args);
|
||||
dialog.show(getSupportFragmentManager(), "release_notes");
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
}
|
@ -2,8 +2,8 @@ package net.i2p.android.i2ptunnel;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.i2p.android.help.HelpActivity;
|
||||
import net.i2p.android.i2ptunnel.util.TunnelConfig;
|
||||
import net.i2p.android.router.HelpActivity;
|
||||
import net.i2p.android.router.I2PFragmentBase;
|
||||
import net.i2p.android.router.R;
|
||||
import net.i2p.android.router.I2PFragmentBase.RouterContextProvider;
|
||||
@ -187,12 +187,11 @@ public class TunnelListFragment extends ListFragment implements
|
||||
case R.id.action_restart_all_tunnels:
|
||||
msgs = mGroup.restartAllControllers();
|
||||
break;
|
||||
// TODO: Enable when Help page finished
|
||||
//case R.id.action_i2ptunnel_help:
|
||||
// Intent hi = new Intent(getActivity(), HelpActivity.class);
|
||||
// hi.putExtra(HelpActivity.REFERRER, "i2ptunnel");
|
||||
// startActivity(hi);
|
||||
// return true;
|
||||
case R.id.action_i2ptunnel_help:
|
||||
Intent hi = new Intent(getActivity(), HelpActivity.class);
|
||||
hi.putExtra(HelpActivity.CATEGORY, HelpActivity.CAT_I2PTUNNEL);
|
||||
startActivity(hi);
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
@ -1,52 +0,0 @@
|
||||
package net.i2p.android.router;
|
||||
|
||||
import net.i2p.android.router.R;
|
||||
import net.i2p.android.router.dialog.TextResourceDialog;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
|
||||
public class HelpActivity extends I2PActivityBase {
|
||||
public static final String REFERRER = "help_referrer";
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mDrawerToggle.setDrawerIndicatorEnabled(false);
|
||||
/*if (savedInstanceState == null) {
|
||||
HelpFragment f = new HelpFragment();
|
||||
f.setArguments(getIntent().getExtras());
|
||||
getSupportFragmentManager().beginTransaction()
|
||||
.add(R.id.main_fragment, f).commit();
|
||||
}*/
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.activity_help_actions, menu);
|
||||
return super.onCreateOptionsMenu(menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.menu_help_licenses:
|
||||
Intent lic = new Intent(HelpActivity.this, LicenseActivity.class);
|
||||
startActivity(lic);
|
||||
return true;
|
||||
case R.id.menu_help_release_notes:
|
||||
TextResourceDialog dialog = new TextResourceDialog();
|
||||
Bundle args = new Bundle();
|
||||
args.putString(TextResourceDialog.TEXT_DIALOG_TITLE,
|
||||
getResources().getString(R.string.label_release_notes));
|
||||
args.putInt(TextResourceDialog.TEXT_RESOURCE_ID, R.raw.releasenotes_txt);
|
||||
dialog.setArguments(args);
|
||||
dialog.show(getSupportFragmentManager(), "release_notes");
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
}
|
@ -4,9 +4,12 @@ import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Build;
|
||||
|
||||
import net.i2p.android.router.util.Util;
|
||||
import net.i2p.data.DataHelper;
|
||||
import net.i2p.util.FileUtil;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@ -15,12 +18,6 @@ import java.util.Properties;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
import net.i2p.android.router.R;
|
||||
import net.i2p.android.router.util.Util;
|
||||
import net.i2p.data.DataHelper;
|
||||
import net.i2p.util.FileUtil;
|
||||
import net.i2p.util.OrderedProperties;
|
||||
|
||||
// Wouldn't this be better as a private class in MainActivity?
|
||||
|
||||
class InitActivities {
|
||||
@ -36,8 +33,7 @@ class InitActivities {
|
||||
|
||||
public InitActivities(Context c) {
|
||||
ctx = c;
|
||||
// This needs to be changed so that we can have an alternative place
|
||||
myDir = c.getFilesDir().getAbsolutePath();
|
||||
myDir = Util.getFileDir(c);
|
||||
_ourVersion = Util.getOurVersion(c);
|
||||
}
|
||||
|
||||
@ -231,41 +227,13 @@ class InitActivities {
|
||||
/**
|
||||
* Load defaults from resource,
|
||||
* then add props from settings,
|
||||
* and write back
|
||||
* and write back.
|
||||
*
|
||||
* @param f relative to base dir
|
||||
* @param overrides local overrides or null
|
||||
*/
|
||||
public void mergeResourceToFile(int resID, String f, Properties overrides) {
|
||||
InputStream in = null;
|
||||
InputStream fin = null;
|
||||
|
||||
try {
|
||||
in = ctx.getResources().openRawResource(resID);
|
||||
Properties props = new OrderedProperties();
|
||||
try {
|
||||
fin = new FileInputStream(new File(myDir, f));
|
||||
DataHelper.loadProps(props, fin);
|
||||
Util.d("Merging resource into file " + f);
|
||||
} catch (IOException ioe) {
|
||||
Util.d("Creating file " + f + " from resource");
|
||||
}
|
||||
|
||||
// write in default settings
|
||||
DataHelper.loadProps(props, in);
|
||||
|
||||
// override with user settings
|
||||
if (overrides != null)
|
||||
props.putAll(overrides);
|
||||
File path = new File(myDir, f);
|
||||
DataHelper.storeProps(props, path);
|
||||
Util.d("Saved " + props.size() +" properties in " + f);
|
||||
} catch (IOException ioe) {
|
||||
} catch (Resources.NotFoundException nfe) {
|
||||
} finally {
|
||||
if (in != null) try { in.close(); } catch (IOException ioe) {}
|
||||
if (fin != null) try { fin.close(); } catch (IOException ioe) {}
|
||||
}
|
||||
private void mergeResourceToFile(int resID, String f, Properties overrides) {
|
||||
Util.mergeResourceToFile(ctx, myDir, f, resID, overrides);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -22,12 +22,14 @@ import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import net.i2p.android.help.HelpActivity;
|
||||
import net.i2p.android.router.dialog.AboutDialog;
|
||||
import net.i2p.android.router.dialog.TextResourceDialog;
|
||||
import net.i2p.android.router.service.IRouterState;
|
||||
import net.i2p.android.router.service.IRouterStateCallback;
|
||||
import net.i2p.android.router.service.RouterService;
|
||||
import net.i2p.android.router.service.State;
|
||||
import net.i2p.android.router.util.Connectivity;
|
||||
import net.i2p.android.router.util.Util;
|
||||
import net.i2p.router.RouterContext;
|
||||
import net.i2p.util.OrderedProperties;
|
||||
@ -88,7 +90,7 @@ public class MainActivity extends I2PActivityBase implements
|
||||
|
||||
private void autoStart() {
|
||||
if (canStart()) {
|
||||
if (Util.isConnected(this)) {
|
||||
if (Connectivity.isConnected(this)) {
|
||||
mAutoStartFromIntent = true;
|
||||
onStartRouterClicked();
|
||||
} else {
|
||||
@ -140,18 +142,12 @@ public class MainActivity extends I2PActivityBase implements
|
||||
dialog.show(getSupportFragmentManager(), "about");
|
||||
return true;
|
||||
|
||||
// TODO: Unhide when Help page finished
|
||||
//case R.id.menu_help:
|
||||
// Intent hi = new Intent(MainActivity.this, HelpActivity.class);
|
||||
// hi.putExtra(HelpActivity.REFERRER, "main");
|
||||
// startActivity(hi);
|
||||
// return true;
|
||||
|
||||
// TODO: Remove when help page finished
|
||||
case R.id.menu_help_licenses:
|
||||
Intent lic = new Intent(MainActivity.this, LicenseActivity.class);
|
||||
startActivity(lic);
|
||||
case R.id.menu_help:
|
||||
Intent hi = new Intent(MainActivity.this, HelpActivity.class);
|
||||
hi.putExtra(HelpActivity.CATEGORY, HelpActivity.CAT_MAIN);
|
||||
startActivity(hi);
|
||||
return true;
|
||||
|
||||
case R.id.menu_help_release_notes:
|
||||
TextResourceDialog rDdialog = new TextResourceDialog();
|
||||
Bundle args = new Bundle();
|
||||
@ -289,7 +285,7 @@ public class MainActivity extends I2PActivityBase implements
|
||||
// MainFragment.RouterControlListener
|
||||
|
||||
public boolean shouldShowOnOff() {
|
||||
return (canStart() && Util.isConnected(this)) || canStop();
|
||||
return (canStart() && Connectivity.isConnected(this)) || canStop();
|
||||
}
|
||||
|
||||
public boolean shouldBeOn() {
|
||||
|
@ -2,9 +2,11 @@ package net.i2p.android.router;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Typeface;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
@ -16,9 +18,11 @@ import android.widget.TableRow;
|
||||
import android.widget.TextView;
|
||||
import android.widget.ToggleButton;
|
||||
|
||||
import net.i2p.android.router.dialog.ConfigureBrowserDialog;
|
||||
import net.i2p.android.router.dialog.FirstStartDialog;
|
||||
import net.i2p.android.router.dialog.VersionDialog;
|
||||
import net.i2p.android.router.service.State;
|
||||
import net.i2p.android.router.util.Connectivity;
|
||||
import net.i2p.android.router.util.LongToggleButton;
|
||||
import net.i2p.android.router.util.Util;
|
||||
import net.i2p.data.DataHelper;
|
||||
@ -44,6 +48,7 @@ public class MainFragment extends I2PFragmentBase {
|
||||
private String _savedStatus;
|
||||
private boolean _keep = true;
|
||||
private boolean _startPressed = false;
|
||||
private static final String PREF_CONFIGURE_BROWSER = "app.dialog.configureBrowser";
|
||||
private static final String PREF_FIRST_START = "app.router.firstStart";
|
||||
private static final String PREF_SHOW_STATS = "i2pandroid.main.showStats";
|
||||
protected static final String PROP_NEW_INSTALL = "i2p.newInstall";
|
||||
@ -205,7 +210,7 @@ public class MainFragment extends I2PFragmentBase {
|
||||
public boolean onBackPressed() {
|
||||
RouterContext ctx = getRouterContext();
|
||||
// RouterService svc = _routerService; Which is better to use?!
|
||||
_keep = Util.isConnected(getActivity()) && (ctx != null || _startPressed);
|
||||
_keep = Connectivity.isConnected(getActivity()) && (ctx != null || _startPressed);
|
||||
Util.d("*********************************************************");
|
||||
Util.d("Back pressed, Keep? " + _keep);
|
||||
Util.d("*********************************************************");
|
||||
@ -264,7 +269,7 @@ public class MainFragment extends I2PFragmentBase {
|
||||
LinearLayout vStatus = (LinearLayout) getActivity().findViewById(R.id.main_status);
|
||||
TextView vStatusText = (TextView) getActivity().findViewById(R.id.main_status_text);
|
||||
|
||||
if(!Util.isConnected(getActivity())) {
|
||||
if(!Connectivity.isConnected(getActivity())) {
|
||||
// Manually set state, RouterService won't be running
|
||||
updateState(State.WAITING);
|
||||
vStatusText.setText("No Internet connection is available");
|
||||
@ -397,24 +402,24 @@ public class MainFragment extends I2PFragmentBase {
|
||||
String name = getName(ctx, client);
|
||||
Hash h = client.calculateHash();
|
||||
TableRow dest = new TableRow(getActivity());
|
||||
//dest.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT));
|
||||
dest.setPadding(16, 4, 0, 4);
|
||||
|
||||
// Client or server
|
||||
ImageView type = new ImageView(getActivity());
|
||||
type.setPadding(6, 6, 6, 6);
|
||||
TextView type = new TextView(getActivity());
|
||||
type.setTextColor(getResources().getColor(android.R.color.primary_text_light));
|
||||
type.setTypeface(Typeface.DEFAULT_BOLD);
|
||||
type.setGravity(Gravity.CENTER);
|
||||
if (ctx.clientManager().shouldPublishLeaseSet(h))
|
||||
type.setImageDrawable(getActivity().getResources()
|
||||
.getDrawable(R.drawable.server));
|
||||
type.setText(R.string.char_server_tunnel);
|
||||
else
|
||||
type.setImageDrawable(getActivity().getResources()
|
||||
.getDrawable(R.drawable.client));
|
||||
type.setText(R.string.char_client_tunnel);
|
||||
dest.addView(type);
|
||||
|
||||
// Name
|
||||
TextView destName = new TextView(getActivity());
|
||||
destName.setPadding(6, 0, 0, 0);
|
||||
destName.setPadding(16, 0, 0, 0);
|
||||
destName.setGravity(Gravity.CENTER_VERTICAL);
|
||||
destName.setText(name);
|
||||
//destName.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT));
|
||||
dest.addView(destName);
|
||||
|
||||
// Status
|
||||
@ -423,14 +428,14 @@ public class MainFragment extends I2PFragmentBase {
|
||||
long timeToExpire = ls.getEarliestLeaseDate() - ctx.clock().now();
|
||||
if (timeToExpire < 0) {
|
||||
// red or yellow light
|
||||
type.setBackgroundColor(Color.TRANSPARENT);
|
||||
type.setBackgroundResource(R.drawable.tunnel_yellow);
|
||||
} else {
|
||||
// green light
|
||||
type.setBackgroundColor(Color.GREEN);
|
||||
type.setBackgroundResource(R.drawable.tunnel_green);
|
||||
}
|
||||
} else {
|
||||
// yellow light
|
||||
type.setBackgroundColor(Color.TRANSPARENT);
|
||||
type.setBackgroundResource(R.drawable.tunnel_yellow);
|
||||
}
|
||||
|
||||
dests.addView(dest);
|
||||
@ -438,7 +443,7 @@ public class MainFragment extends I2PFragmentBase {
|
||||
} else {
|
||||
TableRow empty = new TableRow(getActivity());
|
||||
TextView emptyText = new TextView(getActivity());
|
||||
emptyText.setText("No client tunnels are running yet.");
|
||||
emptyText.setText(R.string.no_client_tunnels_running);
|
||||
empty.addView(emptyText);
|
||||
dests.addView(empty);
|
||||
}
|
||||
@ -487,14 +492,23 @@ public class MainFragment extends I2PFragmentBase {
|
||||
}
|
||||
|
||||
private void checkDialog() {
|
||||
VersionDialog dialog = new VersionDialog();
|
||||
I2PActivityBase ab = (I2PActivityBase) getActivity();
|
||||
boolean configureBrowser = ab.getPref(PREF_CONFIGURE_BROWSER, true);
|
||||
if (configureBrowser) {
|
||||
ConfigureBrowserDialog dialog = new ConfigureBrowserDialog();
|
||||
dialog.show(getActivity().getSupportFragmentManager(), "configurebrowser");
|
||||
ab.setPref(PREF_CONFIGURE_BROWSER, false);
|
||||
}
|
||||
/*VersionDialog dialog = new VersionDialog();
|
||||
String oldVersion = ((I2PActivityBase) getActivity()).getPref(PREF_INSTALLED_VERSION, "??");
|
||||
if(oldVersion.equals("??")) {
|
||||
// TODO Don't show this dialog until it is reworked
|
||||
Bundle args = new Bundle();
|
||||
args.putInt(VersionDialog.DIALOG_TYPE, VersionDialog.DIALOG_NEW_INSTALL);
|
||||
dialog.setArguments(args);
|
||||
dialog.show(getActivity().getSupportFragmentManager(), "newinstall");
|
||||
} else {
|
||||
// TODO Don't show dialog on new version until we have something new to tell them
|
||||
String currentVersion = Util.getOurVersion(getActivity());
|
||||
if(!oldVersion.equals(currentVersion)) {
|
||||
Bundle args = new Bundle();
|
||||
@ -502,7 +516,7 @@ public class MainFragment extends I2PFragmentBase {
|
||||
dialog.setArguments(args);
|
||||
dialog.show(getActivity().getSupportFragmentManager(), "newversion");
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
private void checkFirstStart() {
|
||||
|
@ -2,77 +2,57 @@ package net.i2p.android.router;
|
||||
|
||||
import android.content.res.Resources;
|
||||
import android.os.Bundle;
|
||||
import android.text.Html;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.text.style.URLSpan;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.webkit.WebView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import net.i2p.android.apps.NewsFetcher;
|
||||
import net.i2p.android.router.util.Util;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import net.i2p.android.apps.NewsFetcher;
|
||||
import net.i2p.android.router.R;
|
||||
import net.i2p.android.router.web.I2PWebViewClient;
|
||||
|
||||
public class NewsFragment extends I2PFragmentBase {
|
||||
|
||||
private I2PWebViewClient _wvClient;
|
||||
private long _lastChanged;
|
||||
|
||||
private static final String WARNING = "Warning - while the news is fetched over I2P, " +
|
||||
"any non-I2P links visited in this window are fetched over the regular internet and are " +
|
||||
"not anonymous.\n";
|
||||
|
||||
|
||||
// TODO add some inline style
|
||||
private static final String HEADER = "<html><head></head><body>";
|
||||
private static final String FOOTER = "</body></html>";
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState)
|
||||
{
|
||||
View v = inflater.inflate(R.layout.fragment_news, container, false);
|
||||
WebView wv = (WebView) v.findViewById(R.id.news_webview);
|
||||
wv.getSettings().setLoadsImagesAutomatically(false);
|
||||
// http://stackoverflow.com/questions/2369310/webview-double-tap-zoom-not-working-on-a-motorola-droid-a855
|
||||
wv.getSettings().setUseWideViewPort(true);
|
||||
_wvClient = new I2PWebViewClient();
|
||||
wv.setWebViewClient(_wvClient);
|
||||
wv.getSettings().setBuiltInZoomControls(true);
|
||||
return v;
|
||||
Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.fragment_news, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume()
|
||||
{
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
NewsFetcher nf = NewsFetcher.getInstance();
|
||||
if (nf != null) {
|
||||
// always update the text
|
||||
// Always update the status
|
||||
TextView tv = (TextView) getActivity().findViewById(R.id.news_status);
|
||||
tv.setText(WARNING + nf.status().replace(" ", " "));
|
||||
tv.setText(nf.status().replace(" ", " "));
|
||||
tv.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
// only update the webview if we need to
|
||||
// XXX Gets dir directly instead of the one stored in the Activity (for now)
|
||||
File newsFile = new File(getActivity().getFilesDir().getAbsolutePath(), "docs/news.xml");
|
||||
// Only update the content if we need to
|
||||
File newsFile = new File(Util.getFileDir(getActivity()), "docs/news.xml");
|
||||
boolean newsExists = newsFile.exists();
|
||||
if (_lastChanged > 0 && ((!newsExists) || newsFile.lastModified() < _lastChanged))
|
||||
return;
|
||||
_lastChanged = System.currentTimeMillis();
|
||||
|
||||
WebView wv = (WebView) getActivity().findViewById(R.id.news_webview);
|
||||
|
||||
InputStream in = null;
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream(2048);
|
||||
byte buf[] = new byte[1024];
|
||||
try {
|
||||
if (newsExists) {
|
||||
out.write(HEADER.getBytes());
|
||||
in = new FileInputStream(newsFile);
|
||||
} else {
|
||||
in = getResources().openRawResource(R.raw.initialnews_html);
|
||||
@ -82,30 +62,34 @@ public class NewsFragment extends I2PFragmentBase {
|
||||
while ( (read = in.read(buf)) != -1)
|
||||
out.write(buf, 0, read);
|
||||
|
||||
if (newsExists)
|
||||
out.write(FOOTER.getBytes());
|
||||
|
||||
} catch (IOException ioe) {
|
||||
System.err.println("news error " + ioe);
|
||||
} catch (Resources.NotFoundException nfe) {
|
||||
} finally {
|
||||
if (in != null) try { in.close(); } catch (IOException ioe) {}
|
||||
}
|
||||
|
||||
String news = "";
|
||||
try {
|
||||
String news = out.toString("UTF-8");
|
||||
wv.loadData(news, "text/html", "UTF-8");
|
||||
news = out.toString("UTF-8");
|
||||
} catch (UnsupportedEncodingException uee) {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean onBackPressed() {
|
||||
WebView wv = (WebView) getActivity().findViewById(R.id.news_webview);
|
||||
_wvClient.cancelAll();
|
||||
wv.stopLoading();
|
||||
if (wv.canGoBack()) {
|
||||
wv.goBack();
|
||||
return true;
|
||||
// Get SpannableStringBuilder object from HTML code
|
||||
CharSequence sequence = Html.fromHtml(news);
|
||||
SpannableStringBuilder strBuilder = new SpannableStringBuilder(sequence);
|
||||
|
||||
// Get an array of URLSpan from SpannableStringBuilder object
|
||||
URLSpan[] urlSpans = strBuilder.getSpans(0, strBuilder.length(), URLSpan.class);
|
||||
|
||||
// Remove URLSpans with relative paths, which can't be clicked on
|
||||
for (final URLSpan span : urlSpans) {
|
||||
if (span.getURL().startsWith("/"))
|
||||
strBuilder.removeSpan(span);
|
||||
}
|
||||
return false;
|
||||
|
||||
TextView tv = (TextView) getActivity().findViewById(R.id.news_content);
|
||||
tv.setText(strBuilder);
|
||||
tv.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
}
|
||||
}
|
||||
|
@ -2,27 +2,16 @@ package net.i2p.android.router;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.preference.CheckBoxPreference;
|
||||
import android.preference.PreferenceActivity;
|
||||
import android.preference.PreferenceCategory;
|
||||
import android.preference.PreferenceFragment;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.preference.PreferenceScreen;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
import android.widget.Toast;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.android.router.R;
|
||||
import net.i2p.android.router.service.StatSummarizer;
|
||||
import net.i2p.android.router.util.Util;
|
||||
import net.i2p.router.RouterContext;
|
||||
@ -31,7 +20,11 @@ import net.i2p.stat.Rate;
|
||||
import net.i2p.stat.RateStat;
|
||||
import net.i2p.stat.StatManager;
|
||||
import net.i2p.util.LogManager;
|
||||
import net.i2p.util.OrderedProperties;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.SortedSet;
|
||||
|
||||
public class SettingsActivity extends PreferenceActivity {
|
||||
// Actions for legacy settings
|
||||
@ -51,12 +44,10 @@ public class SettingsActivity extends PreferenceActivity {
|
||||
addPreferencesFromResource(R.xml.settings_net);
|
||||
} else if (ACTION_PREFS_GRAPHS.equals(action)){
|
||||
addPreferencesFromResource(R.xml.settings_graphs);
|
||||
setupGraphSettings(this, getPreferenceScreen(), getRouterContext());
|
||||
setupGraphSettings(this, getPreferenceScreen(), Util.getRouterContext());
|
||||
} else if (ACTION_PREFS_LOGGING.equals(action)) {
|
||||
addPreferencesFromResource(R.xml.settings_logging);
|
||||
RouterContext ctx = getRouterContext();
|
||||
if (ctx != null)
|
||||
setupLoggingSettings(this, getPreferenceScreen(), ctx);
|
||||
setupLoggingSettings(this, getPreferenceScreen(), Util.getRouterContext());
|
||||
} else if (ACTION_PREFS_ADVANCED.equals(action)) {
|
||||
addPreferencesFromResource(R.xml.settings_advanced);
|
||||
}
|
||||
@ -66,14 +57,6 @@ public class SettingsActivity extends PreferenceActivity {
|
||||
}
|
||||
}
|
||||
|
||||
protected static RouterContext getRouterContext() {
|
||||
List<RouterContext> contexts = RouterContext.listContexts();
|
||||
if ( !((contexts == null) || (contexts.isEmpty())) ) {
|
||||
return contexts.get(0);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected static void setupGraphSettings(Context context, PreferenceScreen ps, RouterContext ctx) {
|
||||
if (ctx == null) {
|
||||
PreferenceCategory noRouter = new PreferenceCategory(context);
|
||||
@ -153,10 +136,12 @@ public class SettingsActivity extends PreferenceActivity {
|
||||
buf.append(prefix).append('=').append(level).append('\n');
|
||||
}
|
||||
*/
|
||||
/* Don't show, there are no settings that require the router
|
||||
} else {
|
||||
PreferenceCategory noRouter = new PreferenceCategory(context);
|
||||
noRouter.setTitle(R.string.router_not_running);
|
||||
ps.addPreference(noRouter);
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
@ -176,18 +161,18 @@ public class SettingsActivity extends PreferenceActivity {
|
||||
Properties props = lProps.get(0);
|
||||
Properties logSettings = lProps.get(1);
|
||||
|
||||
boolean restartRequired = Util.checkAndCorrectRouterConfig(this, props);
|
||||
|
||||
// Apply new config if we are running.
|
||||
List<RouterContext> contexts = RouterContext.listContexts();
|
||||
if ( !((contexts == null) || (contexts.isEmpty())) ) {
|
||||
RouterContext _context = contexts.get(0);
|
||||
_context.router().saveConfig(props, null);
|
||||
RouterContext rCtx = Util.getRouterContext();
|
||||
if (rCtx != null) {
|
||||
rCtx.router().saveConfig(props, null);
|
||||
|
||||
// Merge in new log settings
|
||||
saveLoggingChanges(_context, logSettings);
|
||||
saveLoggingChanges(rCtx, logSettings);
|
||||
} else {
|
||||
// Merge in new config settings, write the file.
|
||||
InitActivities init = new InitActivities(this);
|
||||
init.mergeResourceToFile(R.raw.router_config, "router.config", props);
|
||||
Util.mergeResourceToFile(this, Util.getFileDir(this), "router.config", R.raw.router_config, props);
|
||||
|
||||
// Merge in new log settings
|
||||
saveLoggingChanges(I2PAppContext.getGlobalContext(), logSettings);
|
||||
@ -195,6 +180,9 @@ public class SettingsActivity extends PreferenceActivity {
|
||||
|
||||
// Store the settings in Android
|
||||
super.onPause();
|
||||
|
||||
if (restartRequired)
|
||||
Toast.makeText(this, R.string.settings_router_restart_required, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
private void saveLoggingChanges(I2PAppContext ctx, Properties logSettings) {
|
||||
@ -227,14 +215,10 @@ public class SettingsActivity extends PreferenceActivity {
|
||||
addPreferencesFromResource(R.xml.settings_net);
|
||||
} else if ("graphs".equals(settings)) {
|
||||
addPreferencesFromResource(R.xml.settings_graphs);
|
||||
RouterContext ctx = getRouterContext();
|
||||
if (ctx != null)
|
||||
setupGraphSettings(getActivity(), getPreferenceScreen(), ctx);
|
||||
setupGraphSettings(getActivity(), getPreferenceScreen(), Util.getRouterContext());
|
||||
} else if ("logging".equals(settings)) {
|
||||
addPreferencesFromResource(R.xml.settings_logging);
|
||||
RouterContext ctx = getRouterContext();
|
||||
if (ctx != null)
|
||||
setupLoggingSettings(getActivity(), getPreferenceScreen(), ctx);
|
||||
setupLoggingSettings(getActivity(), getPreferenceScreen(), Util.getRouterContext());
|
||||
} else if ("advanced".equals(settings)) {
|
||||
addPreferencesFromResource(R.xml.settings_advanced);
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ import android.widget.Toast;
|
||||
import java.util.List;
|
||||
|
||||
import net.i2p.addressbook.Daemon;
|
||||
import net.i2p.android.router.HelpActivity;
|
||||
import net.i2p.android.help.HelpActivity;
|
||||
import net.i2p.android.router.I2PFragmentBase;
|
||||
import net.i2p.android.router.R;
|
||||
import net.i2p.android.router.I2PFragmentBase.RouterContextProvider;
|
||||
@ -180,12 +180,11 @@ public class AddressbookFragment extends ListFragment implements
|
||||
Intent si = new Intent(getActivity(), AddressbookSettingsActivity.class);
|
||||
startActivity(si);
|
||||
return true;
|
||||
// TODO: Enable when Help page finished
|
||||
//case R.id.action_addressbook_help:
|
||||
// Intent hi = new Intent(getActivity(), HelpActivity.class);
|
||||
// hi.putExtra(HelpActivity.REFERRER, "addressbook");
|
||||
// startActivity(hi);
|
||||
// return true;
|
||||
case R.id.action_addressbook_help:
|
||||
Intent hi = new Intent(getActivity(), HelpActivity.class);
|
||||
hi.putExtra(HelpActivity.CATEGORY, HelpActivity.CAT_ADDRESSBOOK);
|
||||
startActivity(hi);
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
@ -1,10 +1,13 @@
|
||||
package net.i2p.android.router.dialog;
|
||||
|
||||
import net.i2p.android.router.LicenseActivity;
|
||||
import net.i2p.android.router.R;
|
||||
import net.i2p.android.router.util.I2Patterns;
|
||||
import net.i2p.android.router.util.Util;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.text.util.Linkify;
|
||||
@ -33,7 +36,14 @@ public class AboutDialog extends DialogFragment {
|
||||
|
||||
AlertDialog.Builder b = new AlertDialog.Builder(getActivity());
|
||||
b.setTitle(R.string.menu_about)
|
||||
.setView(view);
|
||||
.setView(view)
|
||||
.setNeutralButton(R.string.label_licenses, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialogInterface, int i) {
|
||||
Intent lic = new Intent(getActivity(), LicenseActivity.class);
|
||||
startActivity(lic);
|
||||
}
|
||||
});
|
||||
return b.create();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,42 @@
|
||||
package net.i2p.android.router.dialog;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.text.util.Linkify;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import net.i2p.android.help.HelpActivity;
|
||||
import net.i2p.android.router.R;
|
||||
import net.i2p.android.router.util.I2Patterns;
|
||||
|
||||
public class ConfigureBrowserDialog extends DialogFragment {
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
AlertDialog.Builder b = new AlertDialog.Builder(getActivity());
|
||||
b.setTitle(R.string.configure_browser_title)
|
||||
.setMessage(R.string.configure_browser_for_i2p)
|
||||
.setCancelable(false)
|
||||
.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialogInterface, int i) {
|
||||
dialogInterface.dismiss();
|
||||
Intent hi = new Intent(getActivity(), HelpActivity.class);
|
||||
hi.putExtra(HelpActivity.CATEGORY, HelpActivity.CAT_CONFIGURE_BROWSER);
|
||||
startActivity(hi);
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialogInterface, int i) {
|
||||
dialogInterface.cancel();
|
||||
}
|
||||
});
|
||||
return b.create();
|
||||
}
|
||||
}
|
@ -4,6 +4,7 @@ import net.i2p.android.router.R;
|
||||
import net.i2p.android.router.util.I2Patterns;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.text.util.Linkify;
|
||||
@ -13,7 +14,7 @@ import android.widget.TextView;
|
||||
|
||||
public class FirstStartDialog extends DialogFragment {
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle SavedInstanceState) {
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
LayoutInflater li = LayoutInflater.from(getActivity());
|
||||
View view = li.inflate(R.layout.fragment_dialog_first_start, null);
|
||||
|
||||
@ -24,7 +25,7 @@ public class FirstStartDialog extends DialogFragment {
|
||||
|
||||
AlertDialog.Builder b = new AlertDialog.Builder(getActivity());
|
||||
b.setTitle(R.string.first_start_title)
|
||||
.setView(view);
|
||||
.setView(view);
|
||||
return b.create();
|
||||
}
|
||||
}
|
||||
|
@ -3,17 +3,18 @@ package net.i2p.android.router.dialog;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.text.method.ScrollingMovementMethod;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import net.i2p.android.router.R;
|
||||
import net.i2p.android.router.util.Util;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import net.i2p.android.router.R;
|
||||
import net.i2p.android.router.util.Util;
|
||||
|
||||
/**
|
||||
* Display a raw text resource.
|
||||
@ -30,7 +31,6 @@ public class TextResourceDialog extends DialogFragment {
|
||||
{
|
||||
View v = inflater.inflate(R.layout.fragment_dialog_text_resource, container, false);
|
||||
TextView tv = (TextView) v.findViewById(R.id.text_resource_text);
|
||||
tv.setMovementMethod(ScrollingMovementMethod.getInstance());
|
||||
String title = getArguments().getString(TEXT_DIALOG_TITLE);
|
||||
if (title != null)
|
||||
getDialog().setTitle(title);
|
||||
|
@ -2,12 +2,19 @@ package net.i2p.android.router.log;
|
||||
|
||||
import net.i2p.android.router.I2PFragmentBase;
|
||||
import net.i2p.android.router.R;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.text.method.ScrollingMovementMethod;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
public class LogDetailFragment extends I2PFragmentBase {
|
||||
public static final String LOG_ENTRY = "log_entry";
|
||||
@ -22,6 +29,12 @@ public class LogDetailFragment extends I2PFragmentBase {
|
||||
return f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setHasOptionsMenu(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
@ -34,4 +47,31 @@ public class LogDetailFragment extends I2PFragmentBase {
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
inflater.inflate(R.menu.fragment_log_actions, menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
// Handle presses on the action bar items
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_copy_logs:
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
|
||||
android.text.ClipboardManager clipboard = (android.text.ClipboardManager) getActivity().getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
clipboard.setText(mEntry);
|
||||
} else {
|
||||
android.content.ClipboardManager clipboard = (android.content.ClipboardManager) getActivity().getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
android.content.ClipData clip = android.content.ClipData.newPlainText(
|
||||
getString(R.string.i2p_android_logs), mEntry);
|
||||
clipboard.setPrimaryClip(clip);
|
||||
}
|
||||
|
||||
Toast.makeText(getActivity(), R.string.logs_copied_to_clipboard, Toast.LENGTH_SHORT).show();
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,21 @@
|
||||
package net.i2p.android.router.log;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.ListFragment;
|
||||
import android.support.v4.app.LoaderManager;
|
||||
import android.support.v4.content.Loader;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.android.router.R;
|
||||
@ -25,6 +33,7 @@ public class LogFragment extends ListFragment implements
|
||||
private static final int LEVEL_ALL = 2;
|
||||
|
||||
OnEntrySelectedListener mEntrySelectedCallback;
|
||||
private final List<String> mLogEntries = new ArrayList<String>();
|
||||
private LogAdapter mAdapter;
|
||||
private TextView mHeaderView;
|
||||
private String mLogLevel;
|
||||
@ -34,6 +43,8 @@ public class LogFragment extends ListFragment implements
|
||||
private int mActivatedPosition = ListView.INVALID_POSITION;
|
||||
private boolean mActivateOnItemClick = false;
|
||||
|
||||
private MenuItem mCopyLogs;
|
||||
|
||||
// Container Activity must implement this interface
|
||||
public interface OnEntrySelectedListener {
|
||||
public void onEntrySelected(String entry);
|
||||
@ -62,6 +73,12 @@ public class LogFragment extends ListFragment implements
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setHasOptionsMenu(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
@ -122,6 +139,53 @@ public class LogFragment extends ListFragment implements
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
inflater.inflate(R.menu.fragment_log_actions, menu);
|
||||
mCopyLogs = menu.findItem(R.id.action_copy_logs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPrepareOptionsMenu(Menu menu) {
|
||||
mCopyLogs.setVisible(I2PAppContext.getCurrentContext() != null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
// Handle presses on the action bar items
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_copy_logs:
|
||||
String logText = "";
|
||||
synchronized (mLogEntries) {
|
||||
for (String logEntry : mLogEntries) {
|
||||
logText += logEntry;
|
||||
}
|
||||
}
|
||||
|
||||
boolean isError = "ERROR".equals(mLogLevel);
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
|
||||
android.text.ClipboardManager clipboard = (android.text.ClipboardManager) getActivity().getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
clipboard.setText(logText);
|
||||
} else {
|
||||
android.content.ClipboardManager clipboard = (android.content.ClipboardManager) getActivity().getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
android.content.ClipData clip = android.content.ClipData.newPlainText(
|
||||
isError ? getString(R.string.i2p_android_error_logs) : getString(R.string.i2p_android_logs),
|
||||
logText);
|
||||
clipboard.setPrimaryClip(clip);
|
||||
}
|
||||
|
||||
int textId;
|
||||
if (isError)
|
||||
textId = R.string.error_logs_copied_to_clipboard;
|
||||
else
|
||||
textId = R.string.logs_copied_to_clipboard;
|
||||
Toast.makeText(getActivity(), textId, Toast.LENGTH_SHORT).show();
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns on activate-on-click mode. When this mode is on, list items will be
|
||||
* given the 'activated' state when touched.
|
||||
@ -167,6 +231,10 @@ public class LogFragment extends ListFragment implements
|
||||
List<String> data) {
|
||||
if (loader.getId() == ("ERROR".equals(mLogLevel) ?
|
||||
LEVEL_ERROR : LEVEL_ALL)) {
|
||||
synchronized (mLogEntries) {
|
||||
mLogEntries.clear();
|
||||
mLogEntries.addAll(data);
|
||||
}
|
||||
mAdapter.setData(data);
|
||||
String header = getHeader(data.size(), ("ERROR".equals(mLogLevel)));
|
||||
mHeaderView.setText(header);
|
||||
|
@ -11,6 +11,7 @@ import android.net.NetworkInfo;
|
||||
import android.os.IBinder;
|
||||
import net.i2p.android.router.service.RouterBinder;
|
||||
import net.i2p.android.router.service.RouterService;
|
||||
import net.i2p.android.router.util.Connectivity;
|
||||
import net.i2p.android.router.util.Util;
|
||||
|
||||
public class I2PReceiver extends BroadcastReceiver {
|
||||
@ -33,7 +34,7 @@ public class I2PReceiver extends BroadcastReceiver {
|
||||
intents.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
|
||||
@SuppressWarnings("LeakingThisInConstructor")
|
||||
Intent registerReceiver = context.registerReceiver(this, intents);
|
||||
_wasConnected = Util.isConnected(context);
|
||||
_wasConnected = Connectivity.isConnected(context);
|
||||
}
|
||||
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
@ -57,7 +58,7 @@ public class I2PReceiver extends BroadcastReceiver {
|
||||
|
||||
if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION) ||
|
||||
action.equals(Intent.ACTION_TIME_TICK)) {
|
||||
boolean connected = Util.isConnected(context);
|
||||
boolean connected = Connectivity.isConnected(context);
|
||||
if (_wasConnected && !connected) {
|
||||
// notify + 2 timer ticks
|
||||
if (++_unconnectedCount >= 3) {
|
||||
|
@ -20,6 +20,7 @@ import java.util.Random;
|
||||
|
||||
import net.i2p.android.router.R;
|
||||
import net.i2p.android.router.receiver.I2PReceiver;
|
||||
import net.i2p.android.router.util.Connectivity;
|
||||
import net.i2p.android.router.util.Notifications;
|
||||
import net.i2p.android.router.util.Util;
|
||||
import net.i2p.data.DataHelper;
|
||||
@ -115,7 +116,7 @@ public class RouterService extends Service {
|
||||
return START_NOT_STICKY;
|
||||
}
|
||||
_receiver = new I2PReceiver(this);
|
||||
if(Util.isConnected(this)) {
|
||||
if(Connectivity.isConnected(this)) {
|
||||
if(restart) {
|
||||
_statusBar.replace(StatusBar.ICON_STARTING, "I2P is restarting");
|
||||
} else {
|
||||
@ -149,7 +150,7 @@ public class RouterService extends Service {
|
||||
Util.d(MARKER + this + " waiter handler"
|
||||
+ " Current state is: " + _state);
|
||||
if(_state == State.WAITING) {
|
||||
if(Util.isConnected(RouterService.this)) {
|
||||
if(Connectivity.isConnected(RouterService.this)) {
|
||||
synchronized(_stateLock) {
|
||||
if(_state != State.WAITING) {
|
||||
return;
|
||||
@ -322,12 +323,11 @@ public class RouterService extends Service {
|
||||
return;
|
||||
}
|
||||
setState(State.RUNNING);
|
||||
List<?> contexts = RouterContext.listContexts();
|
||||
if((contexts == null) || (contexts.isEmpty())) {
|
||||
_statusBar.replace(StatusBar.ICON_RUNNING, "I2P is running");
|
||||
_context = Util.getRouterContext();
|
||||
if (_context == null) {
|
||||
throw new IllegalStateException("No contexts. This is usually because the router is either starting up or shutting down.");
|
||||
}
|
||||
_statusBar.replace(StatusBar.ICON_RUNNING, "I2P is running");
|
||||
_context = (RouterContext) contexts.get(0);
|
||||
_context.router().setKillVMOnEnd(false);
|
||||
Job loadJob = new LoadClientsJob(_context, _notif);
|
||||
_context.jobQueue().addJob(loadJob);
|
||||
|
@ -5,6 +5,7 @@ import java.util.List;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import net.i2p.android.router.util.Util;
|
||||
import net.i2p.router.RouterContext;
|
||||
import net.i2p.stat.Rate;
|
||||
import net.i2p.stat.RateStat;
|
||||
@ -18,15 +19,20 @@ public class StatSummarizer implements Runnable {
|
||||
private Thread _thread;
|
||||
|
||||
public StatSummarizer() {
|
||||
_context = RouterContext.listContexts().get(0);
|
||||
_context = Util.getRouterContext();
|
||||
_listeners = new CopyOnWriteArrayList<SummaryListener>();
|
||||
_instance = this;
|
||||
_context.addShutdownTask(new Shutdown());
|
||||
if (_context != null)
|
||||
_context.addShutdownTask(new Shutdown());
|
||||
}
|
||||
|
||||
public static StatSummarizer instance() { return _instance; }
|
||||
|
||||
public void run() {
|
||||
// We can't do anything without a RouterContext
|
||||
if (_context == null)
|
||||
return;
|
||||
|
||||
_thread = Thread.currentThread();
|
||||
String specs = "";
|
||||
while (_isRunning && _context.router().isAlive()) {
|
||||
|
134
app/src/main/java/net/i2p/android/router/util/Connectivity.java
Normal file
134
app/src/main/java/net/i2p/android/router/util/Connectivity.java
Normal file
@ -0,0 +1,134 @@
|
||||
// License: MIT
|
||||
// http://opensource.org/licenses/MIT
|
||||
package net.i2p.android.router.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.NetworkInfo;
|
||||
import android.telephony.TelephonyManager;
|
||||
|
||||
/**
|
||||
* Check device's network connectivity and speed.
|
||||
*
|
||||
* @author emil http://stackoverflow.com/users/220710/emil
|
||||
* @author str4d
|
||||
*/
|
||||
public class Connectivity {
|
||||
/**
|
||||
* Get the network info.
|
||||
*
|
||||
* @param context the Context.
|
||||
* @return the active NetworkInfo.
|
||||
*/
|
||||
public static NetworkInfo getNetworkInfo(Context context) {
|
||||
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
return cm.getActiveNetworkInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if there is any connectivity at all.
|
||||
*
|
||||
* @param context the Context.
|
||||
* @return true if we are connected to a network, false otherwise.
|
||||
*/
|
||||
public static boolean isConnected(Context context) {
|
||||
NetworkInfo info = Connectivity.getNetworkInfo(context);
|
||||
// Works on emulator and devices.
|
||||
// Note the use of isAvailable() - without this, isConnected() can
|
||||
// return true when Wifi is disabled.
|
||||
// http://stackoverflow.com/a/2937915
|
||||
return (info != null && info.isAvailable() && info.isConnected());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if there is any connectivity to a Wifi network.
|
||||
*
|
||||
* @param context the Context.
|
||||
* @return true if we are connected to a Wifi network, false otherwise.
|
||||
*/
|
||||
public static boolean isConnectedWifi(Context context) {
|
||||
NetworkInfo info = Connectivity.getNetworkInfo(context);
|
||||
return (info != null && info.isAvailable() && info.isConnected() &&
|
||||
info.getType() == ConnectivityManager.TYPE_WIFI);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if there is any connectivity to a mobile network.
|
||||
*
|
||||
* @param context the Context.
|
||||
* @return true if we are connected to a mobile network, false otherwise.
|
||||
*/
|
||||
public static boolean isConnectedMobile(Context context) {
|
||||
NetworkInfo info = Connectivity.getNetworkInfo(context);
|
||||
return (info != null && info.isAvailable() && info.isConnected() &&
|
||||
info.getType() == ConnectivityManager.TYPE_MOBILE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if there is fast connectivity.
|
||||
*
|
||||
* @param context the Context.
|
||||
* @return true if we have "fast" connectivity, false otherwise.
|
||||
*/
|
||||
public static boolean isConnectedFast(Context context) {
|
||||
NetworkInfo info = Connectivity.getNetworkInfo(context);
|
||||
return (info != null && info.isAvailable() && info.isConnected() &&
|
||||
Connectivity.isConnectionFast(info.getType(), info.getSubtype()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the connection is fast.
|
||||
*
|
||||
* @param type the network type.
|
||||
* @param subType the network subtype.
|
||||
* @return true if the provided type/subtype combination is classified as fast.
|
||||
*/
|
||||
public static boolean isConnectionFast(int type, int subType) {
|
||||
if (type == ConnectivityManager.TYPE_WIFI) {
|
||||
return true;
|
||||
} else if (type == ConnectivityManager.TYPE_MOBILE) {
|
||||
switch (subType) {
|
||||
case TelephonyManager.NETWORK_TYPE_1xRTT:
|
||||
return false; // ~ 50-100 kbps
|
||||
case TelephonyManager.NETWORK_TYPE_CDMA:
|
||||
return false; // ~ 14-64 kbps
|
||||
case TelephonyManager.NETWORK_TYPE_EDGE:
|
||||
return false; // ~ 50-100 kbps
|
||||
case TelephonyManager.NETWORK_TYPE_EVDO_0:
|
||||
return true; // ~ 400-1000 kbps
|
||||
case TelephonyManager.NETWORK_TYPE_EVDO_A:
|
||||
return true; // ~ 600-1400 kbps
|
||||
case TelephonyManager.NETWORK_TYPE_GPRS:
|
||||
return false; // ~ 100 kbps
|
||||
case TelephonyManager.NETWORK_TYPE_HSDPA:
|
||||
return true; // ~ 2-14 Mbps
|
||||
case TelephonyManager.NETWORK_TYPE_HSPA:
|
||||
return true; // ~ 700-1700 kbps
|
||||
case TelephonyManager.NETWORK_TYPE_HSUPA:
|
||||
return true; // ~ 1-23 Mbps
|
||||
case TelephonyManager.NETWORK_TYPE_UMTS:
|
||||
return true; // ~ 400-7000 kbps
|
||||
/*
|
||||
* Above API level 7, make sure to set android:targetSdkVersion
|
||||
* to appropriate level to use these
|
||||
*/
|
||||
case TelephonyManager.NETWORK_TYPE_EHRPD: // API level 11
|
||||
return true; // ~ 1-2 Mbps
|
||||
case TelephonyManager.NETWORK_TYPE_EVDO_B: // API level 9
|
||||
return true; // ~ 5 Mbps
|
||||
case TelephonyManager.NETWORK_TYPE_HSPAP: // API level 13
|
||||
return true; // ~ 10-20 Mbps
|
||||
case TelephonyManager.NETWORK_TYPE_IDEN: // API level 8
|
||||
return false; // ~25 kbps
|
||||
case TelephonyManager.NETWORK_TYPE_LTE: // API level 11
|
||||
return true; // ~ 10+ Mbps
|
||||
// Unknown
|
||||
case TelephonyManager.NETWORK_TYPE_UNKNOWN:
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@ -4,23 +4,28 @@ import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.NetworkInfo;
|
||||
import android.os.Build;
|
||||
import android.content.res.Resources;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.data.DataHelper;
|
||||
import net.i2p.router.Router;
|
||||
import net.i2p.router.RouterContext;
|
||||
import net.i2p.router.transport.TransportManager;
|
||||
import net.i2p.util.OrderedProperties;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
public abstract class Util {
|
||||
private static final boolean _isEmulator = Build.MODEL.equals("sdk");
|
||||
|
||||
public static String getOurVersion(Context ctx) {
|
||||
PackageManager pm = ctx.getPackageManager();
|
||||
String us = ctx.getPackageName();
|
||||
@ -36,18 +41,17 @@ public abstract class Util {
|
||||
return "??";
|
||||
}
|
||||
|
||||
public static boolean isConnected(Context ctx) {
|
||||
// emulator always returns null NetworkInfo
|
||||
if (_isEmulator)
|
||||
return true;
|
||||
NetworkInfo current = getNetworkInfo(ctx);
|
||||
return current != null && current.isConnected();
|
||||
}
|
||||
|
||||
public static NetworkInfo getNetworkInfo(Context ctx) {
|
||||
ConnectivityManager cm = (ConnectivityManager) ctx.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
NetworkInfo current = cm.getActiveNetworkInfo();
|
||||
return current;
|
||||
/**
|
||||
* Get the active RouterContext.
|
||||
*
|
||||
* @return the active RouterContext, or null
|
||||
*/
|
||||
public static RouterContext getRouterContext() {
|
||||
List<RouterContext> contexts = RouterContext.listContexts();
|
||||
if ( !((contexts == null) || (contexts.isEmpty())) ) {
|
||||
return contexts.get(0);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static final String ANDROID_TAG = "I2P";
|
||||
@ -177,4 +181,131 @@ public abstract class Util {
|
||||
|
||||
return pList;
|
||||
}
|
||||
|
||||
// propName -> defaultValue
|
||||
private static HashMap<String, Boolean> booleanOptionsRequiringRestart = new HashMap<String, Boolean>();
|
||||
private static HashMap<String, String> stringOptionsRequiringRestart = new HashMap<String, String>();
|
||||
static {
|
||||
HashMap<String, Boolean> boolToAdd = new HashMap<String, Boolean>();
|
||||
HashMap<String, String> strToAdd = new HashMap<String, String>();
|
||||
|
||||
boolToAdd.put(TransportManager.PROP_ENABLE_UPNP, true);
|
||||
boolToAdd.put(TransportManager.PROP_ENABLE_NTCP, true);
|
||||
boolToAdd.put(TransportManager.PROP_ENABLE_UDP, true);
|
||||
boolToAdd.put(Router.PROP_HIDDEN, false);
|
||||
|
||||
booleanOptionsRequiringRestart.putAll(boolToAdd);
|
||||
stringOptionsRequiringRestart.putAll(strToAdd);
|
||||
}
|
||||
/**
|
||||
* This function performs two tasks:
|
||||
* <ul><li>
|
||||
* The Properties object is modified to ensure that all options are valid
|
||||
* for the current state of the Android device (e.g. what type of network
|
||||
* the device is connected to).
|
||||
* </li><li>
|
||||
* The Properties object is checked to determine whether any options have
|
||||
* changed that will require a router restart.
|
||||
* </li></ul>
|
||||
*
|
||||
* @param props a Properties object containing the router.config
|
||||
* @return true if the router needs to be restarted.
|
||||
*/
|
||||
public static boolean checkAndCorrectRouterConfig(Context context, Properties props) {
|
||||
// Disable UPnP on mobile networks, ignoring user's configuration
|
||||
// TODO disabled until changes elsewhere are finished
|
||||
//if (Connectivity.isConnectedMobile(context)) {
|
||||
// props.setProperty(TransportManager.PROP_ENABLE_UPNP, Boolean.toString(false));
|
||||
//}
|
||||
|
||||
// Now check if a restart is required
|
||||
boolean restartRequired = false;
|
||||
RouterContext rCtx = getRouterContext();
|
||||
if (rCtx != null) {
|
||||
for (Map.Entry<String, Boolean> option : booleanOptionsRequiringRestart.entrySet()) {
|
||||
String propName = option.getKey();
|
||||
boolean defaultValue = option.getValue();
|
||||
restartRequired |= (
|
||||
Boolean.parseBoolean(props.getProperty(propName, Boolean.toString(defaultValue))) !=
|
||||
(defaultValue ? rCtx.getBooleanPropertyDefaultTrue(propName) : rCtx.getBooleanProperty(propName))
|
||||
);
|
||||
}
|
||||
if (!restartRequired) { // Cut out now if we already know the answer
|
||||
for (Map.Entry<String, String> option : stringOptionsRequiringRestart.entrySet()) {
|
||||
String propName = option.getKey();
|
||||
String defaultValue = option.getValue();
|
||||
restartRequired |= props.getProperty(propName, defaultValue).equals(
|
||||
rCtx.getProperty(propName, defaultValue));
|
||||
}
|
||||
}
|
||||
}
|
||||
return restartRequired;
|
||||
}
|
||||
|
||||
public static String getFileDir(Context context) {
|
||||
// This needs to be changed so that we can have an alternative place
|
||||
return context.getFilesDir().getAbsolutePath();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write properties to a file. If the file does not exist, it is created.
|
||||
* If the properties already exist in the file, they are updated.
|
||||
*
|
||||
* @param dir the file directory
|
||||
* @param file relative to dir
|
||||
* @param props properties to set
|
||||
*/
|
||||
public static void writePropertiesToFile(Context ctx, String dir, String file, Properties props) {
|
||||
mergeResourceToFile(ctx, dir, file, 0, props);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load defaults from resource, then add props from settings, and write back.
|
||||
* If resID is 0, defaults are not written over the existing file content.
|
||||
*
|
||||
* @param dir the file directory
|
||||
* @param file relative to dir
|
||||
* @param resID the ID of the default resource, or 0
|
||||
* @param userProps local properties or null
|
||||
*/
|
||||
public static void mergeResourceToFile(Context ctx, String dir, String file, int resID, Properties userProps) {
|
||||
InputStream fin = null;
|
||||
InputStream in = null;
|
||||
|
||||
try {
|
||||
Properties props = new OrderedProperties();
|
||||
try {
|
||||
fin = new FileInputStream(new File(dir, file));
|
||||
DataHelper.loadProps(props, fin);
|
||||
if (resID > 0)
|
||||
Util.d("Merging resource into file " + file);
|
||||
else
|
||||
Util.d("Merging properties into file " + file);
|
||||
} catch (IOException ioe) {
|
||||
if (resID > 0)
|
||||
Util.d("Creating file " + file + " from resource");
|
||||
else
|
||||
Util.d("Creating file " + file + " from properties");
|
||||
}
|
||||
|
||||
// write in default settings
|
||||
if (resID > 0)
|
||||
in = ctx.getResources().openRawResource(resID);
|
||||
if (in != null)
|
||||
DataHelper.loadProps(props, in);
|
||||
|
||||
// override with user settings
|
||||
if (userProps != null)
|
||||
props.putAll(userProps);
|
||||
|
||||
File path = new File(dir, file);
|
||||
DataHelper.storeProps(props, path);
|
||||
Util.d("Saved " + props.size() +" properties in " + file);
|
||||
} catch (IOException ioe) {
|
||||
} catch (Resources.NotFoundException nfe) {
|
||||
} finally {
|
||||
if (in != null) try { in.close(); } catch (IOException ioe) {}
|
||||
if (fin != null) try { fin.close(); } catch (IOException ioe) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ import java.io.OutputStream;
|
||||
import net.i2p.android.apps.EepGetFetcher;
|
||||
import net.i2p.android.router.provider.CacheProvider;
|
||||
import net.i2p.android.router.util.AppCache;
|
||||
import net.i2p.android.router.util.Connectivity;
|
||||
import net.i2p.android.router.util.Util;
|
||||
import net.i2p.data.DataHelper;
|
||||
import net.i2p.util.EepGet;
|
||||
@ -77,7 +78,7 @@ public class I2PWebViewClient extends WebViewClient {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!Util.isConnected(view.getContext())) {
|
||||
if (!Connectivity.isConnected(view.getContext())) {
|
||||
fail(view, "No Internet connection is available");
|
||||
return true;
|
||||
}
|
||||
|
@ -0,0 +1,162 @@
|
||||
/*
|
||||
* Copyright (C) 2013-2014 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||
* Copyright (C) 2013 Mohammed Lakkadshaw
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.sufficientlysecure.htmltextview;
|
||||
|
||||
import java.util.Vector;
|
||||
|
||||
import org.xml.sax.XMLReader;
|
||||
|
||||
import android.text.Editable;
|
||||
import android.text.Html;
|
||||
import android.text.Layout;
|
||||
import android.text.Spannable;
|
||||
import android.text.style.AlignmentSpan;
|
||||
import android.text.style.BulletSpan;
|
||||
import android.text.style.LeadingMarginSpan;
|
||||
import android.text.style.TypefaceSpan;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* Some parts of this code are based on android.text.Html
|
||||
*/
|
||||
public class HtmlTagHandler implements Html.TagHandler {
|
||||
private int mListItemCount = 0;
|
||||
private Vector<String> mListParents = new Vector<String>();
|
||||
|
||||
private static class Code {
|
||||
}
|
||||
|
||||
private static class Center {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleTag(final boolean opening, final String tag, Editable output, final XMLReader xmlReader) {
|
||||
if (opening) {
|
||||
// opening tag
|
||||
if (HtmlTextView.DEBUG) {
|
||||
Log.d(HtmlTextView.TAG, "opening, output: " + output.toString());
|
||||
}
|
||||
|
||||
if (tag.equalsIgnoreCase("ul") || tag.equalsIgnoreCase("ol") || tag.equalsIgnoreCase("dd")) {
|
||||
mListParents.add(tag);
|
||||
mListItemCount = 0;
|
||||
} else if (tag.equalsIgnoreCase("code")) {
|
||||
start(output, new Code());
|
||||
} else if (tag.equalsIgnoreCase("center")) {
|
||||
start(output, new Center());
|
||||
}
|
||||
} else {
|
||||
// closing tag
|
||||
if (HtmlTextView.DEBUG) {
|
||||
Log.d(HtmlTextView.TAG, "closing, output: " + output.toString());
|
||||
}
|
||||
|
||||
if (tag.equalsIgnoreCase("ul") || tag.equalsIgnoreCase("ol") || tag.equalsIgnoreCase("dd")) {
|
||||
mListParents.remove(tag);
|
||||
mListItemCount = 0;
|
||||
} else if (tag.equalsIgnoreCase("li")) {
|
||||
handleListTag(output);
|
||||
} else if (tag.equalsIgnoreCase("code")) {
|
||||
end(output, Code.class, new TypefaceSpan("monospace"), false);
|
||||
} else if (tag.equalsIgnoreCase("center")) {
|
||||
end(output, Center.class, new AlignmentSpan.Standard(Layout.Alignment.ALIGN_CENTER), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark the opening tag by using private classes
|
||||
*
|
||||
* @param output
|
||||
* @param mark
|
||||
*/
|
||||
private void start(Editable output, Object mark) {
|
||||
int len = output.length();
|
||||
output.setSpan(mark, len, len, Spannable.SPAN_MARK_MARK);
|
||||
|
||||
if (HtmlTextView.DEBUG) {
|
||||
Log.d(HtmlTextView.TAG, "len: " + len);
|
||||
}
|
||||
}
|
||||
|
||||
private void end(Editable output, Class kind, Object repl, boolean paragraphStyle) {
|
||||
Object obj = getLast(output, kind);
|
||||
// start of the tag
|
||||
int where = output.getSpanStart(obj);
|
||||
// end of the tag
|
||||
int len = output.length();
|
||||
|
||||
output.removeSpan(obj);
|
||||
|
||||
if (where != len) {
|
||||
// paragraph styles like AlignmentSpan need to end with a new line!
|
||||
if (paragraphStyle) {
|
||||
output.append("\n");
|
||||
len++;
|
||||
}
|
||||
output.setSpan(repl, where, len, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
}
|
||||
|
||||
if (HtmlTextView.DEBUG) {
|
||||
Log.d(HtmlTextView.TAG, "where: " + where);
|
||||
Log.d(HtmlTextView.TAG, "len: " + len);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get last marked position of a specific tag kind (private class)
|
||||
*
|
||||
* @param text
|
||||
* @param kind
|
||||
* @return
|
||||
*/
|
||||
private Object getLast(Editable text, Class kind) {
|
||||
Object[] objs = text.getSpans(0, text.length(), kind);
|
||||
if (objs.length == 0) {
|
||||
return null;
|
||||
} else {
|
||||
for (int i = objs.length; i > 0; i--) {
|
||||
if (text.getSpanFlags(objs[i - 1]) == Spannable.SPAN_MARK_MARK) {
|
||||
return objs[i - 1];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void handleListTag(Editable output) {
|
||||
if (mListParents.lastElement().equals("ul")) {
|
||||
output.append("\n");
|
||||
String[] split = output.toString().split("\n");
|
||||
|
||||
int lastIndex = split.length - 1;
|
||||
int start = output.length() - split[lastIndex].length() - 1;
|
||||
output.setSpan(new BulletSpan(15 * mListParents.size()), start, output.length(), 0);
|
||||
} else if (mListParents.lastElement().equals("ol")) {
|
||||
mListItemCount++;
|
||||
|
||||
output.append("\n");
|
||||
String[] split = output.toString().split("\n");
|
||||
|
||||
int lastIndex = split.length - 1;
|
||||
int start = output.length() - split[lastIndex].length() - 1;
|
||||
output.insert(start, mListItemCount + ". ");
|
||||
output.setSpan(new LeadingMarginSpan.Standard(15 * mListParents.size()), start, output.length(), 0);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (C) 2013-2014 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.sufficientlysecure.htmltextview;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.Html;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
public class HtmlTextView extends JellyBeanSpanFixTextView {
|
||||
|
||||
public static final String TAG = "HtmlTextView";
|
||||
public static final boolean DEBUG = false;
|
||||
|
||||
public HtmlTextView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
public HtmlTextView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public HtmlTextView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* http://stackoverflow.com/questions/309424/read-convert-an-inputstream-to-a-string
|
||||
*
|
||||
* @param is
|
||||
* @return
|
||||
*/
|
||||
static private String convertStreamToString(java.io.InputStream is) {
|
||||
java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
|
||||
return s.hasNext() ? s.next() : "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads HTML from a raw resource, i.e., a HTML file in res/raw/.
|
||||
* This allows translatable resource (e.g., res/raw-de/ for german).
|
||||
* The containing HTML is parsed to Android's Spannable format and then displayed.
|
||||
*
|
||||
* @param context
|
||||
* @param id for example: R.raw.help
|
||||
*/
|
||||
public void setHtmlFromRawResource(Context context, int id, boolean useLocalDrawables) {
|
||||
// load html from html file from /res/raw
|
||||
InputStream inputStreamText = context.getResources().openRawResource(id);
|
||||
|
||||
setHtmlFromString(convertStreamToString(inputStreamText), useLocalDrawables);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses String containing HTML to Android's Spannable format and displays it in this TextView.
|
||||
*
|
||||
* @param html String containing HTML, for example: "<b>Hello world!</b>"
|
||||
*/
|
||||
public void setHtmlFromString(String html, boolean useLocalDrawables) {
|
||||
Html.ImageGetter imgGetter;
|
||||
if (useLocalDrawables) {
|
||||
imgGetter = new LocalImageGetter(getContext());
|
||||
} else {
|
||||
imgGetter = new UrlImageGetter(this, getContext());
|
||||
}
|
||||
// this uses Android's Html class for basic parsing, and HtmlTagHandler
|
||||
setText(Html.fromHtml(html, imgGetter, new HtmlTagHandler()));
|
||||
|
||||
// make links work
|
||||
setMovementMethod(LinkMovementMethod.getInstance());
|
||||
|
||||
// no flickering when clicking textview for Android < 4, but overriders color...
|
||||
// text.setTextColor(getResources().getColor(android.R.color.secondary_text_dark_nodisable));
|
||||
}
|
||||
}
|
@ -0,0 +1,212 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||
* Copyright (C) 2012 Pierre-Yves Ricau <py.ricau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.sufficientlysecure.htmltextview;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.widget.TextView;
|
||||
|
||||
/**
|
||||
* <p/>
|
||||
* A {@link android.widget.TextView} that insert spaces around its text spans where needed to prevent
|
||||
* {@link IndexOutOfBoundsException} in {@link #onMeasure(int, int)} on Jelly Bean.
|
||||
* <p/>
|
||||
* When {@link #onMeasure(int, int)} throws an exception, we try to fix the text by adding spaces
|
||||
* around spans, until it works again. We then try removing some of the added spans, to minimize the
|
||||
* insertions.
|
||||
* <p/>
|
||||
* The fix is time consuming (a few ms, it depends on the size of your text), but it should only
|
||||
* happen once per text change.
|
||||
* <p/>
|
||||
* See http://code.google.com/p/android/issues/detail?id=35466
|
||||
*/
|
||||
public class JellyBeanSpanFixTextView extends TextView {
|
||||
|
||||
private static class FixingResult {
|
||||
public final boolean fixed;
|
||||
public final List<Object> spansWithSpacesBefore;
|
||||
public final List<Object> spansWithSpacesAfter;
|
||||
|
||||
public static FixingResult fixed(List<Object> spansWithSpacesBefore,
|
||||
List<Object> spansWithSpacesAfter) {
|
||||
return new FixingResult(true, spansWithSpacesBefore, spansWithSpacesAfter);
|
||||
}
|
||||
|
||||
public static FixingResult notFixed() {
|
||||
return new FixingResult(false, null, null);
|
||||
}
|
||||
|
||||
private FixingResult(boolean fixed, List<Object> spansWithSpacesBefore,
|
||||
List<Object> spansWithSpacesAfter) {
|
||||
this.fixed = fixed;
|
||||
this.spansWithSpacesBefore = spansWithSpacesBefore;
|
||||
this.spansWithSpacesAfter = spansWithSpacesAfter;
|
||||
}
|
||||
}
|
||||
|
||||
public JellyBeanSpanFixTextView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
public JellyBeanSpanFixTextView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public JellyBeanSpanFixTextView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
try {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
} catch (IndexOutOfBoundsException e) {
|
||||
fixOnMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If possible, fixes the Spanned text by adding spaces around spans when needed.
|
||||
*/
|
||||
private void fixOnMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
CharSequence text = getText();
|
||||
if (text instanceof Spanned) {
|
||||
SpannableStringBuilder builder = new SpannableStringBuilder(text);
|
||||
fixSpannedWithSpaces(builder, widthMeasureSpec, heightMeasureSpec);
|
||||
} else {
|
||||
if (HtmlTextView.DEBUG) {
|
||||
Log.d(HtmlTextView.TAG, "The text isn't a Spanned");
|
||||
}
|
||||
fallbackToString(widthMeasureSpec, heightMeasureSpec);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add spaces around spans until the text is fixed, and then removes the unneeded spaces
|
||||
*/
|
||||
private void fixSpannedWithSpaces(SpannableStringBuilder builder, int widthMeasureSpec,
|
||||
int heightMeasureSpec) {
|
||||
long startFix = System.currentTimeMillis();
|
||||
|
||||
FixingResult result = addSpacesAroundSpansUntilFixed(builder, widthMeasureSpec,
|
||||
heightMeasureSpec);
|
||||
|
||||
if (result.fixed) {
|
||||
removeUnneededSpaces(widthMeasureSpec, heightMeasureSpec, builder, result);
|
||||
} else {
|
||||
fallbackToString(widthMeasureSpec, heightMeasureSpec);
|
||||
}
|
||||
|
||||
if (HtmlTextView.DEBUG) {
|
||||
long fixDuration = System.currentTimeMillis() - startFix;
|
||||
Log.d(HtmlTextView.TAG, "fixSpannedWithSpaces() duration in ms: " + fixDuration);
|
||||
}
|
||||
}
|
||||
|
||||
private FixingResult addSpacesAroundSpansUntilFixed(SpannableStringBuilder builder,
|
||||
int widthMeasureSpec, int heightMeasureSpec) {
|
||||
|
||||
Object[] spans = builder.getSpans(0, builder.length(), Object.class);
|
||||
List<Object> spansWithSpacesBefore = new ArrayList<Object>(spans.length);
|
||||
List<Object> spansWithSpacesAfter = new ArrayList<Object>(spans.length);
|
||||
|
||||
for (Object span : spans) {
|
||||
int spanStart = builder.getSpanStart(span);
|
||||
if (isNotSpace(builder, spanStart - 1)) {
|
||||
builder.insert(spanStart, " ");
|
||||
spansWithSpacesBefore.add(span);
|
||||
}
|
||||
|
||||
int spanEnd = builder.getSpanEnd(span);
|
||||
if (isNotSpace(builder, spanEnd)) {
|
||||
builder.insert(spanEnd, " ");
|
||||
spansWithSpacesAfter.add(span);
|
||||
}
|
||||
|
||||
try {
|
||||
setTextAndMeasure(builder, widthMeasureSpec, heightMeasureSpec);
|
||||
return FixingResult.fixed(spansWithSpacesBefore, spansWithSpacesAfter);
|
||||
} catch (IndexOutOfBoundsException notFixed) {
|
||||
}
|
||||
}
|
||||
if (HtmlTextView.DEBUG) {
|
||||
Log.d(HtmlTextView.TAG, "Could not fix the Spanned by adding spaces around spans");
|
||||
}
|
||||
return FixingResult.notFixed();
|
||||
}
|
||||
|
||||
private boolean isNotSpace(CharSequence text, int where) {
|
||||
if (where < 0) {
|
||||
return true;
|
||||
}
|
||||
return text.charAt(where) != ' ';
|
||||
}
|
||||
|
||||
private void setTextAndMeasure(CharSequence text, int widthMeasureSpec, int heightMeasureSpec) {
|
||||
setText(text);
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
}
|
||||
|
||||
private void removeUnneededSpaces(int widthMeasureSpec, int heightMeasureSpec,
|
||||
SpannableStringBuilder builder, FixingResult result) {
|
||||
|
||||
for (Object span : result.spansWithSpacesAfter) {
|
||||
int spanEnd = builder.getSpanEnd(span);
|
||||
builder.delete(spanEnd, spanEnd + 1);
|
||||
try {
|
||||
setTextAndMeasure(builder, widthMeasureSpec, heightMeasureSpec);
|
||||
} catch (IndexOutOfBoundsException ignored) {
|
||||
builder.insert(spanEnd, " ");
|
||||
}
|
||||
}
|
||||
|
||||
boolean needReset = true;
|
||||
for (Object span : result.spansWithSpacesBefore) {
|
||||
int spanStart = builder.getSpanStart(span);
|
||||
builder.delete(spanStart - 1, spanStart);
|
||||
try {
|
||||
setTextAndMeasure(builder, widthMeasureSpec, heightMeasureSpec);
|
||||
needReset = false;
|
||||
} catch (IndexOutOfBoundsException ignored) {
|
||||
needReset = true;
|
||||
int newSpanStart = spanStart - 1;
|
||||
builder.insert(newSpanStart, " ");
|
||||
}
|
||||
}
|
||||
|
||||
if (needReset) {
|
||||
setText(builder);
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
}
|
||||
}
|
||||
|
||||
private void fallbackToString(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
if (HtmlTextView.DEBUG) {
|
||||
Log.d(HtmlTextView.TAG, "Fallback to unspanned text");
|
||||
}
|
||||
String fallbackText = getText().toString();
|
||||
setTextAndMeasure(fallbackText, widthMeasureSpec, heightMeasureSpec);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||
* Copyright (C) 2014 drawk
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.sufficientlysecure.htmltextview;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.text.Html;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* Copied from http://stackoverflow.com/a/22298833
|
||||
*/
|
||||
public class LocalImageGetter implements Html.ImageGetter {
|
||||
Context c;
|
||||
|
||||
public LocalImageGetter(Context c) {
|
||||
this.c = c;
|
||||
}
|
||||
|
||||
public Drawable getDrawable(String source) {
|
||||
int id = c.getResources().getIdentifier(source, "drawable", c.getPackageName());
|
||||
|
||||
if (id == 0) {
|
||||
// the drawable resource wasn't found in our package, maybe it is a stock android drawable?
|
||||
id = c.getResources().getIdentifier(source, "drawable", "android");
|
||||
}
|
||||
|
||||
if (id == 0) {
|
||||
// prevent a crash if the resource still can't be found
|
||||
Log.e(HtmlTextView.TAG, "source could not be found: " + source);
|
||||
return null;
|
||||
} else {
|
||||
Drawable d = c.getResources().getDrawable(id);
|
||||
d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
|
||||
return d;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Antarix Tandon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.sufficientlysecure.htmltextview;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.AsyncTask;
|
||||
import android.text.Html.ImageGetter;
|
||||
import android.view.View;
|
||||
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.impl.client.DefaultHttpClient;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.MalformedURLException;
|
||||
|
||||
public class UrlImageGetter implements ImageGetter {
|
||||
Context c;
|
||||
View container;
|
||||
|
||||
/**
|
||||
* Construct the URLImageParser which will execute AsyncTask and refresh the container
|
||||
*
|
||||
* @param t
|
||||
* @param c
|
||||
*/
|
||||
public UrlImageGetter(View t, Context c) {
|
||||
this.c = c;
|
||||
this.container = t;
|
||||
}
|
||||
|
||||
public Drawable getDrawable(String source) {
|
||||
UrlDrawable urlDrawable = new UrlDrawable();
|
||||
|
||||
// get the actual source
|
||||
ImageGetterAsyncTask asyncTask = new ImageGetterAsyncTask(urlDrawable);
|
||||
|
||||
asyncTask.execute(source);
|
||||
|
||||
// return reference to URLDrawable which will asynchronously load the image specified in the src tag
|
||||
return urlDrawable;
|
||||
}
|
||||
|
||||
public class ImageGetterAsyncTask extends AsyncTask<String, Void, Drawable> {
|
||||
UrlDrawable urlDrawable;
|
||||
|
||||
public ImageGetterAsyncTask(UrlDrawable d) {
|
||||
this.urlDrawable = d;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Drawable doInBackground(String... params) {
|
||||
String source = params[0];
|
||||
return fetchDrawable(source);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Drawable result) {
|
||||
// set the correct bound according to the result from HTTP call
|
||||
urlDrawable.setBounds(0, 0, 0 + result.getIntrinsicWidth(), 0 + result.getIntrinsicHeight());
|
||||
|
||||
// change the reference of the current drawable to the result from the HTTP call
|
||||
urlDrawable.drawable = result;
|
||||
|
||||
// redraw the image by invalidating the container
|
||||
UrlImageGetter.this.container.invalidate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Drawable from URL
|
||||
*
|
||||
* @param urlString
|
||||
* @return
|
||||
*/
|
||||
public Drawable fetchDrawable(String urlString) {
|
||||
try {
|
||||
InputStream is = fetch(urlString);
|
||||
Drawable drawable = Drawable.createFromStream(is, "src");
|
||||
drawable.setBounds(0, 0, 0 + drawable.getIntrinsicWidth(), 0 + drawable.getIntrinsicHeight());
|
||||
return drawable;
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private InputStream fetch(String urlString) throws MalformedURLException, IOException {
|
||||
DefaultHttpClient httpClient = new DefaultHttpClient();
|
||||
HttpGet request = new HttpGet(urlString);
|
||||
HttpResponse response = httpClient.execute(request);
|
||||
return response.getEntity().getContent();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public class UrlDrawable extends BitmapDrawable {
|
||||
protected Drawable drawable;
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
// override the draw to facilitate refresh function later
|
||||
if (drawable != null) {
|
||||
drawable.draw(canvas);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
BIN
app/src/main/res/drawable-hdpi/ic_content_copy.png
Normal file
BIN
app/src/main/res/drawable-hdpi/ic_content_copy.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
BIN
app/src/main/res/drawable-mdpi/ic_content_copy.png
Normal file
BIN
app/src/main/res/drawable-mdpi/ic_content_copy.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.3 KiB |
BIN
app/src/main/res/drawable-xhdpi/ic_content_copy.png
Normal file
BIN
app/src/main/res/drawable-xhdpi/ic_content_copy.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
Binary file not shown.
Before Width: | Height: | Size: 612 B |
Binary file not shown.
Before Width: | Height: | Size: 530 B |
8
app/src/main/res/drawable/tunnel_green.xml
Normal file
8
app/src/main/res/drawable/tunnel_green.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="oval">
|
||||
<solid android:color="@color/indicator_green" />
|
||||
<size android:height="@dimen/tunnel_indicator"
|
||||
android:width="@dimen/tunnel_indicator" />
|
||||
</shape>
|
8
app/src/main/res/drawable/tunnel_red.xml
Normal file
8
app/src/main/res/drawable/tunnel_red.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="oval">
|
||||
<solid android:color="@color/indicator_red" />
|
||||
<size android:height="@dimen/tunnel_indicator"
|
||||
android:width="@dimen/tunnel_indicator" />
|
||||
</shape>
|
8
app/src/main/res/drawable/tunnel_yellow.xml
Normal file
8
app/src/main/res/drawable/tunnel_yellow.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="oval">
|
||||
<solid android:color="@color/indicator_yellow" />
|
||||
<size android:height="@dimen/tunnel_indicator"
|
||||
android:width="@dimen/tunnel_indicator" />
|
||||
</shape>
|
8
app/src/main/res/layout/activity_help.xml
Normal file
8
app/src/main/res/layout/activity_help.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/main_fragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
</FrameLayout>
|
@ -1,17 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:padding="10dp"
|
||||
>
|
||||
<TextView
|
||||
android:id="@+id/text_resource_text"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:scrollbars="vertical"
|
||||
android:text="@string/label_release_notes"
|
||||
android:textColor="@android:color/secondary_text_dark"
|
||||
/>
|
||||
</LinearLayout>
|
||||
android:padding="10dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_resource_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/label_release_notes"
|
||||
android:textColor="@android:color/secondary_text_dark" />
|
||||
</ScrollView>
|
||||
|
||||
|
@ -1,20 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:padding="10dp"
|
||||
>
|
||||
<TextView
|
||||
android:id="@+id/news_status"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/label_news_status"
|
||||
/>
|
||||
<WebView
|
||||
android:id="@+id/news_webview"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
/>
|
||||
</LinearLayout>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="10dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/news_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_above="@+id/news_status"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/news_status"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="end"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:visibility="gone" />
|
||||
</RelativeLayout>
|
||||
|
||||
|
@ -5,9 +5,8 @@
|
||||
android:icon="@android:drawable/ic_menu_preferences"
|
||||
i2pandroid:showAsAction="never" >
|
||||
</item>
|
||||
<!-- Hide for now
|
||||
<item android:title="@string/menu_help"
|
||||
android:id="@+id/menu_help"
|
||||
i2pandroid:showAsAction="never" >
|
||||
</item> -->
|
||||
</item>
|
||||
</menu>
|
||||
|
@ -4,10 +4,6 @@
|
||||
android:id="@+id/menu_about"
|
||||
i2pandroid:showAsAction="never" >
|
||||
</item>
|
||||
<!-- Show directly here for now -->
|
||||
<item android:id="@+id/menu_help_licenses"
|
||||
android:title="@string/label_licenses"
|
||||
i2pandroid:showAsAction="never" />
|
||||
<item android:id="@+id/menu_help_release_notes"
|
||||
android:title="@string/label_release_notes"
|
||||
i2pandroid:showAsAction="never" />
|
||||
|
@ -13,8 +13,7 @@
|
||||
<item android:id="@+id/action_addressbook_settings"
|
||||
android:title="@string/menu_settings"
|
||||
i2pandroid:showAsAction="never" />
|
||||
<!-- Hide for now
|
||||
<item android:id="@+id/action_addressbook_help"
|
||||
android:title="@string/menu_help"
|
||||
i2pandroid:showAsAction="never" /> -->
|
||||
i2pandroid:showAsAction="never" />
|
||||
</menu>
|
||||
|
@ -14,9 +14,8 @@
|
||||
<item android:id="@+id/action_restart_all_tunnels"
|
||||
android:title="@string/action_i2ptunnel_restart_all"
|
||||
i2pandroid:showAsAction="never" />
|
||||
<!-- Hide for now
|
||||
<item android:id="@+id/action_i2ptunnel_help"
|
||||
android:title="@string/menu_help"
|
||||
i2pandroid:showAsAction="never" /> -->
|
||||
i2pandroid:showAsAction="never" />
|
||||
|
||||
</menu>
|
||||
|
8
app/src/main/res/menu/fragment_log_actions.xml
Normal file
8
app/src/main/res/menu/fragment_log_actions.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:i2pandroid="http://schemas.android.com/apk/res-auto" >
|
||||
<item android:id="@+id/action_copy_logs"
|
||||
android:title="@string/copy_logs"
|
||||
android:icon="@drawable/ic_content_copy"
|
||||
i2pandroid:showAsAction="ifRoom" />
|
||||
</menu>
|
12
app/src/main/res/raw/help_addressbook.html
Normal file
12
app/src/main/res/raw/help_addressbook.html
Normal file
@ -0,0 +1,12 @@
|
||||
<html>
|
||||
<head></head>
|
||||
<body>
|
||||
<h2>What is the addressbook?</h2>
|
||||
<p>The addressbook contains a list of I2P domain names and their Destinations (the I2P equivalent of an IP address).</p>
|
||||
<p>Every domain name corresponds to a service. Some of these domain names may be for websites; some are not. Many of them are now defunct; when the original operator takes down a service or loses its encryption keys, the corresponding domain name is lost.</p>
|
||||
|
||||
<h2>How are domain names added to the addressbook?</h2>
|
||||
<p>By default, the addressbook is subscribed to several I2P domain registration services. The domain names on the "Default" list are all from these services.</p>
|
||||
<p>You can manually add domain names on the "Private" list.</p>
|
||||
</body>
|
||||
</html>
|
33
app/src/main/res/raw/help_configure_browser.html
Normal file
33
app/src/main/res/raw/help_configure_browser.html
Normal file
@ -0,0 +1,33 @@
|
||||
<html>
|
||||
<head></head>
|
||||
<body>
|
||||
<h2>Pre-configured HTTP proxy</h2>
|
||||
<p>The app starts an HTTP proxy at localhost port 4444. To use it, configure your browser's HTTP proxy setting to use localhost:4444.</p>
|
||||
<p>The HTTP proxy is tested with the "Orweb" app. It should also work with Firefox 4 Mobile and the ProxyMob Firefox plugin, if you have at least 512 MB of RAM.</p>
|
||||
|
||||
<h2>Embedded web browser</h2>
|
||||
<p>An embedded web browser is provided for convenience that will open .i2p addresses. However, it is not recommended for general use; users should download the Orweb browser, or Firefox Mobile and the ProxyMob Firefox plugin.</p>
|
||||
<p>The browser does not use the outproxy for regular web sites. Javascript is disabled.</p>
|
||||
|
||||
<p>The following problems with eepsites are probably not fixable except on Android 3.0 (Honeycomb - i.e. tablets) and higher due to API limitations. The workaround is to use Firefox Mobile 4 and the ProxMob plugin (see below).</p>
|
||||
<ol>
|
||||
<li>Leaks .i2p DNS requests</li>
|
||||
<li>Can't load cross-site images or CSS</li>
|
||||
<li>No POSTs to forms</li>
|
||||
</ol>
|
||||
|
||||
<p>For eepsites, there are several other things to note:</p>
|
||||
<ol>
|
||||
<li>No way to type in addresses</li>
|
||||
<li>Several issues with images and CSS fetches</li>
|
||||
<li>Non-HTML links (pdf, text, images, torrent, etc.) probably don't work</li>
|
||||
<li>Frame support is flaky</li>
|
||||
</ol>
|
||||
|
||||
<p>For eepsites and websites, problems include:</p>
|
||||
<ol>
|
||||
<li>No cookies</li>
|
||||
<li>History and back issues</li>
|
||||
</ol>
|
||||
</body>
|
||||
</html>
|
16
app/src/main/res/raw/help_i2ptunnel.html
Normal file
16
app/src/main/res/raw/help_i2ptunnel.html
Normal file
@ -0,0 +1,16 @@
|
||||
<html>
|
||||
<head></head>
|
||||
<body>
|
||||
<h2>Using clients with pre-configured tunnels</h2>
|
||||
<p>The app starts an HTTP proxy at localhost port 4444 and IRC client tunnels at localhost ports 6668 - 6672. The IRC clients are "shared clients" on the same tunnels. Once you see the tunnel icon turn green on the main console (several minutes after startup), you should be able to connect.</p>
|
||||
|
||||
<p>The IRC proxy is tested with the "Android IRC Free" app. The IRC proxy destinations are:</p>
|
||||
<ol>
|
||||
<li>Port 6668: IRC2P - irc.postman.i2p, irc.freshcoffee.i2p, and irc.echelon.i2p</li>
|
||||
<li>Port 6669: irc.welterde.i2p</li>
|
||||
<li>Port 6670: irc.telecomix.i2p (probably down)</li>
|
||||
<li>Port 6671: irc.killyourtv.i2p</li>
|
||||
<li>Port 6672: Nameless IRC - irc.stream.i2p</li>
|
||||
</ol>
|
||||
</body>
|
||||
</html>
|
11
app/src/main/res/raw/help_main.html
Normal file
11
app/src/main/res/raw/help_main.html
Normal file
@ -0,0 +1,11 @@
|
||||
<html>
|
||||
<head></head>
|
||||
<body>
|
||||
<h2>What is this app for?</h2>
|
||||
<p>I2P Android enables your device to connect to the I2P network.</p>
|
||||
|
||||
<h2>How do I use it?</h2>
|
||||
<p>If you want to view I2P sites, see the "Browser configuration" help category.</p>
|
||||
<p>With this app installed, other apps that are designed for I2P will use it automatically.</p>
|
||||
</body>
|
||||
</html>
|
@ -1,6 +1,3 @@
|
||||
<html>
|
||||
<head></head>
|
||||
<body>
|
||||
<div lang="en">
|
||||
<h3>Congratulations on getting I2P installed!</h3>
|
||||
<p>
|
||||
@ -12,15 +9,13 @@ While you are waiting, please read the release notes and welcome page.
|
||||
</p>
|
||||
<p>
|
||||
Once you have client tunnels,
|
||||
please <b>check out</b> our
|
||||
please <b>check out</b> our
|
||||
<a href="http://i2p-projekt.i2p/faq">FAQ</a>.
|
||||
Or use the <a href="https://geti2p.net/faq">non-anonymous link</a>
|
||||
Or use the <a href="https://geti2p.net/faq">non-anonymous link</a>
|
||||
if you don't want to wait for tunnels.
|
||||
</p>
|
||||
<p>
|
||||
Point your IRC client to <b>localhost:6668</b> and say hi to us on
|
||||
<a href="irc://127.0.0.1:6668/i2p-dev">#i2p-dev</a> or <a href="irc://127.0.0.1:6668/i2p">#i2p</a>.
|
||||
Point your IRC client to <b>localhost:6668</b> and say hi to us on
|
||||
<a href="irc://127.0.0.1:6668/i2p-dev">#i2p-dev</a> or <a href="irc://127.0.0.1:6668/i2p">#i2p</a>.
|
||||
</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,60 +1,24 @@
|
||||
******* Please read all of the following *******
|
||||
|
||||
This is an alpha release of the I2P Android app.
|
||||
WARNING - This is BETA SOFTWARE.
|
||||
* It may crash your phone.
|
||||
* Do not rely upon it for strong anonymity.
|
||||
* Tunnels may be as short as one hop.
|
||||
* There may be serious security holes in the app.
|
||||
|
||||
WARNING - This is ALPHA SOFTWARE. It may crash your phone. Do not rely upon it for strong anonymity. Tunnels may be as short as one hop. There may be serious security holes in the app.
|
||||
|
||||
Minimum Android OS is 2.2 (API 8). It uses a lot of RAM. You need at least 256 MB of RAM. 512 should be much better.
|
||||
Minimum Android OS is 2.3 (API 9). It uses a lot of RAM. You need at least 256 MB of RAM. 512 should be much better.
|
||||
|
||||
The app may use a lot of RAM even after the router has stopped and there is no icon in the notification bar. Go to Settings -> Applications -> Running Services and stop the I2P service if necessary. Or Settings -> Applications -> Manage Applications -> Running -> I2P and force stop.
|
||||
|
||||
The app may be moved to the SD card. The app does not store any files on the SD card.
|
||||
|
||||
The app runs on either WIFI or mobile networks. For now, the app is relatively low bandwidth. It allows a max of 20 participating tunnels.
|
||||
The app runs on either wifi or mobile networks. For now, the app is relatively low bandwidth. It allows a max of 20 participating tunnels.
|
||||
|
||||
The app uses both UDP and TCP for router-router connections, with a maximum of 36 connections on each transport. UPnP is enabled.
|
||||
|
||||
I2P's NTP is disabled for API 11 (Honeycomb) and above, as those versions include NTP support. If you have cell service, your phone or tablet should have the correct time. If you do not have cell service, ensure your device has accurate time.
|
||||
|
||||
The app will work best when you are not changing IPs. If you are moving around, changing WIFI nodes, or switching between mobile and WIFI networks, it won't work well.
|
||||
|
||||
|
||||
Using clients with the router
|
||||
-----------------------------
|
||||
|
||||
The app starts an HTTP proxy at localhost port 4444 and IRC client tunnels at localhost ports 6668 - 6672. The IRC clients are "shared clients" on the same tunnels. Once you see the tunnel icon turn green on the main console (several minutes after startup), you should be able to connect.
|
||||
|
||||
The HTTP proxy is tested with the "Orweb" app. It should also work with Firefox 4 Mobile and the ProxyMob Firefox plugin, if you have at least 512 MB of RAM.
|
||||
|
||||
The IRC proxy is tested with the "Android IRC Free" app. The IRC proxy destinations are:
|
||||
* Port 6668: IRC2P - irc.postman.i2p, irc.freshcoffee.i2p, and irc.echelon.i2p
|
||||
* Port 6669: irc.welterde.i2p
|
||||
* Port 6670: irc.telecomix.i2p (probably down)
|
||||
* Port 6671: irc.killyourtv.i2p
|
||||
* Port 6672: Nameless IRC - irc.stream.i2p
|
||||
|
||||
|
||||
Embedded web browser
|
||||
--------------------
|
||||
|
||||
An embedded web browser is provided for convenience that will open .i2p addresses. However, it is not recommended for general use; users should download the Orweb browser, or Firefox Mobile and the ProxyMob Firefox plugin.
|
||||
|
||||
The browser does not use the outproxy for regular web sites. Javascript is disabled.
|
||||
|
||||
The following problems with eepsites are probably not fixable except on Android 3.0 (Honeycomb - i.e. tablets) and higher due to API limitations. The workaround is to use Firefox Mobile 4 and the ProxMob plugin (see below).
|
||||
- Leaks .i2p DNS requests
|
||||
- Can't load cross-site images or CSS
|
||||
- No POSTs to forms
|
||||
|
||||
For eepsites, there are several other things to note:
|
||||
- No way to type in addresses
|
||||
- Several issues with images and CSS fetches
|
||||
- Non-HTML links (pdf, text, images, torrent, etc.) probably don't work
|
||||
- Frame support is flaky
|
||||
|
||||
For eepsites and websites, problems include:
|
||||
- No cookies
|
||||
- History and back issues
|
||||
The app will work best when you are not changing IPs. If you are moving around, changing wifi networks, or switching between mobile and wifi networks, it won't work well.
|
||||
|
||||
|
||||
Further anonymity warnings
|
||||
@ -62,7 +26,6 @@ Further anonymity warnings
|
||||
|
||||
* Exploratory and Client Tunnels are 2 hops
|
||||
* Sharing IRC clients on same tunnels allows for linking
|
||||
* Not well-tested
|
||||
* There are .i2p DNS leaks
|
||||
* Cell phones aren't exactly secure environments
|
||||
* This app does not attempt to "sanitize" your phone, make you safe from Google, or capture and route traffic from any other apps over I2P
|
||||
|
@ -1,4 +1,6 @@
|
||||
# initial router.config
|
||||
# Initial router.config
|
||||
# Settings here MUST match the defaults in res/xml/settings_*.xml
|
||||
#
|
||||
# temp directory now set in Init.java
|
||||
#i2p.dir.temp=/data/data/net.i2p.android.router/files/tmp
|
||||
#i2p.dir.pid=/data/data/net.i2p.android.router/files/tmp
|
||||
|
@ -1,3 +1,3 @@
|
||||
http://www.i2p2.i2p/hosts.txt
|
||||
http://i2p-projekt.i2p/hosts.txt
|
||||
http://i2host.i2p/cgi-bin/i2hostetag
|
||||
http://stats.i2p/cgi-bin/newhosts.txt
|
||||
|
@ -16,7 +16,6 @@
|
||||
<string name="label_info_and_pages">Informationen und Seiten</string>
|
||||
<string name="label_welcome_page">Begrüßungsseite</string>
|
||||
<string name="label_news">Neuigkeiten</string>
|
||||
<string name="label_news_status">Neuste Nachrichten von I2P</string>
|
||||
<string name="label_peers_status">Teilnehmer</string>
|
||||
<string name="label_release_notes">Veröffentlichungshinweise</string>
|
||||
<string name="label_licenses">Lizenzen</string>
|
||||
@ -25,11 +24,17 @@
|
||||
<string name="label_graphs">Graphen</string>
|
||||
<string name="button_router_off">Lange drücken, um I2P zu starten</string>
|
||||
<string name="button_router_on">I2P läuft (lange drücken, um zu stoppen)</string>
|
||||
<!--Character to indicate a client tunnel. Usually first letter of the word "client".-->
|
||||
<string name="char_client_tunnel">C</string>
|
||||
<!--Character to indicate a server tunnel. Usually first letter of the word "server".-->
|
||||
<string name="char_server_tunnel">S</string>
|
||||
<string name="no_client_tunnels_running">Keine Kliententunnel laufen noch.</string>
|
||||
<string name="configure_browser_title">Browser konfigurieren?</string>
|
||||
<string name="first_start_title">Herzlichen Glückwunsch, du hast I2P installiert!</string>
|
||||
<string name="first_start_welcome"><b>Willkommen im I2P</b> Bitte <b>hab Geduld</b>, während I2P startet und Teilnehmer findet.</string>
|
||||
<string name="first_start_read">Während du wartest, lies bitte die Veröffentlichungshinweise und die Startseite.</string>
|
||||
<string name="first_start_faq">Sobald du Kliententunnels hast, <b>lies</b> bitte unsere FAQs:</string>
|
||||
<string name="first_start_faq_nonanon">Oder benutze unsere nichtanonymen Links, wenn du nicht auf die Tunnel warten willst.</string>
|
||||
<string name="first_start_faq_nonanon">Oder benutze unsere nicht-anonymen Links, wenn du nicht auf die Tunnel warten willst.</string>
|
||||
<string name="first_start_irc">Verbinde dich mit deinem IRC-Klienten zu <b>localhost:6668</b> und schau bei uns vorbei:</string>
|
||||
<string name="drawer_open">Navigation öffnen</string>
|
||||
<string name="drawer_close">Navigation schließen</string>
|
||||
@ -43,7 +48,7 @@
|
||||
<string name="action_i2ptunnel_stop">Stoppe den Tunnel</string>
|
||||
<string name="action_i2ptunnel_start_all">Alle Tunnel starten</string>
|
||||
<string name="action_i2ptunnel_stop_all">Alle Tunnel anhalten</string>
|
||||
<string name="action_i2ptunnel_restart_all">Alle Tunnel neustarten</string>
|
||||
<string name="action_i2ptunnel_restart_all">Alle Tunnel neu starten</string>
|
||||
<string name="action_reload">Neu laden</string>
|
||||
<string name="action_refresh">Auffrischen</string>
|
||||
<string name="hint_search_addressbook">Durchsuche das Adressbuch</string>
|
||||
@ -71,7 +76,7 @@
|
||||
<string name="settings_label_network">Netzwerk</string>
|
||||
<string name="settings_label_hiddenMode">Beteiligung</string>
|
||||
<string name="settings_desc_hiddenMode">Tarnmodus ausschalten</string>
|
||||
<string name="settings_label_maxPartTunnels">maximale Anzahl an Tunneln</string>
|
||||
<string name="settings_label_maxPartTunnels">Maximal beteiligte Tunnel</string>
|
||||
<string name="settings_desc_maxPartTunnels">Maximalanzahl an zu routenden Tunneln (Standard=20)</string>
|
||||
<string name="settings_dialog_maxPartTunnels">Maximalanzahl an zu routenden Tunneln</string>
|
||||
<string name="settings_label_sharePercent">Weiterleitungsanteil</string>
|
||||
@ -89,8 +94,8 @@
|
||||
<string name="settings_desc_i2cp">lausche auf Port 7654</string>
|
||||
<string name="settings_label_exploratory_pool">Satz an Erkundungstunneln</string>
|
||||
<string name="settings_desc_exploratory_pool">Tunnelparameter</string>
|
||||
<string name="settings_label_expl_inbound">eingehende Tunnel</string>
|
||||
<string name="settings_label_expl_outbound">ausgehende Tunnel</string>
|
||||
<string name="settings_label_expl_inbound">Eingehende Tunnel</string>
|
||||
<string name="settings_label_expl_outbound">Ausgehende Tunnel</string>
|
||||
<string name="settings_label_expl_length">Länge</string>
|
||||
<string name="settings_summ_expl_length">%s Sprünge</string>
|
||||
<string name="settings_desc_expl_length">Anzahl der Sprünge</string>
|
||||
@ -103,6 +108,7 @@
|
||||
<string name="settings_label_expl_backupQuantity">Anzahl der Reservetunnel</string>
|
||||
<string name="settings_summ_expl_backupQuantity">%s Tunnel</string>
|
||||
<string name="settings_desc_expl_backupQuantity">Wie viele Reservertunnel</string>
|
||||
<string name="settings_router_restart_required">Bitte starten Sie I2P neu, um die Änderungen anzuwenden</string>
|
||||
<string name="menu_about">Über uns</string>
|
||||
<string name="about_version">Version:</string>
|
||||
<string name="about_project">Projektseite:</string>
|
||||
@ -142,8 +148,8 @@
|
||||
<string name="i2ptunnel_delete_confirm_message">Tunnel löschen?</string>
|
||||
<string name="i2ptunnel_delete_confirm_button">Tunnel löschen</string>
|
||||
<string name="i2ptunnel_wizard_k_client_server">Klient oder Server</string>
|
||||
<string name="i2ptunnel_wizard_v_client">Klienten-Tunnel</string>
|
||||
<string name="i2ptunnel_wizard_v_server">Server-Tunnel</string>
|
||||
<string name="i2ptunnel_wizard_v_client">Kliententunnel</string>
|
||||
<string name="i2ptunnel_wizard_v_server">Servertunnel</string>
|
||||
<string name="i2ptunnel_wizard_k_type">Tunneltyp</string>
|
||||
<string name="i2ptunnel_wizard_k_name">Name</string>
|
||||
<string name="i2ptunnel_wizard_k_desc">Beschreibung</string>
|
||||
@ -175,4 +181,10 @@
|
||||
<string name="i2ptunnel_view_target">Ziel:</string>
|
||||
<string name="i2ptunnel_view_access_point">Zugangspunkt:</string>
|
||||
<string name="i2ptunnel_view_autostart">Autostart</string>
|
||||
<string name="copy_logs">Protokolle kopieren</string>
|
||||
<string name="i2p_android_error_logs">I2P Android-Fehlerprotokolle</string>
|
||||
<string name="i2p_android_logs">I2P Android-Protokolle</string>
|
||||
<string name="error_logs_copied_to_clipboard">Fehlerprotokolle in die Zwischenablage kopiert</string>
|
||||
<string name="logs_copied_to_clipboard">Protokolle in die Zwischenablage kopiert</string>
|
||||
<string name="label_browser_configuration">Browserkonfiguration</string>
|
||||
</resources>
|
||||
|
@ -16,7 +16,6 @@
|
||||
<string name="label_info_and_pages">Información y páginas</string>
|
||||
<string name="label_welcome_page">Página de Bienvenida</string>
|
||||
<string name="label_news">Noticias</string>
|
||||
<string name="label_news_status">Últimas noticias sobre I2P</string>
|
||||
<string name="label_peers_status">Pares</string>
|
||||
<string name="label_release_notes">Notas de Versiones</string>
|
||||
<string name="label_licenses">Licencias</string>
|
||||
@ -25,6 +24,13 @@
|
||||
<string name="label_graphs">Gráficas</string>
|
||||
<string name="button_router_off">Mantenga pulsado para iniciar I2P</string>
|
||||
<string name="button_router_on">I2P está ejecutándose (mantenga pulsado para detenerlo)</string>
|
||||
<!--Character to indicate a client tunnel. Usually first letter of the word "client".-->
|
||||
<string name="char_client_tunnel">C</string>
|
||||
<!--Character to indicate a server tunnel. Usually first letter of the word "server".-->
|
||||
<string name="char_server_tunnel">S</string>
|
||||
<string name="no_client_tunnels_running">Ya no hay túneles de cliente ejecutándose.</string>
|
||||
<string name="configure_browser_title">¿Configurar navegador?</string>
|
||||
<string name="configure_browser_for_i2p">¿Le gustaría configurar un navegador para ver sitios I2P? (También puede hacer esto más tarde desde el menú de ayuda).</string>
|
||||
<string name="first_start_title">¡Felicidades por conseguir instalar I2P!</string>
|
||||
<string name="first_start_welcome"><b>¡Bienvenido a I2P!</b> Por favor <b>tenga paciencia</b> mientras I2P se inicia y busca pares (\'peers\').</string>
|
||||
<string name="first_start_read">Mientras esté esperando, por favor lea las notas de la versión y la página de bienvenida.</string>
|
||||
@ -103,6 +109,7 @@
|
||||
<string name="settings_label_expl_backupQuantity">Cantidad de respaldos</string>
|
||||
<string name="settings_summ_expl_backupQuantity">%s túneles</string>
|
||||
<string name="settings_desc_expl_backupQuantity">Cuantos túneles de respaldo</string>
|
||||
<string name="settings_router_restart_required">Por favor reinicie I2P para aplicar los cambios</string>
|
||||
<string name="menu_about">Acerca de</string>
|
||||
<string name="about_version">Versión:</string>
|
||||
<string name="about_project">Página principal del proyecto:</string>
|
||||
@ -175,4 +182,10 @@
|
||||
<string name="i2ptunnel_view_target">Objetivo:</string>
|
||||
<string name="i2ptunnel_view_access_point">Punto de acceso:</string>
|
||||
<string name="i2ptunnel_view_autostart">Auto-iniciar</string>
|
||||
<string name="copy_logs">Copiar registros (logs)</string>
|
||||
<string name="i2p_android_error_logs">Registros (logs) de errores de I2P Android</string>
|
||||
<string name="i2p_android_logs">Registros (logs) de I2P Android</string>
|
||||
<string name="error_logs_copied_to_clipboard">Los registros (logs) de errores se copiaron al portapapeles</string>
|
||||
<string name="logs_copied_to_clipboard">Los registros (logs) se copiaron al portapapeles</string>
|
||||
<string name="label_browser_configuration">Configuración del navegador</string>
|
||||
</resources>
|
||||
|
@ -16,7 +16,6 @@
|
||||
<string name="label_info_and_pages">Information et pages</string>
|
||||
<string name="label_welcome_page">Page d\'accueil</string>
|
||||
<string name="label_news">Nouvelles</string>
|
||||
<string name="label_news_status">Dernières nouvelles de I2P</string>
|
||||
<string name="label_peers_status">Pairs</string>
|
||||
<string name="label_release_notes">Notes de version</string>
|
||||
<string name="label_licenses">Licences</string>
|
||||
@ -25,6 +24,8 @@
|
||||
<string name="label_graphs">Graphiques</string>
|
||||
<string name="button_router_off">Presser longtemps pour démarrer I2P</string>
|
||||
<string name="button_router_on">I2P est en marche (presser longtemps pour arrêter)</string>
|
||||
<!--Character to indicate a client tunnel. Usually first letter of the word "client".-->
|
||||
<!--Character to indicate a server tunnel. Usually first letter of the word "server".-->
|
||||
<string name="first_start_title">Félicitations pour avoir installé I2P !</string>
|
||||
<string name="first_start_welcome"><b>Bienvenue sur I2P !</b> Veuillez <b>patienter</b> pendant qu\'I2P démarre et trouve des pairs.</string>
|
||||
<string name="first_start_read">Pendant que vous patientez, vous pouvez lire les informations de mise à jour et la page d\'accueil.</string>
|
||||
|
@ -16,7 +16,6 @@
|
||||
<string name="label_info_and_pages">Informasi dan halaman</string>
|
||||
<string name="label_welcome_page">Laman Sambutan</string>
|
||||
<string name="label_news">News</string>
|
||||
<string name="label_news_status">Berita terbaru I2P</string>
|
||||
<string name="label_peers_status">Peers</string>
|
||||
<string name="label_release_notes">Catatan Rilis</string>
|
||||
<string name="label_licenses">Lisensi</string>
|
||||
@ -25,6 +24,8 @@
|
||||
<string name="label_graphs">Grafik</string>
|
||||
<string name="button_router_off">Tekan dan tahan untuk memulai I2P</string>
|
||||
<string name="button_router_on">I2P sedang berjalan (tekan dan tahan untuk menghentikan)</string>
|
||||
<!--Character to indicate a client tunnel. Usually first letter of the word "client".-->
|
||||
<!--Character to indicate a server tunnel. Usually first letter of the word "server".-->
|
||||
<string name="first_start_title">Selamat atas terpasangnya I2P!</string>
|
||||
<string name="first_start_welcome"><b>Selamat datang di I2P</b> Mohon <b>bersabar</b> karena I2P boot up dan menemukan peers.</string>
|
||||
<string name="first_start_read">Sementara Anda menunggu, silahkan baca catatn rilis dan laman sambutan.</string>
|
||||
|
@ -16,7 +16,6 @@
|
||||
<string name="label_info_and_pages">Informazioni e pagine</string>
|
||||
<string name="label_welcome_page">Pagina di benvenuto</string>
|
||||
<string name="label_news">News</string>
|
||||
<string name="label_news_status">Ultime news I2P</string>
|
||||
<string name="label_peers_status">Peers</string>
|
||||
<string name="label_release_notes">Note di rilascio</string>
|
||||
<string name="label_licenses">Licenze</string>
|
||||
@ -25,6 +24,8 @@
|
||||
<string name="label_graphs">Grafici</string>
|
||||
<string name="button_router_off">Tieni premuto per avviare I2P</string>
|
||||
<string name="button_router_on">I2P è in funzione (tieni premuto per fermare)</string>
|
||||
<!--Character to indicate a client tunnel. Usually first letter of the word "client".-->
|
||||
<!--Character to indicate a server tunnel. Usually first letter of the word "server".-->
|
||||
<string name="first_start_title">Congratulazioni per aver installato I2P!</string>
|
||||
<string name="first_start_welcome"><b>Benvenuto su I2P!</b> <b>Sii paziente</b> mentre I2P si avvia e trova i peer.</string>
|
||||
<string name="first_start_read">Mentre aspetti, puoi leggere le note di rilascio e la pagina di benvenuto.</string>
|
||||
|
@ -16,7 +16,6 @@
|
||||
<string name="label_info_and_pages">情報とページ</string>
|
||||
<string name="label_welcome_page">ウェルカムページ</string>
|
||||
<string name="label_news">ニュース</string>
|
||||
<string name="label_news_status">最新の I2P のニュース</string>
|
||||
<string name="label_peers_status">ピア</string>
|
||||
<string name="label_release_notes">リリース・ノート</string>
|
||||
<string name="label_licenses">ライセンス</string>
|
||||
@ -25,6 +24,8 @@
|
||||
<string name="label_graphs">グラフ</string>
|
||||
<string name="button_router_off">長押しして I2P を起動</string>
|
||||
<string name="button_router_on">I2P を起動中 (長押しで中止)</string>
|
||||
<!--Character to indicate a client tunnel. Usually first letter of the word "client".-->
|
||||
<!--Character to indicate a server tunnel. Usually first letter of the word "server".-->
|
||||
<string name="first_start_title">I2P のインストールおめでとうございます!</string>
|
||||
<string name="first_start_welcome"><b>I2P へようこそ!</b> I2P が立ち上がり、ピアを見つけるまで<b>我慢してください</b>。</string>
|
||||
<string name="first_start_read">待っている間、リリースノートとウェルカムページをお読みください。</string>
|
||||
|
@ -16,7 +16,6 @@
|
||||
<string name="label_info_and_pages">정보와 페이지</string>
|
||||
<string name="label_welcome_page">환영 페이지</string>
|
||||
<string name="label_news">뉴스</string>
|
||||
<string name="label_news_status">최신 I2P 뉴스</string>
|
||||
<string name="label_peers_status">피어</string>
|
||||
<string name="label_release_notes">릴리즈 노트</string>
|
||||
<string name="label_licenses">라이센스</string>
|
||||
@ -25,6 +24,8 @@
|
||||
<string name="label_graphs">그래프</string>
|
||||
<string name="button_router_off">길게 눌러 I2P 시작</string>
|
||||
<string name="button_router_on">I2P가 실행중입니다 (길게 눌러 정지)</string>
|
||||
<!--Character to indicate a client tunnel. Usually first letter of the word "client".-->
|
||||
<!--Character to indicate a server tunnel. Usually first letter of the word "server".-->
|
||||
<string name="first_start_title">I2P가 설치 된것을 환영합니다!</string>
|
||||
<string name="first_start_welcome"><b>I2P에 환영합니다!</b> I2P가 시작되고 피어들을 찾을때까지 <b>기다려주세요</b>.</string>
|
||||
<string name="first_start_read">기다리는 동안, 릴리즈 노트와 환영 페이지를 읽어보세요.</string>
|
||||
@ -49,6 +50,9 @@
|
||||
<string name="hint_search_addressbook">주소록 검색</string>
|
||||
<string name="action_reload_subscriptions">구독 다시 불러오기</string>
|
||||
<string name="router_not_running">라우터가 실행중이지 않습니다.</string>
|
||||
<string name="stats_not_ready">통계 관리자가 아직 준비되지 않았습니다. 나중에 다시 시도하세요.</string>
|
||||
<string name="no_graphs_configured">설정된 그래프가 없습니다. 설정 메뉴에서 그래프로 표시할 통계를 고를 수 있습니다. 모든 변경은 60초 후에 적용됩니다.</string>
|
||||
<string name="configure_graphs">그래프 설정</string>
|
||||
<string name="graphs_not_ready">그래프가 준비되지 않았거나, 라우터가 실행중이 아닙니다. 나중에 다시 시도하세요.</string>
|
||||
<string name="netdb_routers_empty">NetDB에 라우터들이 없습니다.</string>
|
||||
<string name="netdb_leases_empty">NetDB에 LeaseSet들이 없습니다.</string>
|
||||
@ -112,4 +116,61 @@
|
||||
<string name="addressbook_add_wizard_k_name">이름</string>
|
||||
<string name="addressbook_add_wizard_k_destination">목적지</string>
|
||||
<string name="addressbook_add_wizard_desc_name">이름</string>
|
||||
<string name="addressbook_add_wizard_desc_destination">도착점의 B64를 붙여 넣으세요. 파일 관리자가 설치되어 있다면, B64를 포함하는 텍스트 파일을 선택할 수 있습니다.</string>
|
||||
<string name="nsu_iae_illegal_char">호스트 이름 \"%1$s\" 는 부적절한 글자 %2$s 를 포함하고 있습니다</string>
|
||||
<string name="nsu_iae_cannot_start_with">호스트 이름은 \"%s\" 로 시작할 수 없습니다</string>
|
||||
<string name="nsu_iae_cannot_end_with">호스트 이름은 \"%s\" 로 끝날 수 없습니다</string>
|
||||
<string name="nsu_iae_cannot_contain">호스트 이름은 \"%s\"를 포함할 수 없습니다</string>
|
||||
<string name="nsu_iae_requires_conversion">호스트 이름 \"%s\" 는 ASCII 글자로 치환이 필요하지만 변환 라이브러리는 안드로이드 버전에서 지원되지 않습니다</string>
|
||||
<string name="i2ptunnel_type_client">표준 클라이언트</string>
|
||||
<string name="i2ptunnel_type_httpclient">HTTP 클라이언트</string>
|
||||
<string name="i2ptunnel_type_ircclient">IRC 클라이언트</string>
|
||||
<string name="i2ptunnel_type_server">표준 서버</string>
|
||||
<string name="i2ptunnel_type_httpserver">HTTP 서버</string>
|
||||
<string name="i2ptunnel_type_sockstunnel">SOCKS 4/4a/5 프록시</string>
|
||||
<string name="i2ptunnel_type_socksirctunnel">SOCKS IRC 프록시</string>
|
||||
<string name="i2ptunnel_type_connectclient">연결/SSL/HTTPS 프록시</string>
|
||||
<string name="i2ptunnel_type_ircserver">IRC 서버</string>
|
||||
<string name="i2ptunnel_type_streamrclient">Streamr 클라이언트</string>
|
||||
<string name="i2ptunnel_type_streamrserver">Streamr 서버</string>
|
||||
<string name="i2ptunnel_type_httpbidirserver">HTTP bidir</string>
|
||||
<string name="i2ptunnel_not_initialized">터널이 아직 시작되지 않았습니다. 2분 후에 다시 로드하세요.</string>
|
||||
<string name="i2ptunnel_new_tunnel">새 터널</string>
|
||||
<string name="i2ptunnel_msg_config_saved">설정 변경 저장됨</string>
|
||||
<string name="i2ptunnel_msg_config_save_failed">설정 저장 실패</string>
|
||||
<string name="i2ptunnel_msg_tunnel_starting">터널 시작중</string>
|
||||
<string name="i2ptunnel_msg_tunnel_stopping">터널 중지중</string>
|
||||
<string name="i2ptunnel_delete_confirm_message">터널을 삭제합니까?</string>
|
||||
<string name="i2ptunnel_delete_confirm_button">터널 삭제</string>
|
||||
<string name="i2ptunnel_wizard_k_client_server">클라이언트 또는 서버</string>
|
||||
<string name="i2ptunnel_wizard_v_client">클라이언트 터널</string>
|
||||
<string name="i2ptunnel_wizard_v_server">서버 터널</string>
|
||||
<string name="i2ptunnel_wizard_k_type">터널 종류</string>
|
||||
<string name="i2ptunnel_wizard_k_name">이름</string>
|
||||
<string name="i2ptunnel_wizard_k_desc">설명</string>
|
||||
<string name="i2ptunnel_wizard_k_dest">도착지</string>
|
||||
<string name="i2ptunnel_wizard_k_outproxies">나가는 프록시</string>
|
||||
<string name="i2ptunnel_wizard_k_target_host">목표 호스트</string>
|
||||
<string name="i2ptunnel_wizard_k_target_port">목표 포트</string>
|
||||
<string name="i2ptunnel_wizard_k_auto_start">자동 시작</string>
|
||||
<string name="next">다음</string>
|
||||
<string name="prev">이전</string>
|
||||
<string name="finish">제출</string>
|
||||
<string name="review">리뷰</string>
|
||||
<string name="enabled">활성화됨</string>
|
||||
<string name="i2ptunnel_wizard_desc_name">터널 리스트에서 구별하기 위한 터널의 이름</string>
|
||||
<string name="i2ptunnel_wizard_desc_desc">터널의 설명. 선택적이고 단순 정보용.</string>
|
||||
<string name="i2ptunnel_wizard_desc_dest">클라이언트 터널이 접속하야 하는 I2P 서비스 도착점 입력. 전체 Base 64 도착점 키나 사용자의 주소록에 있는 I2P URL 사용 가능.</string>
|
||||
<string name="i2ptunnel_wizard_desc_outproxies">만약 이 터널 종류의 나가는 프록시를 안다면 (HTTP 또는 SOCKS), 입력. 여러 프록시들을 콤마로 구별.</string>
|
||||
<string name="i2ptunnel_wizard_desc_target_host">서비스가 작동중인 IP, 대부분의 경우 같은 기기이기 때문에 127.0.0.1이 자동 입력됨.</string>
|
||||
<string name="i2ptunnel_wizard_desc_target_port">서비스가 접속을 받아들일 포트.</string>
|
||||
<string name="i2ptunnel_wizard_desc_reachable_on">이 터널을 접근할 수 있는 컴퓨터 혹은 스마트폰 제한.</string>
|
||||
<string name="i2ptunnel_wizard_desc_auto_start">라우터가 시작할때 터널도 같이 실행?</string>
|
||||
<string name="i2ptunnel_wizard_submit_confirm_message">터널을 만들까요?</string>
|
||||
<string name="i2ptunnel_wizard_submit_confirm_button">터널 </string>
|
||||
<string name="i2ptunnel_view_type">종류:</string>
|
||||
<string name="i2ptunnel_view_desc">설명:</string>
|
||||
<string name="i2ptunnel_view_target">목표:</string>
|
||||
<string name="i2ptunnel_view_access_point">엑세스 포인트:</string>
|
||||
<string name="i2ptunnel_view_autostart">자동 시작</string>
|
||||
</resources>
|
||||
|
@ -16,7 +16,6 @@
|
||||
<string name="label_info_and_pages">Informasjon og sider</string>
|
||||
<string name="label_welcome_page">Velkomstside</string>
|
||||
<string name="label_news">Nyheter</string>
|
||||
<string name="label_news_status">Siste I2P-nytt</string>
|
||||
<string name="label_peers_status">Likemenn</string>
|
||||
<string name="label_release_notes">Versjonsnotater</string>
|
||||
<string name="label_licenses">Lisenser</string>
|
||||
@ -25,6 +24,8 @@
|
||||
<string name="label_graphs">Grafer</string>
|
||||
<string name="button_router_off">Hold inne kappen for å starte I2P</string>
|
||||
<string name="button_router_on">I2P kjører (hold inne knappen for å stoppe)</string>
|
||||
<!--Character to indicate a client tunnel. Usually first letter of the word "client".-->
|
||||
<!--Character to indicate a server tunnel. Usually first letter of the word "server".-->
|
||||
<string name="first_start_title">Til lykke med ny installasjon av I2P!</string>
|
||||
<string name="first_start_welcome"><b> Velkommen til I2P</b> Vennligst <b>ha tålmodighet</b> mens I2P starter opp og finner likemenn.</string>
|
||||
<string name="first_start_read">Mens du venter, vennligst les versjons-notatene og velkomstsiden.</string>
|
||||
|
@ -15,7 +15,6 @@
|
||||
<string name="label_info_and_pages">Informatie en pagina\'s</string>
|
||||
<string name="label_welcome_page">Welkomspagina</string>
|
||||
<string name="label_news">Nieuws</string>
|
||||
<string name="label_news_status">Laatste I2P-nieuws</string>
|
||||
<string name="label_peers_status">Peers</string>
|
||||
<string name="label_release_notes">Versieopmerkingen</string>
|
||||
<string name="label_licenses">Licenties</string>
|
||||
@ -24,6 +23,8 @@
|
||||
<string name="label_graphs">Grafieken</string>
|
||||
<string name="button_router_off">Lang drukken om I2P te starten</string>
|
||||
<string name="button_router_on">I2P is actief (lang drukken om te stoppen)</string>
|
||||
<!--Character to indicate a client tunnel. Usually first letter of the word "client".-->
|
||||
<!--Character to indicate a server tunnel. Usually first letter of the word "server".-->
|
||||
<string name="first_start_title">Gefeliciteerd met de installatie van I2P!</string>
|
||||
<string name="first_start_welcome"><b>Welkom bij I2P! Heb geduld alstublieft</b> terwijl I2P opstart en peers zoekt.</string>
|
||||
<string name="first_start_read">Terwijl je wacht, lees alstublieft de release aantekeningen en welkom pagina.</string>
|
||||
|
@ -16,7 +16,6 @@
|
||||
<string name="label_info_and_pages">Informacje i strony</string>
|
||||
<string name="label_welcome_page">Strona Powitalna</string>
|
||||
<string name="label_news">Wiadomości</string>
|
||||
<string name="label_news_status">Najnowsze wiadomości o I2P</string>
|
||||
<string name="label_peers_status">Peery</string>
|
||||
<string name="label_release_notes">Informacje o wydaniu</string>
|
||||
<string name="label_licenses">Licencje</string>
|
||||
@ -25,6 +24,8 @@
|
||||
<string name="label_graphs">Wykresy</string>
|
||||
<string name="button_router_off">Dotknij na dłużej aby uruchomić I2P</string>
|
||||
<string name="button_router_on">I2P jest włączone (dotknij na dłużej aby zatrzymać)</string>
|
||||
<!--Character to indicate a client tunnel. Usually first letter of the word "client".-->
|
||||
<!--Character to indicate a server tunnel. Usually first letter of the word "server".-->
|
||||
<string name="first_start_title">Gratulacje w zainstalowaniu I2P!</string>
|
||||
<string name="first_start_welcome"><b>Witamy w I2P!</b> Proszę <b>bądz cierpliwy</b> bo I2P właśnie się uruchamia i szuka peerów.</string>
|
||||
<string name="first_start_read">W międzyczasie, prosimy o zapoznanie się z notatkami tego wydania oraz stroną powitalną.</string>
|
||||
|
@ -15,13 +15,14 @@
|
||||
<string name="label_info_and_pages">Informações e paginas</string>
|
||||
<string name="label_welcome_page">Página de boas-vindas</string>
|
||||
<string name="label_news">Novidades</string>
|
||||
<string name="label_news_status">Últimas notícias sobre a I2P</string>
|
||||
<string name="label_peers_status">Nós</string>
|
||||
<string name="label_release_notes">Comunicados de lançamento</string>
|
||||
<string name="label_licenses">Licenças</string>
|
||||
<string name="label_nonanon_info">Informação não-anônima</string>
|
||||
<string name="label_browse">Navegador</string>
|
||||
<string name="label_graphs">Gráficos</string>
|
||||
<!--Character to indicate a client tunnel. Usually first letter of the word "client".-->
|
||||
<!--Character to indicate a server tunnel. Usually first letter of the word "server".-->
|
||||
<string name="first_start_title">Parabéns em instalar o I2P!</string>
|
||||
<string name="first_start_welcome"><b>Bem-Vindo ao I2P!</b> Por favor <b> tenha paciência </b> enquanto o I2P inicia e procura por peers.</string>
|
||||
<string name="first_start_read">Enquanto você está esperando, por favor leia as notas de lançamento e a página de boas vindas.</string>
|
||||
|
@ -16,14 +16,16 @@
|
||||
<string name="label_info_and_pages">Informații și pagini</string>
|
||||
<string name="label_welcome_page">Pagina de start</string>
|
||||
<string name="label_news">Noutăți</string>
|
||||
<string name="label_news_status">Ultimele știri I2P</string>
|
||||
<string name="label_peers_status">Parteneri</string>
|
||||
<string name="label_release_notes">Note de publicare</string>
|
||||
<string name="label_licenses">Licențe</string>
|
||||
<string name="label_nonanon_info">Informații non-anonim</string>
|
||||
<string name="label_browse">Navighează</string>
|
||||
<string name="label_graphs">Grafice</string>
|
||||
<string name="button_router_off">Apasari lung pentru a porni I2P</string>
|
||||
<string name="button_router_on">I2P ruleaza (tineti apasat pentru a oprii)</string>
|
||||
<!--Character to indicate a client tunnel. Usually first letter of the word "client".-->
|
||||
<!--Character to indicate a server tunnel. Usually first letter of the word "server".-->
|
||||
<string name="first_start_title">Felicitari pentru instalarea I2P!</string>
|
||||
<string name="action_search">Cauta</string>
|
||||
<string name="action_add">Adaugă</string>
|
||||
@ -31,10 +33,25 @@
|
||||
<string name="action_delete">Sterge</string>
|
||||
<string name="action_router_start">Porneste Router</string>
|
||||
<string name="action_router_stop">Opreste Router</string>
|
||||
<string name="action_i2ptunnel_start">Pornește tunelul</string>
|
||||
<string name="action_i2ptunnel_stop">Oprește tunelul</string>
|
||||
<string name="action_i2ptunnel_start_all">Pornește toate tunelurile</string>
|
||||
<string name="action_i2ptunnel_stop_all">Oprește toate tunelurile</string>
|
||||
<string name="action_i2ptunnel_restart_all">Repornește toate tunelurile</string>
|
||||
<string name="action_reload">Reîncarcă</string>
|
||||
<string name="action_refresh">Reâmprospătează</string>
|
||||
<string name="hint_search_addressbook">Caută agenda</string>
|
||||
<string name="action_reload_subscriptions">Reâncarcă abonamentele</string>
|
||||
<string name="router_not_running">Ruterul nu rulează.</string>
|
||||
<string name="configure_graphs">Configurează graficele</string>
|
||||
<string name="graphs_not_ready">Graficele nu sunt gata, sau ruterul nu rulează. Încercați mai târziu.</string>
|
||||
<string name="netdb_routers_empty">Nu sunt rutere în NetDB.</string>
|
||||
<string name="notification_status_bw">Lățime de bandă: %1$s KBps desc / %2$s KBps în</string>
|
||||
<string name="menu_settings">Configurări</string>
|
||||
<string name="settings_enable">Activează</string>
|
||||
<string name="settings_desc_subscriptions">URLs de abonare:</string>
|
||||
<string name="settings_label_bandwidth_net">Lățime de bandă și rețea</string>
|
||||
<string name="settings_label_bandwidth">Lățime de bandă</string>
|
||||
<string name="settings_label_bw_inbound">viteza de intrare</string>
|
||||
<string name="settings_desc_bw_inbound">Viteza maximă de încărcare:</string>
|
||||
<string name="settings_label_bw_outbound">viteza de iesire</string>
|
||||
@ -49,7 +66,9 @@
|
||||
<string name="settings_desc_sharePercent">Procentul de lățime de bandă pentru partajare (implicit = 80)</string>
|
||||
<string name="settings_dialog_sharePercent">Procentul de lățime de bandă pentru partajare </string>
|
||||
<string name="settings_desc_upnp">Deschide automat porturile firewall</string>
|
||||
<string name="settings_label_default_log_level">Nivel implicit jurnal</string>
|
||||
<string name="settings_label_advanced">Avansat</string>
|
||||
<string name="settings_label_showStats">Statistici ruter</string>
|
||||
<string name="settings_label_transports">Transporturi</string>
|
||||
<string name="settings_label_maxConns">Maxim conexiuni</string>
|
||||
<string name="settings_label_i2cp">Interfata I2CP</string>
|
||||
@ -61,13 +80,20 @@
|
||||
<string name="settings_label_expl_length">Lungime</string>
|
||||
<string name="settings_desc_expl_length">Cât de multe hamei să utilizeze</string>
|
||||
<string name="settings_label_expl_lengthVariance">variație hamei</string>
|
||||
<string name="settings_summ_expl_lengthVariance">%s</string>
|
||||
<string name="settings_desc_expl_lengthVariance">Cât de multe hamei de a adăuga la întâmplare</string>
|
||||
<string name="settings_label_expl_quantity">Cantitate</string>
|
||||
<string name="settings_summ_expl_quantity">%s tuneluri</string>
|
||||
<string name="settings_desc_expl_quantity">Cât de multe tunele</string>
|
||||
<string name="settings_label_expl_backupQuantity">Cantitatea de rezervă</string>
|
||||
<string name="settings_summ_expl_backupQuantity">%s tuneluri</string>
|
||||
<string name="settings_desc_expl_backupQuantity">Câți copii de rezervă tunel</string>
|
||||
<string name="menu_about">Despre</string>
|
||||
<string name="about_version">Versiune:</string>
|
||||
<string name="about_bugs">Defecte și suport:</string>
|
||||
<string name="about_helpwanted">Doresc ajutor!</string>
|
||||
<string name="about_volunteer">Doriți să faceți aplicația mai bună? Voluntari pe forumul Android:</string>
|
||||
<string name="about_donate">Doriți să donați bani sau bitcoins pentru cumpărarea de mai multe dispozitive Android pentru dezvoltare și testare? Mergeți la:</string>
|
||||
<string name="menu_help">Ajutor</string>
|
||||
<string name="addressbook_search_header">%s gasit</string>
|
||||
<string name="addressbook_add_wizard_k_name">Nume</string>
|
||||
@ -87,6 +113,8 @@
|
||||
<string name="i2ptunnel_wizard_k_auto_start">Auto pornire</string>
|
||||
<string name="next">Urmatorul</string>
|
||||
<string name="prev">Anteriorul</string>
|
||||
<string name="i2ptunnel_wizard_submit_confirm_message">Se creează tunelul?</string>
|
||||
<string name="i2ptunnel_wizard_submit_confirm_button">Creare tunel</string>
|
||||
<string name="i2ptunnel_view_type">Tip:</string>
|
||||
<string name="i2ptunnel_view_desc">Descriere:</string>
|
||||
<string name="i2ptunnel_view_target">Tinta:</string>
|
||||
|
@ -16,7 +16,6 @@
|
||||
<string name="label_info_and_pages">Информация и страницы</string>
|
||||
<string name="label_welcome_page">Начальная страница</string>
|
||||
<string name="label_news">Новости</string>
|
||||
<string name="label_news_status">Последние новости I2P</string>
|
||||
<string name="label_peers_status">Пиры</string>
|
||||
<string name="label_release_notes">Примечания к выпуску</string>
|
||||
<string name="label_licenses">Лицензии</string>
|
||||
@ -25,6 +24,8 @@
|
||||
<string name="label_graphs">Графики</string>
|
||||
<string name="button_router_off">Долгое нажатие для запуска I2P</string>
|
||||
<string name="button_router_on">I2P работает (долгое нажатие для остановки)</string>
|
||||
<!--Character to indicate a client tunnel. Usually first letter of the word "client".-->
|
||||
<!--Character to indicate a server tunnel. Usually first letter of the word "server".-->
|
||||
<string name="first_start_title">Поздравляем с установкой I2P!</string>
|
||||
<string name="first_start_welcome"><b>Добро пожаловать в I2P!</b> Пожалуйста, <b>дождитесь</b> пока I2P загрузится и найдет узлы.</string>
|
||||
<string name="first_start_read">Пока вы ждете, пожалуйста, прочтите информацию о релизе и страницу приветствия.</string>
|
||||
|
@ -16,7 +16,6 @@
|
||||
<string name="label_info_and_pages">Informácie a stránky</string>
|
||||
<string name="label_welcome_page">Uvítacia stránka</string>
|
||||
<string name="label_news">Novinky</string>
|
||||
<string name="label_news_status">Najnovšie I2P správy</string>
|
||||
<string name="label_peers_status">Peerovia</string>
|
||||
<string name="label_release_notes">Poznámky k vydaniu</string>
|
||||
<string name="label_licenses">Licencie</string>
|
||||
@ -25,6 +24,8 @@
|
||||
<string name="label_graphs">Grafy</string>
|
||||
<string name="button_router_off">Dlhšie stlačte pre spustenie I2P</string>
|
||||
<string name="button_router_on">I2P je spustený (dlhšie stlačte pre zastavenie)</string>
|
||||
<!--Character to indicate a client tunnel. Usually first letter of the word "client".-->
|
||||
<!--Character to indicate a server tunnel. Usually first letter of the word "server".-->
|
||||
<string name="first_start_title">Gratulácia k nainštalovaniu I2P!</string>
|
||||
<string name="first_start_welcome"><b>Vitajte v I2P!</b> Prosím <b>majte trpezlivosť</b>, kým sa I2P nabootuje a nájde peerov.</string>
|
||||
<string name="first_start_read">Zatiaľ čo budete čakať, prosím prečítajte si poznámky k vydaniu a úvodnú stránku.</string>
|
||||
|
@ -16,7 +16,6 @@
|
||||
<string name="label_info_and_pages">Informacioni dhe faqet.</string>
|
||||
<string name="label_welcome_page">Faqja mirëseardhëse. </string>
|
||||
<string name="label_news">Lajmet. </string>
|
||||
<string name="label_news_status">Lajmet më të fundit për I2P\'në. </string>
|
||||
<string name="label_peers_status">Të barabartit/shokët. </string>
|
||||
<string name="label_release_notes">Shënime lëshimi</string>
|
||||
<string name="label_licenses">Lisencat</string>
|
||||
@ -25,6 +24,8 @@
|
||||
<string name="label_graphs">Grafikët</string>
|
||||
<string name="button_router_off">Mbaje tastin për ta filluar I2P\'në</string>
|
||||
<string name="button_router_on">I2P është në funkcion (mbaje tastin gjatë për ta ndalur) </string>
|
||||
<!--Character to indicate a client tunnel. Usually first letter of the word "client".-->
|
||||
<!--Character to indicate a server tunnel. Usually first letter of the word "server".-->
|
||||
<string name="first_start_title">Urime që arritët ta instaloni I2P\'në!</string>
|
||||
<string name="first_start_welcome"><b>Mirë se vini në I2P!<b> Ju lutem <b>duroni<b> deri sa I2P të boot dhe tåe gjejë peers, </string>
|
||||
<string name="first_start_read">Deri sa jeni duke pritur, ju lutem lexoni notat që janë lëshuar dhe vizitoni faqen e mirëseardhjes. </string>
|
||||
|
@ -16,7 +16,6 @@
|
||||
<string name="label_info_and_pages">信息及页面</string>
|
||||
<string name="label_welcome_page">欢迎页面</string>
|
||||
<string name="label_news">新闻</string>
|
||||
<string name="label_news_status">I2P 最新消息</string>
|
||||
<string name="label_peers_status">节点</string>
|
||||
<string name="label_release_notes">版本说明</string>
|
||||
<string name="label_licenses">许可证</string>
|
||||
@ -25,6 +24,13 @@
|
||||
<string name="label_graphs">图</string>
|
||||
<string name="button_router_off">长按启动I2P</string>
|
||||
<string name="button_router_on">I2P 正在运行(长按停止)</string>
|
||||
<!--Character to indicate a client tunnel. Usually first letter of the word "client".-->
|
||||
<string name="char_client_tunnel">C</string>
|
||||
<!--Character to indicate a server tunnel. Usually first letter of the word "server".-->
|
||||
<string name="char_server_tunnel">S</string>
|
||||
<string name="no_client_tunnels_running">还没有可信的客户端隧道正在运行。</string>
|
||||
<string name="configure_browser_title">配置浏览器?</string>
|
||||
<string name="configure_browser_for_i2p">您想配置一个浏览器来查看 I2P 站点吗?(您也可以以后再从帮助菜单设置这个)</string>
|
||||
<string name="first_start_title">恭喜I2P已安装</string>
|
||||
<string name="first_start_welcome"><b>欢迎来到I2P!</b> 当I2P 启动和找到同行时,请 <b>保持耐心</b>.</string>
|
||||
<string name="first_start_read">你在等候时,请阅读发布说明和欢迎页面.</string>
|
||||
@ -70,7 +76,7 @@
|
||||
<string name="settings_desc_bw_outbound">最大出站速度</string>
|
||||
<string name="settings_label_network">网络</string>
|
||||
<string name="settings_label_hiddenMode">参与</string>
|
||||
<string name="settings_desc_hiddenMode">关闭隐藏模式</string>
|
||||
<string name="settings_desc_hiddenMode">关闭隐身模式</string>
|
||||
<string name="settings_label_maxPartTunnels">最大参与隧道数</string>
|
||||
<string name="settings_desc_maxPartTunnels">参与贡献的最大隧道数量(默认=20)</string>
|
||||
<string name="settings_dialog_maxPartTunnels">参与的最大隧道数量</string>
|
||||
@ -103,6 +109,7 @@
|
||||
<string name="settings_label_expl_backupQuantity">备用数量</string>
|
||||
<string name="settings_summ_expl_backupQuantity">%s 隧道</string>
|
||||
<string name="settings_desc_expl_backupQuantity">备用隧道数量</string>
|
||||
<string name="settings_router_restart_required">请重新启动 I2P 以应用此更改</string>
|
||||
<string name="menu_about">关于</string>
|
||||
<string name="about_version">版本:</string>
|
||||
<string name="about_project">项目主页:</string>
|
||||
@ -175,4 +182,10 @@
|
||||
<string name="i2ptunnel_view_target">目标:</string>
|
||||
<string name="i2ptunnel_view_access_point">接入点:</string>
|
||||
<string name="i2ptunnel_view_autostart">自动启动</string>
|
||||
<string name="copy_logs">复制日志</string>
|
||||
<string name="i2p_android_error_logs">I2P Android 错误日志</string>
|
||||
<string name="i2p_android_logs">I2P Android 日志</string>
|
||||
<string name="error_logs_copied_to_clipboard">错误日志已复制到剪贴板</string>
|
||||
<string name="logs_copied_to_clipboard">日志已复制到剪贴板</string>
|
||||
<string name="label_browser_configuration">浏览器配置</string>
|
||||
</resources>
|
||||
|
@ -37,4 +37,10 @@
|
||||
<item>1</item>
|
||||
<item>2</item>
|
||||
</string-array>
|
||||
<string-array name="help_categories">
|
||||
<item>@string/app_name</item>
|
||||
<item>@string/label_browser_configuration</item>
|
||||
<item>@string/label_addressbook</item>
|
||||
<item>@string/label_i2ptunnel</item>
|
||||
</string-array>
|
||||
</resources>
|
||||
|
@ -1,4 +1,8 @@
|
||||
<resources>
|
||||
<color name="indicator_red">#ffff0000</color>
|
||||
<color name="indicator_yellow">#ffffff00</color>
|
||||
<color name="indicator_green">#ff00ff00</color>
|
||||
|
||||
<color name="step_pager_previous_tab_color">#4433b5e5</color>
|
||||
<color name="step_pager_selected_tab_color">#ff0099cc</color>
|
||||
<color name="step_pager_selected_last_tab_color">#ff669900</color>
|
||||
|
@ -3,6 +3,8 @@
|
||||
<dimen name="activity_horizontal_margin">16dp</dimen>
|
||||
<dimen name="activity_vertical_margin">16dp</dimen>
|
||||
|
||||
<dimen name="tunnel_indicator">20dp</dimen>
|
||||
|
||||
<dimen name="step_pager_tab_width">32dp</dimen>
|
||||
<dimen name="step_pager_tab_height">3dp</dimen>
|
||||
<dimen name="step_pager_tab_spacing">4dp</dimen>
|
||||
|
@ -18,7 +18,6 @@
|
||||
<string name="label_info_and_pages">Information and pages</string>
|
||||
<string name="label_welcome_page">Welcome Page</string>
|
||||
<string name="label_news">News</string>
|
||||
<string name="label_news_status">Latest I2P News</string>
|
||||
<string name="label_peers_status">Peers</string>
|
||||
<string name="label_release_notes">Release Notes</string>
|
||||
<string name="label_licenses">Licenses</string>
|
||||
@ -29,6 +28,14 @@
|
||||
<string name="button_router_off">Long press to start I2P</string>
|
||||
<string name="button_router_on">I2P is running (long press to stop)</string>
|
||||
|
||||
<!-- Character to indicate a client tunnel. Usually first letter of the word "client". -->
|
||||
<string name="char_client_tunnel">C</string>
|
||||
<!-- Character to indicate a server tunnel. Usually first letter of the word "server". -->
|
||||
<string name="char_server_tunnel">S</string>
|
||||
<string name="no_client_tunnels_running">No client tunnels are running yet.</string>
|
||||
|
||||
<string name="configure_browser_title">Configure browser?</string>
|
||||
<string name="configure_browser_for_i2p">Would you like to configure a browser to view I2P sites? (You can also do this later from the help menu.)</string>
|
||||
<string name="first_start_title">Congratulations on getting I2P installed!</string>
|
||||
<string name="first_start_welcome"><b>Welcome to I2P!</b> Please <b>have patience</b> as I2P boots up and finds peers.</string>
|
||||
<string name="first_start_read">While you are waiting, please read the release notes and welcome page.</string>
|
||||
@ -117,6 +124,8 @@
|
||||
<string name="settings_summ_expl_backupQuantity">%s tunnels</string>
|
||||
<string name="settings_desc_expl_backupQuantity">How many tunnel backups</string>
|
||||
|
||||
<string name="settings_router_restart_required">Please restart I2P to apply the changes</string>
|
||||
|
||||
<string name="menu_about">About</string>
|
||||
<string name="about_version">Version:</string>
|
||||
<string name="about_project">Project Home:</string>
|
||||
@ -203,4 +212,12 @@
|
||||
<string name="i2ptunnel_view_target">Target:</string>
|
||||
<string name="i2ptunnel_view_access_point">Access point:</string>
|
||||
<string name="i2ptunnel_view_autostart">Auto-start</string>
|
||||
|
||||
<string name="copy_logs">Copy logs</string>
|
||||
<string name="i2p_android_error_logs">I2P Android Error Logs</string>
|
||||
<string name="i2p_android_logs">I2P Android Logs</string>
|
||||
<string name="error_logs_copied_to_clipboard">Error logs copied to clipboard</string>
|
||||
<string name="logs_copied_to_clipboard">Logs copied to clipboard</string>
|
||||
|
||||
<string name="label_browser_configuration">Browser configuration</string>
|
||||
</resources>
|
@ -1,4 +1,6 @@
|
||||
<resources>
|
||||
<style name="I2PAndroid" parent="Theme.AppCompat" />
|
||||
|
||||
<style name="WizardPageContainer">
|
||||
<item name="android:layout_width">match_parent</item>
|
||||
<item name="android:layout_height">match_parent</item>
|
||||
|
@ -68,12 +68,14 @@
|
||||
<!--
|
||||
i2cp.disableInterface=true
|
||||
-->
|
||||
<!-- Hidden because we have the client library now.
|
||||
<CheckBoxPreference
|
||||
android:key="i2cp.disableInterface"
|
||||
android:defaultValue="false"
|
||||
android:title="@string/settings_label_i2cp"
|
||||
android:summary="@string/settings_desc_i2cp"
|
||||
/>
|
||||
-->
|
||||
|
||||
<PreferenceScreen
|
||||
android:key="settings_exploratory_pool"
|
||||
|
@ -36,15 +36,22 @@
|
||||
<PreferenceCategory
|
||||
android:key="settings_network"
|
||||
android:title="@string/settings_label_network">
|
||||
<!--
|
||||
Temporarily hidden because of problems with changing defaults.
|
||||
We don't want to cause network instability because we have thousands of
|
||||
new unstable routers churning the network, and can't change their
|
||||
default settings.
|
||||
<CheckBoxPreference
|
||||
android:key="router.hiddenMode"
|
||||
android:defaultValue="true"
|
||||
android:title="@string/settings_label_hiddenMode"
|
||||
android:summary="@string/settings_desc_hiddenMode"
|
||||
/>
|
||||
-->
|
||||
<!--
|
||||
router.maxParticipatingTunnels=0
|
||||
-->
|
||||
<!--
|
||||
<com.hlidskialf.android.preference.SeekBarPreference
|
||||
android:key="router.maxParticipatingTunnels"
|
||||
android:defaultValue="20"
|
||||
@ -55,9 +62,11 @@
|
||||
android:text=" Tunnels"
|
||||
android:dependency="router.hiddenMode"
|
||||
/>
|
||||
-->
|
||||
<!--
|
||||
router.sharePercentage=10
|
||||
-->
|
||||
<!--
|
||||
<com.hlidskialf.android.preference.SeekBarPreference
|
||||
android:key="router.sharePercentage"
|
||||
android:defaultValue="80"
|
||||
@ -69,6 +78,7 @@
|
||||
android:dependency="router.hiddenMode"
|
||||
android:shouldDisableView="true"
|
||||
/>
|
||||
-->
|
||||
|
||||
<!--
|
||||
i2np.upnp.enable=false
|
||||
|
8
client/src/main/res/values-cs/strings.xml
Normal file
8
client/src/main/res/values-cs/strings.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<resources>
|
||||
<string name="yes">Ano</string>
|
||||
<string name="no">Ne</string>
|
||||
<string name="install_i2p_android">Instalovat I2P Android?</string>
|
||||
<string name="you_must_have_i2p_android">Musíte mít nainstalovaný a zapnutý I2P Android. Přejete si jej nainstalovat?</string>
|
||||
<string name="start_i2p_android">Otevřít I2P Android?</string>
|
||||
</resources>
|
Reference in New Issue
Block a user