Compare commits

...

102 Commits

Author SHA1 Message Date
788445f6ce New translations 2013-10-15 19:52:39 +00:00
e4c9095626 merge of '73d2724826ecdabe3e124af9e485c44fe7188117'
and '977f74485a75e34e7488c13e06849f6dfb5d2d2a'
2013-08-12 01:44:37 +00:00
dd90ea9874 Put full strings in android:dialogMessage for SeekBarPreference
The SeekBarPreference class needs fixing to follow resource references.
2013-08-12 01:44:31 +00:00
zzz
53c7770e4e - Handle 4-digit core version
- Set API in version string to min version
2013-08-11 14:50:01 +00:00
21274f0335 Added es translation 2013-08-11 13:58:21 +00:00
4ccf3e713d tr-rTR -> tr to support other regions as well 2013-08-11 13:58:05 +00:00
48f84f1a1b Added tr_TR translations 2013-08-10 01:19:45 +00:00
eb4ae2c66d Set minimum percentage, add language code mapping for tr_TR 2013-08-10 01:06:37 +00:00
6d340dc056 Added Transifex config 2013-08-09 06:22:47 +00:00
f312b7c6f1 Extracted more strings 2013-08-09 03:24:15 +00:00
a42bd73de3 Comment out add button in AddressbookActivity 2013-08-08 14:24:59 +00:00
4424392bdc Comment out add button until it does something 2013-08-08 14:17:11 +00:00
bfe71213f8 Extracted more strings 2013-08-08 14:07:34 +00:00
cd2a12c8ed Use dp instead of px, removed invalid property (for LinearLayout) 2013-08-08 13:45:50 +00:00
4ca2ed756f Updated README.txt 2013-08-08 13:30:54 +00:00
a4abfd8fb8 Updated support library path to match README.txt 2013-08-08 13:30:41 +00:00
9d754c29ae Moved ic_content_new.png to proper folder 2013-08-08 13:05:17 +00:00
0101e63bce Updated .mtn-ignore 2013-08-08 03:33:40 +00:00
75fe8bfbe0 Removed another old import 2013-08-08 03:23:16 +00:00
806f6edbf1 Removed old import 2013-08-08 03:07:16 +00:00
767ff4f3d2 Merged methods 2013-08-08 02:55:52 +00:00
07fafb03b6 Added ActionBar to Addressbook, placeholder add action 2013-08-08 02:52:02 +00:00
e98f86b29a Updated .mtn-ignore 2013-08-08 02:33:07 +00:00
18bc4f141d Setup for ActionBar using appcompat support library
The path in project.properties will require local overriding. I tried directly
referencing the SDK with ${sdk.dir} but the build fails with an absolute path
to a library.
2013-08-07 13:07:49 +00:00
a3792bad7a Set target SDK to 18 2013-08-07 12:37:34 +00:00
745bd3fa94 Set target SDK to 18 2013-08-07 12:00:15 +00:00
97692a4635 Use color style instead of explicit color 2013-08-07 03:35:06 +00:00
3fe7575dab Removed FrameLayout 2013-08-06 05:41:23 +00:00
a7fc5090f3 Simplified settings layout, pulled strings into resource file 2013-08-05 14:41:08 +00:00
6154f64120 Set text resource color to stop color-change on touch 2013-08-05 12:52:13 +00:00
0e5ca23732 Fixed bug in main.xml 2013-08-04 04:34:17 +00:00
c47e7dab31 Added Eclipse project files
To satisfy dependencies, import the following other projects from i2p.i2p into
the same Eclipse workspace as i2p.android.base:
i2p_sdk       - core/java/
i2p_router    - router/java/
i2ptunnel     - apps/i2ptunnel/java/
BOB           - apps/BOB/
addressbook   - apps/addressbook/
jetty         - apps/jetty/
ministreaming - apps/ministreaming/java/
2013-08-04 04:33:56 +00:00
zzz
472fa6d49e - Adjust default configs, esp. ones on the settings page
- Update release notes
- Lower log levels
- Spelling fixes on settings page
2013-07-30 19:52:25 +00:00
60ece9d4d2 fix honeycomb notification annoyance 2012-12-14 02:07:22 +00:00
afd656c6b4 Fixes to peers webviewer 2012-10-04 16:46:03 +00:00
78e250a207 Small stats cleanup 2012-09-20 02:15:32 +00:00
134db2ecd3 Allow _fast_ quit v.s. graceful when user hits stop and then back button. 2012-09-11 13:10:11 +00:00
53caad9f2a Fix state recognition on restart. 2012-09-11 12:44:00 +00:00
742df967e2 Clean up poorly formed code (lint), fix close on rotate. 2012-09-11 09:14:46 +00:00
5d0c5c30eb Fix stale notification icon + refactoring 2012-09-11 06:32:53 +00:00
cb9924a0bf (Security fix) Fully kill the app and remove it from memory if not running. 2012-09-11 02:32:44 +00:00
3ceed9a6b3 Remove checks for properties, as-per zzz 2012-09-10 21:14:47 +00:00
c3d95a608d fix numaric typo 2012-09-06 13:00:31 +00:00
1b004a628e Fix bad router config for ports. This really belongs in the core... 2012-09-05 06:09:03 +00:00
b080bd387a If no participating tunnles, blank that status line out. 2012-09-04 12:19:24 +00:00
7a429674a7 Add missing colon 2012-09-04 06:52:12 +00:00
45a1511cab Add 10pixel border, adjust scrollbars 2012-09-04 06:46:28 +00:00
6c7be97ed5 FatCowIcons license was not copied from i2p.i2p, so I added it to custom_rules.xml
(for copying on build) and changed LicenseActivity to show it.
2012-09-03 22:58:10 +00:00
3244509cab Added icons to the UI. Used fatcow icons since the license is allready in place.
Screenshots could be found at: http://meeh.i2p/android/ui/2/
2012-09-03 22:19:08 +00:00
43a20d18c5 last adjustment to i2ptunnel config 2012-08-31 13:57:26 +00:00
e2332543ec Fix kytv's irc server settings, oops 2012-08-31 04:26:05 +00:00
4d68da45b4 Seperate out kytv's irc server 2012-08-31 04:17:24 +00:00
084ed85467 no more bouncy castle, wrapper.log fix 2012-08-28 13:17:46 +00:00
1d060fd419 Revert UPnP now that it was fixed. 2012-08-18 00:00:03 +00:00
a95ca82a3e Make service foreground, so droid does not stop us 2012-08-17 22:42:00 +00:00
c13101d535 More sensable defaults, especially dangerous 1 hop tunnels. 2012-08-13 00:07:15 +00:00
7dc7697c14 fix mysterious file name, force routerjars 2012-08-12 22:50:39 +00:00
91fb0a2248 Adding res/menu/activity_addressbook_settings.xml 2012-08-12 19:40:32 +00:00
2663cc7d57 Forgot a resource file. 2012-08-12 18:48:52 +00:00
f9fce317d3 Added support for ndk building in osx. (Hope i did't breake it.. worked on osx 10.8 / ubuntu 12.04)
Also did some changes in AddressbookSettingsActivity; changed the way subscriptions.txt is readed and removed tabs. also changed some handlings in save function.
2012-08-12 16:29:25 +00:00
f87a3eb03c Cleaned up a bug I made making it unavailable on ubntu and most surely other linux distros.
I've think I have fixed it, but it would be perfect if someone with good shell skills could check.
2012-08-12 14:41:20 +00:00
zzz
36a0f2c678 - Enable SSL reseed
- Update README.txt and release notes
- Add irc.killyourtv.i2p to IRC list
- Use new buildI2PTunnelJar target
- LogWriter cleanup
2012-08-12 11:25:06 +00:00
f8fe3f082a Added support for building jni in osx. Also forgot to add new source files from last commit. 2012-08-12 04:02:24 +00:00
6e130185de Added AddressbookSettingsActivity, and a link via settings. It's now possible to update subscriptions.txt on android. 2012-08-12 03:55:13 +00:00
006fc1dc51 Moving i2plogo to top and fixed a typo. 2012-08-11 21:05:21 +00:00
87836ddab6 Some UI changes to the main activity.
* Rearanged views
* Bigger buttons
* Removed wallpaper
* Added topic labels
2012-08-11 20:49:12 +00:00
ff7154b525 oops, forgot to add arrays.xml 2012-08-11 15:59:11 +00:00
7a829236b9 Add data usage stat 2012-08-08 03:31:41 +00:00
d3edd31155 test commit 2012-08-04 12:57:08 +00:00
455726f05a merge of '28e40eada54b4ffaffbdedb720514e9c75bde890'
and 'ed5a9580c190b1f53ebc6c46fe936b6c80114779'
2012-08-03 03:55:49 +00:00
5dc9d729f4 Fix buildnumber js, add more settings 2012-08-03 03:53:20 +00:00
6d42b93de4 merge of 'a6013429f41dd5ea107ee5e56da100592f7ede0c'
and 'eddaa1f2aaa94d303db9952dc8a04e7f10a19bf3'
2012-08-03 02:38:24 +00:00
39b54c41ab Remove duplicate Debug, move wrapper.log delete to a better place. 2012-08-03 02:37:40 +00:00
f8920298ee merge of 'b8271f21729bb5732b5383ee78febb68bde639af'
and 'c300165977b04a83f75252de61018f9122d0b2fc'
2012-08-03 01:08:33 +00:00
cc3b37c4c0 change install location to auto 2012-08-03 01:08:21 +00:00
0cdd5a5d88 merge of '382962c8f01043a3d3b75c95bf3d469b5aabc799'
and 'bc7602f413292ff3e11f3c9dbeb513075f10af14'
2012-08-03 00:58:00 +00:00
b61bc8f5ef move manifest files, change install location to auto, additional ant file tweaks 2012-08-03 00:57:44 +00:00
2a6a2ef7a7 merge of '96f925faf1d190d7b7d71c043d3b73853cc7a9f7'
and 'a081d5b6c58932415d009872ca843b36587fc455'
2012-08-01 14:59:49 +00:00
245f69f2d3 Fix build problems for the routerjars libs stuff... Should build fine now. 2012-08-01 14:59:29 +00:00
4c43b6f5d5 merge of 'cd63013f274d56bce70efcc4b1f0004411f9013a'
and 'eea8516ab4cd7b29f403d17fff0272a38d3cba7c'
2012-08-01 13:37:50 +00:00
28230c914d finish sync 2012-08-01 13:36:30 +00:00
f7e1acdb68 merge of '6a29ded18e13ec9d52d9af1abc2cbc21d2cc80d0'
and '8b6ea99d1c37c57f25c94df8231ae4a6e765db8c'
2012-08-01 13:32:13 +00:00
995cd7f327 javascript all the buildnumber stuff, new target incrementBuild, use when i2p.i2p source has not changed, but android source has changed. 2012-08-01 13:29:14 +00:00
zzz
1e024c22da fixup after merge 2012-07-31 23:11:22 +00:00
zzz
4e853a753f merge of '099d95534fe893da4acef3a0b5ab0ea8d74b2d79'
and 'aec2af21d2c3fe9b04ec51cb63fa8ef1188a3eb6'
2012-07-31 23:07:18 +00:00
01547e9a20 Add missing file 2012-07-31 20:01:59 +00:00
zzz
09b2af14fd merge of '9bda005612c09e3581b62178a01594526384c36b'
and 'f5cf8336fa20e64d9ff7dc28776621fb88ccef5c'
2012-07-31 19:52:23 +00:00
f5d06470e4 incrementBuild target, be sure to execute it manually from ant to increment build number 2012-07-31 19:42:49 +00:00
c9abfa80f0 Make SeekBar away from edges and away from value view 2012-07-29 21:36:16 +00:00
f34ef46dbf Make SeekBar width expand in a way that actually makes sense for the value range 2012-07-29 21:18:16 +00:00
0c30296888 Huge refactor, fixes, settings, put jbigi.so back in too. 2012-07-28 00:34:05 +00:00
3fd373ad8c less transparent icons, they were too dark, and difficult to see 2012-07-25 14:03:15 +00:00
41091dce25 BOB 2012-07-24 19:21:17 +00:00
0fbaeb0ea4 Don't ask for signing passphrase on the lib build 2012-07-24 05:59:45 +00:00
19791a5965 builds fine now 2012-07-24 05:25:49 +00:00
9d4c0aa839 Reorganize router to own sub-project to avoid build errors 2012-07-24 05:16:21 +00:00
0b12a952cb update README.txt 2012-07-23 23:47:16 +00:00
a95aa6e89b Janitorial work, imports and some warnings 2012-07-23 09:33:42 +00:00
f13c772509 install certificates 2012-07-22 02:17:04 +00:00
0f28c4d807 archive certificates 2012-07-21 19:54:08 +00:00
a649d434c7 Finish fixing ant issues, needs work yet. 2012-07-15 08:42:47 +00:00
23c5710d42 Move to newer ASDK and ant, does not compile 2012-06-30 16:31:56 +00:00
95 changed files with 3812 additions and 1336 deletions

14
.classpath Normal file
View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="gen"/>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
<classpathentry combineaccessrules="false" kind="src" path="/i2p_sdk"/>
<classpathentry combineaccessrules="false" kind="src" path="/i2p_router"/>
<classpathentry combineaccessrules="false" kind="src" path="/i2ptunnel"/>
<classpathentry combineaccessrules="false" kind="src" path="/BOB"/>
<classpathentry combineaccessrules="false" kind="src" path="/addressbook"/>
<classpathentry kind="output" path="bin/classes"/>
</classpath>

View File

@ -22,3 +22,11 @@ _jsp\.java$
~$ ~$
/build/ /build/
/classes/ /classes/
# Android-specific ignores
^bin
^gen
^routerjars/bin
^routerjars/gen
AndroidManifest.xml
local.properties

33
.project Normal file
View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>I2P_Android</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

11
.tx/config Normal file
View File

@ -0,0 +1,11 @@
[main]
host = https://www.transifex.com
lang_map = ru_RU: ru, sv_SE: sv, tr_TR: tr, zh_CN: zh
[I2P.android]
file_filter = res/values-<lang>/strings.xml
source_file = res/values/strings.xml
source_lang = en
type = ANDROID
minimum_perc = 50

View File

@ -1,16 +1,18 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="net.i2p.android.router" package="net.i2p.android.router"
android.versionCode="4720640" android.versionCode="0"
android.versionName="0.9.1-0_b1-API8" android.versionName="0.0.0-0_b0-API8"
android:installLocation="preferExternal" android:installLocation="auto"
> >
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-sdk android:minSdkVersion="8" /> <uses-sdk android:minSdkVersion="8"
android:targetSdkVersion="18" />
<application android:label="@string/app_name" <application android:label="@string/app_name"
android:theme="@style/Theme.AppCompat"
android:icon="@drawable/ic_launcher_itoopie" > android:icon="@drawable/ic_launcher_itoopie" >
<service android:name=".service.RouterService" <service android:name=".service.RouterService"
android:label="@string/app_name" android:label="@string/app_name"
@ -20,7 +22,6 @@
<activity android:name=".activity.MainActivity" <activity android:name=".activity.MainActivity"
android:label="@string/app_name" android:label="@string/app_name"
android:icon="@drawable/ic_launcher_itoopie" android:icon="@drawable/ic_launcher_itoopie"
android.theme="@android:style/Theme.NoTitleBar"
android:launchMode="singleTop" > android:launchMode="singleTop" >
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
@ -29,21 +30,17 @@
</activity> </activity>
<activity android:name=".activity.NewsActivity" <activity android:name=".activity.NewsActivity"
android:label="I2P News" android:label="I2P News"
android:configChanges="orientation|keyboardHidden" android:configChanges="orientation|keyboardHidden" >
android.theme="@android:style/Theme.NoTitleBar" >
</activity> </activity>
<activity android:name=".activity.TextResourceActivity" <activity android:name=".activity.TextResourceActivity"
android:label="I2P Information" android:label="I2P Information" >
android.theme="@android:style/Theme.NoTitleBar" >
</activity> </activity>
<activity android:name=".activity.LicenseActivity" <activity android:name=".activity.LicenseActivity"
android:label="I2P License Information" android:label="I2P License Information" >
android.theme="@android:style/Theme.NoTitleBar" >
</activity> </activity>
<activity android:name=".activity.WebActivity" <activity android:name=".activity.WebActivity"
android:label="I2P Web Browser" android:label="I2P Web Browser"
android:configChanges="orientation|keyboardHidden" android:configChanges="orientation|keyboardHidden" >
android.theme="@android:style/Theme.NoTitleBar" >
<intent-filter> <intent-filter>
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
@ -53,23 +50,23 @@
</activity> </activity>
<activity android:name=".activity.SettingsActivity" <activity android:name=".activity.SettingsActivity"
android:label="I2P Settings" android:label="I2P Settings"
android.theme="@android:style/Theme.NoTitleBar" android:launchMode="singleTop" >
</activity>
<activity android:name=".activity.AddressbookSettingsActivity"
android:label="I2P Addressbook Settings"
android:launchMode="singleTop" > android:launchMode="singleTop" >
</activity> </activity>
<activity android:name=".activity.AddressbookActivity" <activity android:name=".activity.AddressbookActivity"
android:label="I2P Address Book" android:label="Addressbook"
android.theme="@android:style/Theme.NoTitleBar"
android:launchMode="singleTop" > android:launchMode="singleTop" >
</activity> </activity>
<activity android:name=".activity.LogActivity" <activity android:name=".activity.LogActivity"
android:label="I2P Logs" android:label="I2P Logs" >
android.theme="@android:style/Theme.NoTitleBar" >
</activity> </activity>
<activity android:name=".activity.PeersActivity" <activity android:name=".activity.PeersActivity"
android:label="I2P Peers and Transport Status" android:label="I2P Peers and Transport Status"
android:configChanges="orientation|keyboardHidden" android:configChanges="orientation|keyboardHidden"
android.theme="@android:style/Theme.NoTitleBar"
android:launchMode="singleTop" > android:launchMode="singleTop" >
</activity> </activity>
</application> </application>
</manifest> </manifest>

View File

@ -1,73 +1,111 @@
These instructions are for a recent Android SDK (1.6 or later). These instructions are for a recent Android SDK (Rev 20 or better) on Linux.
These instructions were last updated for SDK Tools Version 11 with Windows building is not currently supported.
SDK Platform-tools Version 5, June 2011.
These instructions were last updated for SDK Tools Version 20 with
SDK Platform-tools Version 12 from updates.
The i2p source must be installed in ../i2p.i2p, The i2p source must be installed in ../i2p.i2p,
or else add i2psrc=/path/to/source in the local.properties file. or else add i2psrc=/path/to/source in the local.properties file.
===================== =====================
#Download the SDK from http://developer.android.com/sdk/index.html Dependencies:
#Unzip the android SDK in ../
#So then the android tools will be in ../android-sdk-linux_86/tools/ - Java SDK (preferably Oracle/Sun or OpenJDK) 1.6.0 or higher
- Apache Ant 1.8.0 or higher
- I2P source in ../i2p.i2p
- Android SDK (tested with Rev 20 and platform-tools version 12)
=====================
Instructions:
# Download the SDK from http://developer.android.com/sdk/index.html
# Unzip the android SDK in ../
# So then the android tools will be in ../android-sdk-linux/tools/
# #
# Run the GUI updater, which you must do to get an SDK Platform: # Run the GUI updater, which you must do to get an SDK Platform:
../android-sdk-linux_86/tools/android & ../android-sdk-linux/tools/android &
# now go to the available packages tab, check the box and click refresh, # now go to the available packages tab, check the box and click refresh,
# and download an SDK Platform # and download an SDK Platform
# Since I2P is configured to run on 1.1 or higher # Since I2P is targeted at 4.3 (API 18)
# (API 2) download that one. Otherwise you must change the # download at least that one. Otherwise you must change the
# target in default.properties from android-2 to andriod-x # target in project.properties from android-18 to andriod-x
# where x is the API version. # where x is the API version.
# I2P is configured to run on 2.2 (API 8) or higher using the
# Android Support Library, so download that as well
# (it's under "Extras").
# To run the debugger (ddms) you also need to download the # To run the debugger (ddms) you also need to download the
# "Android SDK Platform-Tools" package from the GUI updater. # "Android SDK Platform-Tools" package from the GUI updater.
# create a file local.properties with the following line (without the leading # of course): # create a file local.properties with the following line (without the leading # of course),
# sdk.dir=/path/to/your/android-sdk-linux_86 # do NOT use a relative path
# The old property was sdk-location=/path/to/your/android-sdk-linux_86 # sdk.dir=/path/to/your/android-sdk-linux
# but it changed in more recent tools. # Copy this file to the routerjars/ directory, it is needed in both places.
# If your SDK is not in ../android-sdk-linux/ then you must
# override the location of the Android Support Library. Add
# the following line to local.properties
# do NOT use an absolute path
# android.library.reference.2=path/to/your/android-sdk-linux/extras/android/support/v7/appcompat
# Don't add it to the local.properties in the routerjars/ directory.
# DO NOT create a new project or anything. It's all set up right here for you. # DO NOT create a new project or anything. It's all set up right here for you.
# Create the android 2.2 (API 8) virtual device # Create the android 4.3 (API 18) virtual device
# (don't make a custom hardware profile) # (don't make a custom hardware profile)
../android-sdk-linux_86/tools/android create avd --name i2p --target 8 ../android-sdk-linux/tools/android create avd --name i2p --target 18
#then run the emulator: # then run the emulator:
# This may take a LONG time the first time (half an hour or more)... # This may take a LONG time the first time (half an hour or more)...
# Run the debugger to ensure it is making progress # Run the debugger to ensure it is making progress
# -no-boot-anim for faster boot # -no-boot-anim for faster boot
# -dns-server 8.8.8.8 if the router can't reseed # -dns-server 8.8.8.8 if the router can't reseed
#../android-sdk-linux_86/tools/emulator -avd i2p -no-boot-anim -dns-server 8.8.8.8 & # ../android-sdk-linux/tools/emulator -avd i2p -no-boot-anim -dns-server 8.8.8.8 &
../android-sdk-linux_86/tools/emulator -avd i2p & ../android-sdk-linux/tools/emulator -avd i2p &
# or to talk to a real phone in debug mode: # or to talk to a real device in debug mode:
# You have to do this if you get a permission error - # You have to do this if you get a permission error -
# Stop ddms, unplug the phone, do the following, # Stop ddms, unplug the device, do the following,
# then plug in the phone, then start ddms # then plug in the device, then start ddms
adb kill-server adb kill-server
sudo adb start-server sudo adb start-server
adb devices adb devices
#then wait a couple minutes until the emulator is up # then wait a couple minutes until the emulator or device is up
#then install the I2P app # compile and install for a release
ant install ant release
ant installr
#then run the debugger # or compile and install for a debug version
../android-sdk-linux_86/tools/ddms & ant debug
ant installd
#to rebuild and reinstall to emulator or phone: # then run the debugger
ant reinstall ../android-sdk-linux/tools/ddms &
# Now click on the I2P icon on your phone! # to rebuild and reinstall to emulator or device:
ant clean
# then do which ever from the above compile and install choices.
# to uninstall
ant uninstall
# or use your device's menu.
# Other ant tagets are available, just type
ant
# Anyway, with I2P installed, click on the I2P icon on your device and enjoy!
#other helpful commands #other helpful commands
../android-sdk-linux_86/platform-tools/adb shell ../android-sdk-linux/platform-tools/adb shell
../android-sdk-linux_86/platform-tools/adb pull /some/file/on/emulator some-local-dir/ ../android-sdk-linux/platform-tools/adb pull /some/file/on/emulator some-local-dir/
# copy the Dev Tools app from the emulator to your phone # copy the Dev Tools app from the emulator to your device
adb -e pull /system/app/Development.apk ./Development.apk adb -e pull /system/app/Development.apk ./Development.apk
adb -d install Development.apk adb -d install Development.apk

411
build.xml
View File

@ -1,376 +1,83 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--
- Portions copied and modified from Android SDK
- Copyright (c) 2005-2008, The Android Open Source Project
- Apache 2.0 license
- See licenses/LICENSE-Apache2.0.txt
-->
<project name="I2PAndroid" default="help"> <project name="I2PAndroid" default="help">
<!-- The local.properties file is created and updated by the 'android' tool. <!-- The local.properties file is created and updated by the 'android' tool.
It contain the path to the SDK. It should *NOT* be checked in in Version It contains the path to the SDK. It should *NOT* be checked into
Control Systems. --> Version Control Systems. -->
<property file="local.properties"/> <property file="local.properties" />
<!-- The build.properties file can be created by you and is never touched <!-- The ant.properties file can be created by you. It is only edited by the
by the 'android' tool. This is the place to change some of the default property values 'android' tool to add properties to it.
used by the Ant rules. This is the place to change some Ant specific build properties.
Here are some properties you may want to change/update: Here are some properties you may want to change/update:
application-package source.dir
the name of your application package as defined in the manifest. Used by the The name of the source directory. Default is 'src'.
'uninstall' rule. out.dir
source-folder The name of the output directory. Default is 'bin'.
the name of the source folder. Default is 'src'.
out-folder
the name of the output folder. Default is 'bin'.
Properties related to the SDK location or the project target should be updated For other overridable properties, look at the beginning of the rules
using the 'android' tool with the 'update' action. files in the SDK, at tools/ant/build.xml
This file is an integral part of the build system for your application and Properties related to the SDK location or the project target should
should be checked in in Version Control Systems. be updated using the 'android' tool with the 'update' action.
This file is an integral part of the build system for your
application and should be checked into Version Control Systems.
--> -->
<property file="build.properties"/> <property file="ant.properties" />
<!-- set the old name to the new name -->
<property name="sdk-location" value="${sdk.dir}" />
<!-- The default.properties file is created and updated by the 'android' tool, as well <!-- The project.properties file is created and updated by the 'android'
as ADT. tool, as well as ADT.
This file is an integral part of the build system for your application and
should be checked in in Version Control Systems. -->
<property file="default.properties"/>
<!-- Custom Android task to deal with the project target, and import the proper rules. This contains project specific properties such as project target, and library
This requires ant 1.6.0 or above. --> dependencies. Lower level build properties are stored in ant.properties
<path id="android.antlibs"> (or in .classpath for Eclipse projects).
<pathelement path="${sdk-location}/tools/lib/anttasks.jar" />
<pathelement path="${sdk-location}/tools/lib/sdklib.jar" />
<pathelement path="${sdk-location}/tools/lib/androidprefs.jar" />
<pathelement path="${sdk-location}/tools/lib/apkbuilder.jar" />
<pathelement path="${sdk-location}/tools/lib/jarutils.jar" />
</path>
<taskdef name="setup" This file is an integral part of the build system for your
classname="com.android.ant.SetupTask" application and should be checked into Version Control Systems. -->
classpathref="android.antlibs"/> <loadproperties srcFile="project.properties" />
<!-- Execute the Android Setup task that will setup some properties specific to the target, <!-- quick check on sdk.dir -->
and import the rules files. <fail
To customize the rules, copy/paste them below the task, and disable import by setting message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through an env var"
the import attribute to false: unless="sdk.dir"
<setup import="false" /> />
This will ensure that the properties are setup correctly but that your customized
targets are used.
-->
<setup import="true" />
<!-- <!--
================================================================================ Import per project custom build rules if present at the root of the project.
New I2P rules This is the place to put custom intermediary targets such as:
================================================================================ -pre-build
-pre-compile
-post-compile (This is typically used for code obfuscation.
Compiled code location: ${out.classes.absolute.dir}
If this is not done in place, override ${out.dex.input.absolute.dir})
-post-package
-post-build
-pre-clean
--> -->
<import file="custom_rules.xml" optional="true" />
<!-- overrides of those in main_rules.xml --> <!-- Import the actual build file.
<target name="-pre-build" depends="findI2PSource, copy-i2p-resources, incrementBuild" > To customize existing targets, there are two options:
<!-- aapt messes up when resources are added or deleted, just build every time --> - Customize only one target:
<delete dir="${gen.absolute.dir}/net" verbose="${verbose}" /> - copy/paste the target into this file, *before* the
<!-- screw it, do the classes too, until I add the depend class --> <import> task.
<delete dir="${out.absolute.dir}/classes/net" verbose="${verbose}" /> - customize it to your needs.
</target> - Customize the whole content of build.xml
- copy/paste the content of the rules files (minus the top node)
into this file, replacing the <import> task.
- customize to your needs.
<target name="-pre-compile" depends="buildrouter" /> ***********************
****** IMPORTANT ******
<target name="-post-compile" depends="hackcleanup, jbigi" /> ***********************
In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
<!-- new rules --> in order to avoid having your file be overridden by tools such as "android update project"
<target name="findI2PSource" >
<!-- override with i2psrc=path/to/source in local.properties -->
<property name="i2psrc" value="../i2p.i2p" />
<property name="i2pbase" location="${i2psrc}" />
<available file="${i2psrc}" property="i2p.present" />
<fail message="I2P source directory ${i2psrc} was not found. Install it there or set i2psrc=/path/to/source in local.properties" >
<condition>
<not>
<isset property="i2p.present" />
</not>
</condition>
</fail>
<echo message="Using I2P source at ${i2pbase}" />
</target>
<target name="buildrouter" depends="findI2PSource, -dirs" >
<!-- build router and core -->
<ant dir="${i2pbase}" >
<target name="buildRouter" />
<target name="buildI2PTunnel" />
<target name="buildAddressbook" />
</ant>
<!-- router -->
<copy file="${i2pbase}/build/router.jar" todir="${jar.libs.dir}" />
<!-- core -->
<!-- org.bouncycastle.crypto already in android
but we need a little trickery because our HMac is incompatible...
and the libs aren't in the SDK to compile against??? -->
<jar destfile="${jar.libs.dir}/crypto.jar" >
<zipfileset src="${i2pbase}/build/i2p.jar" >
<include name="org/bouncycastle/crypto/Digest.class" />
<include name="org/bouncycastle/crypto/Mac.class" />
<include name="org/bouncycastle/crypto/digests/GeneralDigest.class" />
<include name="org/bouncycastle/crypto/digests/MD5Digest.class" />
</zipfileset >
</jar>
<!-- lots of unneeded stuff could be deleted here -->
<jar destfile="${jar.libs.dir}/i2p.jar" >
<zipfileset src="${i2pbase}/build/i2p.jar" >
<exclude name="net/i2p/util/LogWriter.class" />
<exclude name="net/i2p/util/SecureDirectory.class" />
<exclude name="net/i2p/util/SecureFile.class" />
<exclude name="net/i2p/util/SecureFileOutputStream.class" />
<exclude name="org/bouncycastle/crypto/Digest.class" />
<exclude name="org/bouncycastle/crypto/Mac.class" />
<exclude name="org/bouncycastle/crypto/digests/GeneralDigest.class" />
<exclude name="org/bouncycastle/crypto/digests/MD5Digest.class" />
</zipfileset >
</jar>
<!-- i2ptunnel -->
<copy file="${i2pbase}/apps/ministreaming/java/build/mstreaming.jar" todir="${jar.libs.dir}" />
<copy file="${i2pbase}/apps/streaming/java/build/streaming.jar" todir="${jar.libs.dir}" />
<jar destfile="${jar.libs.dir}/i2ptunnel.jar" >
<zipfileset src="${i2pbase}/apps/i2ptunnel/java/build/i2ptunnel.jar" >
<exclude name="net/i2p/i2ptunnel/I2PTunnelGUI.class" />
</zipfileset >
</jar>
<!-- addressbook - make a jar, it's a war in the i2p distro -->
<jar destfile="${jar.libs.dir}/addressbook.jar"
basedir="${i2pbase}/apps/addressbook/build"
excludes="net/i2p/addressbook/Servlet.class" />
</target>
<!-- some resources -->
<target name="copy-i2p-resources" depends="findI2PSource, -dirs" >
<copy file="LICENSE.txt" tofile="res/raw/license_app_txt" />
<copy file="licenses/LICENSE-Apache2.0.txt" tofile="res/raw/license_apache20_txt" />
<copy file="${i2pbase}/installer/resources/themes/console/images/i2plogo.png" todir="res/drawable/" />
<copy file="${i2pbase}/installer/resources/themes/console/images/outbound.png" todir="res/drawable/" />
<copy file="${i2pbase}/installer/resources/themes/console/images/inbound.png" todir="res/drawable/" />
<copy file="${i2pbase}/installer/resources/themes/console/light/images/header.png" todir="res/drawable/" />
<copy file="${i2pbase}/installer/resources/themes/console/light/console.css" tofile="res/raw/console_css" />
<copy file="${i2pbase}/installer/resources/blocklist.txt" tofile="res/raw/blocklist_txt" />
<copy file="${i2pbase}/installer/resources/hosts.txt" tofile="res/raw/hosts_txt" />
<copy file="${i2pbase}/licenses/LICENSE-ElGamalDSA.txt" tofile="res/raw/license_elgamaldsa_txt" />
<copy file="${i2pbase}/licenses/LICENSE-SHA256.txt" tofile="res/raw/license_sha256_txt" />
<copy file="${i2pbase}/licenses/LICENSE-BSD.txt" tofile="res/raw/license_bsd_txt" />
<copy file="${i2pbase}/licenses/LICENSE-SNTP.txt" tofile="res/raw/license_sntp_txt" />
<copy file="${i2pbase}/licenses/LICENSE-LGPLv2.1.txt" tofile="res/raw/license_lgplv2_1_txt" />
<copy file="${i2pbase}/licenses/LICENSE-InstallCert.txt" tofile="res/raw/license_installcert_txt" />
<copy file="${i2pbase}/licenses/LICENSE-BlockFile.txt" tofile="res/raw/license_blockfile_txt" />
<copy file="${i2pbase}/licenses/LICENSE-GPLv2.txt" tofile="res/raw/license_gplv2_txt" />
<copy file="${i2pbase}/licenses/LICENSE-GPLv3.txt" tofile="res/raw/license_gplv3_txt" />
<copy file="${i2pbase}/licenses/LICENSE-LGPLv3.txt" tofile="res/raw/license_lgplv3_txt" />
<copy file="${i2pbase}/licenses/LICENSE-Addressbook.txt" tofile="res/raw/license_addressbook_txt" />
</target>
<target name="hackcleanup">
<delete file="${jar.libs.dir}/crypto.jar" />
</target>
<target name="jbigi" depends="findI2PSource" >
<exec executable="sh" osfamily="unix" failonerror="true">
<arg value="-c" />
<arg value="jni/build.sh ${i2pbase}" />
</exec>
<copy file="jni/libjbigi.so" todir="${native.libs.dir}/armeabi" />
</target>
<target name="incrementBuild" depends="findI2PSource" >
<buildnumber file="scripts/build.number" />
<exec executable="sh" osfamily="unix" failonerror="true">
<arg value="-c" />
<arg value="scripts/setversion.sh ${i2pbase}" />
</exec>
<!-- this loads my.version.code and my.version.name -->
<property file="scripts/version.properties" />
</target>
<!-- install now does both -->
<target name="reinstall" depends="install" />
<target name="distclean" depends="clean">
<delete dir="${jar.libs.dir}" verbose="${verbose}" />
<delete file="res/drawable/i2plogo.png" verbose="${verbose}"/>
<delete file="res/drawable/outbound.png" verbose="${verbose}"/>
<delete file="res/drawable/inbound.png" verbose="${verbose}"/>
<delete file="res/drawable/header.png" verbose="${verbose}"/>
<delete file="res/raw/console_css" verbose="${verbose}"/>
<delete file="res/raw/blocklist_txt" verbose="${verbose}" />
<delete file="res/raw/hosts_txt" verbose="${verbose}" />
<delete file="res/raw/license_app_txt" />
<delete file="res/raw/license_apache20_txt" />
<delete file="res/raw/license_elgamaldsa_txt" />
<delete file="res/raw/license_sha256_txt" />
<delete file="res/raw/license_bsd_txt" />
<delete file="res/raw/license_sntp_txt" />
<delete file="res/raw/license_lgplv2_1_txt" />
<delete file="res/raw/license_installcert_txt" />
<delete file="res/raw/license_blockfile_txt" />
<delete file="res/raw/license_gplv2_txt" />
<delete file="res/raw/license_gplv3_txt" />
<delete file="res/raw/license_lgplv3_txt" />
<delete dir="jni/build/" verbose="${verbose}" />
<delete file="scripts/build.number" verbose="${verbose}" />
<delete file="scripts/version.properties" verbose="${verbose}" />
</target>
<!-- just to make it easier -->
<target name="create-signing-keys" >
<echo message="key store is ${key.store}" />
<echo message="key store password is ${key.store.password}" />
<echo message="key alias is ${key.alias}" />
<input message="Enter common name for new key (your name): " addproperty="release.cn" />
<fail message="You must enter a name" >
<condition>
<equals arg1="${release.cn}" arg2="" />
</condition>
</fail>
<input message="Enter password for new key (6 characters minimum): " addproperty="release.password" />
<fail message="You must enter a password" >
<condition>
<equals arg1="${release.password}" arg2="" />
</condition>
</fail>
<echo message="Generating keys, this may take a while..." />
<exec executable="keytool" inputstring="${release.password}${line.separator}${release.password}${line.separator}" osfamily="unix" failonerror="true">
<arg value="-genkey" />
<arg value="-v" />
<arg value="-alias" />
<arg value="${key.alias}" />
<arg value="-keystore" />
<arg value="${key.store}" />
<arg value="-validity" />
<arg value="10000" />
<arg value="-keyalg" />
<arg value="RSA" />
<arg value="-keysize" />
<arg value="4096" />
<arg value="-storepass" />
<arg value="${key.store.password}" />
<arg value="-dname" />
<arg value="cn=${release.cn}, ou=Apps, o=I2P, c=DE" />
</exec>
<echo message="Created keys:" />
<exec executable="keytool" inputstring="android${line.separator}" osfamily="unix" failonerror="true">
<arg value="-list" />
<arg value="-v" />
<arg value="-alias" />
<arg value="${key.alias}" />
<arg value="-keystore" />
<arg value="${key.store}" />
</exec>
<echo message="BACK UP your key store file ${key.store} and your password!" />
</target>
<target name="verifyKeystore" >
<available file="${key.store}" property="keystore.present" />
<fail message="You must first create a keystore and keys with 'ant create-signing-keys'" >
<condition>
<not>
<isset property="keystore.present" />
</not>
</condition>
</fail>
</target>
<target name="verifyWorkspace" >
<echo message="Everything is checked in, right? Let's be sure:" />
<exec executable="mtn" failonerror="true">
<arg value="st" />
</exec>
<echo message="If there are any modified files above, stop now!" />
<echo message="(except AndroidManifest.xml)" />
</target>
<target name="verify" depends="verifyKeystore, verifyWorkspace, release" >
<exec executable="jarsigner" osfamily="unix" failonerror="true">
<arg value="-verify" />
<arg value="-verbose" />
<arg value="-certs" />
<arg value="${out.release.file}" />
</exec>
<echo message="" />
<echo message="Release file is ${out.release.file}" />
<echo message="Android version name: ${my.version.name}" />
<echo message="Android version code: ${my.version.code}" />
<echo message="File size:" />
<exec executable="ls" failonerror="true">
<arg value="-l" />
<arg value="${out.release.file}" />
</exec>
<echo message="SHA256 sum:" />
<exec executable="sha256sum" failonerror="true">
<arg value="${out.release.file}" />
</exec>
<echo message="Don't forget to mtn ci AndroidManifest.xml" />
<echo message="Don't forget to mtn tag w: android-${my.version.name}" />
<copy file="${out.release.file}" tofile="I2PAndroid-${my.version.name}.apk" />
<echo message="Release file copied to I2PAndroid-${my.version.name}.apk" />
</target>
<!--
================================================================================
From here down copied from SDK tools/ant/main_rules.xml from Tools version 11
and then modified
================================================================================
--> -->
<!-- version-tag: 1 -->
<!-- not necessary to copy if setup import="true" --> <import file="${sdk.dir}/tools/ant/build.xml" />
<!--
override this because the ant task com.android.ant.AaptExecLoopTask has issues:
a) it uses version.code which main_rules sets to "" and
b) it can't set versionName via the aapt task, have to use the aapt command line
-->
<!-- Puts the project's resources into the output package file
This actually can create multiple resource package in case
Some custom apk with specific configuration have been
declared in default.properties.
-->
<target name="-package-resources">
<echo>Packaging resources</echo>
<exec executable="${aapt}" failonerror="true" >
<arg value="package" />
<arg value="--version-code" />
<arg value="${my.version.code}" />
<arg value="--version-name" />
<arg value="${my.version.name}" />
<arg value="-f" />
<arg value="-m" />
<arg value="-M" />
<arg value="AndroidManifest.xml" />
<arg value="-I" />
<arg value="${android.jar}" />
<arg value="-S" />
<arg value="${resource.absolute.dir}" />
<arg value="-J" />
<arg value="${gen.absolute.dir}" />
<arg value="-F" />
<arg value="${out.absolute.dir}/${resource.package.file.name}" />
</exec>
</target>
</project> </project>

601
custom_rules.xml Normal file
View File

@ -0,0 +1,601 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="imported">
<!-- override with i2psrc=path/to/source in local.properties -->
<property name="i2psrc" value="../i2p.i2p" />
<property name="i2pbase" location="${i2psrc}" />
<available file="${i2psrc}" property="i2p.present" />
<fail message="I2P source directory ${i2psrc} was not found. Install it there or set i2psrc=/path/to/source in local.properties" >
<condition>
<not>
<isset property="i2p.present" />
</not>
</condition>
</fail>
<echo message="Using I2P source at ${i2pbase}" />
<!-- Utility scripts -->
<!-- Split a string -->
<scriptdef name="split" language="javascript">
<attribute name="value"/>
<attribute name="sep"/>
<attribute name="prefix"/>
<![CDATA[
values = attributes.get("value").split(attributes.get("sep"));
for(i = 0; i < values.length; i++) {
project.setNewProperty(attributes.get("prefix") + "." + i, values[i]);
}
]]>
</scriptdef>
<!-- Normalize the core version number -->
<scriptdef name="setcore" language="javascript">
<attribute name="value"/>
<![CDATA[
value = attributes.get("value").split("\n")[0];
values = value.split('\\.');
dots = values.length - 1;
major = values[0];
minor = "0";
release = "0";
point = "";
if(dots > 0) {
minor = values[1];
if(dots > 1) {
release = values[2];
if (dots > 2) {
point = "." + values[3];
}
}
}
project.setNewProperty("CORE", major + "." + minor + "." + release + point);
project.setNewProperty("CORE.major", major);
project.setNewProperty("CORE.minor", minor);
project.setNewProperty("CORE.release", release);
project.setNewProperty("CORE.point", point);
]]>
</scriptdef>
<!-- Normalize the router build number -->
<scriptdef name="normalizeitem" language="javascript">
<attribute name="value"/>
<attribute name="name" />
<![CDATA[
value = attributes.get("value").split("\n")[0].trim();
project.setNewProperty(attributes.get("name"), value);
]]>
</scriptdef>
<!-- input prefix, major, minor, release, routerbuild, androidbuild, sdk
Assigns a version string and version number -->
<scriptdef name="generateversions" language="javascript">
<attribute name="prefix"/>
<attribute name="major"/>
<attribute name="minor"/>
<attribute name="release"/>
<attribute name="point"/>
<attribute name="routerbuild"/>
<attribute name="androidbuild"/>
<attribute name="sdk"/>
<![CDATA[
Major = attributes.get("major") + ".";
Minor = attributes.get("minor") + ".";
Release = attributes.get("release");
Point = attributes.get("point") + "-";
Routerbuild = attributes.get("routerbuild") +"_b";
Androidbuild = attributes.get("androidbuild") +"-API";
SDK = attributes.get("sdk");
project.setNewProperty(attributes.get("prefix") + ".full", Major + Minor + Release + Point + Routerbuild + Androidbuild + SDK);
/*
* Android version code is an integer.
* So we have 31 bits.
* MAJOR 4 bits 0-15
* MINOR 8 bits 0-255
* RELEASE 8 bits 0-255
* ROUTERBUILD 7 bits 0-127
* ANDROIDBUILD 4 bits 0-15
*
* Note that ANDROIDBUILD is modded % 16, it will wrap,
* beware of that if you release multiple builds using the
* same ROUTERBUILD, or clear it if you update ROUTERBUILD
* Subtract 1 from ANDROIDBUILD since it starts at 1 after distclean.
*
* WARNING - 4th core field ("point") is ignored. Be sure to increment android build number.
*/
iMajor = ((parseInt(Major) % 16) << 27);
iMinor = ((parseInt(Minor) % 256) << 19);
iRelease = ((parseInt(Release)% 256) << 11);
iRouterbuild = ((parseInt(Routerbuild) % 128) << 4);
iAndroidbuild = ((parseInt(Androidbuild) - 1) % 16);
itotal = iMajor + iMinor + iRelease + iRouterbuild + iAndroidbuild;
project.setNewProperty(attributes.get("prefix") + ".vercode", itotal);
]]>
</scriptdef>
<!-- if file 'condition' != "true" write 'properties' to file 'name' -->
<scriptdef name="ifnotpresent" language="javascript">
<attribute name="file" />
<attribute name="condition" />
<![CDATA[
importClass(java.io.File);
importClass(java.util.Properties);
importClass(java.io.FileOutputStream);
importClass(java.io.ByteArrayInputStream);
doit = !attributes.get("condition").equals("true");
if(doit) {
props = new Properties();
props.setProperty("build.number", "1");
cfg = new File(attributes.get("file"));
fo = new FileOutputStream(cfg);
props.store(fo, "AUTO-GENERATED FILE, DO NOT EDIT!");
fo.close();
}
]]>
</scriptdef>
<!-- increment the build number -->
<scriptdef name="incbuildnumber" language="javascript">
<attribute name="file" />
<![CDATA[
importClass(java.io.File);
importClass(java.util.Properties);
importClass(java.io.FileOutputStream);
importClass(java.io.FileInputStream);
props = new Properties();
cfg = new File(attributes.get("file"));
fi = new FileInputStream(cfg);
props.load(fi);
fi.close();
m = (parseInt(props.getProperty("build.number")) + 1).toString();
props.setProperty("build.number", m);
fo = new FileOutputStream(cfg);
props.store(fo, "AUTO-GENERATED FILE, DO NOT EDIT!");
fo.close();
]]>
</scriptdef>
<!-- Update property and xml files as needed -->
<scriptdef name="propertyfilechecks" language="javascript">
<attribute name="file" />
<attribute name="condition" />
<attribute name="propsdata" />
<attribute name="buildfile" />
<attribute name="mainxml" />
<attribute name="libxml" />
<![CDATA[
importClass(java.io.File);
importClass(java.util.Properties);
importClass(java.io.FileOutputStream);
importClass(java.io.FileInputStream);
importClass(java.io.ByteArrayInputStream);
importClass(java.io.InputStream);
importClass(java.util.regex.Matcher);
importClass(java.util.regex.Pattern);
importClass(java.io.BufferedReader);
importClass(java.io.BufferedWriter);
importClass(java.lang.StringBuffer);
importClass(java.io.InputStreamReader);
importClass(java.io.FileWriter);
doit = !attributes.get("condition").equals("true");
props = new Properties();
str = attributes.get("propsdata").toString();
is = new ByteArrayInputStream(str.getBytes());
props.load(is);
cfg = new File(attributes.get("file"));
if(doit) {
echo = project.createTask("echo");
echo.setMessage("Creating file='" + attributes.get("file") + "'\n" + props);
echo.perform();
fo = new FileOutputStream(cfg);
props.store(fo, "AUTO-GENERATED FILE, DO NOT EDIT!");
fo.close();
}
/* load and compare keys that start with 'last." */
oldprops = new Properties();
fi = new FileInputStream(cfg);
oldprops.load(fi);
fi.close();
keys = props.propertyNames();
ok = true;
while (keys.hasMoreElements()) {
key = keys.nextElement();
if (!oldprops.containsKey(key)) {
ok = false;
break;
}
if(key.startsWith("last.")) {
if(!oldprops.getProperty(key).equals(props.getProperty(key))) {
ok = false;
break;
}
}
}
if (!ok) {
/* update version.props */
echo = project.createTask("echo");
echo.setMessage("(1)Updating file='" + attributes.get("file") + "'\n" + props);
echo.perform();
fo = new FileOutputStream(cfg);
props.store(fo, "AUTO-GENERATED FILE, DO NOT EDIT!");
fo.close();
/* reset build.number */
bprops = new Properties();
bprops.setProperty("build.number", "1");
echo = project.createTask("echo");
echo.setMessage("(2)Updating file='" + attributes.get("buildfile") + "'\n" + bprops);
echo.perform();
cfg = new File(attributes.get("buildfile"));
fo = new FileOutputStream(cfg);
bprops.store(fo, "AUTO-GENERATED FILE, DO NOT EDIT!");
fo.close();
} else {
/* just update version.props */
echo = project.createTask("echo");
echo.setMessage("(3)Updating file='" + attributes.get("file") + "'\n" + props);
echo.perform();
fo = new FileOutputStream(cfg);
props.store(fo, "AUTO-GENERATED FILE, DO NOT EDIT!");
fo.close();
}
sp1 = 'android.versionCode="[0-9]*"';
rp1 = 'android.versionCode="' + props.getProperty("my.version.code") + '"';
sp2 = 'android.versionName="[^"]*"';
rp2 = 'android.versionName="' + props.getProperty("my.version.name") + '"';
/* sed primary manifest */
cfg = File(attributes.get("mainxml") + ".in");
buffer = new StringBuffer();
fi = new FileInputStream(cfg);
reader = new BufferedReader(new InputStreamReader(fi));
while((line = reader.readLine()) != null) {
rep = line.replaceAll(sp1, rp1);
newline = rep.replaceAll(sp2, rp2);
buffer.append(newline + "\n");
}
fi.close();
out = new BufferedWriter(new FileWriter(attributes.get("mainxml")));
out.write(buffer.toString());
out.close();
/* sed secondary manifest */
cfg = File(attributes.get("libxml") + ".in");
buffer = new StringBuffer();
fi = new FileInputStream(cfg);
reader = new BufferedReader(new InputStreamReader(fi));
while((line = reader.readLine()) != null) {
rep = line.replaceAll(sp1, rp1);
newline = rep.replaceAll(sp2, rp2);
buffer.append(newline + "\n");
}
fi.close();
out = new BufferedWriter(new FileWriter(attributes.get("libxml")));
out.write(buffer.toString());
out.close();
]]>
</scriptdef>
<!-- files of interest -->
<property name="MANIFESTfilename" value="AndroidManifest.xml" />
<property name="MANIFESTROUTERfilename" value="routerjars/AndroidManifest.xml" />
<!-- Get i2p.i2p infos -->
<property name="COREfilename" value="${i2psrc}/core/java/src/net/i2p/CoreVersion.java"/>
<loadfile srcfile="${COREfilename}" property="COREfile" encoding="UTF-8" >
<filterchain>
<tokenfilter>
<containsregex pattern='^.*public.+final.+static.+String.+VERSION.*"(.*)".*' replace="\1" />
</tokenfilter>
</filterchain>
</loadfile>
<setcore value="${COREfile}" />
<echo message="CORE `${CORE}`" />
<property name="ROUTERBUILDfilename" value="${i2psrc}/router/java/src/net/i2p/router/RouterVersion.java" />
<loadfile srcfile="${ROUTERBUILDfilename}" property="ROUTERBUILDfile" encoding="UTF-8" >
<filterchain>
<tokenfilter>
<containsregex pattern='^.*public.+final.+static.+long.+BUILD.*=[^0-9]*([0-9]+)[^0-9]+.*' replace="\1" />
</tokenfilter>
</filterchain>
</loadfile>
<normalizeitem name="ROUTERBUILD" value="${ROUTERBUILDfile}" />
<echo message="ROUTERBUILD `${ROUTERBUILD}`" />
<property name="buildversionfilename" value="scripts/build.number" />
<available file="${buildversionfilename}" property="buildversionfilename.present" />
<!-- if the file isn't there, do buildnumber to create it! -->
<ifnotpresent file="${buildversionfilename}" condition="${buildversionfilename.present}" />
<loadfile srcfile="${buildversionfilename}" property="buildversionfile" encoding="UTF-8" >
<filterchain>
<tokenfilter>
<containsregex pattern='^build.number=[^0-9]*([0-9]+)[^0-9]*.*' replace="\1" />
</tokenfilter>
</filterchain>
</loadfile>
<normalizeitem name="buildversion" value="${buildversionfile}" />
<echo message="buildversion `${buildversion}`" />
<!--
<split value="${target}" sep="-" prefix="gettarget"/>
-->
<property name="gettarget.1" value="${minSdkVersion}" />
<echo message="API${gettarget.1}" />
<!-- generate the version infos that we will want to see -->
<generateversions prefix="zap" major="${CORE.major}"
minor="${CORE.minor}" release="${CORE.release}" point="${CORE.point}"
routerbuild="${ROUTERBUILD}" androidbuild="${buildversion}"
sdk="${gettarget.1}"/>
<echo message="checking for changes in ${zap.full}" />
<property name="allversionsfilename" value="scripts/version.properties" />
<available file="${allversionsfilename}" property="allversionsfilename.present" />
<!-- if the file is not available, create it with the current infos -->
<propertyfilechecks file="${allversionsfilename}" condition="${allversionsfilename.present}"
propsdata="my.version.name=${zap.full}&#10;my.version.code=${zap.vercode}&#10;last.CORE=${CORE}&#10;last.ROUTERBUILD=${ROUTERBUILD}&#10;"
buildfile="${buildversionfilename}"
mainxml="${MANIFESTfilename}"
libxml="${MANIFESTROUTERfilename}"
/>
<loadfile srcfile="${allversionsfilename}" property="allversionsfile" encoding="UTF-8"/>
<echo message="${allversionsfile}" />
<property file="${buildversionfile}" />
<!-- this loads my.version.code and my.version.name, and performs a copy -->
<property file="${allversionsfilename}" />
<property name="version.code" value="${my.version.code}" />
<property name="version.name" value="${my.version.name}" />
<echo message="version.code '${version.code}', 'version.name '${version.name}', '${my.version.name}'" />
<!-- If we are missing any jars, we _MUST_ make them ahead of time so
the build does not fail! _HOWEVER_ we must only do this if we are
_BUILDING_! Apache Ant does not allow us to know what target we are
about to run, because the authors believe it is 'evil' and other
nonsense. So for now (so sorry!) we force build it ahead of time
always, no matter what target was selected, until some better way
of resolving this issue apears.
-->
<ant dir="routerjars" inheritall="false" useNativeBasedir="true" >
<target name="buildrouter" />
</ant>
<!--
================================================================================
New I2P rules
================================================================================
-->
<!--
You must execute this target manually to force increment of the build number.
Sorry if this is an extra step.
-*- Sponge
-->
<target name="incrementBuild" >
<incbuildnumber file="${buildversionfilename}" />
</target>
<!-- overrides of those in main_rules.xml -->
<target name="-pre-build" depends="copy-i2p-resources" >
<!-- aapt messes up when resources are added or deleted, just build every time
<delete dir="${gen.absolute.dir}/net" verbose="${verbose}" />
-->
<!-- screw it, do the classes too, until I add the depend class
<delete dir="${out.absolute.dir}/classes/net" verbose="${verbose}" />
-->
</target>
<!--
<target name="-pre-compile" depends="jbigi, buildrouter" />
<target name="-post-compile" depends="hackcleanup" />
-->
<!--
Creates the output directories if they don't exist yet.
-->
<target name="-dirs">
<echo>Creating output directories if needed...</echo>
<mkdir dir="${resource.absolute.dir}" />
<mkdir dir="${gen.absolute.dir}" />
<mkdir dir="${out.absolute.dir}" />
<mkdir dir="${out.classes.absolute.dir}" />
</target>
<!-- some resources -->
<target name="copy-i2p-resources" depends="-dirs" >
<copy file="LICENSE.txt" tofile="res/raw/license_app_txt" />
<copy file="licenses/LICENSE-Apache2.0.txt" tofile="res/raw/license_apache20_txt" />
<copy file="${i2pbase}/installer/resources/themes/console/images/i2plogo.png" todir="res/drawable/" />
<!--
No, no, no. Wrong, wrong, wrong. Static web sources should be in
the assets directory.
<copy file="${i2pbase}/installer/resources/themes/console/images/outbound.png" todir="res/drawable/" />
<copy file="${i2pbase}/installer/resources/themes/console/images/inbound.png" todir="res/drawable/" />
<copy file="${i2pbase}/installer/resources/themes/console/light/images/header.png" todir="res/drawable/" />
<copy file="${i2pbase}/installer/resources/themes/console/light/console.css" tofile="res/drawable/console_css" />
-->
<copy file="${i2pbase}/installer/resources/themes/console/images/i2plogo.png" todir="assets/themes/console/images/" />
<copy file="${i2pbase}/installer/resources/themes/console/images/outbound.png" todir="assets/themes/console/images/" />
<copy file="${i2pbase}/installer/resources/themes/console/images/inbound.png" todir="assets/themes/console/images/" />
<copy file="${i2pbase}/installer/resources/themes/console/light/images/header.png" todir="assets/themes/console/light/images/" />
<copy file="${i2pbase}/installer/resources/themes/console/light/console.css" todir="assets/themes/console/light/" />
<copy file="${i2pbase}/installer/resources/blocklist.txt" tofile="res/raw/blocklist_txt" />
<copy file="${i2pbase}/installer/resources/hosts.txt" tofile="res/raw/hosts_txt" />
<copy file="${i2pbase}/licenses/LICENSE-ElGamalDSA.txt" tofile="res/raw/license_elgamaldsa_txt" />
<copy file="${i2pbase}/licenses/LICENSE-SHA256.txt" tofile="res/raw/license_sha256_txt" />
<copy file="${i2pbase}/licenses/LICENSE-BSD.txt" tofile="res/raw/license_bsd_txt" />
<copy file="${i2pbase}/licenses/LICENSE-SNTP.txt" tofile="res/raw/license_sntp_txt" />
<copy file="${i2pbase}/licenses/LICENSE-LGPLv2.1.txt" tofile="res/raw/license_lgplv2_1_txt" />
<copy file="${i2pbase}/licenses/LICENSE-InstallCert.txt" tofile="res/raw/license_installcert_txt" />
<copy file="${i2pbase}/licenses/LICENSE-BlockFile.txt" tofile="res/raw/license_blockfile_txt" />
<copy file="${i2pbase}/licenses/LICENSE-GPLv2.txt" tofile="res/raw/license_gplv2_txt" />
<copy file="${i2pbase}/licenses/LICENSE-GPLv3.txt" tofile="res/raw/license_gplv3_txt" />
<copy file="${i2pbase}/licenses/LICENSE-LGPLv3.txt" tofile="res/raw/license_lgplv3_txt" />
<copy file="${i2pbase}/licenses/LICENSE-FatCowIcons.txt" tofile="res/raw/license_fatcowicons_txt" />
<copy file="${i2pbase}/licenses/LICENSE-Addressbook.txt" tofile="res/raw/license_addressbook_txt" />
<delete file="res/raw/certificates_zip" />
<zip update="true" destfile="res/raw/certificates_zip">
<fileset dir="${i2pbase}/installer/resources/certificates/" />
</zip>
</target>
<!-- install now does both -->
<target name="reinstall" depends="install" />
<target name="-pre-clean">
<delete dir="${jar.libs.dir}" verbose="${verbose}" />
<delete file="res/drawable/i2plogo.png" verbose="${verbose}"/>
<delete file="res/drawable/outbound.png" verbose="${verbose}"/>
<delete file="res/drawable/inbound.png" verbose="${verbose}"/>
<delete file="res/drawable/header.png" verbose="${verbose}"/>
<delete file="res/raw/console_css" verbose="${verbose}"/>
<delete file="assets/themes/console/images/i2plogo.png" />
<delete file="assets/themes/console/images/outbound.png" />
<delete file="assets/themes/console/images/inbound.png" />
<delete file="assets/themes/console/light/images/header.png" />
<delete file="assets/themes/console/light/console.css" />
<delete file="res/raw/blocklist_txt" verbose="${verbose}" />
<delete file="res/raw/hosts_txt" verbose="${verbose}" />
<delete file="res/raw/license_app_txt" />
<delete file="res/raw/license_apache20_txt" />
<delete file="res/raw/license_elgamaldsa_txt" />
<delete file="res/raw/license_sha256_txt" />
<delete file="res/raw/license_bsd_txt" />
<delete file="res/raw/license_sntp_txt" />
<delete file="res/raw/license_lgplv2_1_txt" />
<delete file="res/raw/license_installcert_txt" />
<delete file="res/raw/license_blockfile_txt" />
<delete file="res/raw/license_gplv2_txt" />
<delete file="res/raw/license_gplv3_txt" />
<delete file="res/raw/license_lgplv3_txt" />
<delete file="res/raw/certificates_zip" />
</target>
<target name="distclean" depends="clean">
<ant dir="routerjars" inheritall="false" useNativeBasedir="true" >
<target name="distclean" />
</ant>
<delete file="scripts/build.number" verbose="${verbose}" />
<delete file="scripts/version.properties" verbose="${verbose}" />
<delete file="AndroidManifest.xml" verbose="${verbose}" />
</target>
<!-- just to make it easier -->
<target name="create-signing-keys" >
<echo message="key store is ${key.store}" />
<echo message="key store password is ${key.store.password}" />
<echo message="key alias is ${key.alias}" />
<input message="Enter common name for new key (your name): " addproperty="release.cn" />
<fail message="You must enter a name" >
<condition>
<equals arg1="${release.cn}" arg2="" />
</condition>
</fail>
<input message="Enter password for new key (6 characters minimum): " addproperty="release.password" />
<fail message="You must enter a password" >
<condition>
<equals arg1="${release.password}" arg2="" />
</condition>
</fail>
<echo message="Generating keys, this may take a while..." />
<exec executable="keytool" inputstring="${release.password}${line.separator}${release.password}${line.separator}" osfamily="unix" failonerror="true">
<arg value="-genkey" />
<arg value="-v" />
<arg value="-alias" />
<arg value="${key.alias}" />
<arg value="-keystore" />
<arg value="${key.store}" />
<arg value="-validity" />
<arg value="10000" />
<arg value="-keyalg" />
<arg value="RSA" />
<arg value="-keysize" />
<arg value="4096" />
<arg value="-storepass" />
<arg value="${key.store.password}" />
<arg value="-dname" />
<arg value="cn=${release.cn}, ou=Apps, o=I2P, c=DE" />
</exec>
<echo message="Created keys:" />
<exec executable="keytool" inputstring="android${line.separator}" osfamily="unix" failonerror="true">
<arg value="-list" />
<arg value="-v" />
<arg value="-alias" />
<arg value="${key.alias}" />
<arg value="-keystore" />
<arg value="${key.store}" />
</exec>
<echo message="BACK UP your key store file ${key.store} and your password!" />
</target>
<target name="verifyKeystore" >
<available file="${key.store}" property="keystore.present" />
<fail message="You must first create a keystore and keys with 'ant create-signing-keys'" >
<condition>
<not>
<isset property="keystore.present" />
</not>
</condition>
</fail>
</target>
<target name="verifyWorkspace" >
<echo message="Everything is checked in, right? Let's be sure:" />
<exec executable="mtn" failonerror="true">
<arg value="st" />
</exec>
<echo message="If there are any modified files above, stop now!" />
<echo message="(except AndroidManifest.xml)" />
</target>
<target name="verify" depends="verifyKeystore, verifyWorkspace, release" >
<exec executable="jarsigner" osfamily="unix" failonerror="true">
<arg value="-verify" />
<arg value="-verbose" />
<arg value="-certs" />
<arg value="${out.release.file}" />
</exec>
<echo message="" />
<echo message="Release file is ${out.release.file}" />
<echo message="Android version name: ${my.version.name}" />
<echo message="Android version code: ${my.version.code}" />
<echo message="File size:" />
<exec executable="ls" failonerror="true">
<arg value="-l" />
<arg value="${out.release.file}" />
</exec>
<echo message="SHA256 sum:" />
<exec executable="sha256sum" failonerror="true">
<arg value="${out.release.file}" />
</exec>
<echo message="Don't forget to mtn ci AndroidManifest.xml" />
<echo message="Don't forget to mtn tag w: android-${my.version.name}" />
<copy file="${out.release.file}" tofile="I2PAndroid-${my.version.name}.apk" />
<echo message="Release file copied to I2PAndroid-${my.version.name}.apk" />
</target>
</project>

20
proguard-project.txt Normal file
View File

@ -0,0 +1,20 @@
# To enable ProGuard in your project, edit project.properties
# to define the proguard.config property as described in that file.
#
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in ${sdk.dir}/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the ProGuard
# include property in project.properties.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

20
project.properties Normal file
View File

@ -0,0 +1,20 @@
# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must be checked in Version Control Systems.
#
# To customize properties used by the Ant build system use,
# "build.properties", and override values to adapt the script to your
# project structure.
# Project target.
target=android-18
# Must match that in AndroidManifest.xml.in
minSdkVersion=8
# I2P router libs
android.library.reference.1=./routerjars
# Android Support Library
# If the relative path differs in your local environment,
# override this in the base local.properties
# (not routerjars/local.properties)
android.library.reference.2=../android-sdk-linux/extras/android/support/v7/appcompat

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

BIN
res/drawable/log_icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
res/drawable/peers_icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/addressbook_list"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</ListView>

View File

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:fillViewport="true"
android:padding="10px"
android:scrollbarStyle="outsideInset"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:id="@+id/textView1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Addressbook Settings"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Subscriptions"
android:textAppearance="?android:attr/textAppearanceMedium" />
<EditText
android:id="@+id/subscriptions_content"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textMultiLine"
android:maxLines="@integer/min_lines"
android:minLines="@integer/min_lines" >
<requestFocus />
</EditText>
<Button
android:id="@+id/button_save_subscriptions"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Save subscriptions.txt" />
</LinearLayout>
</ScrollView>

View File

@ -3,125 +3,151 @@
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="fill_parent" android:layout_height="fill_parent"
android:fillViewport="true" android:fillViewport="true"
android:padding="10px"
android:scrollbarStyle="outsideInset"
> >
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout
android:orientation="vertical" android:orientation="vertical"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="@drawable/movie_wallpaper"
> >
<ImageView
android:layout_width="fill_parent" <ImageView
android:layout_height="wrap_content" android:layout_width="fill_parent"
android:src="@drawable/i2plogo" android:layout_height="wrap_content"
/> android:src="@drawable/i2plogo" />
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" <TextView
android:layout_width="fill_parent" android:id="@+id/textView4"
android:layout_height="wrap_content" android:layout_width="wrap_content"
> android:layout_height="wrap_content"
<Button android:text="@string/label_statistics"
android:id="@+id/website_button" android:textAppearance="?android:attr/textAppearanceLarge" />
android:layout_width="wrap_content"
android:layout_height="wrap_content" <TextView
android:text="Web Site\n(non-anon)" android:id="@+id/main_status_text"
/> android:layout_width="fill_parent"
<Button android:layout_height="wrap_content" />
android:id="@+id/faq_button"
android:layout_width="wrap_content" <TextView
android:layout_height="wrap_content" android:id="@+id/textView1"
android:text="FAQ\n(non-anon)" android:layout_width="wrap_content"
/> android:layout_height="wrap_content"
<Button android:text="@string/label_main_controls"
android:id="@+id/welcome_button" android:textAppearance="?android:attr/textAppearanceLarge" />
android:layout_width="wrap_content"
android:layout_height="wrap_content" <Button
android:text="Welcome\nPage" android:id="@+id/router_start_button"
/> android:layout_width="match_parent"
</LinearLayout> android:layout_height="68dp"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:text="@string/action_router_start"
android:orientation="horizontal" android:drawableLeft="@drawable/start_router_icon" />
android:layout_width="fill_parent"
android:layout_height="wrap_content" <Button
> android:id="@+id/router_quit_button"
<Button android:layout_width="match_parent"
android:id="@+id/news_button" android:layout_height="68dp"
android:layout_width="wrap_content" android:text="@string/action_router_stop"
android:layout_height="wrap_content" android:drawableLeft="@drawable/stop_router_icon" />
android:text="News" <!--
/> <Button
<Button
android:id="@+id/releasenotes_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Release Notes"
/>
<Button
android:id="@+id/licenses_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Licenses"
/>
</LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<Button
android:id="@+id/addressbook_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Address Book"
/>
<Button
android:id="@+id/logs_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Logs"
/>
<Button
android:id="@+id/error_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Error Logs"
/>
<Button
android:id="@+id/peers_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Peers"
/>
</LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<Button
android:id="@+id/router_start_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Start Router"
/>
<Button
android:id="@+id/router_stop_button" android:id="@+id/router_stop_button"
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="OLD STOP" android:text="OLD STOP"
/> android:drawableLeft="@drawable/stop_router_icon" />
<Button -->
android:id="@+id/router_quit_button"
android:layout_width="wrap_content" <TextView
android:layout_height="wrap_content" android:id="@+id/textView2"
android:text="Stop Router" android:layout_width="wrap_content"
/> android:layout_height="wrap_content"
</LinearLayout> android:text="@string/label_tools"
<TextView android:textAppearance="?android:attr/textAppearanceMedium" />
android:id="@+id/main_status_text"
android:layout_width="fill_parent" <Button
android:layout_height="wrap_content" android:id="@+id/addressbook_button"
android:text="" android:layout_width="match_parent"
/> android:layout_height="wrap_content"
android:text="@string/label_addressbook"
android:drawableLeft="@drawable/addressbook_icon" />
<Button
android:id="@+id/logs_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/label_logs"
android:drawableLeft="@drawable/log_icon" />
<Button
android:id="@+id/error_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/label_error_logs"
android:drawableLeft="@drawable/error_log_icon" />
<Button
android:id="@+id/peers_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/label_peers_status"
android:drawableLeft="@drawable/peers_icon" />
<TextView
android:id="@+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/label_info_and_pages"
android:textAppearance="?android:attr/textAppearanceMedium" />
<Button
android:id="@+id/welcome_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/label_welcome_page"
android:drawableLeft="@drawable/information_icon" />
<Button
android:id="@+id/news_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/label_news"
android:drawableLeft="@drawable/information_icon" />
<Button
android:id="@+id/releasenotes_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/label_release_notes"
android:drawableLeft="@drawable/information_icon" />
<Button
android:id="@+id/licenses_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/label_licenses"
android:drawableLeft="@drawable/information_icon" />
<TextView
android:id="@+id/textView5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/label_nonanon_info"
android:textAppearance="?android:attr/textAppearanceMedium" />
<Button
android:id="@+id/website_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/label_website_nonanon"
android:drawableLeft="@drawable/nonanon_info_icon" />
<Button
android:id="@+id/faq_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/label_faq_nonanon"
android:drawableLeft="@drawable/nonanon_info_icon" />
</LinearLayout> </LinearLayout>
</ScrollView> </ScrollView>

View File

@ -3,18 +3,18 @@
android:orientation="vertical" android:orientation="vertical"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="fill_parent" android:layout_height="fill_parent"
android:padding="10dp"
> >
<TextView <TextView
android:id="@+id/news_status" android:id="@+id/news_status"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_centerHorizontal="true" android:text="@string/label_news_status"
android:text="Latest I2P News"
/> />
<WebView <WebView
android:id="@+id/news_webview" android:id="@+id/news_webview"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="fill_parent" android:layout_height="fill_parent"
/> />
</LinearLayout> </LinearLayout>

View File

@ -3,18 +3,19 @@
android:orientation="vertical" android:orientation="vertical"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="fill_parent" android:layout_height="fill_parent"
android:layout_margin="2dp"
android:padding="10dp"
> >
<TextView <TextView
android:id="@+id/peers_status" android:id="@+id/peers_status"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_centerHorizontal="true" android:text="@string/label_peers_status"
android:text="Peers"
/> />
<WebView <WebView
android:id="@+id/peers_webview" android:id="@+id/peers_webview"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="fill_parent" android:layout_height="fill_parent"
/> />
</LinearLayout> </LinearLayout>

View File

@ -3,13 +3,15 @@
android:orientation="vertical" android:orientation="vertical"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="fill_parent" android:layout_height="fill_parent"
android:padding="10dp"
> >
<TextView <TextView
android:id="@+id/text_resource_text" android:id="@+id/text_resource_text"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="fill_parent" android:layout_height="fill_parent"
android:scrollbars="vertical" android:scrollbars="vertical"
android:text="Release Notes" android:text="@string/label_release_notes"
android:textColor="@android:color/secondary_text_dark"
/> />
</LinearLayout> </LinearLayout>

View File

@ -3,18 +3,18 @@
android:orientation="vertical" android:orientation="vertical"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="fill_parent" android:layout_height="fill_parent"
android:padding="10dp"
> >
<TextView <TextView
android:id="@+id/browser_status" android:id="@+id/browser_status"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_centerHorizontal="true" android:text="@string/label_news_status"
android:text="Latest I2P News"
/> />
<WebView <WebView
android:id="@+id/browser_webview" android:id="@+id/browser_webview"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="fill_parent" android:layout_height="fill_parent"
/> />
</LinearLayout> </LinearLayout>

View File

@ -0,0 +1,12 @@
<?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" >
<!-- Add, should appear as action buttons --><!--
<item android:id="@+id/action_add_to_addressbook"
android:title="@string/action_add"
android:icon="@drawable/ic_content_new"
i2pandroid:showAsAction="ifRoom" />-->
<!-- Settings, should always be in the overflow -->
<item android:id="@+id/action_addressbook_settings"
android:title="@string/menu_settings"
i2pandroid:showAsAction="never" /></menu>

View File

@ -0,0 +1,5 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/menu_settings"
android:title="@string/menu_settings"
android:orderInCategory="100" />
</menu>

View File

@ -1,25 +1,25 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"> <menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:title="Start Router" <item android:title="@string/action_router_start"
android:id="@+id/menu_start" android:id="@+id/menu_start"
android:icon="@drawable/ic_menu_play_clip" > android:icon="@drawable/ic_menu_play_clip" >
</item> </item>
<item android:title="Stop Router" <item android:title="@string/action_router_stop"
android:id="@+id/menu_stop" android:id="@+id/menu_stop"
android:icon="@android:drawable/ic_menu_close_clear_cancel" > android:icon="@android:drawable/ic_menu_close_clear_cancel" >
</item> </item>
<item android:title="Address Book" <item android:title="@string/label_addressbook"
android:id="@+id/menu_addressbook" android:id="@+id/menu_addressbook"
android:icon="@drawable/ic_menu_friendslist" > android:icon="@drawable/ic_menu_friendslist" >
</item> </item>
<item android:title="Reload" <item android:title="@string/action_reload"
android:id="@+id/menu_reload" android:id="@+id/menu_reload"
android:icon="@drawable/ic_menu_refresh" > android:icon="@drawable/ic_menu_refresh" >
</item> </item>
<item android:title="I2P Home" <item android:title="@string/label_home"
android:id="@+id/menu_home" android:id="@+id/menu_home"
android:icon="@drawable/ic_menu_home" > android:icon="@drawable/ic_menu_home" >
</item> </item>
<item android:title="Settings" <item android:title="@string/menu_settings"
android:id="@+id/menu_settings" android:id="@+id/menu_settings"
android:icon="@android:drawable/ic_menu_preferences" > android:icon="@android:drawable/ic_menu_preferences" >
</item> </item>

View File

@ -2,23 +2,23 @@
tunnel.0.name=I2P HTTP Proxy tunnel.0.name=I2P HTTP Proxy
tunnel.0.description=HTTP proxy for browsing eepsites and the web tunnel.0.description=HTTP proxy for browsing eepsites and the web
tunnel.0.type=httpclient tunnel.0.type=httpclient
tunnel.0.sharedClient=true tunnel.0.sharedClient=false
tunnel.0.interface=127.0.0.1 tunnel.0.interface=127.0.0.1
tunnel.0.listenPort=4444 tunnel.0.listenPort=4444
tunnel.0.proxyList=false.i2p tunnel.0.proxyList=false.i2p
tunnel.0.i2cpHost=127.0.0.1 tunnel.0.i2cpHost=127.0.0.1
tunnel.0.i2cpPort=7654 tunnel.0.i2cpPort=7654
tunnel.0.option.inbound.nickname=shared clients tunnel.0.option.inbound.nickname=I2P HTTP Proxy
tunnel.0.option.outbound.nickname=shared clients tunnel.0.option.outbound.nickname=I2P HTTP Proxy
#tunnel.0.option.i2cp.delayOpen=true #tunnel.0.option.i2cp.delayOpen=true
tunnel.0.option.i2cp.reduceIdleTime=600000 tunnel.0.option.i2cp.reduceIdleTime=600000
tunnel.0.option.i2cp.reduceOnIdle=true tunnel.0.option.i2cp.reduceOnIdle=true
tunnel.0.option.i2cp.reduceQuantity=1 tunnel.0.option.i2cp.reduceQuantity=1
tunnel.0.option.i2p.streaming.connectDelay=1000 tunnel.0.option.i2p.streaming.connectDelay=1000
tunnel.0.option.inbound.length=1 tunnel.0.option.inbound.length=2
tunnel.0.option.inbound.lengthVariance=1 tunnel.0.option.inbound.lengthVariance=0
tunnel.0.option.outbound.length=1 tunnel.0.option.outbound.length=2
tunnel.0.option.outbound.lengthVariance=1 tunnel.0.option.outbound.lengthVariance=0
tunnel.0.startOnLoad=true tunnel.0.startOnLoad=true
# irc # irc
@ -28,7 +28,7 @@ tunnel.1.type=ircclient
tunnel.1.sharedClient=true tunnel.1.sharedClient=true
tunnel.1.interface=127.0.0.1 tunnel.1.interface=127.0.0.1
tunnel.1.listenPort=6668 tunnel.1.listenPort=6668
tunnel.1.targetDestination=irc.postman.i2p,irc.freshcoffee.i2p tunnel.1.targetDestination=irc.postman.i2p,irc.freshcoffee.i2p,irc.echelon.i2p
tunnel.1.i2cpHost=127.0.0.1 tunnel.1.i2cpHost=127.0.0.1
tunnel.1.i2cpPort=7654 tunnel.1.i2cpPort=7654
tunnel.1.option.inbound.nickname=shared clients tunnel.1.option.inbound.nickname=shared clients
@ -38,10 +38,10 @@ tunnel.1.option.i2cp.reduceIdleTime=600000
tunnel.1.option.i2cp.reduceOnIdle=true tunnel.1.option.i2cp.reduceOnIdle=true
tunnel.1.option.i2cp.reduceQuantity=1 tunnel.1.option.i2cp.reduceQuantity=1
tunnel.1.option.i2p.streaming.connectDelay=1000 tunnel.1.option.i2p.streaming.connectDelay=1000
tunnel.1.option.inbound.length=1 tunnel.1.option.inbound.length=2
tunnel.1.option.inbound.lengthVariance=1 tunnel.1.option.inbound.lengthVariance=0
tunnel.1.option.outbound.length=1 tunnel.1.option.outbound.length=2
tunnel.1.option.outbound.lengthVariance=1 tunnel.1.option.outbound.lengthVariance=0
tunnel.1.startOnLoad=true tunnel.1.startOnLoad=true
# irc # irc
@ -61,10 +61,10 @@ tunnel.2.option.i2cp.reduceIdleTime=600000
tunnel.2.option.i2cp.reduceOnIdle=true tunnel.2.option.i2cp.reduceOnIdle=true
tunnel.2.option.i2cp.reduceQuantity=1 tunnel.2.option.i2cp.reduceQuantity=1
tunnel.2.option.i2p.streaming.connectDelay=1000 tunnel.2.option.i2p.streaming.connectDelay=1000
tunnel.2.option.inbound.length=1 tunnel.2.option.inbound.length=2
tunnel.2.option.inbound.lengthVariance=1 tunnel.2.option.inbound.lengthVariance=0
tunnel.2.option.outbound.length=1 tunnel.2.option.outbound.length=2
tunnel.2.option.outbound.lengthVariance=1 tunnel.2.option.outbound.lengthVariance=0
tunnel.2.startOnLoad=true tunnel.2.startOnLoad=true
# irc # irc
@ -84,8 +84,31 @@ tunnel.3.option.i2cp.reduceIdleTime=600000
tunnel.3.option.i2cp.reduceOnIdle=true tunnel.3.option.i2cp.reduceOnIdle=true
tunnel.3.option.i2cp.reduceQuantity=1 tunnel.3.option.i2cp.reduceQuantity=1
tunnel.3.option.i2p.streaming.connectDelay=1000 tunnel.3.option.i2p.streaming.connectDelay=1000
tunnel.3.option.inbound.length=1 tunnel.3.option.inbound.length=2
tunnel.3.option.inbound.lengthVariance=1 tunnel.3.option.inbound.lengthVariance=0
tunnel.3.option.outbound.length=1 tunnel.3.option.outbound.length=2
tunnel.3.option.outbound.lengthVariance=1 tunnel.3.option.outbound.lengthVariance=0
tunnel.3.startOnLoad=true tunnel.3.startOnLoad=true
# irc irc.killyourtv.i2p
tunnel.4.name=irckytv
tunnel.4.description=IRC proxy to access anonymous IRC servers
tunnel.4.type=ircclient
tunnel.4.sharedClient=true
tunnel.4.interface=127.0.0.1
tunnel.4.listenPort=6671
tunnel.4.targetDestination=irc.killyourtv.i2p
tunnel.4.i2cpHost=127.0.0.1
tunnel.4.i2cpPort=7654
tunnel.4.option.inbound.nickname=shared clients
tunnel.4.option.outbound.nickname=shared clients
#tunnel.4.option.i2cp.delayOpen=true
tunnel.4.option.i2cp.reduceIdleTime=600000
tunnel.4.option.i2cp.reduceOnIdle=true
tunnel.4.option.i2cp.reduceQuantity=1
tunnel.4.option.i2p.streaming.connectDelay=1000
tunnel.4.option.inbound.length=2
tunnel.4.option.inbound.lengthVariance=0
tunnel.4.option.outbound.length=2
tunnel.4.option.outbound.lengthVariance=0
tunnel.4.startOnLoad=true

View File

@ -1,23 +1,23 @@
logger.consoleBufferSize=250 logger.consoleBufferSize=250
logger.dateFormat=MM/dd HH:mm:ss.SSS logger.dateFormat=MM/dd HH:mm:ss.SSS
logger.defaultLevel=WARN logger.defaultLevel=ERROR
logger.displayOnScreen=true logger.displayOnScreen=true
logger.logFileSize=64k logger.logFileSize=64k
logger.logRotationLimit=2 logger.logRotationLimit=2
logger.minimumOnScreenLevel=WARN logger.minimumOnScreenLevel=ERROR
logger.record.net.i2p.crypto=WARN logger.record.net.i2p.crypto=ERROR
logger.record.net.i2p.router.InNetMessagePool=WARN logger.record.net.i2p.router.InNetMessagePool=ERROR
logger.record.net.i2p.router.Router=WARN logger.record.net.i2p.router.Router=ERROR
logger.record.net.i2p.router.Shitlist=WARN logger.record.net.i2p.router.Shitlist=ERROR
logger.record.net.i2p.router.networkdb=WARN logger.record.net.i2p.router.networkdb=ERROR
logger.record.net.i2p.router.peermanager=WARN logger.record.net.i2p.router.peermanager=ERROR
logger.record.net.i2p.router.peermanager.ProfileOrganizer=WARN logger.record.net.i2p.router.peermanager.ProfileOrganizer=ERROR
logger.record.net.i2p.router.transport=ERROR logger.record.net.i2p.router.transport=ERROR
logger.record.net.i2p.router.transport.FIFOBandwidthRefiller=ERROR logger.record.net.i2p.router.transport.FIFOBandwidthRefiller=ERROR
logger.record.net.i2p.router.tunnel=WARN logger.record.net.i2p.router.tunnel=ERROR
logger.record.net.i2p.stat.Rate=ERROR logger.record.net.i2p.stat.Rate=ERROR
logger.record.net.i2p.util.I2PThread=ERROR logger.record.net.i2p.util.I2PThread=ERROR
logger.record.net.i2p.util.LogManager=WARN logger.record.net.i2p.util.LogManager=ERROR
logger.record.net.i2p.util.LogWriter=WARN logger.record.net.i2p.util.LogWriter=ERROR
logger.record.net.i2p.util.NativeBigInteger=ERROR logger.record.net.i2p.util.NativeBigInteger=ERROR
logger.record.net.org.cybergarage.util.Debug=DEBUG logger.record.net.org.cybergarage.util.Debug=ERROR

View File

@ -10,13 +10,11 @@ The app may use a lot of RAM even after the router has stopped and there is no i
The app may be moved to the SD card. The app does not store any files on the SD card. 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 very low bandwidth, as it does not allow participating tunnels. It does not route traffic for other routers. 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 TCP only for router-router connections, with a maximum of 24 simultaneous. UDP is disabled. The app uses both UDP and TCP for router-router connections, with a maximum of 36 connections on each transport. UPnP is enabled.
UPnP is disabled. With UDP disabled also, you do not publish an IP address and should not be getting incoming connections. 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.
NTP is disabled. 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. 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.
@ -28,7 +26,7 @@ Embedded web browser
The browser does not use the outproxy for regular web sites. Javascript is disabled. 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) due to API limitations. I don't have a tablet to test on, so I haven't made any effort to work on it. The workaround is to use Firefox Mobile 4 and the ProxMob plugin (see below). The following problems with eepsites are probably not fixable except on Android 3.0 (Honeycomb - i.e. tablets) and higher due to API limitations. I don't have a tablet to test on, so I haven't made any effort to work on it. The workaround is to use Firefox Mobile 4 and the ProxMob plugin (see below).
- Leaks .i2p DNS requests - Leaks .i2p DNS requests
- Can't load cross-site images or CSS - Can't load cross-site images or CSS
- No POSTs to forms - No POSTs to forms
@ -47,21 +45,21 @@ For eepsites and websites, problems include:
Using clients with the router Using clients with the router
----------------------------- -----------------------------
The app starts an HTTP proxy at localhost port 4444 and transparent IRC proxies at localhost ports 6668, 6669, and 6670. These are "shared clients" on the same tunnels. Once you see in and out client tunnels listed on the router status (several minutes after startup), you should be able to connect. The app starts an HTTP proxy at localhost port 4444 and transparent IRC proxies at localhost ports 6668 - 6671. These are "shared clients" on the same tunnels. Once you see in and out client tunnels listed on the router status (several minutes after startup), you should be able to connect.
The HTTP proxy should work with Firefox 4 Mobile and the ProxyMob Firefox plugin, if you have at least 512 MB of RAM. If it works it should avoid all the problems with the embedded web browser listed above. I can't test it as I have a 256 MB Droid. The HTTP proxy should work with Firefox 4 Mobile and the ProxyMob Firefox plugin, if you have at least 512 MB of RAM. If it works it should avoid all the problems with the embedded web browser listed above. I can't test it as I have a 256 MB Droid.
The IRC proxy is tested with the "Android IRC Free" app. The IRC proxy destinations are: The IRC proxy is tested with the "Android IRC Free" app. The IRC proxy destinations are:
* Port 6668: irc.postman.i2p and irc.freshcoffee.i2p * Port 6668: IRC2P - irc.postman.i2p, irc.freshcoffee.i2p, and irc.echelon.i2p
* Port 6669: irc.welterde.i2p * Port 6669: irc.welterde.i2p
* Port 6670: irc.telecomix.i2p * Port 6670: irc.telecomix.i2p (probably down)
* Port 6671: irc.killyourtv.i2p
Further anonymity warnings Further anonymity warnings
-------------------------- --------------------------
* Reseeding is via http * Exploratory and Client Tunnels are 2 hops
* Exploratory and Client Tunnels are 1 hop + 0-1 hops
* Sharing IRC and HTTP proxies on same tunnels allows for linking * Sharing IRC and HTTP proxies on same tunnels allows for linking
* Not well-tested * Not well-tested
* There are .i2p DNS leaks * There are .i2p DNS leaks

View File

@ -2,15 +2,21 @@
# temp directory now set in Init.java # temp directory now set in Init.java
#i2p.dir.temp=/data/data/net.i2p.android.router/files/tmp #i2p.dir.temp=/data/data/net.i2p.android.router/files/tmp
#i2p.dir.pid=/data/data/net.i2p.android.router/files/tmp #i2p.dir.pid=/data/data/net.i2p.android.router/files/tmp
#
# save memory # save memory
# I've done some testing, and the amount 'saved' is not all that much.
# I will, however, leave this alone, for now.
#
prng.buffers=2 prng.buffers=2
prng.bufferSize=32768 prng.bufferSize=32768
router.decayingBloomFilterM=20 router.decayingBloomFilterM=20
stat.full=false stat.full=false
# #
# Don't run NTP client, the phone should have a valid time # Don't run NTP client, the phone should have a valid time
# # Tablets are not phones, turn this on. I've seen the phone not have
time.disabled=true # accurate time too (yes, really) and the router had too much skew.
# I've even seen current tablets that have NTP on lose or gain time.
time.disabled=false
# #
# no external I2CP (7654) # no external I2CP (7654)
# #
@ -25,35 +31,48 @@ i2p.hostsfilelist=hosts.txt
##### Tunnels ##### Tunnels
# #
router.inboundPool.backupQuantity=0 router.inboundPool.backupQuantity=0
router.inboundPool.length=1 router.inboundPool.length=2
router.inboundPool.lengthVariance=1 router.inboundPool.lengthVariance=0
router.inboundPool.quantity=2 router.inboundPool.quantity=2
router.outboundPool.backupQuantity=0 router.outboundPool.backupQuantity=0
router.outboundPool.length=1 router.outboundPool.length=2
router.outboundPool.lengthVariance=1 router.outboundPool.lengthVariance=0
router.outboundPool.quantity=2 router.outboundPool.quantity=2
router.maxParticipatingTunnels=0 router.maxParticipatingTunnels=20
router.sharePercentage=10 router.sharePercentage=80
# #
##### Transport ##### Transport
# #
i2np.bandwidth.inboundKBytesPerSecond=100 i2np.bandwidth.inboundKBytesPerSecond=100
i2np.bandwidth.outboundKBytesPerSecond=30 i2np.bandwidth.outboundKBytesPerSecond=50
# #
# NTCP # NTCP
# #
#i2np.ntcp.enable=false i2np.ntcp.enable=true
i2np.ntcp.maxConnections=24 i2np.ntcp.maxConnections=32
# #
# UDP disabled for now # UDP
# #
i2np.udp.enable=false i2np.udp.enable=true
i2np.udp.maxConnections=12 i2np.udp.maxConnections=32
# #
# #
# not on android # not on android
i2np.upnp.enable=false
routerconsole.geoip.enable=false routerconsole.geoip.enable=false
# #
# temp until certs are included # false is default but was true in 0.9.1-0_b1 release so have to set it back
router.reseedSSLDisable=true router.reseedSSLDisable=false
#
# Tablets are not phones. It does not hurt to have this on by default.
#
i2np.upnp.enable=true
#
# Hidden by default, this turns off sharing, etc.
# bad idea, reduces user experience. Paranoids should set this only.
router.hiddenMode=false
#
# Bad idea, disable it!
#
router.floodfillParticipant=false

62
res/values-es/strings.xml Normal file
View File

@ -0,0 +1,62 @@
<?xml version='1.0' encoding='UTF-8'?>
<resources>
<string name="app_name">I2P</string>
<string name="welcome_new_install">¡Bienvenido a I2P! Esta aplicación es un software ALFA y no proporciona un fuerte anonimato. Por favor, lea las notas de veriones y la información sobre la licencia.</string>
<string name="welcome_new_version">Nueva versión instalada. Por favor lea las notas de versiones. Versión:</string>
<string name="label_home">Inicio de I2P</string>
<string name="label_statistics">Estadísticas</string>
<string name="label_main_controls">Controles Principales</string>
<string name="label_tools">Herramientas de I2P</string>
<string name="label_addressbook">Libreta de direcciones</string>
<string name="label_logs">Registros</string>
<string name="label_error_logs">Registros de Errores</string>
<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>
<string name="label_nonanon_info">Información no anónima</string>
<string name="label_website_nonanon">Página web (no anónima)</string>
<string name="label_faq_nonanon">FAQ (no anónimo)</string>
<string name="action_add">Añadir</string>
<string name="action_router_start">Iniciar el Ruter</string>
<string name="action_router_stop">Apagar el Ruter</string>
<string name="action_reload">Recargar</string>
<string name="menu_settings">Preferencias</string>
<string name="settings_enable">Activar</string>
<string name="settings_label_subscriptions">Librete de direcciones I2P</string>
<string name="settings_desc_subscriptions">URLs de subscripción</string>
<string name="settings_label_bandwidth">Red y ancho de banda</string>
<string name="settings_label_bw_inbound">Velocidad de entrada</string>
<string name="settings_desc_bw_inbound">Velocidad máxima de entrada</string>
<string name="settings_label_bw_outbound">Velocidad de salida</string>
<string name="settings_desc_bw_outbound">Velocidad máxima de salida</string>
<string name="settings_label_hiddenMode">Participación</string>
<string name="settings_desc_hiddenMode">Desactivar modo oculto</string>
<string name="settings_label_maxPartTunnels">Máximo número de túneles participantes</string>
<string name="settings_desc_maxPartTunnels">Máximo núemero de túneles en los que participar (por defecto=20)</string>
<string name="settings_dialog_maxPartTunnels">Máximo número de túneles en los que participar</string>
<string name="settings_label_sharePercent">Porcentaje de participación</string>
<string name="settings_desc_sharePercent">Porcentaje y ancho de banda a compartir (por defecto=80)</string>
<string name="settings_dialog_sharePercent">Procentaje del ancho de banda a compartir</string>
<string name="settings_desc_upnp">Abrir los puertos del cortafuegos automáticamente</string>
<string name="settings_label_advanced">Avanzado</string>
<string name="settings_label_transports">Trnasportes</string>
<string name="settings_label_maxConns">Máximo número de conexiones</string>
<string name="settings_label_i2cp">Interfaz de I2CP</string>
<string name="settings_desc_i2cp">Escuchar en el puerto 7654</string>
<string name="settings_label_exploratory_pool">Grupo exploratiorio</string>
<string name="settings_desc_exploratory_pool">Parámetros del Túnel</string>
<string name="settings_label_expl_inbound">Túneles de entrada</string>
<string name="settings_label_expl_outbound">Túneles de salida</string>
<string name="settings_label_expl_length">Tamaño</string>
<string name="settings_desc_expl_length">Cuantos saltos usar</string>
<string name="settings_label_expl_lengthVariance">Variación del salto</string>
<string name="settings_desc_expl_lengthVariance">Cuántos saltos se añadirán aleatoriamente.</string>
<string name="settings_label_expl_quantity">Cantidad</string>
<string name="settings_desc_expl_quantity">Cuantos túneles</string>
<string name="settings_label_expl_backupQuantity">Cantidad de respaldos</string>
<string name="settings_desc_expl_backupQuantity">Cuantos túneles de respaldo</string>
</resources>

62
res/values-fr/strings.xml Normal file
View File

@ -0,0 +1,62 @@
<?xml version='1.0' encoding='UTF-8'?>
<resources>
<string name="app_name">I2P</string>
<string name="welcome_new_install">Bienvenue sur I2P ! Cette application est un logiciel en version ALPHA, et elle ne prévoit pas un fort anonymat. Veuillez lire les notes de version et les informations de licence.</string>
<string name="welcome_new_version">Nouvelle version installée. Veuillez lire les notes de version. Version :</string>
<string name="label_home">I2P maison</string>
<string name="label_statistics">Statistiques</string>
<string name="label_main_controls">Commandes principales</string>
<string name="label_tools">Outils I2P</string>
<string name="label_addressbook">Carnet d\'adresses</string>
<string name="label_logs">Logs</string>
<string name="label_error_logs">Logs d\'erreurs</string>
<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">Nouvelles récentes 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>
<string name="label_nonanon_info">Information non anonyme</string>
<string name="label_website_nonanon">Site Web (non-anon)</string>
<string name="label_faq_nonanon">FAQ (non-anon)</string>
<string name="action_add">Ajouter</string>
<string name="action_router_start">Démarrer routeur</string>
<string name="action_router_stop">Arrêter routeur</string>
<string name="action_reload">Recharger</string>
<string name="menu_settings">Réglages</string>
<string name="settings_enable">Activer</string>
<string name="settings_label_subscriptions">Carnet d\'adresses I2P</string>
<string name="settings_desc_subscriptions">URLs d\'abonnement</string>
<string name="settings_label_bandwidth">Bande passante et réseau</string>
<string name="settings_label_bw_inbound">Vitesse entrante</string>
<string name="settings_desc_bw_inbound">Vitesse entrante maximum</string>
<string name="settings_label_bw_outbound">Vitesse sortante</string>
<string name="settings_desc_bw_outbound">Vitesse sortante maximum</string>
<string name="settings_label_hiddenMode">Participation</string>
<string name="settings_desc_hiddenMode">Désactiver le mode caché</string>
<string name="settings_label_maxPartTunnels">Tunnels participants max</string>
<string name="settings_desc_maxPartTunnels">Maximum de tunnels auquels participer (défaut=20)</string>
<string name="settings_dialog_maxPartTunnels">Maximum de tunnels auquels participer</string>
<string name="settings_label_sharePercent">Pourcentage partagé</string>
<string name="settings_desc_sharePercent">Pourcentage de bande passante à partager (défaut=80)</string>
<string name="settings_dialog_sharePercent">Pourcentage de bande passante à partager</string>
<string name="settings_desc_upnp">Ouvrir automatiquement les ports du pare-feu</string>
<string name="settings_label_advanced">Avancé</string>
<string name="settings_label_transports">Transports</string>
<string name="settings_label_maxConns">Connexions max</string>
<string name="settings_label_i2cp">Interface I2CP</string>
<string name="settings_desc_i2cp">Écoute sur le port 7654</string>
<string name="settings_label_exploratory_pool">Pool exploratoire</string>
<string name="settings_desc_exploratory_pool">Paramètres du tunnel</string>
<string name="settings_label_expl_inbound">Tunnels entrants</string>
<string name="settings_label_expl_outbound">Tunnels sortants</string>
<string name="settings_label_expl_length">Longueur</string>
<string name="settings_desc_expl_length">Combien de sauts utiliser</string>
<string name="settings_label_expl_lengthVariance">Variance de saut</string>
<string name="settings_desc_expl_lengthVariance">Combien de sauts ajouter au hasard</string>
<string name="settings_label_expl_quantity">Quantité</string>
<string name="settings_desc_expl_quantity">Combien de tunnels</string>
<string name="settings_label_expl_backupQuantity">Quantité secours</string>
<string name="settings_desc_expl_backupQuantity">Combien de tunnels de secours</string>
</resources>

34
res/values-it/strings.xml Normal file
View File

@ -0,0 +1,34 @@
<?xml version='1.0' encoding='UTF-8'?>
<resources>
<string name="app_name">I2P</string>
<string name="label_home">I2P Home</string>
<string name="label_statistics">Statistiche</string>
<string name="label_main_controls">Controlli principali</string>
<string name="label_tools">I2P Tools</string>
<string name="label_addressbook">Rubrica</string>
<string name="label_logs">Logs</string>
<string name="label_error_logs">Log errori</string>
<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>
<string name="label_nonanon_info">Informazioni non anonime</string>
<string name="label_website_nonanon">Sito (non-anon)</string>
<string name="label_faq_nonanon">FAQ (non-anon)</string>
<string name="action_add">Aggiungi</string>
<string name="action_router_start">Start Router</string>
<string name="action_router_stop">Stop Router</string>
<string name="action_reload">Ricarica</string>
<string name="menu_settings">Impostazioni</string>
<string name="settings_enable">Attiva</string>
<string name="settings_label_subscriptions">Rubrica I2P</string>
<string name="settings_desc_subscriptions">URL sottoscrizioni</string>
<string name="settings_label_bandwidth">Banda e rete</string>
<string name="settings_label_bw_inbound">Velocità in entrata</string>
<string name="settings_desc_bw_inbound">Velocità massima in entrata</string>
<string name="settings_label_bw_outbound">Velocità in uscita</string>
<string name="settings_desc_bw_outbound">Velocità massima in uscita</string>
</resources>

34
res/values-pt/strings.xml Normal file
View File

@ -0,0 +1,34 @@
<?xml version='1.0' encoding='UTF-8'?>
<resources>
<string name="app_name">I2P</string>
<string name="welcome_new_install">Bem-vindo ao I2P! Este aplicativo é um software ALPHA e não proporciona um forte anonimato. Por favor, leia as notas de lançamento e informações de licença.</string>
<string name="welcome_new_version">Nova versão instalada. Por favor, leias as notas de lançamento. Versão:</string>
<string name="label_home">Início I2P</string>
<string name="label_statistics">Estastísticas</string>
<string name="label_main_controls">Controles Principais</string>
<string name="label_tools">Ferramentas I2P</string>
<string name="label_addressbook">Endereços</string>
<string name="label_logs">Registros</string>
<string name="label_error_logs">Registros de Erros</string>
<string name="label_info_and_pages">Informação e páginas</string>
<string name="label_welcome_page">Página de boas vindas</string>
<string name="label_news">Notícias</string>
<string name="label_news_status">Últimas Notícias do I2P</string>
<string name="label_peers_status">Pares</string>
<string name="label_release_notes">Notas da Versão</string>
<string name="label_licenses">Licenças</string>
<string name="label_nonanon_info">Informação não anônima</string>
<string name="label_website_nonanon">Site (não anônimo)</string>
<string name="label_faq_nonanon">FAQ (não anônimo)</string>
<string name="action_add">Adicionar</string>
<string name="action_router_start">Iniciar Roteador</string>
<string name="action_router_stop">Parar Roteador</string>
<string name="action_reload">Recarregar</string>
<string name="menu_settings">Configurações</string>
<string name="settings_enable">Habilitar</string>
<string name="settings_label_subscriptions">Endereços I2P</string>
<string name="settings_desc_subscriptions">Subscrição de URLs</string>
<string name="settings_label_hiddenMode">Participação</string>
<string name="settings_label_advanced">Avançado</string>
<string name="settings_desc_i2cp">Escutando na porta 7654</string>
</resources>

62
res/values-ru/strings.xml Normal file
View File

@ -0,0 +1,62 @@
<?xml version='1.0' encoding='UTF-8'?>
<resources>
<string name="app_name">I2P</string>
<string name="welcome_new_install">Добро пожаловать в I2P! Это приложение является альфа-версией и оно не обеспечивает сильной анонимности. Пожалуйста, прочтите примечания к выпуску и информацию о лицензии.</string>
<string name="welcome_new_version">Новая версия установлена. Пожалуйста, прочтите примечания к выпуску. Версия:</string>
<string name="label_home">Домашняя страница I2P</string>
<string name="label_statistics">Статистика</string>
<string name="label_main_controls">Основные средства управления</string>
<string name="label_tools">Инструменты I2P</string>
<string name="label_addressbook">Адресная книга</string>
<string name="label_logs">Журналы</string>
<string name="label_error_logs">Журнал ошибок</string>
<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>
<string name="label_nonanon_info">Не анонимная информация</string>
<string name="label_website_nonanon">Веб Сайт (не анонимно)</string>
<string name="label_faq_nonanon">FAQ (не анонимно)</string>
<string name="action_add">Добавить</string>
<string name="action_router_start">Запустить маршрутизатор</string>
<string name="action_router_stop">Остановить маршрутизатор</string>
<string name="action_reload">Перезагрузить</string>
<string name="menu_settings">Настройки</string>
<string name="settings_enable">Включить</string>
<string name="settings_label_subscriptions">Адресная книга I2P</string>
<string name="settings_desc_subscriptions">Подписки на URL</string>
<string name="settings_label_bandwidth">Пропускная способность и сети</string>
<string name="settings_label_bw_inbound">Входящая скорость</string>
<string name="settings_desc_bw_inbound">Максимальная входящая скорость</string>
<string name="settings_label_bw_outbound">Исходящая скорость</string>
<string name="settings_desc_bw_outbound">Максимальная исходящая скорость</string>
<string name="settings_label_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>
<string name="settings_label_sharePercent">Процент транзитного трафика</string>
<string name="settings_desc_sharePercent">Процент пропускной способности на раздачу (по умолчанию = 80)</string>
<string name="settings_dialog_sharePercent">Процент пропускной способности на раздачу</string>
<string name="settings_desc_upnp">Автооткрытие портов брандмауэра</string>
<string name="settings_label_advanced">Расширенные</string>
<string name="settings_label_transports">Транспортные протоколы</string>
<string name="settings_label_maxConns">Максимум соединений</string>
<string name="settings_label_i2cp">I2CP-интерфейс</string>
<string name="settings_desc_i2cp">Слушать на порту 7654</string>
<string name="settings_label_exploratory_pool">Зондирующий пул</string>
<string name="settings_desc_exploratory_pool">Параметры тоннелей</string>
<string name="settings_label_expl_inbound">Входящие туннели</string>
<string name="settings_label_expl_outbound">Исходящие туннели</string>
<string name="settings_label_expl_length">Длина</string>
<string name="settings_desc_expl_length">Сколько хопов использовать</string>
<string name="settings_label_expl_lengthVariance">Хоп разброс</string>
<string name="settings_desc_expl_lengthVariance">Сколько хопов добавлять случайно</string>
<string name="settings_label_expl_quantity">Количество</string>
<string name="settings_desc_expl_quantity">Сколько туннелей</string>
<string name="settings_label_expl_backupQuantity">Резервное количество</string>
<string name="settings_desc_expl_backupQuantity"> Сколько туннелей резервировать</string>
</resources>

62
res/values-sv/strings.xml Normal file
View File

@ -0,0 +1,62 @@
<?xml version='1.0' encoding='UTF-8'?>
<resources>
<string name="app_name">I2P</string>
<string name="welcome_new_install">Välkommen till I2P! Denhär appen är ALFA-mjukvara och erbjuder inte stark anonymitet.\nVar god läs release kommentarerna och licens-information.</string>
<string name="welcome_new_version">Ny version installerad. Var god läs release kommentarerna. Version: </string>
<string name="label_home">I2P Hem</string>
<string name="label_statistics">Statistik</string>
<string name="label_main_controls">Huvudinställningar</string>
<string name="label_tools">I2P Verktyg</string>
<string name="label_addressbook">Adressbok</string>
<string name="label_logs">Loggar</string>
<string name="label_error_logs">Felloggar</string>
<string name="label_info_and_pages">Information och sidor</string>
<string name="label_welcome_page">Välkomstsida</string>
<string name="label_news">Nyheter</string>
<string name="label_news_status">Senaste I2P nyheterna</string>
<string name="label_peers_status">Peers</string>
<string name="label_release_notes">Releasekommentarer</string>
<string name="label_licenses">Licenser</string>
<string name="label_nonanon_info">Icke-anonym Information</string>
<string name="label_website_nonanon">Webb-sida (ej-anonym)</string>
<string name="label_faq_nonanon">FAQ (ej-anonym)</string>
<string name="action_add">Lägg till</string>
<string name="action_router_start">Starta Router</string>
<string name="action_router_stop">Stanna Router</string>
<string name="action_reload">Läs om</string>
<string name="menu_settings">Inställningar</string>
<string name="settings_enable">Aktivera</string>
<string name="settings_label_subscriptions">I2P Adressbok</string>
<string name="settings_desc_subscriptions">Prenumerations URL</string>
<string name="settings_label_bandwidth">Bandbredd och nätverk</string>
<string name="settings_label_bw_inbound">Inåtgående hastighet</string>
<string name="settings_desc_bw_inbound">Maximal inåtgående hastighet</string>
<string name="settings_label_bw_outbound">Utgående hastighet</string>
<string name="settings_desc_bw_outbound">Maximal utgående hastighet</string>
<string name="settings_label_hiddenMode">Deltagande</string>
<string name="settings_desc_hiddenMode">Slå av gömt läge</string>
<string name="settings_label_maxPartTunnels">Max deltagande tunnlar</string>
<string name="settings_desc_maxPartTunnels">Max tunnlar at delta i (standard=20)</string>
<string name="settings_dialog_maxPartTunnels">Max tunnlar att delta i</string>
<string name="settings_label_sharePercent">Delningsprocent</string>
<string name="settings_desc_sharePercent">Procent av bandbredd att dela (standard=80)</string>
<string name="settings_dialog_sharePercent">Procent av bandbredd at dela</string>
<string name="settings_desc_upnp">Öppna portar i brandvägg automatiskt</string>
<string name="settings_label_advanced">Avancerat</string>
<string name="settings_label_transports">Transporter</string>
<string name="settings_label_maxConns">Max anslutningar</string>
<string name="settings_label_i2cp">I2CP interfrace</string>
<string name="settings_desc_i2cp">Lyssnar på port 7654</string>
<string name="settings_label_exploratory_pool">Utforskande pool</string>
<string name="settings_desc_exploratory_pool">Tunnelparametrar</string>
<string name="settings_label_expl_inbound">Inåtgående tunnlar</string>
<string name="settings_label_expl_outbound">Utåtgående tunnlar</string>
<string name="settings_label_expl_length">Längd</string>
<string name="settings_desc_expl_length">Hur många hopp vi använder</string>
<string name="settings_label_expl_lengthVariance">Hopp variation</string>
<string name="settings_desc_expl_lengthVariance">Hur många hopp vi slumpmässigt lägger till</string>
<string name="settings_label_expl_quantity">Kvantitet</string>
<string name="settings_desc_expl_quantity">Hur många tunnlar</string>
<string name="settings_label_expl_backupQuantity">Backup kvantitet</string>
<string name="settings_desc_expl_backupQuantity">Hur många reservtunnlar</string>
</resources>

62
res/values-tr/strings.xml Normal file
View File

@ -0,0 +1,62 @@
<?xml version='1.0' encoding='UTF-8'?>
<resources>
<string name="app_name">I2P</string>
<string name="welcome_new_install">I2P dünyasına hoş geldiniz. Bu uygulama henüz ALPHA geliştirme düzeyindedir ve yaygın olarak herkese açılmamıştır. Lütfen notları ve lisans bilgilerini okuyun.</string>
<string name="welcome_new_version">Yeni sürüm yüklendi. Lütfen yayım notlarını okuyun. Sürüm:</string>
<string name="label_home">I2P Anasayfası</string>
<string name="label_statistics">İstatistikler</string>
<string name="label_main_controls">Temel Denetimler</string>
<string name="label_tools">I2P Araçları</string>
<string name="label_addressbook">Adres defteri</string>
<string name="label_logs">Günlükler</string>
<string name="label_error_logs">Hata Günlükleri</string>
<string name="label_info_and_pages">Bilgiler ve sayfalar</string>
<string name="label_welcome_page">Karşılama Sayfası</string>
<string name="label_news">Haberler</string>
<string name="label_news_status">Son I2P Haberleri</string>
<string name="label_peers_status">Eşler</string>
<string name="label_release_notes">Yayım Notları</string>
<string name="label_licenses">Lisanslar</string>
<string name="label_nonanon_info">Herkese Açık Olmayan Bilgiler</string>
<string name="label_website_nonanon">Web Sitesi (herkese açık değil)</string>
<string name="label_faq_nonanon">SSS (herkese açık değil)</string>
<string name="action_add">Ekleyin</string>
<string name="action_router_start">Yönelticiyi Başlatın</string>
<string name="action_router_stop">Yönelticiyi Durdurun</string>
<string name="action_reload">Yeniden Yükleyin</string>
<string name="menu_settings">Ayarlar</string>
<string name="settings_enable">Etkinleştirin</string>
<string name="settings_label_subscriptions">I2P Adres Defteri</string>
<string name="settings_desc_subscriptions">Abonelik İnternet Adresleri</string>
<string name="settings_label_bandwidth">Bant genişliği ve ağ</string>
<string name="settings_label_bw_inbound">Geliş hızı</string>
<string name="settings_desc_bw_inbound">En fazla geliş hızı</string>
<string name="settings_label_bw_outbound">Gidiş hızı</string>
<string name="settings_desc_bw_outbound">En fazla gidiş hızı</string>
<string name="settings_label_hiddenMode">Katılım</string>
<string name="settings_desc_hiddenMode">Gizli kipi kapatın</string>
<string name="settings_label_maxPartTunnels">Katılınacak en fazla tünel sayısı </string>
<string name="settings_desc_maxPartTunnels">Katılınacak en fazla tünel sayısı (varsayılan=20)</string>
<string name="settings_dialog_maxPartTunnels">Katılınacak en fazla tünel sayısı </string>
<string name="settings_label_sharePercent">Paylaşım yüzdei</string>
<string name="settings_desc_sharePercent">Paylaşılan bant genişliği yüzdesi (varsayılan=80)</string>
<string name="settings_dialog_sharePercent">Paylaşılacak bant genişliği yüzdesi</string>
<string name="settings_desc_upnp">Güvenlik duvarı kapıları kendiliğinden açılsın</string>
<string name="settings_label_advanced">Gelişmiş</string>
<string name="settings_label_transports">Aktarımlar</string>
<string name="settings_label_maxConns">En fazla bağlantı</string>
<string name="settings_label_i2cp">I2CP Arayüzü</string>
<string name="settings_desc_i2cp">7654. kapı dinlensin</string>
<string name="settings_label_exploratory_pool">Keşif havuzu</string>
<string name="settings_desc_exploratory_pool">Tunel ayarları</string>
<string name="settings_label_expl_inbound">Gelen tüneller</string>
<string name="settings_label_expl_outbound">Giden tüneller</string>
<string name="settings_label_expl_length">Uzunluk</string>
<string name="settings_desc_expl_length">Kullanılacak sıçrama sayısı</string>
<string name="settings_label_expl_lengthVariance">Sıçrama çeşitliliği</string>
<string name="settings_desc_expl_lengthVariance">Rastgele eklenecek sıçrama sayısı</string>
<string name="settings_label_expl_quantity">Nicelik</string>
<string name="settings_desc_expl_quantity">Tünel sayısı</string>
<string name="settings_label_expl_backupQuantity">Yedek niceliği</string>
<string name="settings_desc_expl_backupQuantity">Tünel yedeği sayısı</string>
</resources>

62
res/values-vi/strings.xml Normal file
View File

@ -0,0 +1,62 @@
<?xml version='1.0' encoding='UTF-8'?>
<resources>
<string name="app_name">I2P</string>
<string name="welcome_new_install">Chào mừng bạn đã sử dụng I2P! Đây là phiên bản ALPHA và có thể vẫn chưa được hoàn thiện đầy đủ các tính năng. Vui lòng đọc các tính năng có trong phần ghi chú về phiên bản cũng như thông tin về giấy phép sử dụng.</string>
<string name="welcome_new_version">Phiên bản mới đã được cài đặt. Vui lòng đọc kỹ phần chú ý cài đặt. Phiên bản:</string>
<string name="label_home">Trang chủ I2P</string>
<string name="label_statistics">Thống kê</string>
<string name="label_main_controls">Điều khiển chính</string>
<string name="label_tools">Công cụ I2P</string>
<string name="label_addressbook">Sổ địa chỉ</string>
<string name="label_logs">Nhật trình</string>
<string name="label_error_logs">Nhật trình về lỗi</string>
<string name="label_info_and_pages">Tin tức và trang tin</string>
<string name="label_welcome_page">Trang chào mừng</string>
<string name="label_news">Tin tức</string>
<string name="label_news_status">Thông tin mới nhất về I2P</string>
<string name="label_peers_status">Mạng ngang hàng</string>
<string name="label_release_notes">Ghi chú phát hành</string>
<string name="label_licenses">Giấy phép</string>
<string name="label_nonanon_info">Thông tin không được ẩn danh</string>
<string name="label_website_nonanon">Website (trang chính)</string>
<string name="label_faq_nonanon">Các câu hỏi thường gặp (chính)</string>
<string name="action_add">Thêm vào</string>
<string name="action_router_start">Bắt đầu định tuyến</string>
<string name="action_router_stop">Dừng lại định tuyến</string>
<string name="action_reload">Tải lại</string>
<string name="menu_settings">Thiết lập</string>
<string name="settings_enable">Cho phép</string>
<string name="settings_label_subscriptions">Sổ địa chỉ I2P</string>
<string name="settings_desc_subscriptions">Đường dẫn đăng ký theo dõi</string>
<string name="settings_label_bandwidth">Băng thông và mạng lưới</string>
<string name="settings_label_bw_inbound">Tốc độ hướng vào</string>
<string name="settings_desc_bw_inbound">Tốc độ hướng vào tối đa</string>
<string name="settings_label_bw_outbound">Tốc độ hướng ra</string>
<string name="settings_desc_bw_outbound">Tốc độ hướng ra tối đa</string>
<string name="settings_label_hiddenMode">Sự tham gia</string>
<string name="settings_desc_hiddenMode">Tắt chế độ ẩn</string>
<string name="settings_label_maxPartTunnels">Số đường hầm tối đa liên quan</string>
<string name="settings_desc_maxPartTunnels">Số đường hầm tối đa tham gia vào (mặc định là=20)</string>
<string name="settings_dialog_maxPartTunnels">Số đường hầm tối đa có liên quan</string>
<string name="settings_label_sharePercent">Chia tỉ lệ phần trăm</string>
<string name="settings_desc_sharePercent">Phần trăm của lượng băng thông dùng cho chia sẻ (mặc định=80)</string>
<string name="settings_dialog_sharePercent">Phần trăm của lượng băng thông dùng cho chia sẻ</string>
<string name="settings_desc_upnp">Tự động mở kết nối ở cổng dữ liệu cho tường lửa</string>
<string name="settings_label_advanced">Nâng cao</string>
<string name="settings_label_transports">Giao thông</string>
<string name="settings_label_maxConns">Số kết nối tối đa</string>
<string name="settings_label_i2cp">Giao diện I2CP</string>
<string name="settings_desc_i2cp">Đón nhận thông tin trên cổng 7654</string>
<string name="settings_label_exploratory_pool">Công cụ khám phá</string>
<string name="settings_desc_exploratory_pool">Thông số đường hầm</string>
<string name="settings_label_expl_inbound">Hướng vào đường hầm</string>
<string name="settings_label_expl_outbound">Hướng đi ra đường hầm</string>
<string name="settings_label_expl_length">Độ dài</string>
<string name="settings_desc_expl_length">Số lượng hop được sử dụng</string>
<string name="settings_label_expl_lengthVariance">Khoảng chênh lệch hop</string>
<string name="settings_desc_expl_lengthVariance">Số lượng hop ngẫu nhiên được thêm vào</string>
<string name="settings_label_expl_quantity">Số lượng</string>
<string name="settings_desc_expl_quantity">Số lượng đường hầm</string>
<string name="settings_label_expl_backupQuantity">Đường hầm dự trữ</string>
<string name="settings_desc_expl_backupQuantity">Số lượng đường hầm dự phòng</string>
</resources>

62
res/values-zh/strings.xml Normal file
View File

@ -0,0 +1,62 @@
<?xml version='1.0' encoding='UTF-8'?>
<resources>
<string name="app_name">I2P</string>
<string name="welcome_new_install">欢迎来到 I2P ! 此程序为 Alpha 版的测试程序,不提供很强的匿名性。请阅读版本发布说明和许可证信息。</string>
<string name="welcome_new_version">新版本已安装,请阅读版本说明。版本:</string>
<string name="label_home">I2P 主页</string>
<string name="label_statistics">统计</string>
<string name="label_main_controls">主要控制项</string>
<string name="label_tools">I2P 工具</string>
<string name="label_addressbook">地址簿</string>
<string name="label_logs">日志</string>
<string name="label_error_logs">错误日志</string>
<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>
<string name="label_nonanon_info">非匿名信息</string>
<string name="label_website_nonanon">网站(公网)</string>
<string name="label_faq_nonanon">FAQ(公网)</string>
<string name="action_add">添加</string>
<string name="action_router_start">启动路由器</string>
<string name="action_router_stop">关闭路由器</string>
<string name="action_reload">重新载入</string>
<string name="menu_settings">设置</string>
<string name="settings_enable">启用</string>
<string name="settings_label_subscriptions">I2P 地址簿</string>
<string name="settings_desc_subscriptions">订阅链接</string>
<string name="settings_label_bandwidth">带宽和网络</string>
<string name="settings_label_bw_inbound">入站速度</string>
<string name="settings_desc_bw_inbound">最大入站速度</string>
<string name="settings_label_bw_outbound">出站速度</string>
<string name="settings_desc_bw_outbound">最大出站速度</string>
<string name="settings_label_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>
<string name="settings_label_sharePercent">共享比例</string>
<string name="settings_desc_sharePercent">共享带宽的最大比例(默认=80%)</string>
<string name="settings_dialog_sharePercent">共享的带宽比例</string>
<string name="settings_desc_upnp">自动打开防火墙端口</string>
<string name="settings_label_advanced">高级</string>
<string name="settings_label_transports">传输</string>
<string name="settings_label_maxConns">最大连接数</string>
<string name="settings_label_i2cp">I2CP 接口</string>
<string name="settings_desc_i2cp">监听端口 7654</string>
<string name="settings_label_exploratory_pool">探索隧道池</string>
<string name="settings_desc_exploratory_pool">隧道参数</string>
<string name="settings_label_expl_inbound">入站隧道</string>
<string name="settings_label_expl_outbound">出站隧道</string>
<string name="settings_label_expl_length">长度</string>
<string name="settings_desc_expl_length">使用跳点数量</string>
<string name="settings_label_expl_lengthVariance">跳数变化量</string>
<string name="settings_desc_expl_lengthVariance">随机添加的跳点数量</string>
<string name="settings_label_expl_quantity">数量</string>
<string name="settings_desc_expl_quantity">隧道数量</string>
<string name="settings_label_expl_backupQuantity">备用数量</string>
<string name="settings_desc_expl_backupQuantity">备用隧道数量</string>
</resources>

16
res/values/arrays.xml Normal file
View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<string-array name="setting0to3">
<item>0</item>
<item>1</item>
<item>2</item>
<item>3</item>
</string-array>
<string-array name="setting2to2">
<item>-2</item>
<item>-1</item>
<item>0</item>
<item>1</item>
<item>2</item>
</string-array>
</resources>

4
res/values/integers.xml Normal file
View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<integer name="min_lines">10</integer>
</resources>

View File

@ -1,6 +1,67 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="app_name">I2P</string> <string name="app_name">I2P</string>
<string name="welcome_new_install">Welcome to I2P! This app is ALPHA software and it does not provide strong anonymity. Please read the release notes and license information.</string> <string name="welcome_new_install">Welcome to I2P! This app is ALPHA software and it does not provide strong anonymity. Please read the release notes and license information.</string>
<string name="welcome_new_version">New version installed. Please read the release notes. Version:</string> <string name="welcome_new_version">New version installed. Please read the release notes. Version:</string>
</resources>
<string name="label_home">I2P Home</string>
<string name="label_statistics">Statistics</string>
<string name="label_main_controls">Main Controls</string>
<string name="label_tools">I2P Tools</string>
<string name="label_addressbook">Addressbook</string>
<string name="label_logs">Logs</string>
<string name="label_error_logs">Error Logs</string>
<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>
<string name="label_nonanon_info">Non Anonymous Information</string>
<string name="label_website_nonanon">Web Site (non-anon)</string>
<string name="label_faq_nonanon">FAQ (non-anon)</string>
<string name="action_add">Add</string>
<string name="action_router_start">Start Router</string>
<string name="action_router_stop">Stop Router</string>
<string name="action_reload">Reload</string>
<string name="menu_settings">Settings</string>
<string name="settings_enable">Enable</string>
<string name="settings_label_subscriptions">I2P Addressbook</string>
<string name="settings_desc_subscriptions">Subscription URLs</string>
<string name="settings_label_bandwidth">Bandwidth and network</string>
<string name="settings_label_bw_inbound">Inbound speed</string>
<string name="settings_desc_bw_inbound">Maximum inbound speed</string>
<string name="settings_label_bw_outbound">Outbound speed</string>
<string name="settings_desc_bw_outbound">Maximum outbound speed</string>
<string name="settings_label_hiddenMode">Participation</string>
<string name="settings_desc_hiddenMode">Turn off hidden mode</string>
<string name="settings_label_maxPartTunnels">Max participating tunnels</string>
<string name="settings_desc_maxPartTunnels">Maximum tunnels to participate in (default=20)</string>
<string name="settings_dialog_maxPartTunnels">Maximum tunnels to participate in</string>
<string name="settings_label_sharePercent">Share percentage</string>
<string name="settings_desc_sharePercent">Percentage of bandwidth to share (default=80)</string>
<string name="settings_dialog_sharePercent">Percentage of bandwidth to share</string>
<string name="settings_desc_upnp">Open firewall ports automatically</string>
<string name="settings_label_advanced">Advanced</string>
<string name="settings_label_transports">Transports</string>
<string name="settings_label_maxConns">Max connections</string>
<string name="settings_label_i2cp">I2CP interface</string>
<string name="settings_desc_i2cp">Listen on port 7654</string>
<string name="settings_label_exploratory_pool">Exploratory pool</string>
<string name="settings_desc_exploratory_pool">Tunnel parameters</string>
<string name="settings_label_expl_inbound">Inbound tunnels</string>
<string name="settings_label_expl_outbound">Outbound tunnels</string>
<string name="settings_label_expl_length">Length</string>
<string name="settings_desc_expl_length">How many hops to use</string>
<string name="settings_label_expl_lengthVariance">Hop variance</string>
<string name="settings_desc_expl_lengthVariance">How many hops to randomly add</string>
<string name="settings_label_expl_quantity">Quantity</string>
<string name="settings_desc_expl_quantity">How many tunnels</string>
<string name="settings_label_expl_backupQuantity">Backup quantity</string>
<string name="settings_desc_expl_backupQuantity">How many tunnel backups</string>
</resources>

View File

@ -1,6 +1,313 @@
<PreferenceScreen <PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:key="settings1"> android:key="settings1">
<Preference
android:title="@string/settings_label_subscriptions"
android:summary="@string/settings_desc_subscriptions"
android:key="addressbook_preferences">
<intent android:targetPackage="net.i2p.android.router" android:targetClass="net.i2p.android.router.activity.AddressbookSettingsActivity" />
</Preference>
<!--
Keys and the default values from current installation:
-->
<PreferenceCategory
android:key="settings_bandwidth"
android:title="@string/settings_label_bandwidth">
<!--
i2np.bandwidth.inboundKBytesPerSecond=100
-->
<com.hlidskialf.android.preference.SeekBarPreference
android:key="i2np.bandwidth.inboundKBytesPerSecond"
android:defaultValue="100"
android:max="1000"
android:title="@string/settings_label_bw_inbound"
android:summary="@string/settings_desc_bw_inbound"
android:dialogMessage="Maximum inbound speed"
android:text=" KBytes/sec"
/>
<!--
i2np.bandwidth.outboundKBytesPerSecond=30
-->
<com.hlidskialf.android.preference.SeekBarPreference
android:key="i2np.bandwidth.outboundKBytesPerSecond"
android:defaultValue="100"
android:max="1000"
android:title="@string/settings_label_bw_outbound"
android:summary="@string/settings_desc_bw_outbound"
android:dialogMessage="Maximum outbound speed"
android:text=" KBytes/sec"
/>
<CheckBoxPreference <CheckBoxPreference
android:key="test" android:title="Check it or not"/> android:key="router.hiddenMode"
android:defaultValue="false"
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"
android:max="500"
android:title="@string/settings_label_maxPartTunnels"
android:summary="@string/settings_desc_maxPartTunnels"
android:dialogMessage="Maximum tunnels to participate in"
android:text=" Tunnels"
android:dependency="router.hiddenMode"
/>
<!--
router.sharePercentage=10
-->
<com.hlidskialf.android.preference.SeekBarPreference
android:key="router.sharePercentage"
android:defaultValue="80"
android:max="100"
android:title="@string/settings_label_sharePercent"
android:summary="@string/settings_desc_sharePercent"
android:dialogMessage="Percentage of bandwidth to share"
android:text="%"
android:dependency="router.hiddenMode"
android:shouldDisableView="true"
/>
<!--
i2np.upnp.enable=false
-->
<CheckBoxPreference
android:key="i2np.upnp.enable"
android:defaultValue="true"
android:title="UPnP"
android:summary="@string/settings_desc_upnp"
/>
</PreferenceCategory>
<PreferenceCategory
android:key="settings_advanced"
android:title="@string/settings_label_advanced">
<PreferenceScreen
android:key="settings_transports"
android:title="@string/settings_label_transports">
<PreferenceCategory
android:key="settings_ntcp"
android:title="NTCP">
<CheckBoxPreference
android:key="i2np.ntcp.enable"
android:defaultValue="true"
android:title="@string/settings_enable"
/>
<!--
i2np.ntcp.maxConnections=24
-->
<com.hlidskialf.android.preference.SeekBarPreference
android:key="i2np.ntcp.maxConnections"
android:defaultValue="32"
android:max="250"
android:title="@string/settings_label_maxConns"
android:summary="Maximum NTCP connections allowed (default=32)"
android:dialogMessage="Maximum NTCP connections"
android:text=" connections"
android:dependency="i2np.ntcp.enable"
android:shouldDisableView="true"
/>
</PreferenceCategory>
<PreferenceCategory
android:key="settings_udp"
android:title="UDP">
<!--
i2np.udp.enable=false
I might hide this one...
-->
<CheckBoxPreference
android:key="i2np.udp.enable"
android:defaultValue="true"
android:title="@string/settings_enable"
android:summary="DO NOT DISABLE THIS"
/>
<!--
i2np.udp.maxConnections=12
-->
<com.hlidskialf.android.preference.SeekBarPreference
android:key="i2np.udp.maxConnections"
android:defaultValue="32"
android:max="500"
android:title="@string/settings_label_maxConns"
android:summary="Maximum UDP connections allowed"
android:dialogMessage="Maximum UDP connections"
android:text=" connections"
android:dependency="i2np.udp.enable"
android:shouldDisableView="true"
/>
</PreferenceCategory>
</PreferenceScreen>
<!--
i2cp.disableInterface=true
-->
<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"
android:title="@string/settings_label_exploratory_pool"
android:summary="@string/settings_desc_exploratory_pool">
<PreferenceCategory
android:key="settings_expl_inbound"
android:title="@string/settings_label_expl_inbound">
<!--
router.inboundPool.length=1
-->
<ListPreference
android:key="router.inboundPool.length"
android:entries="@array/setting0to3"
android:entryValues="@array/setting0to3"
android:title="@string/settings_label_expl_length"
android:summary="@string/settings_desc_expl_length"
android:defaultValue="2"
/>
<!--
router.inboundPool.lengthVariance=1
-->
<ListPreference
android:key="router.inboundPool.lengthVariance"
android:entries="@array/setting2to2"
android:entryValues="@array/setting2to2"
android:title="@string/settings_label_expl_lengthVariance"
android:summary="@string/settings_desc_expl_lengthVariance"
android:defaultValue="0"
/>
<!--
router.inboundPool.quantity=2
-->
<ListPreference
android:key="router.inboundPool.quantity"
android:entries="@array/setting0to3"
android:entryValues="@array/setting0to3"
android:title="@string/settings_label_expl_quantity"
android:summary="@string/settings_desc_expl_quantity"
android:defaultValue="2"
/>
<!--
router.inboundPool.backupQuantity=0
-->
<ListPreference
android:key="router.inboundPool.backupQuantity"
android:entries="@array/setting0to3"
android:entryValues="@array/setting0to3"
android:title="@string/settings_label_expl_backupQuantity"
android:summary="@string/settings_desc_expl_backupQuantity"
android:defaultValue="0"
/>
</PreferenceCategory>
<PreferenceCategory
android:key="settings_expl_outbound"
android:title="@string/settings_label_expl_outbound">
<!--
router.outboundPool.length=1
-->
<ListPreference
android:key="router.outboundPool.length"
android:entries="@array/setting0to3"
android:entryValues="@array/setting0to3"
android:title="@string/settings_label_expl_length"
android:summary="@string/settings_desc_expl_length"
android:defaultValue="2"
/>
<!--
router.outboundPool.lengthVariance=1
-->
<ListPreference
android:key="router.outboundPool.lengthVariance"
android:entries="@array/setting2to2"
android:entryValues="@array/setting2to2"
android:title="@string/settings_label_expl_lengthVariance"
android:summary="@string/settings_desc_expl_lengthVariance"
android:defaultValue="0"
/>
<!--
router.outboundPool.quantity=2
-->
<ListPreference
android:key="router.outboundPool.quantity"
android:entries="@array/setting0to3"
android:entryValues="@array/setting0to3"
android:title="@string/settings_label_expl_quantity"
android:summary="@string/settings_desc_expl_quantity"
android:defaultValue="2"
/>
<!--
router.outboundPool.backupQuantity=0
-->
<ListPreference
android:key="router.outboundPool.backupQuantity"
android:entries="@array/setting0to3"
android:entryValues="@array/setting0to3"
android:title="@string/settings_label_expl_backupQuantity"
android:summary="@string/settings_desc_expl_backupQuantity"
android:defaultValue="0"
/>
</PreferenceCategory>
</PreferenceScreen>
</PreferenceCategory>
<!--
i2p.dir.pid=/data/data/net.i2p.android.router/files/tmp
<EditTextPreference
android:key=""
android:defaultValue=""
android:title=""
/>
i2p.dir.temp=/data/data/net.i2p.android.router/files/tmp
<EditTextPreference
android:key=""
android:defaultValue=""
android:title=""
/>
Futute super advanced options:
prng.bufferSize=32768
prng.buffers=2
router.decayingBloomFilterM=20
routerconsole.geoip.enable=false
time.disabled=false
No edit allowed for:
router.newsLastChecked
i2p.naming.impl
router.firstInstalled
router.firstVersion
router.previousVersion
router.updateLastInstalled
stat.full
-->
</PreferenceScreen> </PreferenceScreen>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="net.i2p.android.router"
android.versionCode="0"
android.versionName="0.0.0-0_b0-API8"
android:installLocation="auto"
>
<uses-sdk android:minSdkVersion="8" />
</manifest>

18
routerjars/ant.properties Normal file
View File

@ -0,0 +1,18 @@
# This file is used to override default values used by the Ant build system.
#
# This file must be checked into Version Control Systems, as it is
# integral to the build system of your project.
# This file is only used by the Ant script.
# You can use this to override default values such as
# 'source.dir' for the location of your java source folder and
# 'out.dir' for the location of your output folder.
# You can also use it define how the release builds are signed by declaring
# the following properties:
# 'key.store' for the location of your keystore and
# 'key.alias' for the name of the key to use.
# The password will be asked during the build when you use the 'release' target.
application-package=net.i2p.router

83
routerjars/build.xml Normal file
View File

@ -0,0 +1,83 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="I2PAndroid" default="help">
<!-- The local.properties file is created and updated by the 'android' tool.
It contains the path to the SDK. It should *NOT* be checked into
Version Control Systems. -->
<property file="local.properties" />
<!-- The ant.properties file can be created by you. It is only edited by the
'android' tool to add properties to it.
This is the place to change some Ant specific build properties.
Here are some properties you may want to change/update:
source.dir
The name of the source directory. Default is 'src'.
out.dir
The name of the output directory. Default is 'bin'.
For other overridable properties, look at the beginning of the rules
files in the SDK, at tools/ant/build.xml
Properties related to the SDK location or the project target should
be updated using the 'android' tool with the 'update' action.
This file is an integral part of the build system for your
application and should be checked into Version Control Systems.
-->
<property file="ant.properties" />
<!-- The project.properties file is created and updated by the 'android'
tool, as well as ADT.
This contains project specific properties such as project target, and library
dependencies. Lower level build properties are stored in ant.properties
(or in .classpath for Eclipse projects).
This file is an integral part of the build system for your
application and should be checked into Version Control Systems. -->
<loadproperties srcFile="project.properties" />
<!-- quick check on sdk.dir -->
<fail
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through an env var"
unless="sdk.dir"
/>
<!--
Import per project custom build rules if present at the root of the project.
This is the place to put custom intermediary targets such as:
-pre-build
-pre-compile
-post-compile (This is typically used for code obfuscation.
Compiled code location: ${out.classes.absolute.dir}
If this is not done in place, override ${out.dex.input.absolute.dir})
-post-package
-post-build
-pre-clean
-->
<import file="custom_rules.xml" optional="true" />
<!-- Import the actual build file.
To customize existing targets, there are two options:
- Customize only one target:
- copy/paste the target into this file, *before* the
<import> task.
- customize it to your needs.
- Customize the whole content of build.xml
- copy/paste the content of the rules files (minus the top node)
into this file, replacing the <import> task.
- customize to your needs.
***********************
****** IMPORTANT ******
***********************
In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
in order to avoid having your file be overridden by tools such as "android update project"
-->
<!-- version-tag: 1 -->
<import file="${sdk.dir}/tools/ant/build.xml" />
</project>

View File

@ -0,0 +1,97 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="routerjars">
<!-- override with i2psrc=path/to/source in local.properties -->
<property name="i2psrc" value="../../i2p.i2p" />
<property name="i2pbase" location="${i2psrc}" />
<available file="${i2pbase}" property="i2p.present" />
<fail message="I2P source directory ${i2pbase} was not found. Install it there or set i2psrc=/path/to/source in local.properties" >
<condition>
<not>
<isset property="i2p.present" />
</not>
</condition>
</fail>
<echo message="Using I2P source at ${i2pbase}" />
<!-- this loads my.version.code and my.version.name -->
<property file="../scripts/version.properties" />
<property name="version.code" value="${my.version.code}" />
<property name="version.name" value="${my.version.name}" />
<echo message="version.code '${version.code}', 'version.name '${version.name}', '${my.version.name}'" />
<target name="-pre-compile" depends="jbigi, buildrouter" />
<!--
Creates the output directories if they don't exist yet.
-->
<target name="-dirs">
<echo>Creating output directories if needed...</echo>
<mkdir dir="${resource.absolute.dir}" />
<mkdir dir="${gen.absolute.dir}" />
<mkdir dir="${out.absolute.dir}" />
<mkdir dir="${out.classes.absolute.dir}" />
</target>
<target name="-pre-clean">
</target>
<!-- new rules -->
<target name="buildrouter" depends="-dirs" >
<!-- build router and core -->
<ant dir="${i2pbase}" inheritall="false" useNativeBasedir="true" >
<target name="buildRouter" />
<target name="buildI2PTunnelJar" />
<target name="buildAddressbook" />
<target name="buildBOB" />
</ant>
<!-- router -->
<copy file="${i2pbase}/build/router.jar" todir="${jar.libs.dir}" />
<!-- bob -->
<copy file="${i2pbase}/apps/BOB/dist/BOB.jar" todir="${jar.libs.dir}" />
<!-- core -->
<!-- lots of unneeded stuff could be deleted here -->
<jar destfile="${jar.libs.dir}/i2p.jar" >
<zipfileset src="${i2pbase}/build/i2p.jar" >
<exclude name="net/i2p/util/LogWriter.class" />
<exclude name="net/i2p/util/SecureDirectory.class" />
<exclude name="net/i2p/util/SecureFile.class" />
<exclude name="net/i2p/util/SecureFileOutputStream.class" />
</zipfileset >
</jar>
<!-- i2ptunnel -->
<copy file="${i2pbase}/apps/ministreaming/java/build/mstreaming.jar" todir="${jar.libs.dir}" />
<copy file="${i2pbase}/apps/streaming/java/build/streaming.jar" todir="${jar.libs.dir}" />
<jar destfile="${jar.libs.dir}/i2ptunnel.jar" >
<zipfileset src="${i2pbase}/apps/i2ptunnel/java/build/i2ptunnel.jar" >
<exclude name="net/i2p/i2ptunnel/I2PTunnelGUI.class" />
</zipfileset >
</jar>
<!-- addressbook - make a jar, it's a war in the i2p distro -->
<jar destfile="${jar.libs.dir}/addressbook.jar"
basedir="${i2pbase}/apps/addressbook/build"
excludes="net/i2p/addressbook/Servlet.class" />
</target>
<target name="jbigi" >
<exec executable="sh" osfamily="unix" failonerror="true">
<arg value="-c" />
<arg value="jni/build.sh ${i2pbase}" />
</exec>
<copy file="jni/libjbigi.so" todir="${jar.libs.dir}/armeabi" />
</target>
<target name="distclean" depends="clean">
<delete dir="${jar.libs.dir}" verbose="${verbose}" />
<delete dir="jni/build/" verbose="${verbose}" />
<delete file="AndroidManifest.xml" verbose="${verbose}" />
</target>
</project>

View File

@ -1,3 +1,4 @@
#!/bin/bash
# #
# build GMP and libjbigi.so using the Android tools directly # build GMP and libjbigi.so using the Android tools directly
# #
@ -5,7 +6,21 @@
# uncomment to skip # uncomment to skip
# exit 0 # exit 0
THISDIR=$(realpath $(dirname $(which $0))) #
# No, no no, 'realpath' is not standard unix or coreutils.
#
# Use of 'which' is pretty bad too. Since 'which' would hit anything
# with the same filename that is +x in the path, and we don't want to do that,
# we use $0 as-is, because it contains _exactly_ what we are looking for.
#
#THISDIR=$(realpath $(dirname $(which $0)))
## works on linux and other unixes, but not osx.
if [ "`uname -s`" != "Darwin" ]; then
THISDIR=$(dirname $(readlink -ne $0))
else
THISDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
fi
cd $THISDIR cd $THISDIR
LIBFILE=$PWD/libjbigi.so LIBFILE=$PWD/libjbigi.so
@ -16,9 +31,21 @@ then
exit 0 exit 0
fi fi
I2PBASE=${1:-../../i2p.i2p} I2PBASE=${1:-../../../i2p.i2p}
export NDK=$(realpath ../../android-ndk-r5b/) #
# Wrong again. We want to be able to not have to update this script
# every time a new NDK comes out. We solve this by using readlink with
# a wild card, deglobbing automatically sorts to get the highest revision.
# the dot at the end ensures that it is a directory, and not a file.
#
#export NDK=$(realpath ../../android-ndk-r5b/)
## Simple fix for osx development
if [ "`uname -s`" == "Darwin" ]; then
export NDK=/Developer/android/ndk/
else
export NDK="`readlink -n -e $(for last in ../../android-ndk-r*/.; do true; done ; echo $last)`"
fi
# #
# API level, must match that in ../AndroidManifest.xml # API level, must match that in ../AndroidManifest.xml
# #
@ -26,7 +53,11 @@ LEVEL=8
ARCH=arm ARCH=arm
export SYSROOT=$NDK/platforms/android-$LEVEL/arch-$ARCH/ export SYSROOT=$NDK/platforms/android-$LEVEL/arch-$ARCH/
export AABI=arm-linux-androideabi-4.4.3 export AABI=arm-linux-androideabi-4.4.3
export SYSTEM=linux-x86 if [ "`uname -s`" == "Darwin" ]; then
export SYSTEM=darwin-x86
else
export SYSTEM=linux-x86
fi
export BINPREFIX=arm-linux-androideabi- export BINPREFIX=arm-linux-androideabi-
export CC="$NDK/toolchains/$AABI/prebuilt/$SYSTEM/bin/${BINPREFIX}gcc --sysroot=$SYSROOT" export CC="$NDK/toolchains/$AABI/prebuilt/$SYSTEM/bin/${BINPREFIX}gcc --sysroot=$SYSROOT"
# worked without this on 4.3.2, but 5.0.2 couldn't find it # worked without this on 4.3.2, but 5.0.2 couldn't find it
@ -35,7 +66,7 @@ STRIP="$NDK/toolchains/$AABI/prebuilt/$SYSTEM/bin/${BINPREFIX}strip"
#echo "CC is $CC" #echo "CC is $CC"
JBIGI=$(realpath $I2PBASE/core/c/jbigi) JBIGI="$I2PBASE/core/c/jbigi"
# #
# GMP Version # GMP Version
# #
@ -65,13 +96,23 @@ cd build
if [ ! -f config.status ] if [ ! -f config.status ]
then then
echo "Configuring GMP..." echo "Configuring GMP..."
$GMP/configure --with-pic --build=x86-none-linux --host=armv5-eabi-linux || exit 1 if [ "`uname -s`" == "Darwin" ]; then
$GMP/configure --with-pic --build=x86-darwin --host=armv5-eabi-linux || exit 1
else
$GMP/configure --with-pic --build=x86-none-linux --host=armv5-eabi-linux || exit 1
fi
fi fi
echo "Building GMP..." echo "Building GMP..."
make || exit 1 make || exit 1
export JAVA_HOME=$(dirname $(dirname $(realpath $(which javac)))) if [ "`uname -s`" == "Darwin" ]; then
# Depends on version
# TODO: Fix something for finding the newest jdk and set it as home.
export JAVA_HOME="/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/"
else
export JAVA_HOME=$(dirname $(dirname $(realpath $(which javac))))
fi
if [ ! -f "$JAVA_HOME/include/jni.h" ]; then if [ ! -f "$JAVA_HOME/include/jni.h" ]; then
echo "Cannot find jni.h! Looked in '$JAVA_HOME/include/jni.h'" echo "Cannot find jni.h! Looked in '$JAVA_HOME/include/jni.h'"
echo "Please set JAVA_HOME to a java home that has the JNI" echo "Please set JAVA_HOME to a java home that has the JNI"

View File

@ -0,0 +1,20 @@
# To enable ProGuard in your project, edit project.properties
# to define the proguard.config property as described in that file.
#
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in ${sdk.dir}/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the ProGuard
# include property in project.properties.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

View File

@ -8,4 +8,5 @@
# project structure. # project structure.
# Project target. # Project target.
target=android-8 target=android-18
android.library=true

View File

@ -0,0 +1 @@
This directory is intentionally blank.

View File

@ -2,9 +2,20 @@
# Get the version number and fix up AndroidManifest.xml # Get the version number and fix up AndroidManifest.xml
# Public domain # Public domain
# #
THISDIR=$(realpath $(dirname $(which $0)))
#
# No, no no, 'realpath' is not standard unix or coreutils.
#
# Use of 'which' is pretty bad too. Since 'which' would hit anything
# with the same filename that is +x in the path, and we don't want to do that,
# we use $0 as-is, because it contains _exactly_ what we are looking for.
#
#THISDIR=$(realpath $(dirname $(which $0)))
THISDIR=$(dirname $(readlink -ne $0))
cd $THISDIR cd $THISDIR
MANIFEST=../AndroidManifest.xml MANIFEST=../AndroidManifest.xml
MANIFESTROUTER=../routerjars/AndroidManifest.xml
TMP=AndroidManifest.xml.tmp TMP=AndroidManifest.xml.tmp
I2PBASE=${1:-../../i2p.i2p} I2PBASE=${1:-../../i2p.i2p}
@ -59,4 +70,8 @@ SUBST='s/android.versionCode="[0-9]*"/android.versionCode="'${VERSIONINT}'"/'
sed "$SUBST" < $MANIFEST > $TMP sed "$SUBST" < $MANIFEST > $TMP
SUBST='s/android.versionName="[^"]*"/android.versionName="'${VERSIONSTRING}'"/' SUBST='s/android.versionName="[^"]*"/android.versionName="'${VERSIONSTRING}'"/'
sed "$SUBST" < $TMP > $MANIFEST sed "$SUBST" < $TMP > $MANIFEST
SUBST='s/android.versionCode="[0-9]*"/android.versionCode="'${VERSIONINT}'"/'
sed "$SUBST" < $MANIFESTROUTER > $TMP
SUBST='s/android.versionName="[^"]*"/android.versionName="'${VERSIONSTRING}'"/'
sed "$SUBST" < $TMP > $MANIFESTROUTER
rm -f $TMP rm -f $TMP

View File

@ -0,0 +1,156 @@
/*
* The following code was written by Matthew Wiggins
* and is released under the APACHE 2.0 license
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Slight modifications and bugfixes by Sponge <sponge@mail.i2p>
* These modifications are released under the WTFPL (any version)
*
* We don't need negative numbers yet, and may never need to.
*
* XML Usage example:
*
* <com.hlidskialf.android.preference.SeekBarPreference android:key="duration"
* android:title="Duration of something"
* android:summary="How long something will last"
* android:dialogMessage="Something duration"
* android:defaultValue="5"
* android:text=" minutes"
* android:max="60"
* />
*
*/
package com.hlidskialf.android.preference;
import android.content.Context;
import android.preference.DialogPreference;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.SeekBar;
import android.widget.TextView;
public class SeekBarPreference extends DialogPreference implements SeekBar.OnSeekBarChangeListener {
private static final String androidns = "http://schemas.android.com/apk/res/android";
private SeekBar mSeekBar;
private TextView mSplashText;
private TextView mValueText;
private Context mContext;
private String mDialogMessage, mSuffix;
private String mDefault = "0";
private int mMax = 0;
private int mValue = 0;
private int mDirection = LinearLayout.HORIZONTAL;
public SeekBarPreference(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
mDialogMessage = attrs.getAttributeValue(androidns, "dialogMessage");
mSuffix = attrs.getAttributeValue(androidns, "text");
mDefault = attrs.getAttributeValue(androidns, "defaultValue");
mMax = Integer.parseInt(attrs.getAttributeValue(androidns, "max"));
if (attrs.getAttributeValue(androidns, "direction") != null) {
mDirection = Integer.parseInt(attrs.getAttributeValue(androidns, "direction"));
}
}
@Override
protected View onCreateDialogView() {
LinearLayout.LayoutParams params;
LinearLayout layout = new LinearLayout(mContext);
layout.setOrientation(LinearLayout.VERTICAL);
layout.setPadding(6, 6, 6, 10);
// Set the width so that it is as usable as possible.
// We multiplymMax so that the smaller ranges will get a bigger area.
if (mDirection == LinearLayout.HORIZONTAL) {
layout.setMinimumWidth(mMax*5);
} else {
layout.setMinimumHeight(mMax*5);
}
mSplashText = new TextView(mContext);
if (mDialogMessage != null) {
mSplashText.setText(mDialogMessage);
}
layout.addView(mSplashText);
mValueText = new TextView(mContext);
mValueText.setGravity(Gravity.CENTER_HORIZONTAL);
mValueText.setTextSize(32);
params = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
layout.addView(mValueText, params);
mSeekBar = new SeekBar(mContext);
mSeekBar.setOnSeekBarChangeListener(this);
// Move the bar away from the changing text, so you can see it, and
// move it away from the edges to improve usability for the end-ranges.
mSeekBar.setPadding(6, 30, 6, 6);
layout.addView(mSeekBar, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
if (shouldPersist()) {
mValue = Integer.parseInt(getPersistedString(mDefault));
}
mSeekBar.setMax(mMax);
mSeekBar.setProgress(mValue);
return layout;
}
@Override
protected void onBindDialogView(View v) {
super.onBindDialogView(v);
mSeekBar.setMax(mMax);
mSeekBar.setProgress(mValue);
}
@Override
protected void onSetInitialValue(boolean restore, Object defaultValue) {
super.onSetInitialValue(restore, defaultValue);
if (restore) {
mValue = shouldPersist() ? Integer.parseInt(getPersistedString(mDefault)) : 0;
} else {
mValue = (Integer) defaultValue;
}
}
public void onProgressChanged(SeekBar seek, int value, boolean fromTouch) {
String t = String.valueOf(value);
mValueText.setText(mSuffix == null ? t : t.concat(mSuffix));
if (shouldPersist()) {
persistString(t);
}
callChangeListener(new Integer(value));
}
public void onStartTrackingTouch(SeekBar seek) {
}
public void onStopTrackingTouch(SeekBar seek) {
}
public void setMax(int max) {
mMax = max;
}
public int getMax() {
return mMax;
}
public void setProgress(int progress) {
mValue = progress;
if (mSeekBar != null) {
mSeekBar.setProgress(progress);
}
}
public int getProgress() {
return mValue;
}
}

View File

@ -2,10 +2,9 @@ package net.i2p.android.apps;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import net.i2p.I2PAppContext; import net.i2p.I2PAppContext;
import net.i2p.data.DataHelper; import net.i2p.data.DataHelper;
import net.i2p.util.EepGet; import net.i2p.util.EepGet;
@ -47,7 +46,7 @@ public class EepGetFetcher implements EepGet.StatusListener {
_eepget.setWriteErrorToOutput(); _eepget.setWriteErrorToOutput();
//_eepget.addStatusListener(this); //_eepget.addStatusListener(this);
} }
/** /**
* Writes to output stream * Writes to output stream
*/ */
@ -62,7 +61,7 @@ public class EepGetFetcher implements EepGet.StatusListener {
if (writeErrorToStream) if (writeErrorToStream)
_eepget.setWriteErrorToOutput(); _eepget.setWriteErrorToOutput();
} }
public void addStatusListener(EepGet.StatusListener l) { public void addStatusListener(EepGet.StatusListener l) {
_eepget.addStatusListener(l); _eepget.addStatusListener(l);
} }
@ -149,7 +148,7 @@ public class EepGetFetcher implements EepGet.StatusListener {
public void bytesTransferred(long alreadyTransferred, int currentWrite, long bytesTransferred, long bytesRemaining, String url) {} public void bytesTransferred(long alreadyTransferred, int currentWrite, long bytesTransferred, long bytesRemaining, String url) {}
public void transferComplete(long alreadyTransferred, long bytesTransferred, long bytesRemaining, String url, String outputFile, boolean notModified) {} public void transferComplete(long alreadyTransferred, long bytesTransferred, long bytesRemaining, String url, String outputFile, boolean notModified) {}
public void transferFailed(String url, long bytesTransferred, long bytesRemaining, int currentAttempt) {} public void transferFailed(String url, long bytesTransferred, long bytesRemaining, int currentAttempt) {}
public void headerReceived(String url, int attemptNum, String key, String val) {} public void headerReceived(String url, int attemptNum, String key, String val) {}

View File

@ -1,14 +1,7 @@
package net.i2p.android.apps; package net.i2p.android.apps;
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import net.i2p.data.DataHelper; import net.i2p.data.DataHelper;
import net.i2p.router.Router;
import net.i2p.router.RouterContext; import net.i2p.router.RouterContext;
import net.i2p.router.util.RFC822Date; import net.i2p.router.util.RFC822Date;
import net.i2p.util.EepGet; import net.i2p.util.EepGet;
@ -31,11 +24,11 @@ public class NewsFetcher implements Runnable, EepGet.StatusListener {
private File _tempFile; private File _tempFile;
private static NewsFetcher _instance; private static NewsFetcher _instance;
public static final NewsFetcher getInstance() { public static /*final */ NewsFetcher getInstance() {
return _instance; return _instance;
} }
public static final synchronized NewsFetcher getInstance(RouterContext ctx) { public static /* final */ synchronized NewsFetcher getInstance(RouterContext ctx) {
if (_instance != null) if (_instance != null)
return _instance; return _instance;
_instance = new NewsFetcher(ctx); _instance = new NewsFetcher(ctx);
@ -52,7 +45,7 @@ public class NewsFetcher implements Runnable, EepGet.StatusListener {
private static final String DEFAULT_REFRESH_FREQUENCY = 24*60*60*1000 + ""; private static final String DEFAULT_REFRESH_FREQUENCY = 24*60*60*1000 + "";
private static final String PROP_NEWS_URL = "router.newsURL"; private static final String PROP_NEWS_URL = "router.newsURL";
private static final String DEFAULT_NEWS_URL = "http://echelon.i2p/i2p/news.xml"; private static final String DEFAULT_NEWS_URL = "http://echelon.i2p/i2p/news.xml";
private NewsFetcher(RouterContext ctx) { private NewsFetcher(RouterContext ctx) {
_context = ctx; _context = ctx;
_log = ctx.logManager().getLog(NewsFetcher.class); _log = ctx.logManager().getLog(NewsFetcher.class);
@ -68,7 +61,7 @@ public class NewsFetcher implements Runnable, EepGet.StatusListener {
_tempFile = new File(_context.getTempDir(), TEMP_NEWS_FILE); _tempFile = new File(_context.getTempDir(), TEMP_NEWS_FILE);
updateLastFetched(); updateLastFetched();
} }
private void updateLastFetched() { private void updateLastFetched() {
if (_newsFile.exists()) { if (_newsFile.exists()) {
if (_lastUpdated == 0) if (_lastUpdated == 0)
@ -83,7 +76,7 @@ public class NewsFetcher implements Runnable, EepGet.StatusListener {
_lastModified = null; _lastModified = null;
} }
} }
public String status() { public String status() {
StringBuilder buf = new StringBuilder(128); StringBuilder buf = new StringBuilder(128);
long now = _context.clock().now(); long now = _context.clock().now();
@ -100,10 +93,11 @@ public class NewsFetcher implements Runnable, EepGet.StatusListener {
} }
return buf.toString(); return buf.toString();
} }
private static final long INITIAL_DELAY = 5*60*1000; private static final long INITIAL_DELAY = 5*60*1000;
private static final long RUN_DELAY = 30*60*1000; private static final long RUN_DELAY = 30*60*1000;
@SuppressWarnings("SleepWhileInLoop")
public void run() { public void run() {
try { try {
Thread.sleep(INITIAL_DELAY); Thread.sleep(INITIAL_DELAY);
@ -121,7 +115,7 @@ public class NewsFetcher implements Runnable, EepGet.StatusListener {
} }
} }
} }
private boolean shouldFetchNews() { private boolean shouldFetchNews() {
if (_invalidated) if (_invalidated)
return true; return true;
@ -132,7 +126,7 @@ public class NewsFetcher implements Runnable, EepGet.StatusListener {
long ms = Long.parseLong(freq); long ms = Long.parseLong(freq);
if (ms <= 0) if (ms <= 0)
return false; return false;
if (_lastFetch + ms < _context.clock().now()) { if (_lastFetch + ms < _context.clock().now()) {
return true; return true;
} else { } else {
@ -162,10 +156,10 @@ public class NewsFetcher implements Runnable, EepGet.StatusListener {
int proxyPort = 4444; int proxyPort = 4444;
if (_tempFile.exists()) if (_tempFile.exists())
_tempFile.delete(); _tempFile.delete();
try { try {
EepGet get = null; // EepGet get = null;
get = new EepGet(_context, true, proxyHost, proxyPort, 0, _tempFile.getAbsolutePath(), newsURL, true, null, _lastModified); EepGet get = new EepGet(_context, true, proxyHost, proxyPort, 0, _tempFile.getAbsolutePath(), newsURL, true, null, _lastModified);
get.addStatusListener(this); get.addStatusListener(this);
if (get.fetch()) { if (get.fetch()) {
_lastModified = get.getLastModified(); _lastModified = get.getLastModified();
@ -182,7 +176,7 @@ public class NewsFetcher implements Runnable, EepGet.StatusListener {
_log.error("Error fetching the news", t); _log.error("Error fetching the news", t);
} }
} }
public void attemptFailed(String url, long bytesTransferred, long bytesRemaining, int currentAttempt, int numRetries, Exception cause) { public void attemptFailed(String url, long bytesTransferred, long bytesRemaining, int currentAttempt, int numRetries, Exception cause) {
// ignore // ignore
} }
@ -192,7 +186,7 @@ public class NewsFetcher implements Runnable, EepGet.StatusListener {
public void transferComplete(long alreadyTransferred, long bytesTransferred, long bytesRemaining, String url, String outputFile, boolean notModified) { public void transferComplete(long alreadyTransferred, long bytesTransferred, long bytesRemaining, String url, String outputFile, boolean notModified) {
if (_log.shouldLog(Log.INFO)) if (_log.shouldLog(Log.INFO))
_log.info("News fetched from " + url + " with " + (alreadyTransferred+bytesTransferred)); _log.info("News fetched from " + url + " with " + (alreadyTransferred+bytesTransferred));
long now = _context.clock().now(); long now = _context.clock().now();
if (_tempFile.exists()) { if (_tempFile.exists()) {
boolean copied = FileUtil.copy(_tempFile.getAbsolutePath(), _newsFile.getAbsolutePath(), true); boolean copied = FileUtil.copy(_tempFile.getAbsolutePath(), _newsFile.getAbsolutePath(), true);
@ -212,7 +206,7 @@ public class NewsFetcher implements Runnable, EepGet.StatusListener {
_context.router().setConfigSetting(PROP_LAST_CHECKED, "" + now); _context.router().setConfigSetting(PROP_LAST_CHECKED, "" + now);
_context.router().saveConfig(); _context.router().saveConfig();
} }
public void transferFailed(String url, long bytesTransferred, long bytesRemaining, int currentAttempt) { public void transferFailed(String url, long bytesTransferred, long bytesRemaining, int currentAttempt) {
if (_log.shouldLog(Log.WARN)) if (_log.shouldLog(Log.WARN))
_log.warn("Failed to fetch the news from " + url); _log.warn("Failed to fetch the news from " + url);

View File

@ -1,30 +1,32 @@
package net.i2p.android.router.activity; package net.i2p.android.router.activity;
import android.app.ListActivity;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.widget.AdapterView; import android.widget.AdapterView;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.ListView; import android.widget.ListView;
import android.widget.TextView; import android.widget.TextView;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Properties; import java.util.Properties;
import java.util.Set; import java.util.Set;
import net.i2p.android.router.R;
import net.i2p.I2PAppContext; import net.i2p.I2PAppContext;
import net.i2p.android.router.R;
import net.i2p.client.naming.NamingService; import net.i2p.client.naming.NamingService;
public class AddressbookActivity extends ListActivity { public class AddressbookActivity extends ActionBarActivity {
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.activity_addressbook);
// Grab context if router has started, otherwise create new // Grab context if router has started, otherwise create new
// FIXME dup contexts, locking, ... // FIXME dup contexts, locking, ...
@ -51,14 +53,14 @@ public class AddressbookActivity extends ListActivity {
tv.setText("1 host in address book."); tv.setText("1 host in address book.");
else else
tv.setText("No hosts in address book, or your router is not up."); tv.setText("No hosts in address book, or your router is not up.");
ListView lv = getListView(); ListView lv = (ListView) findViewById(R.id.addressbook_list);
lv.addHeaderView(tv, "", false); lv.addHeaderView(tv, "", false);
lv.setTextFilterEnabled(sz > 1); lv.setTextFilterEnabled(sz > 1);
// set the list // set the list
List<String> nameList = new ArrayList(names); List<String> nameList = new ArrayList<String>(names);
Collections.sort(nameList); Collections.sort(nameList);
setListAdapter(new ArrayAdapter<String>(this, R.layout.addressbook_list_item, nameList)); lv.setAdapter(new ArrayAdapter<String>(this, R.layout.addressbook_list_item, nameList));
// set the callback // set the callback
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() { lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@ -70,4 +72,26 @@ public class AddressbookActivity extends ListActivity {
} }
}); });
} }
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.activity_addressbook_actions, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle presses on the action bar items
switch (item.getItemId()) {
//case R.id.action_add_to_addressbook:
// return true;
case R.id.action_addressbook_settings:
Intent intent = new Intent(this, AddressbookSettingsActivity.class);
startActivity(intent);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
} }

View File

@ -0,0 +1,86 @@
package net.i2p.android.router.activity;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import net.i2p.android.router.R;
import net.i2p.util.FileUtil;
public class AddressbookSettingsActivity extends Activity {
protected EditText text_content_subscriptions;
protected Button btn_save_subscriptions;
private String filename = "/addressbook/subscriptions.txt";
private File i2pDir;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_addressbook_settings);
text_content_subscriptions = (EditText) findViewById(R.id.subscriptions_content);
btn_save_subscriptions = (Button) findViewById(R.id.button_save_subscriptions);
init_actions();
i2pDir = new File(getFilesDir(), filename);
load();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_addressbook_settings, menu);
return true;
}
private void init_actions() {
btn_save_subscriptions.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
Context context = getApplicationContext();
CharSequence text;
if (save()) {
text = "subscriptions.txt successfully saved!";
} else {
text = "there was a problem saving subscriptions.txt! Try fix permissions or reinstall i2p.";
}
Toast.makeText(context, text, Toast.LENGTH_SHORT).show();
}
});
}
private boolean load() {
String res = FileUtil.readTextFile(i2pDir.getAbsolutePath(), -1, true);
if (res.length() > 0) {
text_content_subscriptions.setText(res);
return true;
}
Context context = getApplicationContext();
CharSequence text = "Sorry, could not load subscriptions.txt!";
Toast.makeText(context, text, Toast.LENGTH_SHORT).show();
return false;
}
@SuppressWarnings("CallToThreadDumpStack")
private boolean save() {
//
String content = text_content_subscriptions.getText().toString();
FileOutputStream out = null;
try {
out = new FileOutputStream(i2pDir);
byte[] contentInBytes = content.getBytes();
out.write(contentInBytes);
out.close();
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
} finally {
if (out != null) try {out.close(); } catch (IOException ioe) {}
}
}
}

View File

@ -1,16 +1,15 @@
package net.i2p.android.router.activity; package net.i2p.android.router.activity;
import android.app.Activity;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Intent; import android.content.Intent;
import android.content.ServiceConnection; import android.content.ServiceConnection;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.os.Bundle; import android.os.Bundle;
import android.os.IBinder; import android.os.IBinder;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu; import android.view.Menu;
import android.view.MenuInflater; import android.view.MenuInflater;
import android.view.MenuItem; import android.view.MenuItem;
import net.i2p.android.router.R; import net.i2p.android.router.R;
import net.i2p.android.router.binder.RouterBinder; import net.i2p.android.router.binder.RouterBinder;
import net.i2p.android.router.service.RouterService; import net.i2p.android.router.service.RouterService;
@ -24,9 +23,10 @@ import net.i2p.router.peermanager.ProfileOrganizer;
import net.i2p.router.transport.FIFOBandwidthLimiter; import net.i2p.router.transport.FIFOBandwidthLimiter;
import net.i2p.stat.StatManager; import net.i2p.stat.StatManager;
public abstract class I2PActivityBase extends Activity { public abstract class I2PActivityBase extends ActionBarActivity {
protected String _myDir; protected String _myDir;
protected boolean _isBound; protected boolean _isBound;
protected boolean _triedBind;
protected ServiceConnection _connection; protected ServiceConnection _connection;
protected RouterService _routerService; protected RouterService _routerService;
private SharedPreferences _sharedPrefs; private SharedPreferences _sharedPrefs;
@ -229,17 +229,20 @@ public abstract class I2PActivityBase extends Activity {
intent.setClassName(this, "net.i2p.android.router.service.RouterService"); intent.setClassName(this, "net.i2p.android.router.service.RouterService");
Util.i(this + " calling bindService"); Util.i(this + " calling bindService");
_connection = new RouterConnection(); _connection = new RouterConnection();
boolean success = bindService(intent, _connection, autoCreate ? BIND_AUTO_CREATE : 0); _triedBind = bindService(intent, _connection, autoCreate ? BIND_AUTO_CREATE : 0);
Util.i(this + " bindService: auto create? " + autoCreate + " success? " + success); Util.i(this + " bindService: auto create? " + autoCreate + " success? " + _triedBind);
return success; return _triedBind;
} }
protected void unbindRouter() { protected void unbindRouter() {
if (_isBound && _connection != null) { Util.i(this + " unbindRouter called with _isBound:" + _isBound + " _connection:" + _connection + " _triedBind:" + _triedBind);
unbindService(_connection); if (_triedBind && _connection != null)
_routerService = null; unbindService(_connection);
_isBound = false;
} _triedBind = false;
_connection = null;
_routerService = null;
_isBound = false;
} }
protected class RouterConnection implements ServiceConnection { protected class RouterConnection implements ServiceConnection {

View File

@ -1,6 +1,5 @@
package net.i2p.android.router.activity; package net.i2p.android.router.activity;
import android.app.Dialog;
import android.app.ProgressDialog; import android.app.ProgressDialog;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
@ -13,14 +12,12 @@ import android.webkit.HttpAuthHandler;
import android.webkit.WebView; import android.webkit.WebView;
import android.webkit.WebViewClient; import android.webkit.WebViewClient;
import android.widget.Toast; import android.widget.Toast;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import net.i2p.android.apps.EepGetFetcher; import net.i2p.android.apps.EepGetFetcher;
import net.i2p.android.router.provider.CacheProvider; import net.i2p.android.router.provider.CacheProvider;
import net.i2p.android.router.util.AppCache; import net.i2p.android.router.util.AppCache;
@ -47,7 +44,7 @@ class I2PWebViewClient extends WebViewClient {
@Override @Override
public boolean shouldOverrideUrlLoading(WebView view, String url) { public boolean shouldOverrideUrlLoading(WebView view, String url) {
Util.e("Should override? " + url); Util.d("Should override? " + url);
view.stopLoading(); view.stopLoading();
Uri uri = Uri.parse(url); Uri uri = Uri.parse(url);
@ -62,7 +59,7 @@ class I2PWebViewClient extends WebViewClient {
//reverse back to a i2p URI so we can load it here and not in ContentProvider //reverse back to a i2p URI so we can load it here and not in ContentProvider
try { try {
uri = CacheProvider.getI2PUri(uri); uri = CacheProvider.getI2PUri(uri);
Util.e("Reversed content uri back to " + uri); Util.d("Reversed content uri back to " + uri);
} catch (FileNotFoundException fnfe) {} } catch (FileNotFoundException fnfe) {}
url = uri.toString(); url = uri.toString();
} }
@ -76,7 +73,7 @@ class I2PWebViewClient extends WebViewClient {
s = s.toLowerCase(); s = s.toLowerCase();
if (!(s.equals("http") || s.equals("https") || if (!(s.equals("http") || s.equals("https") ||
s.equals(CONTENT))) { s.equals(CONTENT))) {
Util.e("Not loading URL " + url); Util.d("Not loading URL " + url);
return false; return false;
} }
String h = uri.getHost(); String h = uri.getHost();
@ -129,14 +126,14 @@ class I2PWebViewClient extends WebViewClient {
//view.loadUrl(url); //view.loadUrl(url);
BGLoad task = new BackgroundLoad(view); BGLoad task = new BackgroundLoad(view);
_lastTask = task; _lastTask = task;
Util.e("Fetching via web or resource: " + url); Util.d("Fetching via web or resource: " + url);
task.execute(url); task.execute(url);
} }
return true; return true;
} }
private static void fail(View v, String s) { private static void fail(View v, String s) {
Util.e("Fail toast: " + s); Util.d("Fail toast: " + s);
Toast toast = Toast.makeText(v.getContext(), s, Toast.LENGTH_LONG); Toast toast = Toast.makeText(v.getContext(), s, Toast.LENGTH_LONG);
toast.setGravity(Gravity.CENTER, 0, 0); toast.setGravity(Gravity.CENTER, 0, 0);
toast.show(); toast.show();
@ -144,25 +141,25 @@ class I2PWebViewClient extends WebViewClient {
@Override @Override
public void onLoadResource(WebView view, String url) { public void onLoadResource(WebView view, String url) {
Util.e("OLR URL: " + url); Util.d("OLR URL: " + url);
super.onLoadResource(view, url); super.onLoadResource(view, url);
} }
@Override @Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
Util.e("ORE " + errorCode + " Desc: " + description + " URL: " + failingUrl); Util.d("ORE " + errorCode + " Desc: " + description + " URL: " + failingUrl);
super.onReceivedError(view, errorCode, description, failingUrl); super.onReceivedError(view, errorCode, description, failingUrl);
} }
@Override @Override
public void onPageStarted(WebView view, String url, Bitmap favicon) { public void onPageStarted(WebView view, String url, Bitmap favicon) {
Util.e("OPS URL: " + url); Util.d("OPS URL: " + url);
super.onPageStarted(view, url, favicon); super.onPageStarted(view, url, favicon);
} }
@Override @Override
public void onPageFinished(WebView view, String url) { public void onPageFinished(WebView view, String url) {
Util.e("OPF URL: " + url); Util.d("OPF URL: " + url);
ProgressDialog d = _lastDialog; ProgressDialog d = _lastDialog;
if (d != null && d.isShowing()) { if (d != null && d.isShowing()) {
try { try {
@ -176,7 +173,7 @@ class I2PWebViewClient extends WebViewClient {
@Override @Override
public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm) { public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm) {
Util.e("ORHAR URL: " + host); Util.d("ORHAR URL: " + host);
super.onReceivedHttpAuthRequest(view, handler, host, realm); super.onReceivedHttpAuthRequest(view, handler, host, realm);
} }
@ -193,7 +190,7 @@ class I2PWebViewClient extends WebViewClient {
void cancelAll() { void cancelAll() {
BGLoad task = _lastTask; BGLoad task = _lastTask;
if (task != null) { if (task != null) {
Util.e("Cancelling fetches"); Util.d("Cancelling fetches");
task.cancel(true); task.cancel(true);
} }
} }
@ -208,12 +205,12 @@ class I2PWebViewClient extends WebViewClient {
try { try {
//reverse back to a i2p URI so we can delete it from the AppCache //reverse back to a i2p URI so we can delete it from the AppCache
uri = CacheProvider.getI2PUri(uri); uri = CacheProvider.getI2PUri(uri);
Util.e("clearing AppCache entry for current page " + uri); Util.d("clearing AppCache entry for current page " + uri);
AppCache.getInstance(view.getContext()).removeCacheFile(uri); AppCache.getInstance(view.getContext()).removeCacheFile(uri);
} catch (FileNotFoundException fnfe) { } catch (FileNotFoundException fnfe) {
// this actually only deletes the row in the provider, // this actually only deletes the row in the provider,
// not the actual file, but it will be overwritten in the reload. // not the actual file, but it will be overwritten in the reload.
Util.e("clearing provider entry for current page " + url); Util.d("clearing provider entry for current page " + url);
view.getContext().getContentResolver().delete(uri, null, null); view.getContext().getContentResolver().delete(uri, null, null);
} }
} }
@ -280,9 +277,12 @@ class I2PWebViewClient extends WebViewClient {
return Integer.valueOf(0); return Integer.valueOf(0);
} }
@Override
protected void onProgressUpdate(Integer... progress) { protected void onProgressUpdate(Integer... progress) {
if (isCancelled()) //if (isCancelled())
return; // return;
//if (progress[0].intValue() < 0) { //if (progress[0].intValue() < 0) {
// _dialog = ProgressDialog.show(_view.getContext(), "Loading", "some url"); // _dialog = ProgressDialog.show(_view.getContext(), "Loading", "some url");
// _dialog.setOnCancelListener(this); // _dialog.setOnCancelListener(this);
@ -311,7 +311,7 @@ class I2PWebViewClient extends WebViewClient {
File cacheFile = AppCache.getInstance(_view.getContext()).getCacheFile(uri); File cacheFile = AppCache.getInstance(_view.getContext()).getCacheFile(uri);
if (cacheFile.exists()) { if (cacheFile.exists()) {
Uri resUri = AppCache.getInstance(_view.getContext()).getCacheUri(uri); Uri resUri = AppCache.getInstance(_view.getContext()).getCacheUri(uri);
Util.e("Loading " + url + " from resource cache " + resUri); Util.d("Loading " + url + " from resource cache " + resUri);
_view.getSettings().setLoadsImagesAutomatically(true); _view.getSettings().setLoadsImagesAutomatically(true);
_view.getSettings().setBlockNetworkLoads(false); _view.getSettings().setBlockNetworkLoads(false);
try { try {
@ -334,7 +334,7 @@ class I2PWebViewClient extends WebViewClient {
fetcher.addStatusListener(this); fetcher.addStatusListener(this);
boolean success = fetcher.fetch(); boolean success = fetcher.fetch();
if (isCancelled()) { if (isCancelled()) {
Util.e("Fetch cancelled for " + url); Util.d("Fetch cancelled for " + url);
return Integer.valueOf(0); return Integer.valueOf(0);
} }
try { out.close(); } catch (IOException ioe) {} try { out.close(); } catch (IOException ioe) {}
@ -343,20 +343,20 @@ class I2PWebViewClient extends WebViewClient {
// Set as current base // Set as current base
Uri content = AppCache.getInstance(_view.getContext()).addCacheFile(uri, true); Uri content = AppCache.getInstance(_view.getContext()).addCacheFile(uri, true);
if (content != null) { if (content != null) {
Util.e("Stored cache in " + content); Util.d("Stored cache in " + content);
} else { } else {
AppCache.getInstance(_view.getContext()).removeCacheFile(uri); AppCache.getInstance(_view.getContext()).removeCacheFile(uri);
Util.e("cache create error"); Util.d("cache create error");
return Integer.valueOf(0); return Integer.valueOf(0);
} }
Util.e("loading data, base URL: " + uri + " content URL: " + content); Util.d("loading data, base URL: " + uri + " content URL: " + content);
try { try {
_view.loadUrl(content.toString()); _view.loadUrl(content.toString());
} catch (Exception exc) { } catch (Exception exc) {
// CalledFromWrongThreadException // CalledFromWrongThreadException
cancel(false); cancel(false);
} }
Util.e("Fetch failed for " + url); Util.d("Fetch failed for " + url);
} else { } else {
// Load the error message in as a string, delete the file // Load the error message in as a string, delete the file
String t = fetcher.getContentType(); String t = fetcher.getContentType();
@ -378,7 +378,7 @@ class I2PWebViewClient extends WebViewClient {
DataHelper.read(fis, data); DataHelper.read(fis, data);
msg = new String(data, e); msg = new String(data, e);
} catch (IOException ioe) { } catch (IOException ioe) {
Util.e("WVC", ioe); Util.d("WVC", ioe);
msg = HEADER + "I/O error" + FOOTER; msg = HEADER + "I/O error" + FOOTER;
} finally { } finally {
if (fis != null) try { fis.close(); } catch (IOException ioe) {} if (fis != null) try { fis.close(); } catch (IOException ioe) {}
@ -386,7 +386,7 @@ class I2PWebViewClient extends WebViewClient {
} }
AppCache.getInstance(_view.getContext()).removeCacheFile(uri); AppCache.getInstance(_view.getContext()).removeCacheFile(uri);
try { try {
Util.e("loading error data URL: " + url); Util.d("loading error data URL: " + url);
_view.loadDataWithBaseURL(url, msg, t, e, url); _view.loadDataWithBaseURL(url, msg, t, e, url);
} catch (Exception exc) { } catch (Exception exc) {
// CalledFromWrongThreadException // CalledFromWrongThreadException
@ -394,13 +394,14 @@ class I2PWebViewClient extends WebViewClient {
} }
} }
} catch (IOException ioe) { } catch (IOException ioe) {
Util.e("IOE for " + url, ioe); Util.d("IOE for " + url, ioe);
} finally { } finally {
if (out != null) try { out.close(); } catch (IOException ioe) {} if (out != null) try { out.close(); } catch (IOException ioe) {}
} }
return Integer.valueOf(0); return Integer.valueOf(0);
} }
@Override
protected void onProgressUpdate(Integer... progress) { protected void onProgressUpdate(Integer... progress) {
if (isCancelled()) if (isCancelled())
return; return;

View File

@ -0,0 +1,285 @@
package net.i2p.android.router.activity;
import android.content.Context;
import android.content.res.Resources;
import android.os.Build;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
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 {
private final Context ctx;
private final String myDir;
private final String _ourVersion;
private static final String CONFIG_FILE = "android.config";
private static final String PROP_NEW_INSTALL = "i2p.newInstall";
private static final String PROP_NEW_VERSION = "i2p.newVersion";
private static final String PROP_INSTALLED_VERSION = "i2p.version";
public InitActivities(Context c) {
ctx = c;
// This needs to be changed so that we can have an alternative place
myDir = c.getFilesDir().getAbsolutePath();
_ourVersion = Util.getOurVersion(c);
}
void debugStuff() {
Util.i("java.io.tmpdir" + ": " + System.getProperty("java.io.tmpdir"));
Util.i("java.vendor" + ": " + System.getProperty("java.vendor"));
Util.i("java.version" + ": " + System.getProperty("java.version"));
Util.i("os.arch" + ": " + System.getProperty("os.arch"));
Util.i("os.name" + ": " + System.getProperty("os.name"));
Util.i("os.version" + ": " + System.getProperty("os.version"));
Util.i("user.dir" + ": " + System.getProperty("user.dir"));
Util.i("user.home" + ": " + System.getProperty("user.home"));
Util.i("user.name" + ": " + System.getProperty("user.name"));
Util.i("getFilesDir()" + ": " + myDir);
Util.i("max mem" + ": " + DataHelper.formatSize(Runtime.getRuntime().maxMemory()));
Util.i("Package" + ": " + ctx.getPackageName());
Util.i("Version" + ": " + _ourVersion);
Util.i("MODEL" + ": " + Build.MODEL);
Util.i("DISPLAY" + ": " + Build.DISPLAY);
Util.i("VERSION" + ": " + Build.VERSION.RELEASE);
Util.i("SDK" + ": " + Build.VERSION.SDK);
}
void initialize() {
if (checkNewVersion()) {
Properties props = new Properties();
props.setProperty("i2p.dir.temp", myDir + "/tmp");
props.setProperty("i2p.dir.pid", myDir + "/tmp");
// Time disabled in default router.config
// But lots of time problems on Android, not all carriers support NITZ
// and there was no NTP before 3.0. Tablets should be fine?
// Phones in airplane mode with wifi enabled still a problem.
// Deactivated phones in airplane mode definatly won't have correct time.
if (Build.VERSION.SDK_INT < 11) // Honeycomb 3.0
props.setProperty("time.disabled", "false");
mergeResourceToFile(R.raw.router_config, "router.config", props);
mergeResourceToFile(R.raw.logger_config, "logger.config", null);
mergeResourceToFile(R.raw.i2ptunnel_config, "i2ptunnel.config", null);
// FIXME this is a memory hog to merge this way
mergeResourceToFile(R.raw.hosts_txt, "hosts.txt", null);
mergeResourceToFile(R.raw.more_hosts_txt, "hosts.txt", null);
copyResourceToFile(R.raw.blocklist_txt, "blocklist.txt");
File abDir = new File(myDir, "addressbook");
abDir.mkdir();
copyResourceToFile(R.raw.subscriptions_txt, "addressbook/subscriptions.txt");
mergeResourceToFile(R.raw.addressbook_config_txt, "addressbook/config.txt", null);
File docsDir = new File(myDir, "docs");
docsDir.mkdir();
copyResourceToFile(R.raw.ahelper_conflict_header_ht, "docs/ahelper-conflict-header.ht");
copyResourceToFile(R.raw.ahelper_new_header_ht, "docs/ahelper-new-header.ht");
copyResourceToFile(R.raw.auth_header_ht, "docs/auth-header.ht");
copyResourceToFile(R.raw.denied_header_ht, "docs/denied-header.ht");
copyResourceToFile(R.raw.dnf_header_ht, "docs/dnf-header.ht");
copyResourceToFile(R.raw.dnfb_header_ht, "docs/dnfb-header.ht");
copyResourceToFile(R.raw.dnfh_header_ht, "docs/dnfh-header.ht");
copyResourceToFile(R.raw.dnfp_header_ht, "docs/dnfp-header.ht");
copyResourceToFile(R.raw.localhost_header_ht, "docs/localhost-header.ht");
copyResourceToFile(R.raw.noproxy_header_ht, "docs/noproxy-header.ht");
copyResourceToFile(R.raw.protocol_header_ht, "docs/protocol-header.ht");
File cssDir = new File(docsDir, "themes/console/light");
cssDir.mkdirs();
//copyResourceToFile(R.raw.console_css, "docs/themes/console/light/console.css");
//copyResourceToFile(R.raw.android_css, "docs/themes/console/light/android.css");
File imgDir = new File(docsDir, "themes/console/images");
imgDir.mkdir();
copyResourceToFile(R.drawable.i2plogo, "docs/themes/console/images/i2plogo.png");
copyResourceToFile(R.drawable.itoopie_sm, "docs/themes/console/images/itoopie_sm.png");
//copyResourceToFile(R.drawable.outbound, "docs/themes/console/images/outbound.png");
//copyResourceToFile(R.drawable.inbound, "docs/themes/console/images/inbound.png");
File img2Dir = new File(cssDir, "images");
img2Dir.mkdir();
//copyResourceToFile(R.drawable.header, "docs/themes/console/light/images/header.png");
File certDir = new File(myDir, "certificates");
certDir.mkdir();
File certificates = new File(myDir, "certificates");
File[] allcertificates = certificates.listFiles();
if ( allcertificates != null) {
for (int i = 0; i < allcertificates.length; i++) {
File f = allcertificates[i];
Util.i("Deleting old certificate file/dir " + f);
FileUtil.rmdir(f, false);
}
}
unzipResourceToDir(R.raw.certificates_zip, "certificates");
//File netDBDir = new File(myDir, "netDB");
//netDBDir.mkdir();
//unzipResourceToDir(R.raw.netdb_zip, "netDB");
}
// Set up the locations so settings can find them
System.setProperty("i2p.dir.base", myDir);
System.setProperty("i2p.dir.config", myDir);
System.setProperty("wrapper.logfile", myDir + "/wrapper.log");
}
/**
* @param f relative to base dir
*/
private void copyResourceToFile(int resID, String f) {
InputStream in = null;
FileOutputStream out = null;
Util.i("Creating file " + f + " from resource");
byte buf[] = new byte[4096];
try {
// Context methods
in = ctx.getResources().openRawResource(resID);
out = new FileOutputStream(new File(myDir, f));
int read;
while ( (read = in.read(buf)) != -1)
out.write(buf, 0, read);
} catch (IOException ioe) {
} catch (Resources.NotFoundException nfe) {
} finally {
if (in != null) try { in.close(); } catch (IOException ioe) {}
if (out != null) try { out.close(); } catch (IOException ioe) {}
}
}
/**
* @param f relative to base dir
*/
private void unzipResourceToDir(int resID, String f) {
InputStream in = null;
FileOutputStream out = null;
ZipInputStream zis = null;
Util.i("Creating files in '" + myDir + "/" + f + "/' from resource");
try {
// Context methods
in = ctx.getResources().openRawResource(resID);
zis = new ZipInputStream((in));
ZipEntry ze;
while ((ze = zis.getNextEntry()) != null) {
out = null;
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int count;
while ((count = zis.read(buffer)) != -1) {
baos.write(buffer, 0, count);
}
String filename = ze.getName();
Util.i("Creating file " + myDir + "/" + f +"/" + filename + " from resource");
byte[] bytes = baos.toByteArray();
out = new FileOutputStream(new File(myDir + "/" + f +"/" + filename));
out.write(bytes);
} catch (IOException ioe) {
} finally {
if (out != null) { try { out.close(); } catch (IOException ioe) {} out = null; }
}
}
} catch (IOException ioe) {
} catch (Resources.NotFoundException nfe) {
} finally {
if (in != null) try { in.close(); } catch (IOException ioe) {}
if (out != null) try { out.close(); } catch (IOException ioe) {}
if (zis != null) try { zis.close(); } catch (IOException ioe) {}
}
}
/**
* Load defaults from resource,
* then add props from file,
* and write back
* For now, do it backwards so we can override with new apks.
* When we have user configurable stuff, switch it back.
*
* @param f relative to base dir
* @param props local overrides or null
*/
public void mergeResourceToFile(int resID, String f, Properties overrides) {
InputStream in = null;
InputStream fin = null;
byte buf[] = new byte[4096];
try {
in = ctx.getResources().openRawResource(resID);
Properties props = new OrderedProperties();
// keep user settings
//DataHelper.loadProps(props, in);
try {
fin = new FileInputStream(new File(myDir, f));
DataHelper.loadProps(props, fin);
Util.i("Merging resource into file " + f);
} catch (IOException ioe) {
Util.i("Creating file " + f + " from resource");
}
// override user settings
DataHelper.loadProps(props, in);
if (overrides != null)
props.putAll(overrides);
File path = new File(myDir, f);
DataHelper.storeProps(props, path);
Util.i("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) {}
}
}
/**
* Check for new version.
* FIXME we could just use shared prefs for this instead of storing in a file
* @return true if new version
*/
private boolean checkNewVersion() {
Properties props = new Properties();
InputStream fin = null;
try {
fin = ctx.openFileInput(CONFIG_FILE);
DataHelper.loadProps(props, fin);
} catch (IOException ioe) {
Util.i("Looks like a new install");
} finally {
if (fin != null) try { fin.close(); } catch (IOException ioe) {}
}
String oldVersion = props.getProperty(PROP_INSTALLED_VERSION);
boolean newInstall = oldVersion == null;
boolean newVersion = !_ourVersion.equals(oldVersion);
if (newVersion) {
Util.i("New version " + _ourVersion);
props.setProperty(PROP_INSTALLED_VERSION, _ourVersion);
try {
DataHelper.storeProps(props, ctx.getFileStreamPath(CONFIG_FILE));
} catch (IOException ioe) {
Util.i("Failed to write " + CONFIG_FILE);
}
}
return newVersion;
}
}

View File

@ -7,7 +7,6 @@ import android.view.View;
import android.widget.AdapterView; import android.widget.AdapterView;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.ListView; import android.widget.ListView;
import net.i2p.android.router.R; import net.i2p.android.router.R;
public class LicenseActivity extends ListActivity { public class LicenseActivity extends ListActivity {
@ -15,7 +14,7 @@ public class LicenseActivity extends ListActivity {
private static final String[] names = { private static final String[] names = {
"Android Application License", "Apache 2.0", "Android Application License", "Apache 2.0",
"Router License Overview", "Blockfile", "Crypto Filters", "ElGamal / DSA", "Router License Overview", "Blockfile", "Crypto Filters", "ElGamal / DSA",
"GPLv2", "LGPLv2.1", "GPLv3", "LGPLv3", "GPLv2", "LGPLv2.1", "GPLv3", "LGPLv3", "FatCowIcons",
"Ministreaming", "Ministreaming",
"InstallCert", "SHA-256", "SNTP", "Addressbook"}; "InstallCert", "SHA-256", "SNTP", "Addressbook"};
@ -23,7 +22,7 @@ public class LicenseActivity extends ListActivity {
R.raw.license_app_txt, R.raw.license_apache20_txt, R.raw.license_app_txt, R.raw.license_apache20_txt,
R.raw.licenses_txt, R.raw.license_blockfile_txt, R.raw.license_bsd_txt, R.raw.license_elgamaldsa_txt, R.raw.licenses_txt, R.raw.license_blockfile_txt, R.raw.license_bsd_txt, R.raw.license_elgamaldsa_txt,
R.raw.license_gplv2_txt, R.raw.license_lgplv2_1_txt, R.raw.license_gplv3_txt, R.raw.license_lgplv3_txt, R.raw.license_gplv2_txt, R.raw.license_lgplv2_1_txt, R.raw.license_gplv3_txt, R.raw.license_lgplv3_txt,
R.raw.license_bsd_txt, R.raw.license_fatcowicons_txt, R.raw.license_bsd_txt,
R.raw.license_installcert_txt, R.raw.license_sha256_txt, R.raw.license_sntp_txt, R.raw.license_addressbook_txt}; R.raw.license_installcert_txt, R.raw.license_sha256_txt, R.raw.license_sntp_txt, R.raw.license_addressbook_txt};
@Override @Override

View File

@ -4,15 +4,11 @@ import android.app.ListActivity;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.ListView; import android.widget.ListView;
import android.widget.TextView; import android.widget.TextView;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import net.i2p.I2PAppContext; import net.i2p.I2PAppContext;
import net.i2p.android.router.R; import net.i2p.android.router.R;
@ -51,7 +47,8 @@ public class LogActivity extends ListActivity {
Collections.reverse(msgs); Collections.reverse(msgs);
} }
} else { } else {
msgs = Collections.EMPTY_LIST; //msgs = Collections.EMPTY_LIST;
msgs = Collections.emptyList();
header = "No messages, router has not started yet."; header = "No messages, router has not started yet.";
} }

View File

@ -10,9 +10,8 @@ import android.os.Handler;
import android.view.View; import android.view.View;
import android.widget.Button; import android.widget.Button;
import android.widget.TextView; import android.widget.TextView;
import java.io.File;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import net.i2p.android.router.R; import net.i2p.android.router.R;
import net.i2p.android.router.service.RouterService; import net.i2p.android.router.service.RouterService;
import net.i2p.android.router.util.Util; import net.i2p.android.router.util.Util;
@ -25,21 +24,45 @@ public class MainActivity extends I2PActivityBase {
private Runnable _updater; private Runnable _updater;
private Runnable _oneShotUpdate; private Runnable _oneShotUpdate;
private String _savedStatus; private String _savedStatus;
private String _ourVersion;
private boolean _keep = true;
private boolean _startPressed = false;
protected static final String PROP_NEW_INSTALL = "i2p.newInstall"; protected static final String PROP_NEW_INSTALL = "i2p.newInstall";
protected static final String PROP_NEW_VERSION = "i2p.newVersion"; protected static final String PROP_NEW_VERSION = "i2p.newVersion";
protected static final int DIALOG_NEW_INSTALL = 0; protected static final int DIALOG_NEW_INSTALL = 0;
protected static final int DIALOG_NEW_VERSION = 1; protected static final int DIALOG_NEW_VERSION = 1;
/** Called when the activity is first created. */
@Override @Override
public void onCreate(Bundle savedInstanceState) public void onPostCreate(Bundle savedInstanceState) {
{ Util.i("Initializing...");
InitActivities init = new InitActivities(this);
init.debugStuff();
init.initialize();
super.onPostCreate(savedInstanceState);
_ourVersion = Util.getOurVersion(this);
}
/**
* Called when the activity is first created.
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
// Init stuff here so settings work.
_myDir = getFilesDir().getAbsolutePath();
if(savedInstanceState != null) {
String saved = savedInstanceState.getString("status");
if(saved != null) {
_savedStatus = saved;
}
}
_keep = true;
setContentView(R.layout.main); setContentView(R.layout.main);
Button b = (Button) findViewById(R.id.news_button); Button b = (Button) findViewById(R.id.news_button);
b.setOnClickListener(new View.OnClickListener() { b.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) { public void onClick(View view) {
Intent intent = new Intent(view.getContext(), NewsActivity.class); Intent intent = new Intent(view.getContext(), NewsActivity.class);
startActivity(intent); startActivity(intent);
@ -48,6 +71,7 @@ public class MainActivity extends I2PActivityBase {
b = (Button) findViewById(R.id.releasenotes_button); b = (Button) findViewById(R.id.releasenotes_button);
b.setOnClickListener(new View.OnClickListener() { b.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) { public void onClick(View view) {
Intent intent = new Intent(view.getContext(), TextResourceActivity.class); Intent intent = new Intent(view.getContext(), TextResourceActivity.class);
intent.putExtra(TextResourceActivity.TEXT_RESOURCE_ID, R.raw.releasenotes_txt); intent.putExtra(TextResourceActivity.TEXT_RESOURCE_ID, R.raw.releasenotes_txt);
@ -57,6 +81,7 @@ public class MainActivity extends I2PActivityBase {
b = (Button) findViewById(R.id.licenses_button); b = (Button) findViewById(R.id.licenses_button);
b.setOnClickListener(new View.OnClickListener() { b.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) { public void onClick(View view) {
Intent intent = new Intent(view.getContext(), LicenseActivity.class); Intent intent = new Intent(view.getContext(), LicenseActivity.class);
//Intent intent = new Intent(view.getContext(), TextResourceActivity.class); //Intent intent = new Intent(view.getContext(), TextResourceActivity.class);
@ -67,6 +92,7 @@ public class MainActivity extends I2PActivityBase {
b = (Button) findViewById(R.id.website_button); b = (Button) findViewById(R.id.website_button);
b.setOnClickListener(new View.OnClickListener() { b.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) { public void onClick(View view) {
Intent intent = new Intent(view.getContext(), WebActivity.class); Intent intent = new Intent(view.getContext(), WebActivity.class);
//intent.setData((new Uri.Builder()).scheme("http").authority("www.i2p2.de").path("/").build()); //intent.setData((new Uri.Builder()).scheme("http").authority("www.i2p2.de").path("/").build());
@ -77,6 +103,7 @@ public class MainActivity extends I2PActivityBase {
b = (Button) findViewById(R.id.faq_button); b = (Button) findViewById(R.id.faq_button);
b.setOnClickListener(new View.OnClickListener() { b.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) { public void onClick(View view) {
Intent intent = new Intent(view.getContext(), WebActivity.class); Intent intent = new Intent(view.getContext(), WebActivity.class);
//intent.setData((new Uri.Builder()).scheme("http").authority("www.i2p2.de").path("/faq").build()); //intent.setData((new Uri.Builder()).scheme("http").authority("www.i2p2.de").path("/faq").build());
@ -87,6 +114,7 @@ public class MainActivity extends I2PActivityBase {
b = (Button) findViewById(R.id.welcome_button); b = (Button) findViewById(R.id.welcome_button);
b.setOnClickListener(new View.OnClickListener() { b.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) { public void onClick(View view) {
Intent intent = new Intent(view.getContext(), WebActivity.class); Intent intent = new Intent(view.getContext(), WebActivity.class);
intent.putExtra(WebActivity.HTML_RESOURCE_ID, R.raw.welcome_html); intent.putExtra(WebActivity.HTML_RESOURCE_ID, R.raw.welcome_html);
@ -96,6 +124,7 @@ public class MainActivity extends I2PActivityBase {
b = (Button) findViewById(R.id.addressbook_button); b = (Button) findViewById(R.id.addressbook_button);
b.setOnClickListener(new View.OnClickListener() { b.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) { public void onClick(View view) {
Intent intent = new Intent(view.getContext(), AddressbookActivity.class); Intent intent = new Intent(view.getContext(), AddressbookActivity.class);
startActivity(intent); startActivity(intent);
@ -104,6 +133,7 @@ public class MainActivity extends I2PActivityBase {
b = (Button) findViewById(R.id.logs_button); b = (Button) findViewById(R.id.logs_button);
b.setOnClickListener(new View.OnClickListener() { b.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) { public void onClick(View view) {
Intent intent = new Intent(view.getContext(), LogActivity.class); Intent intent = new Intent(view.getContext(), LogActivity.class);
startActivity(intent); startActivity(intent);
@ -112,6 +142,7 @@ public class MainActivity extends I2PActivityBase {
b = (Button) findViewById(R.id.error_button); b = (Button) findViewById(R.id.error_button);
b.setOnClickListener(new View.OnClickListener() { b.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) { public void onClick(View view) {
Intent intent = new Intent(view.getContext(), LogActivity.class); Intent intent = new Intent(view.getContext(), LogActivity.class);
intent.putExtra(LogActivity.ERRORS_ONLY, true); intent.putExtra(LogActivity.ERRORS_ONLY, true);
@ -121,44 +152,44 @@ public class MainActivity extends I2PActivityBase {
b = (Button) findViewById(R.id.peers_button); b = (Button) findViewById(R.id.peers_button);
b.setOnClickListener(new View.OnClickListener() { b.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) { public void onClick(View view) {
Intent intent = new Intent(view.getContext(), PeersActivity.class); Intent intent = new Intent(view.getContext(), PeersActivity.class);
startActivity(intent); startActivity(intent);
} }
}); });
/*
* hidden, unused b = (Button) findViewById(R.id.router_stop_button);
* b.setOnClickListener(new View.OnClickListener() { public void
* onClick(View view) { RouterService svc = _routerService; if (svc !=
* null && _isBound) { setPref(PREF_AUTO_START, false);
* svc.manualStop(); updateOneShot(); } } });
*/
b = (Button) findViewById(R.id.router_start_button); b = (Button) findViewById(R.id.router_start_button);
b.setOnClickListener(new View.OnClickListener() { b.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) { public void onClick(View view) {
_startPressed = true;
RouterService svc = _routerService; RouterService svc = _routerService;
if (svc != null && _isBound) { if(svc != null && _isBound) {
setPref(PREF_AUTO_START, true); setPref(PREF_AUTO_START, true);
svc.manualStart(); svc.manualStart();
} else { } else {
(new File(_myDir, "wrapper.log")).delete();
startRouter(); startRouter();
} }
updateOneShot(); updateOneShot();
} }
}); });
/* hidden, unused */
b = (Button) findViewById(R.id.router_stop_button);
b.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
RouterService svc = _routerService;
if (svc != null && _isBound) {
setPref(PREF_AUTO_START, false);
svc.manualStop();
updateOneShot();
}
}
});
b = (Button) findViewById(R.id.router_quit_button); b = (Button) findViewById(R.id.router_quit_button);
b.setOnClickListener(new View.OnClickListener() { b.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) { public void onClick(View view) {
RouterService svc = _routerService; RouterService svc = _routerService;
if (svc != null && _isBound) { if(svc != null && _isBound) {
setPref(PREF_AUTO_START, false); setPref(PREF_AUTO_START, false);
svc.manualQuit(); svc.manualQuit();
updateOneShot(); updateOneShot();
@ -166,25 +197,17 @@ public class MainActivity extends I2PActivityBase {
} }
}); });
if (savedInstanceState != null) {
String saved = savedInstanceState.getString("status");
if (saved != null) {
_savedStatus = saved;
}
}
_handler = new Handler(); _handler = new Handler();
_updater = new Updater(); _updater = new Updater();
_oneShotUpdate = new OneShotUpdate(); _oneShotUpdate = new OneShotUpdate();
} }
@Override @Override
public void onStart() public void onStart() {
{
super.onStart(); super.onStart();
_handler.removeCallbacks(_updater); _handler.removeCallbacks(_updater);
_handler.removeCallbacks(_oneShotUpdate); _handler.removeCallbacks(_oneShotUpdate);
if (_savedStatus != null) { if(_savedStatus != null) {
TextView tv = (TextView) findViewById(R.id.main_status_text); TextView tv = (TextView) findViewById(R.id.main_status_text);
tv.setText(_savedStatus); tv.setText(_savedStatus);
} }
@ -193,25 +216,23 @@ public class MainActivity extends I2PActivityBase {
} }
@Override @Override
public void onStop() public void onStop() {
{
super.onStop(); super.onStop();
_handler.removeCallbacks(_updater); _handler.removeCallbacks(_updater);
_handler.removeCallbacks(_oneShotUpdate); _handler.removeCallbacks(_oneShotUpdate);
} }
@Override @Override
public void onResume() public void onResume() {
{
super.onResume(); super.onResume();
updateOneShot(); updateOneShot();
} }
@Override @Override
public void onSaveInstanceState(Bundle outState) public void onSaveInstanceState(Bundle outState) {
{ if(_savedStatus != null) {
if (_savedStatus != null)
outState.putString("status", _savedStatus); outState.putString("status", _savedStatus);
}
super.onSaveInstanceState(outState); super.onSaveInstanceState(outState);
} }
@ -220,6 +241,7 @@ public class MainActivity extends I2PActivityBase {
} }
private class OneShotUpdate implements Runnable { private class OneShotUpdate implements Runnable {
public void run() { public void run() {
updateVisibility(); updateVisibility();
updateStatus(); updateStatus();
@ -227,178 +249,259 @@ public class MainActivity extends I2PActivityBase {
} }
private class Updater implements Runnable { private class Updater implements Runnable {
private int counter;
private int counter;
private final int delay = 1000;
private final int toloop = delay / 500;
public void run() { public void run() {
updateVisibility(); updateVisibility();
if (counter++ % 3 == 0) if(counter++ % toloop == 0) {
updateStatus(); updateStatus();
_handler.postDelayed(this, 2500); }
//_handler.postDelayed(this, 2500);
_handler.postDelayed(this, delay);
} }
} }
private void updateVisibility() { private void updateVisibility() {
RouterService svc = _routerService; RouterService svc = _routerService;
boolean showStart = ((svc == null) || (!_isBound) || svc.canManualStart()) && boolean showStart = ((svc == null) || (!_isBound) || svc.canManualStart())
Util.isConnected(this); && Util.isConnected(this);
Button start = (Button) findViewById(R.id.router_start_button); Button start = (Button) findViewById(R.id.router_start_button);
start.setVisibility(showStart ? View.VISIBLE : View.INVISIBLE); start.setVisibility(showStart ? View.VISIBLE : View.INVISIBLE);
boolean showStop = svc != null && _isBound && svc.canManualStop(); boolean showStop = svc != null && _isBound && svc.canManualStop();
// Old stop but leave in memory. Always hide for now. // Old stop but leave in memory. Always hide for now.
Button stop = (Button) findViewById(R.id.router_stop_button); // Button stop = (Button) findViewById(R.id.router_stop_button);
stop.setVisibility( /* showStop ? View.VISIBLE : */ View.INVISIBLE); // stop.setVisibility( /* showStop ? View.VISIBLE : */ View.INVISIBLE);
Button quit = (Button) findViewById(R.id.router_quit_button); Button quit = (Button) findViewById(R.id.router_quit_button);
quit.setVisibility(showStop ? View.VISIBLE : View.INVISIBLE); quit.setVisibility(showStop ? View.VISIBLE : View.INVISIBLE);
} }
@Override
public void onBackPressed() {
RouterContext ctx = getRouterContext();
// RouterService svc = _routerService; Which is better to use?!
_keep = Util.isConnected(this) && (ctx != null || _startPressed);
Util.d("*********************************************************");
Util.d("Back pressed, Keep? " + _keep);
Util.d("*********************************************************");
super.onBackPressed();
}
@Override
public void onDestroy() {
super.onDestroy();
if(!_keep) {
Thread t = new Thread(new KillMe());
t.start();
}
}
private class KillMe implements Runnable {
public void run() {
Util.d("*********************************************************");
Util.d("KillMe started!");
Util.d("*********************************************************");
try {
Thread.sleep(500); // is 500ms long enough?
} catch(InterruptedException ex) {
}
System.exit(0);
}
}
private void updateStatus() { private void updateStatus() {
RouterContext ctx = getRouterContext(); RouterContext ctx = getRouterContext();
TextView tv = (TextView) findViewById(R.id.main_status_text); TextView tv = (TextView) findViewById(R.id.main_status_text);
if (!Util.isConnected(this)) { if(!Util.isConnected(this)) {
tv.setText("No Internet connection is available"); tv.setText("Router version: " + _ourVersion + "\nNo Internet connection is available");
tv.setVisibility(View.VISIBLE); tv.setVisibility(View.VISIBLE);
} else if (ctx != null) { } else if(ctx != null) {
if(_startPressed) {
_startPressed = false;
}
short reach = ctx.commSystem().getReachabilityStatus();
int active = ctx.commSystem().countActivePeers(); int active = ctx.commSystem().countActivePeers();
int known = Math.max(ctx.netDb().getKnownRouters() - 1, 0); int known = Math.max(ctx.netDb().getKnownRouters() - 1, 0);
int inEx = ctx.tunnelManager().getFreeTunnelCount(); int inEx = ctx.tunnelManager().getFreeTunnelCount();
int outEx = ctx.tunnelManager().getOutboundTunnelCount(); int outEx = ctx.tunnelManager().getOutboundTunnelCount();
int inCl = ctx.tunnelManager().getInboundClientTunnelCount(); int inCl = ctx.tunnelManager().getInboundClientTunnelCount();
int outCl = ctx.tunnelManager().getOutboundClientTunnelCount(); int outCl = ctx.tunnelManager().getOutboundClientTunnelCount();
//int part = _context.tunnelManager().getParticipatingCount(); int part = ctx.tunnelManager().getParticipatingCount();
double dLag = ctx.statManager().getRate("jobQueue.jobLag").getRate(60000).getAverageValue(); double dLag = ctx.statManager().getRate("jobQueue.jobLag").getRate(60000).getAverageValue();
String jobLag = DataHelper.formatDuration((long) dLag); String jobLag = DataHelper.formatDuration((long) dLag);
String msgDelay = DataHelper.formatDuration(ctx.throttle().getMessageDelay()); String msgDelay = DataHelper.formatDuration(ctx.throttle().getMessageDelay());
String uptime = DataHelper.formatDuration(ctx.router().getUptime()); String uptime = DataHelper.formatDuration(ctx.router().getUptime());
//String tunnelStatus = _context.throttle().getTunnelStatus();
String netstatus = "Unknown";
if(reach == net.i2p.router.CommSystemFacade.STATUS_DIFFERENT) {
netstatus = "Different";
}
if(reach == net.i2p.router.CommSystemFacade.STATUS_HOSED) {
netstatus = "Hosed";
}
if(reach == net.i2p.router.CommSystemFacade.STATUS_OK) {
netstatus = "OK";
}
if(reach == net.i2p.router.CommSystemFacade.STATUS_REJECT_UNSOLICITED) {
netstatus = "Reject Unsolicited";
}
String tunnelStatus = ctx.throttle().getTunnelStatus();
//ctx.commSystem().getReachabilityStatus();
double inBW = ctx.bandwidthLimiter().getReceiveBps() / 1024; double inBW = ctx.bandwidthLimiter().getReceiveBps() / 1024;
double outBW = ctx.bandwidthLimiter().getSendBps() / 1024; double outBW = ctx.bandwidthLimiter().getSendBps() / 1024;
// control total width // control total width
DecimalFormat fmt; DecimalFormat fmt;
if (inBW >= 1000 || outBW >= 1000) if(inBW >= 1000 || outBW >= 1000) {
fmt = new DecimalFormat("#0"); fmt = new DecimalFormat("#0");
else if (inBW >= 100 || outBW >= 100) } else if(inBW >= 100 || outBW >= 100) {
fmt = new DecimalFormat("#0.0"); fmt = new DecimalFormat("#0.0");
else } else {
fmt = new DecimalFormat("#0.00"); fmt = new DecimalFormat("#0.00");
}
double kBytesIn = ctx.bandwidthLimiter().getTotalAllocatedInboundBytes() / 1024;
double kBytesOut = ctx.bandwidthLimiter().getTotalAllocatedOutboundBytes() / 1024;
// control total width
DecimalFormat kBfmt;
if(kBytesIn >= 1000 || kBytesOut >= 1000) {
kBfmt = new DecimalFormat("#0");
} else if(kBytesIn >= 100 || kBytesOut >= 100) {
kBfmt = new DecimalFormat("#0.0");
} else {
kBfmt = new DecimalFormat("#0.00");
}
String status = String status =
"ROUTER STATUS" + "ROUTER STATUS"
"\nPeers active/known: " + active + " / " + known + + "\nNetwork: " + netstatus
"\nExploratory Tunnels in/out: " + inEx + " / " + outEx + + "\nPeers active/known: " + active + " / " + known
"\nClient Tunnels in/out: " + inCl + " / " + outCl; + "\nExploratory Tunnels in/out: " + inEx + " / " + outEx
//" Pt " + part + + "\nClient Tunnels in/out: " + inCl + " / " + outCl;
// Need to see if we have the participation option set to on.
// I thought there was a router method for that? I guess not! WHY NOT?
// It would be easier if we had a number to test status.
String participate = "\nParticipation: " + tunnelStatus +" (" + part + ")";
String details = String details =
"\nBandwidth in/out: " + fmt.format(inBW) + " / " + fmt.format(outBW) + " KBps" + "\nBandwidth in/out: " + fmt.format(inBW) + " / " + fmt.format(outBW) + " KBps"
"\nMemory: " + DataHelper.formatSize(Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) + + "\nData usage in/out: " + kBfmt.format(kBytesIn) + " / " + kBfmt.format(kBytesOut) + " KB"
"B / " + DataHelper.formatSize(Runtime.getRuntime().maxMemory()) + 'B' + + "\nMemory: " + DataHelper.formatSize(Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory())
"\nJob Lag: " + jobLag + + "B / " + DataHelper.formatSize(Runtime.getRuntime().maxMemory()) + 'B'
"\nMsg Delay: " + msgDelay + + "\nJob Lag: " + jobLag
"\nUptime: " + uptime; + "\nMsg Delay: " + msgDelay
+ "\nUptime: " + uptime;
_savedStatus = status + details; _savedStatus = "Router version: " + _ourVersion + "\n" + status + participate + details;
tv.setText(_savedStatus); tv.setText(_savedStatus);
tv.setVisibility(View.VISIBLE); tv.setVisibility(View.VISIBLE);
} else { } else {
// network but no router context // network but no router context
tv.setVisibility(View.INVISIBLE); tv.setText("Router version: " + _ourVersion + "\n");
/**** //tv.setVisibility(View.INVISIBLE);
RouterService svc = _routerService; /**
String status = * **
"connected? " + Util.isConnected(this) + * RouterService svc = _routerService; String status = "connected? "
"\nMemory: " + DataHelper.formatSize(Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) + * + Util.isConnected(this) + "\nMemory: " +
"B / " + DataHelper.formatSize(Runtime.getRuntime().maxMemory()) + 'B' + * DataHelper.formatSize(Runtime.getRuntime().totalMemory() -
"\nhave ctx? " + (ctx != null) + * Runtime.getRuntime().freeMemory()) + "B / " +
"\nhave svc? " + (svc != null) + * DataHelper.formatSize(Runtime.getRuntime().maxMemory()) + 'B' +
"\nis bound? " + _isBound + * "\nhave ctx? " + (ctx != null) + "\nhave svc? " + (svc != null) +
"\nsvc state: " + (svc == null ? "null" : svc.getState()) + * "\nis bound? " + _isBound + "\nsvc state: " + (svc == null ?
"\ncan start? " + (svc == null ? "null" : svc.canManualStart()) + * "null" : svc.getState()) + "\ncan start? " + (svc == null ?
"\ncan stop? " + (svc == null ? "null" : svc.canManualStop()); * "null" : svc.canManualStart()) + "\ncan stop? " + (svc == null ?
tv.setText(status); * "null" : svc.canManualStop()); tv.setText(status);
tv.setVisibility(View.VISIBLE); * tv.setVisibility(View.VISIBLE);
****/ ***
*/
} }
} }
private void checkDialog() { private void checkDialog() {
String oldVersion = getPref(PREF_INSTALLED_VERSION, "??"); String oldVersion = getPref(PREF_INSTALLED_VERSION, "??");
if (oldVersion.equals("??")) { if(oldVersion.equals("??")) {
showDialog(DIALOG_NEW_INSTALL); showDialog(DIALOG_NEW_INSTALL);
} else { } else {
String currentVersion = Util.getOurVersion(this); String currentVersion = Util.getOurVersion(this);
if (!oldVersion.equals(currentVersion)) if(!oldVersion.equals(currentVersion)) {
showDialog(DIALOG_NEW_VERSION); showDialog(DIALOG_NEW_VERSION);
}
} }
} }
@Override
protected Dialog onCreateDialog(int id) { protected Dialog onCreateDialog(int id) {
final String currentVersion = Util.getOurVersion(this); final String currentVersion = Util.getOurVersion(this);
Dialog rv = null; Dialog rv = null;
AlertDialog.Builder b = new AlertDialog.Builder(this); AlertDialog.Builder b = new AlertDialog.Builder(this);
switch (id) { switch(id) {
case DIALOG_NEW_INSTALL: case DIALOG_NEW_INSTALL:
b.setMessage(getResources().getText(R.string.welcome_new_install)) b.setMessage(getResources().getText(R.string.welcome_new_install)).setCancelable(false).setPositiveButton("OK", new DialogInterface.OnClickListener() {
.setCancelable(false)
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
setPref(PREF_INSTALLED_VERSION, currentVersion);
dialog.cancel();
MainActivity.this.removeDialog(id);
}
})
.setNeutralButton("Release Notes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
setPref(PREF_INSTALLED_VERSION, currentVersion);
dialog.cancel();
MainActivity.this.removeDialog(id);
Intent intent = new Intent(MainActivity.this, TextResourceActivity.class);
intent.putExtra(TextResourceActivity.TEXT_RESOURCE_ID, R.raw.releasenotes_txt);
startActivity(intent);
}
})
.setNegativeButton("Licenses", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
setPref(PREF_INSTALLED_VERSION, currentVersion);
dialog.cancel();
MainActivity.this.removeDialog(id);
Intent intent = new Intent(MainActivity.this, LicenseActivity.class);
startActivity(intent);
}
});
rv = b.create();
break;
case DIALOG_NEW_VERSION: public void onClick(DialogInterface dialog, int id) {
b.setMessage(getResources().getText(R.string.welcome_new_version) + " " + currentVersion) setPref(PREF_INSTALLED_VERSION, currentVersion);
.setCancelable(true) dialog.cancel();
.setPositiveButton("OK", new DialogInterface.OnClickListener() { MainActivity.this.removeDialog(id);
public void onClick(DialogInterface dialog, int id) { }
setPref(PREF_INSTALLED_VERSION, currentVersion); }).setNeutralButton("Release Notes", new DialogInterface.OnClickListener() {
try {
dialog.dismiss();
} catch (Exception e) {}
MainActivity.this.removeDialog(id);
}
})
.setNegativeButton("Release Notes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
setPref(PREF_INSTALLED_VERSION, currentVersion);
try {
dialog.dismiss();
} catch (Exception e) {}
MainActivity.this.removeDialog(id);
Intent intent = new Intent(MainActivity.this, TextResourceActivity.class);
intent.putExtra(TextResourceActivity.TEXT_RESOURCE_ID, R.raw.releasenotes_txt);
startActivity(intent);
}
});
public void onClick(DialogInterface dialog, int id) {
setPref(PREF_INSTALLED_VERSION, currentVersion);
dialog.cancel();
MainActivity.this.removeDialog(id);
Intent intent = new Intent(MainActivity.this, TextResourceActivity.class);
intent.putExtra(TextResourceActivity.TEXT_RESOURCE_ID, R.raw.releasenotes_txt);
startActivity(intent);
}
}).setNegativeButton("Licenses", new DialogInterface.OnClickListener() {
rv = b.create(); public void onClick(DialogInterface dialog, int id) {
break; setPref(PREF_INSTALLED_VERSION, currentVersion);
dialog.cancel();
MainActivity.this.removeDialog(id);
Intent intent = new Intent(MainActivity.this, LicenseActivity.class);
startActivity(intent);
}
});
rv = b.create();
break;
case DIALOG_NEW_VERSION:
b.setMessage(getResources().getText(R.string.welcome_new_version) + " " + currentVersion).setCancelable(true).setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
setPref(PREF_INSTALLED_VERSION, currentVersion);
try {
dialog.dismiss();
} catch(Exception e) {
}
MainActivity.this.removeDialog(id);
}
}).setNegativeButton("Release Notes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
setPref(PREF_INSTALLED_VERSION, currentVersion);
try {
dialog.dismiss();
} catch(Exception e) {
}
MainActivity.this.removeDialog(id);
Intent intent = new Intent(MainActivity.this, TextResourceActivity.class);
intent.putExtra(TextResourceActivity.TEXT_RESOURCE_ID, R.raw.releasenotes_txt);
startActivity(intent);
}
});
rv = b.create();
break;
} }
return rv; return rv;
} }

View File

@ -4,18 +4,15 @@ import android.content.res.Resources;
import android.os.Bundle; import android.os.Bundle;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.webkit.WebView; import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.TextView; import android.widget.TextView;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import net.i2p.android.router.R;
import net.i2p.android.apps.NewsFetcher; import net.i2p.android.apps.NewsFetcher;
import net.i2p.android.router.R;
public class NewsActivity extends I2PActivityBase { public class NewsActivity extends I2PActivityBase {
@ -75,14 +72,14 @@ public class NewsActivity extends I2PActivityBase {
} else { } else {
in = getResources().openRawResource(R.raw.initialnews_html); in = getResources().openRawResource(R.raw.initialnews_html);
} }
int read = 0; int read;
while ( (read = in.read(buf)) != -1) while ( (read = in.read(buf)) != -1)
out.write(buf, 0, read); out.write(buf, 0, read);
if (newsExists) if (newsExists)
out.write(FOOTER.getBytes()); out.write(FOOTER.getBytes());
} catch (IOException ioe) { } catch (IOException ioe) {
System.err.println("news error " + ioe); System.err.println("news error " + ioe);
} catch (Resources.NotFoundException nfe) { } catch (Resources.NotFoundException nfe) {

View File

@ -4,15 +4,11 @@ import android.os.Bundle;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.MenuItem; import android.view.MenuItem;
import android.webkit.WebView; import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.TextView;
import java.io.StringWriter;
import java.io.IOException; import java.io.IOException;
import java.io.UnsupportedEncodingException; import java.io.StringWriter;
import net.i2p.android.router.R; import net.i2p.android.router.R;
import net.i2p.android.router.service.RouterService; import net.i2p.android.router.service.RouterService;
import net.i2p.android.router.util.Util;
import net.i2p.router.CommSystemFacade; import net.i2p.router.CommSystemFacade;
public class PeersActivity extends I2PActivityBase { public class PeersActivity extends I2PActivityBase {
@ -29,7 +25,7 @@ public class PeersActivity extends I2PActivityBase {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.peers); setContentView(R.layout.peers);
WebView wv = (WebView) findViewById(R.id.peers_webview); WebView wv = (WebView) findViewById(R.id.peers_webview);
wv.getSettings().setLoadsImagesAutomatically(false); wv.getSettings().setLoadsImagesAutomatically(true); // was false
// http://stackoverflow.com/questions/2369310/webview-double-tap-zoom-not-working-on-a-motorola-droid-a855 // http://stackoverflow.com/questions/2369310/webview-double-tap-zoom-not-working-on-a-motorola-droid-a855
wv.getSettings().setUseWideViewPort(true); wv.getSettings().setUseWideViewPort(true);
_wvClient = new I2PWebViewClient(this); _wvClient = new I2PWebViewClient(this);
@ -54,6 +50,7 @@ public class PeersActivity extends I2PActivityBase {
private void update() { private void update() {
WebView wv = (WebView) findViewById(R.id.peers_webview); WebView wv = (WebView) findViewById(R.id.peers_webview);
wv.clearHistory(); // fixes having to hit back.
CommSystemFacade comm = getCommSystem(); CommSystemFacade comm = getCommSystem();
String data; String data;
if (comm != null) { if (comm != null) {
@ -62,7 +59,7 @@ public class PeersActivity extends I2PActivityBase {
try { try {
comm.renderStatusHTML(out, "http://thiswontwork.i2p/peers", 0); comm.renderStatusHTML(out, "http://thiswontwork.i2p/peers", 0);
out.append(FOOTER); out.append(FOOTER);
data = out.toString(); data = out.toString().replaceAll("/themes", "themes");
} catch (IOException ioe) { } catch (IOException ioe) {
data = HEADER + "Error: " + ioe + FOOTER; data = HEADER + "Error: " + ioe + FOOTER;
} }
@ -70,10 +67,11 @@ public class PeersActivity extends I2PActivityBase {
data = HEADER + "No peer data available. The router is not running." + FOOTER; data = HEADER + "No peer data available. The router is not running." + FOOTER;
} }
try { try {
wv.loadData(data, "text/html", "UTF-8"); // wv.loadData(data, "text/html", "UTF-8");
// figure out a way to get /themes/console/images/outbound.png to load // figure out a way to get /themes/console/images/outbound.png to load
//String url = "file://" + _myDir + "/docs/"; // String url = "file://" + _myDir + "/docs/";
//wv.loadDataWithBaseURL(url, data, "text/html", "UTF-8", url); String url = "file:///android_asset/";
wv.loadDataWithBaseURL(url, data, "text/html", "UTF-8", url);
} catch (Exception e) { } catch (Exception e) {
} }
} }
@ -84,10 +82,13 @@ public class PeersActivity extends I2PActivityBase {
if ((keyCode == KeyEvent.KEYCODE_BACK)) { if ((keyCode == KeyEvent.KEYCODE_BACK)) {
_wvClient.cancelAll(); _wvClient.cancelAll();
wv.stopLoading(); wv.stopLoading();
if (wv.canGoBack()) {
wv.goBack(); // We do not want to go back, or keep history... Theere is no need to.
return true; // What we DO want to do is exit!
} //if (wv.canGoBack()) {
// wv.goBack();
// return true;
//}
} }
return super.onKeyDown(keyCode, event); return super.onKeyDown(keyCode, event);
} }

View File

@ -1,9 +1,18 @@
package net.i2p.android.router.activity; package net.i2p.android.router.activity;
import android.content.SharedPreferences;
import android.os.Bundle; import android.os.Bundle;
import android.preference.Preference;
import android.preference.PreferenceActivity; import android.preference.PreferenceActivity;
import android.preference.PreferenceManager;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import net.i2p.android.router.R; import net.i2p.android.router.R;
import net.i2p.android.router.util.Util;
import net.i2p.router.RouterContext;
import net.i2p.util.OrderedProperties;
public class SettingsActivity extends PreferenceActivity { public class SettingsActivity extends PreferenceActivity {
@ -12,4 +21,66 @@ public class SettingsActivity extends PreferenceActivity {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.settings1); addPreferencesFromResource(R.xml.settings1);
} }
@Override
protected void onPause() {
// Copy prefs
Properties props = new OrderedProperties();
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
Map<String, ?> all = preferences.getAll();
Iterator<String> iterator = all.keySet().iterator();
// get values from the Map and make them strings.
// This loop avoids needing to convert each one, or even know it's type, or if it exists yet.
while (iterator.hasNext()) {
String x = iterator.next();
// special exception, we must invert the bool for this property only.
if(x.equals("router.hiddenMode")) {
Preference findPreference = findPreference(x);
String string = all.get(x).toString();
String what="true";
if(string.equals(what)) {
what="false";
}
props.setProperty(x, what);
} else if(! x.startsWith("DO_NOT_SAVE")) {
// Disabled?
Preference findPreference = findPreference(x);
if ( findPreference.isEnabled() ) {
String string = all.get(x).toString();
props.setProperty(x, string);
} else {
String summary[] = findPreference.getSummary().toString().split("default=");
String defaultval = summary[summary.length - 1].trim();
if (defaultval.endsWith(")")) {
// strip the ")" off the tail end, this is the default value!
String string = defaultval.substring(0, defaultval.length() - 1);
Util.i("Resetting property '" + x + "' to default '" + string +"'");
props.setProperty(x, string);
}
}
}
}
// Merge in new config settings, write the file.
InitActivities init = new InitActivities(this);
init.mergeResourceToFile(R.raw.router_config, "router.config", 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);
}
super.onPause();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
} }

View File

@ -1,16 +1,14 @@
package net.i2p.android.router.activity; package net.i2p.android.router.activity;
import android.content.res.Resources;
import android.content.Intent; import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle; import android.os.Bundle;
import android.text.method.ScrollingMovementMethod; import android.text.method.ScrollingMovementMethod;
import android.widget.TextView; import android.widget.TextView;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import net.i2p.android.router.R; import net.i2p.android.router.R;
import net.i2p.android.router.util.Util; import net.i2p.android.router.util.Util;
@ -45,7 +43,7 @@ public class TextResourceActivity extends I2PActivityBase {
try { try {
in = getResources().openRawResource(id); in = getResources().openRawResource(id);
int read = 0; int read;
while ( (read = in.read(buf)) != -1) while ( (read = in.read(buf)) != -1)
out.write(buf, 0, read); out.write(buf, 0, read);

View File

@ -7,14 +7,11 @@ import android.os.Bundle;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.MenuItem; import android.view.MenuItem;
import android.webkit.WebView; import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.TextView; import android.widget.TextView;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import net.i2p.android.router.R; import net.i2p.android.router.R;
public class WebActivity extends I2PActivityBase { public class WebActivity extends I2PActivityBase {
@ -62,7 +59,7 @@ public class WebActivity extends I2PActivityBase {
try { try {
in = getResources().openRawResource(id); in = getResources().openRawResource(id);
int read = 0; int read;
while ( (read = in.read(buf)) != -1) while ( (read = in.read(buf)) != -1)
out.write(buf, 0, read); out.write(buf, 0, read);

View File

@ -1,7 +1,6 @@
package net.i2p.android.router.binder; package net.i2p.android.router.binder;
import android.os.Binder; import android.os.Binder;
import net.i2p.android.router.service.RouterService; import net.i2p.android.router.service.RouterService;
public class RouterBinder extends Binder { public class RouterBinder extends Binder {

View File

@ -6,7 +6,6 @@ import android.content.SharedPreferences;
import android.database.Cursor; import android.database.Cursor;
import android.net.Uri; import android.net.Uri;
import android.os.ParcelFileDescriptor; import android.os.ParcelFileDescriptor;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
@ -14,7 +13,6 @@ import java.io.OutputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import net.i2p.android.apps.EepGetFetcher; import net.i2p.android.apps.EepGetFetcher;
import net.i2p.android.router.util.AppCache; import net.i2p.android.router.util.AppCache;
import net.i2p.android.router.util.Util; import net.i2p.android.router.util.Util;
@ -83,7 +81,7 @@ public class CacheProvider extends ContentProvider {
if (q == null || !a.equals(AUTHORITY)) if (q == null || !a.equals(AUTHORITY))
return key; return key;
if (p.contains(QUERY_MARKER)) { if (p.contains(QUERY_MARKER)) {
Util.e("Key contains both queries ?!? " + key); Util.d("Key contains both queries ?!? " + key);
return null; return null;
} }
// twizzle query // twizzle query
@ -112,7 +110,7 @@ public class CacheProvider extends ContentProvider {
@Override @Override
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
Util.e("CacheProvider open " + uri); Util.d("CacheProvider open " + uri);
// if uri is malformed and we have a current base, rectify it // if uri is malformed and we have a current base, rectify it
uri = rectifyContentUri(getCurrentBase(), uri); uri = rectifyContentUri(getCurrentBase(), uri);
@ -123,17 +121,17 @@ public class CacheProvider extends ContentProvider {
try { try {
File file = new File(filePath); File file = new File(filePath);
if (file.exists()) if (file.exists())
Util.e("CacheProvider returning " + file); Util.d("CacheProvider returning " + file);
return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY); return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
} catch (FileNotFoundException fnfe) { } catch (FileNotFoundException fnfe) {
Util.e("CacheProvider not found", fnfe); Util.d("CacheProvider not found", fnfe);
remove(uri); remove(uri);
} }
} }
Util.e("CacheProvider not in cache " + uri); Util.d("CacheProvider not in cache " + uri);
Uri newUri = getI2PUri(uri); Uri newUri = getI2PUri(uri);
Util.e("CacheProvider fetching: " + newUri); Util.d("CacheProvider fetching: " + newUri);
return eepFetch(newUri); return eepFetch(newUri);
} }
@ -163,7 +161,7 @@ public class CacheProvider extends ContentProvider {
} }
} }
String debug = "CacheProvider nonce: " + nonce + " scheme: " + scheme + " host: " + host + " realPath: " + realPath + " query: " + query; String debug = "CacheProvider nonce: " + nonce + " scheme: " + scheme + " host: " + host + " realPath: " + realPath + " query: " + query;
Util.e(debug); Util.d(debug);
if ((!NONCE.equals(nonce)) || if ((!NONCE.equals(nonce)) ||
(!"http".equals(scheme)) || (!"http".equals(scheme)) ||
(host == null) || (host == null) ||
@ -186,7 +184,7 @@ public class CacheProvider extends ContentProvider {
* or the original uri on error, or if no rectification needed * or the original uri on error, or if no rectification needed
*/ */
public static Uri rectifyContentUri(Uri base, Uri uri) { public static Uri rectifyContentUri(Uri base, Uri uri) {
Util.e("rectifyContentUri base: " + base + " and uri: " + uri); Util.d("rectifyContentUri base: " + base + " and uri: " + uri);
if (base == null) if (base == null)
return uri; return uri;
if (!SCHEME.equals(base.getScheme())) if (!SCHEME.equals(base.getScheme()))
@ -224,7 +222,7 @@ public class CacheProvider extends ContentProvider {
buf.append(path); buf.append(path);
if (query != null) if (query != null)
buf.append(QUERY_MARKER).append(query); buf.append(QUERY_MARKER).append(query);
Util.e("rectified from base: " + base + " and uri: " + uri + " to: " + buf); Util.d("rectified from base: " + base + " and uri: " + uri + " to: " + buf);
return Uri.parse(buf.toString()); return Uri.parse(buf.toString());
} }
@ -247,23 +245,23 @@ public class CacheProvider extends ContentProvider {
ParcelFileDescriptor parcel = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY); ParcelFileDescriptor parcel = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
return parcel; return parcel;
} else { } else {
Util.e("CacheProvider Sucess but no data " + uri); Util.d("CacheProvider Sucess but no data " + uri);
} }
} else { } else {
Util.e("CacheProvider Eepget fail " + uri); Util.d("CacheProvider Eepget fail " + uri);
} }
AppCache.getInstance().removeCacheFile(uri); AppCache.getInstance().removeCacheFile(uri);
throw new FileNotFoundException("eepget fail"); throw new FileNotFoundException("eepget fail");
} }
public int delete(Uri uri, String selection, String[] selectionArgs) { public int delete(Uri uri, String selection, String[] selectionArgs) {
Util.e("CacheProvider delete " + uri); Util.d("CacheProvider delete " + uri);
boolean deleted = remove(uri); boolean deleted = remove(uri);
return deleted ? 1 : 0; return deleted ? 1 : 0;
} }
public String getType(Uri uri) { public String getType(Uri uri) {
Util.e("CacheProvider getType " + uri); Util.d("CacheProvider getType " + uri);
return "text/html"; return "text/html";
} }
@ -273,12 +271,12 @@ public class CacheProvider extends ContentProvider {
public Uri insert(Uri uri, ContentValues values) { public Uri insert(Uri uri, ContentValues values) {
String fileURI = values.getAsString(DATA); String fileURI = values.getAsString(DATA);
if (fileURI != null) { if (fileURI != null) {
Util.e("CacheProvider insert " + uri); Util.d("CacheProvider insert " + uri);
put(uri, fileURI); put(uri, fileURI);
} }
Boolean setAsCurrentBase = values.getAsBoolean(CURRENT_BASE); Boolean setAsCurrentBase = values.getAsBoolean(CURRENT_BASE);
if (setAsCurrentBase != null && setAsCurrentBase.booleanValue()) { if (setAsCurrentBase != null && setAsCurrentBase.booleanValue()) {
Util.e("CacheProvider set current base " + uri); Util.d("CacheProvider set current base " + uri);
setCurrentBase(uri); setCurrentBase(uri);
} }
return uri; return uri;
@ -291,7 +289,7 @@ public class CacheProvider extends ContentProvider {
} }
public Cursor query(Uri uri, String[] projection, String selection, String[] selecctionArgs, String sortOrder) { public Cursor query(Uri uri, String[] projection, String selection, String[] selecctionArgs, String sortOrder) {
Util.e("CacheProvider query " + uri); Util.d("CacheProvider query " + uri);
// TODO return a MatrixCursor with a _data entry // TODO return a MatrixCursor with a _data entry
return null; return null;
} }
@ -304,7 +302,7 @@ public class CacheProvider extends ContentProvider {
private void cleanup() { private void cleanup() {
String pfx = CONTENT_URI.toString(); String pfx = CONTENT_URI.toString();
List<String> toDelete = new ArrayList(); List<String> toDelete = new ArrayList<String>();
Map<String, ?> map = _sharedPrefs.getAll(); Map<String, ?> map = _sharedPrefs.getAll();
for (Map.Entry<String, ?> e : map.entrySet()) { for (Map.Entry<String, ?> e : map.entrySet()) {
String path = (String) e.getValue(); String path = (String) e.getValue();

View File

@ -9,7 +9,6 @@ import android.content.ServiceConnection;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.NetworkInfo; import android.net.NetworkInfo;
import android.os.IBinder; import android.os.IBinder;
import net.i2p.android.router.binder.RouterBinder; import net.i2p.android.router.binder.RouterBinder;
import net.i2p.android.router.service.RouterService; import net.i2p.android.router.service.RouterService;
import net.i2p.android.router.util.Util; import net.i2p.android.router.util.Util;
@ -32,7 +31,8 @@ public class I2PReceiver extends BroadcastReceiver {
intents.addAction(Intent.ACTION_TIME_CHANGED); intents.addAction(Intent.ACTION_TIME_CHANGED);
intents.addAction(Intent.ACTION_TIME_TICK); // once per minute, for testing intents.addAction(Intent.ACTION_TIME_TICK); // once per minute, for testing
intents.addAction(ConnectivityManager.CONNECTIVITY_ACTION); intents.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
context.registerReceiver(this, intents); @SuppressWarnings("LeakingThisInConstructor")
Intent registerReceiver = context.registerReceiver(this, intents);
_wasConnected = Util.isConnected(context); _wasConnected = Util.isConnected(context);
} }
@ -47,7 +47,7 @@ public class I2PReceiver extends BroadcastReceiver {
NetworkInfo other = (NetworkInfo) intent.getParcelableExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO); NetworkInfo other = (NetworkInfo) intent.getParcelableExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO);
/***** /*****
Util.w("No conn? " + noConn + " failover? " + failover + Util.w("No conn? " + noConn + " failover? " + failover +
" info: " + info + " other: " + other); " info: " + info + " other: " + other);
printInfo(info); printInfo(info);
printInfo(other); printInfo(other);

View File

@ -1,27 +1,9 @@
package net.i2p.android.router.service; package net.i2p.android.router.service;
import android.content.Context; import android.content.Context;
import android.content.res.Resources;
import android.content.res.Resources.NotFoundException;
import android.os.Build;
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.IOException;
import java.util.List;
import java.util.Properties;
import net.i2p.android.router.R;
import net.i2p.android.router.util.Util; import net.i2p.android.router.util.Util;
import net.i2p.data.DataHelper;
import net.i2p.router.Router;
import net.i2p.router.RouterContext;
import net.i2p.router.RouterLaunch;
import net.i2p.util.FileUtil; import net.i2p.util.FileUtil;
import net.i2p.util.NativeBigInteger;
import net.i2p.util.OrderedProperties;
class Init { class Init {
@ -29,207 +11,24 @@ class Init {
private final String myDir; private final String myDir;
private final String _ourVersion; private final String _ourVersion;
private static final String CONFIG_FILE = "android.config";
private static final String PROP_NEW_INSTALL = "i2p.newInstall";
private static final String PROP_NEW_VERSION = "i2p.newVersion";
private static final String PROP_INSTALLED_VERSION = "i2p.version";
public Init(Context c) { public Init(Context c) {
ctx = c; ctx = c;
myDir = c.getFilesDir().getAbsolutePath(); myDir = c.getFilesDir().getAbsolutePath();
_ourVersion = Util.getOurVersion(c); _ourVersion = Util.getOurVersion(c);
} }
void debugStuff() {
Util.i("java.io.tmpdir" + ": " + System.getProperty("java.io.tmpdir"));
Util.i("java.vendor" + ": " + System.getProperty("java.vendor"));
Util.i("java.version" + ": " + System.getProperty("java.version"));
Util.i("os.arch" + ": " + System.getProperty("os.arch"));
Util.i("os.name" + ": " + System.getProperty("os.name"));
Util.i("os.version" + ": " + System.getProperty("os.version"));
Util.i("user.dir" + ": " + System.getProperty("user.dir"));
Util.i("user.home" + ": " + System.getProperty("user.home"));
Util.i("user.name" + ": " + System.getProperty("user.name"));
Util.i("getFilesDir()" + ": " + myDir);
Util.i("max mem" + ": " + DataHelper.formatSize(Runtime.getRuntime().maxMemory()));
Util.i("Package" + ": " + ctx.getPackageName());
Util.i("Version" + ": " + _ourVersion);
Util.i("MODEL" + ": " + Build.MODEL);
Util.i("DISPLAY" + ": " + Build.DISPLAY);
Util.i("VERSION" + ": " + Build.VERSION.RELEASE);
Util.i("SDK" + ": " + Build.VERSION.SDK);
}
void initialize() { void initialize() {
if (checkNewVersion()) {
Properties props = new Properties();
props.setProperty("i2p.dir.temp", myDir + "/tmp");
props.setProperty("i2p.dir.pid", myDir + "/tmp");
// Time disabled in default router.config
// But lots of time problems on Android, not all carriers support NITZ
// and there was no NTP before 3.0. Tablets should be fine?
// Phones in airplane mode with wifi enabled still a problem.
if (Build.VERSION.SDK_INT < 11) // Honeycomb 3.0
props.setProperty("time.disabled", "false");
mergeResourceToFile(R.raw.router_config, "router.config", props);
mergeResourceToFile(R.raw.logger_config, "logger.config", null);
mergeResourceToFile(R.raw.i2ptunnel_config, "i2ptunnel.config", null);
// FIXME this is a memory hog to merge this way
mergeResourceToFile(R.raw.hosts_txt, "hosts.txt", null);
mergeResourceToFile(R.raw.more_hosts_txt, "hosts.txt", null);
copyResourceToFile(R.raw.blocklist_txt, "blocklist.txt");
File abDir = new File(myDir, "addressbook");
abDir.mkdir();
copyResourceToFile(R.raw.subscriptions_txt, "addressbook/subscriptions.txt");
mergeResourceToFile(R.raw.addressbook_config_txt, "addressbook/config.txt", null);
File docsDir = new File(myDir, "docs");
docsDir.mkdir();
copyResourceToFile(R.raw.ahelper_conflict_header_ht, "docs/ahelper-conflict-header.ht");
copyResourceToFile(R.raw.ahelper_new_header_ht, "docs/ahelper-new-header.ht");
copyResourceToFile(R.raw.auth_header_ht, "docs/auth-header.ht");
copyResourceToFile(R.raw.denied_header_ht, "docs/denied-header.ht");
copyResourceToFile(R.raw.dnf_header_ht, "docs/dnf-header.ht");
copyResourceToFile(R.raw.dnfb_header_ht, "docs/dnfb-header.ht");
copyResourceToFile(R.raw.dnfh_header_ht, "docs/dnfh-header.ht");
copyResourceToFile(R.raw.dnfp_header_ht, "docs/dnfp-header.ht");
copyResourceToFile(R.raw.localhost_header_ht, "docs/localhost-header.ht");
copyResourceToFile(R.raw.noproxy_header_ht, "docs/noproxy-header.ht");
copyResourceToFile(R.raw.protocol_header_ht, "docs/protocol-header.ht");
File cssDir = new File(docsDir, "themes/console/light");
cssDir.mkdirs();
copyResourceToFile(R.raw.console_css, "docs/themes/console/light/console.css");
copyResourceToFile(R.raw.android_css, "docs/themes/console/light/android.css");
File imgDir = new File(docsDir, "themes/console/images");
imgDir.mkdir();
copyResourceToFile(R.drawable.i2plogo, "docs/themes/console/images/i2plogo.png");
copyResourceToFile(R.drawable.itoopie_sm, "docs/themes/console/images/itoopie_sm.png");
copyResourceToFile(R.drawable.outbound, "docs/themes/console/images/outbound.png");
copyResourceToFile(R.drawable.inbound, "docs/themes/console/images/inbound.png");
File img2Dir = new File(cssDir, "images");
img2Dir.mkdir();
copyResourceToFile(R.drawable.header, "docs/themes/console/light/images/header.png");
}
deleteOldFiles(); deleteOldFiles();
// Set up the locations so Router and WorkingDir can find them // Set up the locations so Router and WorkingDir can find them
// We do this again here, in the event settings were changed.
System.setProperty("i2p.dir.base", myDir); System.setProperty("i2p.dir.base", myDir);
System.setProperty("i2p.dir.config", myDir); System.setProperty("i2p.dir.config", myDir);
System.setProperty("wrapper.logfile", myDir + "/wrapper.log"); System.setProperty("wrapper.logfile", myDir + "/wrapper.log");
} }
/**
* @param f relative to base dir
*/
private void copyResourceToFile(int resID, String f) {
InputStream in = null;
FileOutputStream out = null;
Util.i("Creating file " + f + " from resource");
byte buf[] = new byte[4096];
try {
// Context methods
in = ctx.getResources().openRawResource(resID);
out = new FileOutputStream(new File(myDir, f));
int read = 0;
while ( (read = in.read(buf)) != -1)
out.write(buf, 0, read);
} catch (IOException ioe) {
} catch (Resources.NotFoundException nfe) {
} finally {
if (in != null) try { in.close(); } catch (IOException ioe) {}
if (out != null) try { out.close(); } catch (IOException ioe) {}
}
}
/**
* Load defaults from resource,
* then add props from file,
* and write back
* For now, do it backwards so we can override with new apks.
* When we have user configurable stuff, switch it back.
*
* @param f relative to base dir
* @param props local overrides or null
*/
private void mergeResourceToFile(int resID, String f, Properties overrides) {
InputStream in = null;
InputStream fin = null;
byte buf[] = new byte[4096];
try {
in = ctx.getResources().openRawResource(resID);
Properties props = new OrderedProperties();
// keep user settings
//DataHelper.loadProps(props, in);
try {
fin = new FileInputStream(new File(myDir, f));
DataHelper.loadProps(props, fin);
Util.i("Merging resource into file " + f);
} catch (IOException ioe) {
Util.i("Creating file " + f + " from resource");
}
// override user settings
DataHelper.loadProps(props, in);
if (overrides != null)
props.putAll(overrides);
File path = new File(myDir, f);
DataHelper.storeProps(props, path);
Util.i("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) {}
}
}
/**
* Check for new version.
* FIXME we could just use shared prefs for this instead of storing in a file
* @return true if new version
*/
private boolean checkNewVersion() {
Properties props = new Properties();
InputStream fin = null;
try {
fin = ctx.openFileInput(CONFIG_FILE);
DataHelper.loadProps(props, fin);
} catch (IOException ioe) {
Util.i("Looks like a new install");
} finally {
if (fin != null) try { fin.close(); } catch (IOException ioe) {}
}
String oldVersion = props.getProperty(PROP_INSTALLED_VERSION);
boolean newInstall = oldVersion == null;
boolean newVersion = !_ourVersion.equals(oldVersion);
if (newVersion) {
Util.i("New version " + _ourVersion);
props.setProperty(PROP_INSTALLED_VERSION, _ourVersion);
try {
DataHelper.storeProps(props, ctx.getFileStreamPath(CONFIG_FILE));
} catch (IOException ioe) {
Util.i("Failed to write " + CONFIG_FILE);
}
}
return newVersion;
}
private void deleteOldFiles() { private void deleteOldFiles() {
(new File(myDir, "wrapper.log")).delete();
File tmp = new File(myDir, "tmp"); File tmp = new File(myDir, "tmp");
File[] files = tmp.listFiles(); File[] files = tmp.listFiles();
if (files != null) { if (files != null) {

View File

@ -1,5 +1,6 @@
package net.i2p.android.router.service; package net.i2p.android.router.service;
import net.i2p.BOB.BOB;
import net.i2p.addressbook.DaemonThread; import net.i2p.addressbook.DaemonThread;
import net.i2p.android.apps.NewsFetcher; import net.i2p.android.apps.NewsFetcher;
import net.i2p.android.router.util.Util; import net.i2p.android.router.util.Util;
@ -29,9 +30,10 @@ import net.i2p.util.I2PAppThread;
* *
*/ */
class LoadClientsJob extends JobImpl { class LoadClientsJob extends JobImpl {
private Thread _fetcherThread; private Thread _fetcherThread;
private DaemonThread _addressbook; private DaemonThread _addressbook;
private Thread _BOB;
/** this is the delay to load (and start) the clients. */ /** this is the delay to load (and start) the clients. */
private static final long LOAD_DELAY = 90*1000; private static final long LOAD_DELAY = 90*1000;
@ -58,11 +60,21 @@ class LoadClientsJob extends JobImpl {
_addressbook.start(); _addressbook.start();
// add other clients here // add other clients here
Run_BOB bob = new Run_BOB();
_BOB = new I2PAppThread(bob, "BOB", true);
_BOB.start();
getContext().addShutdownTask(new ClientShutdownHook()); getContext().addShutdownTask(new ClientShutdownHook());
} }
private class Run_BOB implements Runnable {
public void run() {
Util.i("BOB starting...");
BOB.main(null);
Util.i("BOB Stopped.");
_BOB = null;
}
}
private class RunI2PTunnel extends JobImpl { private class RunI2PTunnel extends JobImpl {
public RunI2PTunnel(RouterContext ctx) { public RunI2PTunnel(RouterContext ctx) {
@ -84,6 +96,8 @@ class LoadClientsJob extends JobImpl {
public void run() { public void run() {
Util.i("client shutdown hook"); Util.i("client shutdown hook");
// i2ptunnel registers its own hook // i2ptunnel registers its own hook
if (_BOB != null)
BOB.stop();
if (_fetcherThread != null) if (_fetcherThread != null)
_fetcherThread.interrupt(); _fetcherThread.interrupt();
if (_addressbook != null) if (_addressbook != null)

View File

@ -1,19 +1,18 @@
package net.i2p.android.router.service; package net.i2p.android.router.service;
import android.app.Service; import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.IBinder; import android.os.IBinder;
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.util.List; import java.util.List;
import java.util.Properties;
import net.i2p.android.router.R; import java.util.Random;
import net.i2p.android.router.binder.RouterBinder; import net.i2p.android.router.binder.RouterBinder;
import net.i2p.android.router.receiver.I2PReceiver; import net.i2p.android.router.receiver.I2PReceiver;
import net.i2p.android.router.util.Util; import net.i2p.android.router.util.Util;
@ -22,23 +21,25 @@ import net.i2p.router.Job;
import net.i2p.router.Router; import net.i2p.router.Router;
import net.i2p.router.RouterContext; import net.i2p.router.RouterContext;
import net.i2p.router.RouterLaunch; import net.i2p.router.RouterLaunch;
import net.i2p.util.NativeBigInteger; import net.i2p.util.OrderedProperties;
/** /**
* Runs the router * Runs the router
*/ */
public class RouterService extends Service { public class RouterService extends Service {
public enum State {INIT, WAITING, STARTING, RUNNING,
// unplanned (router stopped itself), next: killSelf()
STOPPING, STOPPED,
// button, don't kill service when stopped, stay in MANUAL_STOPPED
MANUAL_STOPPING, MANUAL_STOPPED,
// button, DO kill service when stopped, next: killSelf()
MANUAL_QUITTING, MANUAL_QUITTED,
// Stopped by listener (no network), next: WAITING (spin waiting for network)
NETWORK_STOPPING, NETWORK_STOPPED
}
// These states persist even if we died... Yuck, it causes issues.
public enum State {
INIT, WAITING, STARTING, RUNNING,
// unplanned (router stopped itself), next: killSelf()
STOPPING, STOPPED,
// button, don't kill service when stopped, stay in MANUAL_STOPPED
MANUAL_STOPPING, MANUAL_STOPPED,
// button, DO kill service when stopped, next: killSelf()
MANUAL_QUITTING, MANUAL_QUITTED,
// Stopped by listener (no network), next: WAITING (spin waiting for network)
NETWORK_STOPPING, NETWORK_STOPPED
}
private RouterContext _context; private RouterContext _context;
private String _myDir; private String _myDir;
//private String _apkPath; //private String _apkPath;
@ -50,7 +51,6 @@ public class RouterService extends Service {
private final Object _stateLock = new Object(); private final Object _stateLock = new Object();
private Handler _handler; private Handler _handler;
private Runnable _updater; private Runnable _updater;
private static final String SHARED_PREFS = "net.i2p.android.router"; private static final String SHARED_PREFS = "net.i2p.android.router";
private static final String LAST_STATE = "service.lastState"; private static final String LAST_STATE = "service.lastState";
private static final String EXTRA_RESTART = "restart"; private static final String EXTRA_RESTART = "restart";
@ -60,76 +60,93 @@ public class RouterService extends Service {
public void onCreate() { public void onCreate() {
State lastState = getSavedState(); State lastState = getSavedState();
setState(State.INIT); setState(State.INIT);
Util.i(this + " onCreate called" + Util.i(this + " onCreate called"
" Saved state is: " + lastState + + " Saved state is: " + lastState
" Current state is: " + _state); + " Current state is: " + _state);
//(new File(getFilesDir(), "wrapper.log")).delete(); //(new File(getFilesDir(), "wrapper.log")).delete();
_myDir = getFilesDir().getAbsolutePath(); _myDir = getFilesDir().getAbsolutePath();
// init other stuff here, delete log, etc.
Init init = new Init(this); Init init = new Init(this);
init.debugStuff();
init.initialize(); init.initialize();
//_apkPath = init.getAPKPath(); //_apkPath = init.getAPKPath();
_statusBar = new StatusBar(this); _statusBar = new StatusBar(this);
// kill any old one... will this work? // Remove stale notification icon.
_statusBar.off(); _statusBar.remove();
_binder = new RouterBinder(this); _binder = new RouterBinder(this);
_handler = new Handler(); _handler = new Handler();
_updater = new Updater(); _updater = new Updater();
if (lastState == State.RUNNING) { if(lastState == State.RUNNING) {
Intent intent = new Intent(this, RouterService.class); Intent intent = new Intent(this, RouterService.class);
intent.putExtra(EXTRA_RESTART, true); intent.putExtra(EXTRA_RESTART, true);
onStartCommand(intent, 12345, 67890); onStartCommand(intent, 12345, 67890);
} else if(lastState == State.MANUAL_QUITTING) {
synchronized(_stateLock) {
setState(State.MANUAL_QUITTED);
stopSelf(); // Die.
}
} }
} }
/** NOT called by system if it restarts us after a crash */ /**
* NOT called by system if it restarts us after a crash
*/
@Override @Override
public int onStartCommand(Intent intent, int flags, int startId) { public int onStartCommand(Intent intent, int flags, int startId) {
Util.i(this + " onStart called" + Util.i(this + " onStart called"
" Intent is: " + intent + + " Intent is: " + intent
" Flags is: " + flags + + " Flags is: " + flags
" ID is: " + startId + + " ID is: " + startId
" Current state is: " + _state); + " Current state is: " + _state);
boolean restart = intent != null && intent.getBooleanExtra(EXTRA_RESTART, false); boolean restart = intent != null && intent.getBooleanExtra(EXTRA_RESTART, false);
if (restart) if(restart) {
Util.i(this + " RESTARTING"); Util.i(this + " RESTARTING");
synchronized (_stateLock) { }
if (_state != State.INIT) synchronized(_stateLock) {
//return START_STICKY; if(_state != State.INIT) //return START_STICKY;
{
return START_NOT_STICKY; return START_NOT_STICKY;
}
_receiver = new I2PReceiver(this); _receiver = new I2PReceiver(this);
if (Util.isConnected(this)) { if(Util.isConnected(this)) {
if (restart) if(restart) {
_statusBar.replace(StatusBar.ICON1, "I2P is restarting"); _statusBar.replace(StatusBar.ICON1, "I2P is restarting");
else } else {
_statusBar.replace(StatusBar.ICON1, "I2P is starting up"); _statusBar.replace(StatusBar.ICON1, "I2P is starting up");
}
setState(State.STARTING); setState(State.STARTING);
_starterThread = new Thread(new Starter()); _starterThread = new Thread(new Starter());
_starterThread.start(); _starterThread.start();
} else { } else {
_statusBar.replace(StatusBar.ICON6, "I2P is waiting for a network connection"); _statusBar.replace(StatusBar.ICON6, "I2P is waiting for a network connection");
setState(State.WAITING); setState(State.WAITING);
_handler.postDelayed(new Waiter(), 10*1000); _handler.postDelayed(new Waiter(), 10 * 1000);
} }
} }
_handler.removeCallbacks(_updater); _handler.removeCallbacks(_updater);
_handler.postDelayed(_updater, 50); _handler.postDelayed(_updater, 50);
if(!restart) {
startForeground(1337, _statusBar.getNote());
}
//return START_STICKY; //return START_STICKY;
return START_NOT_STICKY; return START_NOT_STICKY;
} }
/** maybe this goes away when the receiver can bind to us */ /**
* maybe this goes away when the receiver can bind to us
*/
private class Waiter implements Runnable { private class Waiter implements Runnable {
public void run() { public void run() {
Util.i(MARKER + this + " waiter handler" + Util.i(MARKER + this + " waiter handler"
" Current state is: " + _state); + " Current state is: " + _state);
if (_state == State.WAITING) { if(_state == State.WAITING) {
if (Util.isConnected(RouterService.this)) { if(Util.isConnected(RouterService.this)) {
synchronized (_stateLock) { synchronized(_stateLock) {
if (_state != State.WAITING) if(_state != State.WAITING) {
return; return;
}
_statusBar.replace(StatusBar.ICON1, "Network connected, I2P is starting up"); _statusBar.replace(StatusBar.ICON1, "Network connected, I2P is starting up");
setState(State.STARTING); setState(State.STARTING);
_starterThread = new Thread(new Starter()); _starterThread = new Thread(new Starter());
@ -137,28 +154,173 @@ public class RouterService extends Service {
} }
return; return;
} }
_handler.postDelayed(this, 15*1000); _handler.postDelayed(this, 15 * 1000);
} }
} }
} }
private class Starter implements Runnable { private class Starter implements Runnable {
public void run() { public void run() {
Util.i(MARKER + this + " starter thread" + Util.i(MARKER + this + " starter thread"
" Current state is: " + _state); + " Current state is: " + _state);
//Util.i(MARKER + this + " JBigI speed test started"); //Util.i(MARKER + this + " JBigI speed test started");
//NativeBigInteger.main(null); //NativeBigInteger.main(null);
//Util.i(MARKER + this + " JBigI speed test finished, launching router"); //Util.i(MARKER + this + " JBigI speed test finished, launching router");
// Before we launch, fix up any settings that need to be fixed here.
// This should be done in the core, but as of this writing it isn't!
// Step one. Load the propertites.
Properties props = new OrderedProperties();
Properties oldprops = new OrderedProperties();
String wrapName = _myDir + "/router.config";
try {
InputStream fin = new FileInputStream(new File(wrapName));
DataHelper.loadProps(props, fin);
} catch(IOException ioe) {
// shouldn't happen...
}
oldprops.putAll(props);
// Step two, check for any port settings, and copy for those that are missing.
int UDPinbound;
int UDPinlocal;
int TCPinbound;
int TCPinlocal;
UDPinbound = Integer.parseInt(props.getProperty("i2np.udp.port", "-1"));
UDPinlocal = Integer.parseInt(props.getProperty("i2np.udp.internalPort", "-1"));
TCPinbound = Integer.parseInt(props.getProperty("i2np.ntcp.port", "-1"));
TCPinlocal = Integer.parseInt(props.getProperty("i2np.ntcp.internalPort", "-1"));
boolean hasUDPinbound = UDPinbound != -1;
boolean hasUDPinlocal = UDPinlocal != -1;
boolean hasTCPinbound = TCPinbound != -1;
boolean hasTCPinlocal = TCPinlocal != -1;
// check and clear values based on these:
boolean udp = Boolean.parseBoolean(props.getProperty("i2np.udp.enable", "false"));
boolean tcp = Boolean.parseBoolean(props.getProperty("i2np.ntcp.enable", "false"));
// Fix if both are false.
if(!(udp || tcp)) {
// If both are not on, turn them both on.
props.setProperty("i2np.udp.enable", "true");
props.setProperty("i2np.ntcp.enable", "true");
}
// Fix if we have local but no inbound
if(!hasUDPinbound && hasUDPinlocal) {
// if we got a local port and no external port, set it
hasUDPinbound = true;
UDPinbound = UDPinlocal;
}
if(!hasTCPinbound && hasTCPinlocal) {
// if we got a local port and no external port, set it
hasTCPinbound = true;
TCPinbound = TCPinlocal;
}
boolean anyUDP = hasUDPinbound || hasUDPinlocal;
boolean anyTCP = hasTCPinbound || hasTCPinlocal;
boolean anyport = anyUDP || anyTCP;
if(!anyport) {
// generate one for UDPinbound, and fall thru.
// FIX ME: Possibly not the best but should be OK.
Random generator = new Random(System.currentTimeMillis());
UDPinbound = generator.nextInt(55500) + 10000;
anyUDP = true;
}
// Copy missing port numbers
if(anyUDP && !anyTCP) {
TCPinbound = UDPinbound;
TCPinlocal = UDPinlocal;
}
if(anyTCP && !anyUDP) {
UDPinbound = TCPinbound;
UDPinlocal = TCPinlocal;
}
// reset for a retest.
hasUDPinbound = UDPinbound != -1;
hasUDPinlocal = UDPinlocal != -1;
hasTCPinbound = TCPinbound != -1;
hasTCPinlocal = TCPinlocal != -1;
anyUDP = hasUDPinbound || hasUDPinlocal;
anyTCP = hasTCPinbound || hasTCPinlocal;
boolean checkAnyUDP = anyUDP && udp;
boolean checkAnyTCP = anyTCP && tcp;
// Enable things that need to be enabled.
// Disable anything that needs to be disabled.
if(!checkAnyUDP && !checkAnyTCP) {
// enable the one(s) with values.
if(anyUDP) {
udp = true;
}
if(anyTCP) {
tcp = true;
}
}
if(!udp) {
props.setProperty("i2np.udp.enable", "false");
props.remove("i2np.udp.port");
props.remove("i2np.udp.internalPort");
} else {
props.setProperty("i2np.udp.enable", "true");
if(hasUDPinbound) {
props.setProperty("i2np.udp.port", Integer.toString(UDPinbound));
} else {
props.remove("i2np.udp.port");
}
if(hasUDPinlocal) {
props.setProperty("i2np.udp.internalPort", Integer.toString(UDPinlocal));
} else {
props.remove("i2np.udp.internalPort");
}
}
if(!tcp) {
props.setProperty("i2np.ntcp.enable", "false");
props.remove("i2np.ntcp.port");
props.remove("i2np.ntcp.internalPort");
} else {
props.setProperty("i2np.ntcp.enable", "true");
if(hasTCPinbound) {
props.setProperty("i2np.ntcp.port", Integer.toString(TCPinbound));
} else {
props.remove("i2np.ntcp.port");
}
if(hasTCPinlocal) {
props.setProperty("i2np.ntcp.internalPort", Integer.toString(TCPinlocal));
} else {
props.remove("i2np.ntcp.internalPort");
}
}
// WHEW! Now test for any changes.
if(!props.equals(oldprops)) {
// save fixed properties.
try {
DataHelper.storeProps(props, new File(wrapName));
} catch(IOException ioe) {
// shouldn't happen...
}
}
// _NOW_ launch the router!
RouterLaunch.main(null); RouterLaunch.main(null);
synchronized (_stateLock) { synchronized(_stateLock) {
if (_state != State.STARTING) if(_state != State.STARTING) {
return; return;
}
setState(State.RUNNING); setState(State.RUNNING);
List contexts = RouterContext.listContexts(); List<?> contexts = RouterContext.listContexts();
if ( (contexts == null) || (contexts.isEmpty()) ) if((contexts == null) || (contexts.isEmpty())) {
throw new IllegalStateException("No contexts. This is usually because the router is either starting up or shutting down."); throw new IllegalStateException("No contexts. This is usually because the router is either starting up or shutting down.");
}
_statusBar.replace(StatusBar.ICON2, "I2P is running"); _statusBar.replace(StatusBar.ICON2, "I2P is running");
_context = (RouterContext)contexts.get(0); _context = (RouterContext) contexts.get(0);
_context.router().setKillVMOnEnd(false); _context.router().setKillVMOnEnd(false);
Job loadJob = new LoadClientsJob(_context); Job loadJob = new LoadClientsJob(_context);
_context.jobQueue().addJob(loadJob); _context.jobQueue().addJob(loadJob);
@ -171,17 +333,18 @@ public class RouterService extends Service {
} }
private class Updater implements Runnable { private class Updater implements Runnable {
public void run() { public void run() {
RouterContext ctx = _context; RouterContext ctx = _context;
if (ctx != null && _state == State.RUNNING) { if(ctx != null && _state == State.RUNNING) {
Router router = ctx.router(); Router router = ctx.router();
if (router.isAlive()) if(router.isAlive()) {
updateStatus(ctx); updateStatus(ctx);
}
} }
_handler.postDelayed(this, 15*1000); _handler.postDelayed(this, 15 * 1000);
} }
} }
private boolean _hadTunnels; private boolean _hadTunnels;
private void updateStatus(RouterContext ctx) { private void updateStatus(RouterContext ctx) {
@ -196,62 +359,72 @@ public class RouterService extends Service {
double outBW = ctx.bandwidthLimiter().getSendBps() / 1024; double outBW = ctx.bandwidthLimiter().getSendBps() / 1024;
// control total width // control total width
DecimalFormat fmt; DecimalFormat fmt;
if (inBW >= 1000 || outBW >= 1000) if(inBW >= 1000 || outBW >= 1000) {
fmt = new DecimalFormat("#0"); fmt = new DecimalFormat("#0");
else if (inBW >= 100 || outBW >= 100) } else if(inBW >= 100 || outBW >= 100) {
fmt = new DecimalFormat("#0.0"); fmt = new DecimalFormat("#0.0");
else } else {
fmt = new DecimalFormat("#0.00"); fmt = new DecimalFormat("#0.00");
}
String status = String status =
"I2P " + "I2P "
active + '/' + known + " peers connected"; + active + '/' + known + " peers connected";
String details = String details =
fmt.format(inBW) + '/' + fmt.format(outBW) + " KBps" + fmt.format(inBW) + '/' + fmt.format(outBW) + " KBps"
"; Expl " + inEx + '/' + outEx + + "; Expl " + inEx + '/' + outEx
"; Client " + inCl + '/' + outCl; + "; Client " + inCl + '/' + outCl;
boolean haveTunnels = inCl > 0 && outCl > 0; boolean haveTunnels = inCl > 0 && outCl > 0;
if (haveTunnels != _hadTunnels) { if(haveTunnels != _hadTunnels) {
if (haveTunnels) if(haveTunnels) {
_statusBar.replace(StatusBar.ICON3, "Client tunnels are ready"); _statusBar.replace(StatusBar.ICON3, "Client tunnels are ready");
else } else {
_statusBar.replace(StatusBar.ICON2, "Client tunnels are down"); _statusBar.replace(StatusBar.ICON2, "Client tunnels are down");
}
_hadTunnels = haveTunnels; _hadTunnels = haveTunnels;
} }
_statusBar.update(status, details); _statusBar.update(status, details);
} }
@Override @Override
public IBinder onBind(Intent intent) public IBinder onBind(Intent intent) {
{ Util.i(this + "onBind called"
Util.i(this + "onBind called" + + " Current state is: " + _state);
" Current state is: " + _state);
return _binder; return _binder;
} }
// ******** following methods may be accessed from Activities and Receivers ************ @Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
// ******** following methods may be accessed from Activities and Receivers ************
/** /**
* @returns null if router is not running * @returns null if router is not running
*/ */
public RouterContext getRouterContext() { public RouterContext getRouterContext() {
RouterContext rv = _context; RouterContext rv = _context;
if (rv == null) if(rv == null) {
return null; return null;
if (!rv.router().isAlive()) }
if(!rv.router().isAlive()) {
return null; return null;
if (_state != State.RUNNING && }
_state != State.STOPPING && if(_state != State.RUNNING
_state != State.MANUAL_STOPPING && && _state != State.STOPPING
_state != State.MANUAL_QUITTING && && _state != State.MANUAL_STOPPING
_state != State.NETWORK_STOPPING) && _state != State.MANUAL_QUITTING
&& _state != State.NETWORK_STOPPING) {
return null; return null;
}
return rv; return rv;
} }
/** debug */ /**
* debug
*/
public String getState() { public String getState() {
return _state.toString(); return _state.toString();
} }
@ -261,17 +434,19 @@ public class RouterService extends Service {
} }
/** /**
* Stop and don't restart the router, but keep the service * Stop and don't restart the router, but keep the service
*/ */
public void manualStop() { public void manualStop() {
Util.i("manualStop called" + Util.i("manualStop called"
" Current state is: " + _state); + " Current state is: " + _state);
synchronized (_stateLock) { synchronized(_stateLock) {
if (!canManualStop()) if(!canManualStop()) {
return; return;
if (_state == State.STARTING) }
if(_state == State.STARTING) {
_starterThread.interrupt(); _starterThread.interrupt();
if (_state == State.STARTING || _state == State.RUNNING) { }
if(_state == State.STARTING || _state == State.RUNNING) {
_statusBar.replace(StatusBar.ICON4, "Stopping I2P"); _statusBar.replace(StatusBar.ICON4, "Stopping I2P");
Thread stopperThread = new Thread(new Stopper(State.MANUAL_STOPPING, State.MANUAL_STOPPED)); Thread stopperThread = new Thread(new Stopper(State.MANUAL_STOPPING, State.MANUAL_STOPPED));
stopperThread.start(); stopperThread.start();
@ -280,21 +455,23 @@ public class RouterService extends Service {
} }
/** /**
* Stop the router and kill the service * Stop the router and kill the service
*/ */
public void manualQuit() { public void manualQuit() {
Util.i("manualQuit called" + Util.i("manualQuit called"
" Current state is: " + _state); + " Current state is: " + _state);
synchronized (_stateLock) { synchronized(_stateLock) {
if (!canManualStop()) if(!canManualStop()) {
return; return;
if (_state == State.STARTING) }
if(_state == State.STARTING) {
_starterThread.interrupt(); _starterThread.interrupt();
if (_state == State.STARTING || _state == State.RUNNING) { }
if(_state == State.STARTING || _state == State.RUNNING) {
_statusBar.replace(StatusBar.ICON4, "Stopping I2P"); _statusBar.replace(StatusBar.ICON4, "Stopping I2P");
Thread stopperThread = new Thread(new Stopper(State.MANUAL_QUITTING, State.MANUAL_QUITTED)); Thread stopperThread = new Thread(new Stopper(State.MANUAL_QUITTING, State.MANUAL_QUITTED));
stopperThread.start(); stopperThread.start();
} else if (_state == State.WAITING) { } else if(_state == State.WAITING) {
setState(State.MANUAL_QUITTING); setState(State.MANUAL_QUITTING);
(new FinalShutdownHook()).run(); (new FinalShutdownHook()).run();
} }
@ -302,15 +479,16 @@ public class RouterService extends Service {
} }
/** /**
* Stop and then spin waiting for a network connection, then restart * Stop and then spin waiting for a network connection, then restart
*/ */
public void networkStop() { public void networkStop() {
Util.i("networkStop called" + Util.i("networkStop called"
" Current state is: " + _state); + " Current state is: " + _state);
synchronized (_stateLock) { synchronized(_stateLock) {
if (_state == State.STARTING) if(_state == State.STARTING) {
_starterThread.interrupt(); _starterThread.interrupt();
if (_state == State.STARTING || _state == State.RUNNING) { }
if(_state == State.STARTING || _state == State.RUNNING) {
_statusBar.replace(StatusBar.ICON4, "Network disconnected, stopping I2P"); _statusBar.replace(StatusBar.ICON4, "Network disconnected, stopping I2P");
// don't change state, let the shutdown hook do it // don't change state, let the shutdown hook do it
Thread stopperThread = new Thread(new Stopper(State.NETWORK_STOPPING, State.NETWORK_STOPPING)); Thread stopperThread = new Thread(new Stopper(State.NETWORK_STOPPING, State.NETWORK_STOPPING));
@ -325,11 +503,12 @@ public class RouterService extends Service {
} }
public void manualStart() { public void manualStart() {
Util.i("restart called" + Util.i("restart called"
" Current state is: " + _state); + " Current state is: " + _state);
synchronized (_stateLock) { synchronized(_stateLock) {
if (!canManualStart()) if(!canManualStart()) {
return; return;
}
_statusBar.replace(StatusBar.ICON1, "I2P is starting up"); _statusBar.replace(StatusBar.ICON1, "I2P is starting up");
setState(State.STARTING); setState(State.STARTING);
_starterThread = new Thread(new Starter()); _starterThread = new Thread(new Starter());
@ -338,36 +517,36 @@ public class RouterService extends Service {
} }
// ******** end methods accessed from Activities and Receivers ************ // ******** end methods accessed from Activities and Receivers ************
/** /**
* Turn off the status bar. * Turn off the status bar. Unregister the receiver. If we were running,
* Unregister the receiver. * fire up the Stopper thread.
* If we were running, fire up the Stopper thread.
*/ */
@Override @Override
public void onDestroy() { public void onDestroy() {
Util.i("onDestroy called" + Util.i("onDestroy called"
" Current state is: " + _state); + " Current state is: " + _state);
_handler.removeCallbacks(_updater); _handler.removeCallbacks(_updater);
_statusBar.off(); _statusBar.remove();
I2PReceiver rcvr = _receiver; I2PReceiver rcvr = _receiver;
if (rcvr != null) { if(rcvr != null) {
synchronized(rcvr) { synchronized(rcvr) {
try { try {
// throws if not registered // throws if not registered
unregisterReceiver(rcvr); unregisterReceiver(rcvr);
} catch (IllegalArgumentException iae) {} } catch(IllegalArgumentException iae) {
}
//rcvr.unbindRouter(); //rcvr.unbindRouter();
//_receiver = null; //_receiver = null;
} }
} }
synchronized (_stateLock) { synchronized(_stateLock) {
if (_state == State.STARTING) if(_state == State.STARTING) {
_starterThread.interrupt(); _starterThread.interrupt();
if (_state == State.STARTING || _state == State.RUNNING) { }
// should this be in a thread? if(_state == State.STARTING || _state == State.RUNNING) {
// should this be in a thread?
_statusBar.replace(StatusBar.ICON5, "I2P is shutting down"); _statusBar.replace(StatusBar.ICON5, "I2P is shutting down");
Thread stopperThread = new Thread(new Stopper(State.STOPPING, State.STOPPED)); Thread stopperThread = new Thread(new Stopper(State.STOPPING, State.STOPPED));
stopperThread.start(); stopperThread.start();
@ -376,16 +555,17 @@ public class RouterService extends Service {
} }
/** /**
* Transition to the next state. * Transition to the next state. If we still have a context, shut down the
* If we still have a context, shut down the router. * router. Turn off the status bar. Then transition to the stop state.
* Turn off the status bar.
* Then transition to the stop state.
*/ */
private class Stopper implements Runnable { private class Stopper implements Runnable {
private final State nextState; private final State nextState;
private final State stopState; private final State stopState;
/** call holding statelock */ /**
* call holding statelock
*/
public Stopper(State next, State stop) { public Stopper(State next, State stop) {
nextState = next; nextState = next;
stopState = stop; stopState = stop;
@ -393,89 +573,103 @@ public class RouterService extends Service {
} }
public void run() { public void run() {
Util.i(MARKER + this + " stopper thread" + try {
" Current state is: " + _state); Util.i(MARKER + this + " stopper thread"
RouterContext ctx = _context; + " Current state is: " + _state);
if (ctx != null) RouterContext ctx = _context;
ctx.router().shutdown(Router.EXIT_HARD); if(ctx != null) {
_statusBar.off(); ctx.router().shutdown(Router.EXIT_HARD);
Util.i("********** Router shutdown complete"); }
synchronized (_stateLock) { _statusBar.remove();
if (_state == nextState) Util.i("********** Router shutdown complete");
setState(stopState); synchronized(_stateLock) {
if(_state == nextState) {
setState(stopState);
}
}
} finally {
stopForeground(true);
_statusBar.remove();
} }
} }
} }
/** /**
* First (early) hook. * First (early) hook. Update the status bar. Unregister the receiver.
* Update the status bar.
* Unregister the receiver.
*/ */
private class ShutdownHook implements Runnable { private class ShutdownHook implements Runnable {
public void run() { public void run() {
Util.i(this + " shutdown hook" + Util.i(this + " shutdown hook"
" Current state is: " + _state); + " Current state is: " + _state);
_statusBar.replace(StatusBar.ICON5, "I2P is shutting down"); _statusBar.replace(StatusBar.ICON5, "I2P is shutting down");
I2PReceiver rcvr = _receiver; I2PReceiver rcvr = _receiver;
if (rcvr != null) { if(rcvr != null) {
synchronized(rcvr) { synchronized(rcvr) {
try { try {
// throws if not registered // throws if not registered
unregisterReceiver(rcvr); unregisterReceiver(rcvr);
} catch (IllegalArgumentException iae) {} } catch(IllegalArgumentException iae) {
}
//rcvr.unbindRouter(); //rcvr.unbindRouter();
//_receiver = null; //_receiver = null;
} }
} }
synchronized (_stateLock) { synchronized(_stateLock) {
// null out to release the memory // null out to release the memory
_context = null; _context = null;
if (_state == State.STARTING) if(_state == State.STARTING) {
_starterThread.interrupt(); _starterThread.interrupt();
if (_state == State.WAITING || _state == State.STARTING || }
_state == State.RUNNING) if(_state == State.WAITING || _state == State.STARTING
|| _state == State.RUNNING) {
setState(State.STOPPING); setState(State.STOPPING);
}
} }
} }
} }
/** /**
* Second (late) hook. * Second (late) hook. Turn off the status bar. Null out the context. If we
* Turn off the status bar. * were stopped manually, do nothing. If we were stopped because of no
* Null out the context. * network, start the waiter thread. If it stopped of unknown causes or from
* If we were stopped manually, do nothing. * manualQuit(), kill the Service.
* If we were stopped because of no network, start the waiter thread.
* If it stopped of unknown causes or from manualQuit(), kill the Service.
*/ */
private class FinalShutdownHook implements Runnable { private class FinalShutdownHook implements Runnable {
public void run() {
Util.i(this + " final shutdown hook" +
" Current state is: " + _state);
_statusBar.off();
//I2PReceiver rcvr = _receiver;
synchronized (_stateLock) { public void run() {
// null out to release the memory try {
_context = null; Util.i(this + " final shutdown hook"
Runtime.getRuntime().gc(); + " Current state is: " + _state);
if (_state == State.STARTING) //I2PReceiver rcvr = _receiver;
_starterThread.interrupt();
if (_state == State.MANUAL_STOPPING) { synchronized(_stateLock) {
setState(State.MANUAL_STOPPED); // null out to release the memory
} else if (_state == State.NETWORK_STOPPING) { _context = null;
// start waiter handler Runtime.getRuntime().gc();
setState(State.WAITING); if(_state == State.STARTING) {
_handler.postDelayed(new Waiter(), 10*1000); _starterThread.interrupt();
} else if (_state == State.STARTING || _state == State.RUNNING || }
_state == State.STOPPING) { if(_state == State.MANUAL_STOPPING) {
Util.i(this + " died of unknown causes"); setState(State.MANUAL_STOPPED);
setState(State.STOPPED); } else if(_state == State.NETWORK_STOPPING) {
stopSelf(); // start waiter handler
} else if (_state == State.MANUAL_QUITTING) { setState(State.WAITING);
setState(State.MANUAL_QUITTED); _handler.postDelayed(new Waiter(), 10 * 1000);
stopSelf(); } else if(_state == State.STARTING || _state == State.RUNNING
|| _state == State.STOPPING) {
Util.i(this + " died of unknown causes");
setState(State.STOPPED);
stopForeground(true);
stopSelf();
} else if(_state == State.MANUAL_QUITTING) {
setState(State.MANUAL_QUITTED);
stopForeground(true);
stopSelf();
}
} }
} finally {
_statusBar.remove();
} }
} }
} }
@ -483,9 +677,10 @@ public class RouterService extends Service {
private State getSavedState() { private State getSavedState() {
SharedPreferences prefs = getSharedPreferences(SHARED_PREFS, 0); SharedPreferences prefs = getSharedPreferences(SHARED_PREFS, 0);
String stateString = prefs.getString(LAST_STATE, State.INIT.toString()); String stateString = prefs.getString(LAST_STATE, State.INIT.toString());
for (State s : State.values()) { for(State s : State.values()) {
if (s.toString().equals(stateString)) if(s.toString().equals(stateString)) {
return s; return s;
}
} }
return State.INIT; return State.INIT;
} }
@ -495,7 +690,9 @@ public class RouterService extends Service {
saveState(); saveState();
} }
/** @return success */ /**
* @return success
*/
private boolean saveState() { private boolean saveState() {
SharedPreferences prefs = getSharedPreferences(SHARED_PREFS, 0); SharedPreferences prefs = getSharedPreferences(SHARED_PREFS, 0);
SharedPreferences.Editor edit = prefs.edit(); SharedPreferences.Editor edit = prefs.edit();

View File

@ -5,9 +5,6 @@ import android.app.NotificationManager;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import java.lang.Thread.UncaughtExceptionHandler;
import net.i2p.android.router.R; import net.i2p.android.router.R;
import net.i2p.android.router.activity.MainActivity; import net.i2p.android.router.activity.MainActivity;
@ -18,7 +15,7 @@ class StatusBar {
private final Notification notif; private final Notification notif;
private final NotificationManager mgr; private final NotificationManager mgr;
private static final int ID = 1; private static final int ID = 1337;
public static final int ICON1 = R.drawable.ic_launcher_itoopie_300; public static final int ICON1 = R.drawable.ic_launcher_itoopie_300;
public static final int ICON2 = R.drawable.ic_launcher_itoopie_330; public static final int ICON2 = R.drawable.ic_launcher_itoopie_330;
@ -38,7 +35,9 @@ class StatusBar {
String text = "Starting I2P"; String text = "Starting I2P";
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
notif = new Notification(icon, text, now); notif = new Notification(icon, text, now);
notif.flags |= Notification.FLAG_ONGOING_EVENT | Notification.FLAG_NO_CLEAR; notif.flags |= Notification.FLAG_ONLY_ALERT_ONCE;
// notif.flags |= Notification.FLAG_ONGOING_EVENT;
notif.flags |= Notification.FLAG_NO_CLEAR;
intent = new Intent(ctx, MainActivity.class); intent = new Intent(ctx, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
} }
@ -63,6 +62,10 @@ class StatusBar {
} }
public void off() { public void off() {
//mgr.cancel(ID);
}
public void remove() {
mgr.cancel(ID); mgr.cancel(ID);
} }
@ -86,8 +89,12 @@ class StatusBar {
} catch (Throwable ex) {} } catch (Throwable ex) {}
} }
System.err.println("In CrashHandler " + e); System.err.println("In CrashHandler " + e);
e.printStackTrace(); e.printStackTrace(System.err);
defaultUEH.uncaughtException(t, e); defaultUEH.uncaughtException(t, e);
} }
} }
public Notification getNote() {
return notif;
}
} }

View File

@ -4,10 +4,9 @@ import android.content.ContentResolver;
import android.content.ContentValues; import android.content.ContentValues;
import android.content.Context; import android.content.Context;
import android.net.Uri; import android.net.Uri;
import java.io.IOException;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@ -15,9 +14,7 @@ import java.util.Comparator;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import net.i2p.android.router.provider.CacheProvider; import net.i2p.android.router.provider.CacheProvider;
import net.i2p.android.router.util.Util;
/** /**
* A least recently used cache with a max number of entries * A least recently used cache with a max number of entries
@ -62,7 +59,7 @@ public class AppCache {
private AppCache(Context ctx) { private AppCache(Context ctx) {
_cacheDir = new File(ctx.getCacheDir(), DIR_NAME); _cacheDir = new File(ctx.getCacheDir(), DIR_NAME);
_cacheDir.mkdir(); _cacheDir.mkdir();
Util.e("AppCache cache dir " + _cacheDir); Util.d("AppCache cache dir " + _cacheDir);
_resolver = ctx.getContentResolver(); _resolver = ctx.getContentResolver();
_cache = new LHM(MAX_FILES); _cache = new LHM(MAX_FILES);
initialize(); initialize();
@ -122,7 +119,7 @@ public class AppCache {
public Uri getCacheUri(Uri key) { public Uri getCacheUri(Uri key) {
int hash = toHash(key); int hash = toHash(key);
// poke the LRU // poke the LRU
Object present = null; Object present;
synchronized(_cache) { synchronized(_cache) {
present = _cache.get(Integer.valueOf(hash)); present = _cache.get(Integer.valueOf(hash));
} }
@ -145,9 +142,9 @@ public class AppCache {
private void initialize() { private void initialize() {
_totalSize = 0; _totalSize = 0;
List<File> fileList = new ArrayList(MAX_FILES); List<File> fileList = new ArrayList<File>(MAX_FILES);
long total = enumerate(_cacheDir, fileList); long total = enumerate(_cacheDir, fileList);
Util.e("AppCache found " + fileList.size() + " files totalling " + total + " bytes"); Util.d("AppCache found " + fileList.size() + " files totalling " + total + " bytes");
Collections.sort(fileList, new FileComparator()); Collections.sort(fileList, new FileComparator());
// oldest first, delete if too big or too old, else add to LHM // oldest first, delete if too big or too old, else add to LHM
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
@ -160,7 +157,7 @@ public class AppCache {
// TODO insertContent // TODO insertContent
} }
} }
Util.e("after init " + _cache.size() + " files totalling " + total + " bytes"); Util.d("after init " + _cache.size() + " files totalling " + total + " bytes");
} }
/** oldest first */ /** oldest first */
@ -201,7 +198,7 @@ public class AppCache {
_cache.put(Integer.valueOf(hash), DUMMY); _cache.put(Integer.valueOf(hash), DUMMY);
} }
} catch (IllegalArgumentException iae) { } catch (IllegalArgumentException iae) {
Util.e("Huh bad file?" + iae); Util.d("Huh bad file?" + iae);
f.delete(); f.delete();
} }
} }
@ -285,6 +282,7 @@ public class AppCache {
* on remove. * on remove.
*/ */
private static class LHM extends LinkedHashMap<Integer, Object> { private static class LHM extends LinkedHashMap<Integer, Object> {
private static final long serialVersionUID = 1L;
private final int _max; private final int _max;
public LHM(int max) { public LHM(int max) {
@ -312,7 +310,7 @@ public class AppCache {
if (f.exists()) { if (f.exists()) {
_totalSize -= f.length(); _totalSize -= f.length();
f.delete(); f.delete();
Util.e("AppCache deleted file " + f); Util.d("AppCache deleted file " + f);
} }
} }
return rv; return rv;

View File

@ -6,7 +6,6 @@ import android.content.pm.PackageManager;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.NetworkInfo; import android.net.NetworkInfo;
import android.os.Build; import android.os.Build;
import net.i2p.I2PAppContext; import net.i2p.I2PAppContext;
import net.i2p.util.Log; import net.i2p.util.Log;

View File

@ -6,10 +6,8 @@ package net.i2p.util;
*/ */
import java.io.File; import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.List;
import java.util.Queue; import java.util.Queue;
/** /**
@ -28,7 +26,7 @@ class LogWriter implements Runnable {
private LogManager _manager; private LogManager _manager;
private boolean _write; private boolean _write;
private LogWriter() { // nop private LogWriter() { // nop
} }
@ -39,7 +37,7 @@ class LogWriter implements Runnable {
public void stopWriting() { public void stopWriting() {
_write = false; _write = false;
} }
public void run() { public void run() {
_write = true; _write = true;
try { try {
@ -50,7 +48,7 @@ class LogWriter implements Runnable {
} }
} catch (Exception e) { } catch (Exception e) {
System.err.println("Error writing the logs: " + e.getMessage()); System.err.println("Error writing the logs: " + e.getMessage());
e.printStackTrace(); e.printStackTrace(System.err);
} }
} }
@ -74,12 +72,12 @@ class LogWriter implements Runnable {
} }
} }
} catch (Throwable t) { } catch (Throwable t) {
t.printStackTrace(); t.printStackTrace(System.err);
} finally { } finally {
if (shouldWait) { if (shouldWait) {
try { try {
synchronized (this) { synchronized (this) {
this.wait(10*1000); this.wait(10*1000);
} }
} catch (InterruptedException ie) { // nop } catch (InterruptedException ie) { // nop
} }
@ -90,7 +88,7 @@ class LogWriter implements Runnable {
public String currentFile() { public String currentFile() {
return _currentFile != null ? _currentFile.getAbsolutePath() : "uninitialized"; return _currentFile != null ? _currentFile.getAbsolutePath() : "uninitialized";
} }
private void rereadConfig() { private void rereadConfig() {
long now = Clock.getInstance().now(); long now = Clock.getInstance().now();
if (now - _lastReadConfig > CONFIG_READ_ITERVAL) { if (now - _lastReadConfig > CONFIG_READ_ITERVAL) {
@ -122,7 +120,7 @@ class LogWriter implements Runnable {
private static final String ANDROID_LOG_TAG = "I2P"; private static final String ANDROID_LOG_TAG = "I2P";
public void log(int priority, Class src, String name, String threadName, String msg) { public void log(int priority, Class<?> src, String name, String threadName, String msg) {
if (src != null) { if (src != null) {
String tag = src.getName(); String tag = src.getName();
int dot = tag.lastIndexOf("."); int dot = tag.lastIndexOf(".");
@ -143,7 +141,7 @@ class LogWriter implements Runnable {
'[' + threadName + "] " + msg); '[' + threadName + "] " + msg);
} }
public void log(int priority, Class src, String name, String threadName, String msg, Throwable t) { public void log(int priority, Class<?> src, String name, String threadName, String msg, Throwable t) {
if (src != null) { if (src != null) {
String tag = src.getName(); String tag = src.getName();
int dot = tag.lastIndexOf("."); int dot = tag.lastIndexOf(".");
@ -181,16 +179,4 @@ class LogWriter implements Runnable {
return android.util.Log.ERROR; return android.util.Log.ERROR;
} }
} }
private static final String replace(String pattern, int num) {
char c[] = pattern.toCharArray();
StringBuffer buf = new StringBuffer();
for (int i = 0; i < c.length; i++) {
if ( (c[i] != '#') && (c[i] != '@') )
buf.append(c[i]);
else
buf.append(num);
}
return buf.toString();
}
} }

View File

@ -7,6 +7,7 @@ import java.io.File;
* @since 0.8.7 * @since 0.8.7
*/ */
public class SecureDirectory extends File { public class SecureDirectory extends File {
private static final long serialVersionUID = 1L;
public SecureDirectory(String pathname) { public SecureDirectory(String pathname) {
super(pathname); super(pathname);

View File

@ -7,6 +7,7 @@ import java.io.File;
* @since 0.8.7 * @since 0.8.7
*/ */
public class SecureFile extends SecureDirectory { public class SecureFile extends SecureDirectory {
private static final long serialVersionUID = 1L;
public SecureFile(String pathname) { public SecureFile(String pathname) {
super(pathname); super(pathname);

View File

@ -4,8 +4,6 @@ import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import net.i2p.I2PAppContext;
/** /**
* setXXX() not available until API level 9 (Platform Version 2.3) * setXXX() not available until API level 9 (Platform Version 2.3)
* @since 0.8.7 * @since 0.8.7