Compare commits

...

104 Commits

Author SHA1 Message Date
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
zzz
abe20c95d0 - Enable NTP based on SDK version
- Disable SSL reseed (temp until merge)
- Update release notes
- Restrict addressbook to only hosts.txt file
2012-07-30 21:59:15 +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
zzz
52a60b37e2 handle core versions without the 3rd digit 2012-06-29 12:43:09 +00:00
zzz
adb5c56f26 disable upnp again 2011-07-10 13:45:25 +00:00
zzz
177ac2e3a1 - Addressbook message tweak
- Tweak log levels
2011-07-05 13:07:03 +00:00
zzz
1219725e6a - Notification icon rotations
- Clean up debug text on main screen
- Move most logging from System.err.println to Util
- Stub out HTTP auth handler
- Don't restart Peers page on orientation change
- Add inbound/outbound arrows, not loaded yet
- Tweak log levels
2011-07-04 16:15:45 +00:00
88 changed files with 3537 additions and 1378 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/
/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 = tr_TR: tr
[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"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="net.i2p.android.router"
android.versionCode="4208704"
android.versionName="0.8.7-4_b1-API8"
android:installLocation="preferExternal"
android.versionCode="0"
android.versionName="0.0.0-0_b0-API8"
android:installLocation="auto"
>
<uses-permission android:name="android.permission.INTERNET" />
<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"
android:theme="@style/Theme.AppCompat"
android:icon="@drawable/ic_launcher_itoopie" >
<service android:name=".service.RouterService"
android:label="@string/app_name"
@ -20,7 +22,6 @@
<activity android:name=".activity.MainActivity"
android:label="@string/app_name"
android:icon="@drawable/ic_launcher_itoopie"
android.theme="@android:style/Theme.NoTitleBar"
android:launchMode="singleTop" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@ -29,21 +30,17 @@
</activity>
<activity android:name=".activity.NewsActivity"
android:label="I2P News"
android:configChanges="orientation|keyboardHidden"
android.theme="@android:style/Theme.NoTitleBar" >
android:configChanges="orientation|keyboardHidden" >
</activity>
<activity android:name=".activity.TextResourceActivity"
android:label="I2P Information"
android.theme="@android:style/Theme.NoTitleBar" >
android:label="I2P Information" >
</activity>
<activity android:name=".activity.LicenseActivity"
android:label="I2P License Information"
android.theme="@android:style/Theme.NoTitleBar" >
android:label="I2P License Information" >
</activity>
<activity android:name=".activity.WebActivity"
android:label="I2P Web Browser"
android:configChanges="orientation|keyboardHidden"
android.theme="@android:style/Theme.NoTitleBar" >
android:configChanges="orientation|keyboardHidden" >
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
@ -53,22 +50,23 @@
</activity>
<activity android:name=".activity.SettingsActivity"
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" >
</activity>
<activity android:name=".activity.AddressbookActivity"
android:label="I2P Address Book"
android.theme="@android:style/Theme.NoTitleBar"
android:label="Addressbook"
android:launchMode="singleTop" >
</activity>
<activity android:name=".activity.LogActivity"
android:label="I2P Logs"
android.theme="@android:style/Theme.NoTitleBar" >
android:label="I2P Logs" >
</activity>
<activity android:name=".activity.PeersActivity"
android:label="I2P Peers and Transport Status"
android.theme="@android:style/Theme.NoTitleBar"
android:configChanges="orientation|keyboardHidden"
android:launchMode="singleTop" >
</activity>
</application>
</manifest>
</manifest>

View File

@ -1,73 +1,111 @@
These instructions are for a recent Android SDK (1.6 or later).
These instructions were last updated for SDK Tools Version 11 with
SDK Platform-tools Version 5, June 2011.
These instructions are for a recent Android SDK (Rev 20 or better) on Linux.
Windows building is not currently supported.
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,
or else add i2psrc=/path/to/source in the local.properties file.
=====================
#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_86/tools/
Dependencies:
- 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:
../android-sdk-linux_86/tools/android &
../android-sdk-linux/tools/android &
# now go to the available packages tab, check the box and click refresh,
# and download an SDK Platform
# Since I2P is configured to run on 1.1 or higher
# (API 2) download that one. Otherwise you must change the
# target in default.properties from android-2 to andriod-x
# Since I2P is targeted at 4.3 (API 18)
# download at least that one. Otherwise you must change the
# target in project.properties from android-18 to andriod-x
# 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
# "Android SDK Platform-Tools" package from the GUI updater.
# create a file local.properties with the following line (without the leading # of course):
# sdk.dir=/path/to/your/android-sdk-linux_86
# The old property was sdk-location=/path/to/your/android-sdk-linux_86
# but it changed in more recent tools.
# create a file local.properties with the following line (without the leading # of course),
# do NOT use a relative path
# sdk.dir=/path/to/your/android-sdk-linux
# 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.
# 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)
../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)...
# Run the debugger to ensure it is making progress
# -no-boot-anim for faster boot
# -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_86/tools/emulator -avd i2p &
# -no-boot-anim for faster boot
# -dns-server 8.8.8.8 if the router can't reseed
# ../android-sdk-linux/tools/emulator -avd i2p -no-boot-anim -dns-server 8.8.8.8 &
../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 -
# Stop ddms, unplug the phone, do the following,
# then plug in the phone, then start ddms
# Stop ddms, unplug the device, do the following,
# then plug in the device, then start ddms
adb kill-server
sudo adb start-server
adb devices
#then wait a couple minutes until the emulator is up
#then install the I2P app
ant install
# then wait a couple minutes until the emulator or device is up
# compile and install for a release
ant release
ant installr
#then run the debugger
../android-sdk-linux_86/tools/ddms &
# or compile and install for a debug version
ant debug
ant installd
#to rebuild and reinstall to emulator or phone:
ant reinstall
# then run the debugger
../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
../android-sdk-linux_86/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 shell
../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 -d install Development.apk

407
build.xml
View File

@ -1,372 +1,83 @@
<?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">
<!-- 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
Control Systems. -->
<property file="local.properties"/>
It contains the path to the SDK. It should *NOT* be checked into
Version Control Systems. -->
<property file="local.properties" />
<!-- The build.properties file can be created by you and is never touched
by the 'android' tool. This is the place to change some of the default property values
used by the Ant rules.
<!-- 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:
application-package
the name of your application package as defined in the manifest. Used by the
'uninstall' rule.
source-folder
the name of the source folder. Default is 'src'.
out-folder
the name of the output folder. Default is 'bin'.
source.dir
The name of the source directory. Default is 'src'.
out.dir
The name of the output directory. Default is 'bin'.
Properties related to the SDK location or the project target should be updated
using the 'android' tool with the 'update' action.
For other overridable properties, look at the beginning of the rules
files in the SDK, at tools/ant/build.xml
This file is an integral part of the build system for your application and
should be checked in in Version Control Systems.
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="build.properties"/>
<!-- set the old name to the new name -->
<property name="sdk-location" value="${sdk.dir}" />
<property file="ant.properties" />
<!-- The default.properties file is created and updated by the 'android' 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"/>
<!-- The project.properties file is created and updated by the 'android'
tool, as well as ADT.
<!-- Custom Android task to deal with the project target, and import the proper rules.
This requires ant 1.6.0 or above. -->
<path id="android.antlibs">
<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>
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).
<taskdef name="setup"
classname="com.android.ant.SetupTask"
classpathref="android.antlibs"/>
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" />
<!-- Execute the Android Setup task that will setup some properties specific to the target,
and import the rules files.
To customize the rules, copy/paste them below the task, and disable import by setting
the import attribute to false:
<setup import="false" />
This will ensure that the properties are setup correctly but that your customized
targets are used.
-->
<setup import="true" />
<!-- 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"
/>
<!--
================================================================================
New I2P rules
================================================================================
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" />
<!-- overrides of those in main_rules.xml -->
<!-- Import the actual build file.
<target name="-pre-build" depends="findI2PSource, copy-i2p-resources, incrementBuild" >
<!-- 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>
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.
<target name="-pre-compile" depends="buildrouter" />
<target name="-post-compile" depends="hackcleanup, jbigi" />
<!-- new rules -->
<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/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/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
================================================================================
***********************
****** 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"
-->
<!-- not necessary to copy if setup import="true" -->
<!--
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>
<!-- version-tag: 1 -->
<import file="${sdk.dir}/tools/ant/build.xml" />
</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.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

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_height="fill_parent"
android:fillViewport="true"
android:padding="10px"
android:scrollbarStyle="outsideInset"
>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@drawable/movie_wallpaper"
>
<ImageView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:src="@drawable/i2plogo"
/>
<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/website_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Web Site\n(non-anon)"
/>
<Button
android:id="@+id/faq_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="FAQ\n(non-anon)"
/>
<Button
android:id="@+id/welcome_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Welcome\nPage"
/>
</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/news_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="News"
/>
<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
<ImageView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:src="@drawable/i2plogo" />
<TextView
android:id="@+id/textView4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/label_statistics"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="@+id/main_status_text"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/label_main_controls"
android:textAppearance="?android:attr/textAppearanceLarge" />
<Button
android:id="@+id/router_start_button"
android:layout_width="match_parent"
android:layout_height="68dp"
android:text="@string/action_router_start"
android:drawableLeft="@drawable/start_router_icon" />
<Button
android:id="@+id/router_quit_button"
android:layout_width="match_parent"
android:layout_height="68dp"
android:text="@string/action_router_stop"
android:drawableLeft="@drawable/stop_router_icon" />
<!--
<Button
android:id="@+id/router_stop_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="OLD STOP"
/>
<Button
android:id="@+id/router_quit_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Stop Router"
/>
</LinearLayout>
<TextView
android:id="@+id/main_status_text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text=""
/>
android:drawableLeft="@drawable/stop_router_icon" />
-->
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/label_tools"
android:textAppearance="?android:attr/textAppearanceMedium" />
<Button
android:id="@+id/addressbook_button"
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>
</ScrollView>

View File

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

View File

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

View File

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

View File

@ -3,18 +3,18 @@
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10dp"
>
<TextView
<TextView
android:id="@+id/browser_status"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:text="Latest I2P News"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/label_news_status"
/>
<WebView
<WebView
android:id="@+id/browser_webview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</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">
<item android:title="Start Router"
<item android:title="@string/action_router_start"
android:id="@+id/menu_start"
android:icon="@drawable/ic_menu_play_clip" >
</item>
<item android:title="Stop Router"
<item android:title="@string/action_router_stop"
android:id="@+id/menu_stop"
android:icon="@android:drawable/ic_menu_close_clear_cancel" >
</item>
<item android:title="Address Book"
<item android:title="@string/label_addressbook"
android:id="@+id/menu_addressbook"
android:icon="@drawable/ic_menu_friendslist" >
</item>
<item android:title="Reload"
<item android:title="@string/action_reload"
android:id="@+id/menu_reload"
android:icon="@drawable/ic_menu_refresh" >
</item>
<item android:title="I2P Home"
<item android:title="@string/label_home"
android:id="@+id/menu_home"
android:icon="@drawable/ic_menu_home" >
</item>
<item android:title="Settings"
<item android:title="@string/menu_settings"
android:id="@+id/menu_settings"
android:icon="@android:drawable/ic_menu_preferences" >
</item>

View File

@ -2,23 +2,23 @@
tunnel.0.name=I2P HTTP Proxy
tunnel.0.description=HTTP proxy for browsing eepsites and the web
tunnel.0.type=httpclient
tunnel.0.sharedClient=true
tunnel.0.sharedClient=false
tunnel.0.interface=127.0.0.1
tunnel.0.listenPort=4444
tunnel.0.proxyList=false.i2p
tunnel.0.i2cpHost=127.0.0.1
tunnel.0.i2cpPort=7654
tunnel.0.option.inbound.nickname=shared clients
tunnel.0.option.outbound.nickname=shared clients
tunnel.0.option.inbound.nickname=I2P HTTP Proxy
tunnel.0.option.outbound.nickname=I2P HTTP Proxy
#tunnel.0.option.i2cp.delayOpen=true
tunnel.0.option.i2cp.reduceIdleTime=600000
tunnel.0.option.i2cp.reduceOnIdle=true
tunnel.0.option.i2cp.reduceQuantity=1
tunnel.0.option.i2p.streaming.connectDelay=1000
tunnel.0.option.inbound.length=1
tunnel.0.option.inbound.lengthVariance=1
tunnel.0.option.outbound.length=1
tunnel.0.option.outbound.lengthVariance=1
tunnel.0.option.inbound.length=2
tunnel.0.option.inbound.lengthVariance=0
tunnel.0.option.outbound.length=2
tunnel.0.option.outbound.lengthVariance=0
tunnel.0.startOnLoad=true
# irc
@ -28,7 +28,7 @@ tunnel.1.type=ircclient
tunnel.1.sharedClient=true
tunnel.1.interface=127.0.0.1
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.i2cpPort=7654
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.reduceQuantity=1
tunnel.1.option.i2p.streaming.connectDelay=1000
tunnel.1.option.inbound.length=1
tunnel.1.option.inbound.lengthVariance=1
tunnel.1.option.outbound.length=1
tunnel.1.option.outbound.lengthVariance=1
tunnel.1.option.inbound.length=2
tunnel.1.option.inbound.lengthVariance=0
tunnel.1.option.outbound.length=2
tunnel.1.option.outbound.lengthVariance=0
tunnel.1.startOnLoad=true
# irc
@ -61,10 +61,10 @@ tunnel.2.option.i2cp.reduceIdleTime=600000
tunnel.2.option.i2cp.reduceOnIdle=true
tunnel.2.option.i2cp.reduceQuantity=1
tunnel.2.option.i2p.streaming.connectDelay=1000
tunnel.2.option.inbound.length=1
tunnel.2.option.inbound.lengthVariance=1
tunnel.2.option.outbound.length=1
tunnel.2.option.outbound.lengthVariance=1
tunnel.2.option.inbound.length=2
tunnel.2.option.inbound.lengthVariance=0
tunnel.2.option.outbound.length=2
tunnel.2.option.outbound.lengthVariance=0
tunnel.2.startOnLoad=true
# irc
@ -84,8 +84,31 @@ tunnel.3.option.i2cp.reduceIdleTime=600000
tunnel.3.option.i2cp.reduceOnIdle=true
tunnel.3.option.i2cp.reduceQuantity=1
tunnel.3.option.i2p.streaming.connectDelay=1000
tunnel.3.option.inbound.length=1
tunnel.3.option.inbound.lengthVariance=1
tunnel.3.option.outbound.length=1
tunnel.3.option.outbound.lengthVariance=1
tunnel.3.option.inbound.length=2
tunnel.3.option.inbound.lengthVariance=0
tunnel.3.option.outbound.length=2
tunnel.3.option.outbound.lengthVariance=0
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.dateFormat=MM/dd HH:mm:ss.SSS
logger.defaultLevel=INFO
logger.defaultLevel=ERROR
logger.displayOnScreen=true
logger.logFileSize=64k
logger.logRotationLimit=2
logger.minimumOnScreenLevel=WARN
logger.record.net.i2p.crypto=WARN
logger.record.net.i2p.router.InNetMessagePool=WARN
logger.record.net.i2p.router.Router=INFO
logger.record.net.i2p.router.Shitlist=WARN
logger.record.net.i2p.router.networkdb=WARN
logger.record.net.i2p.router.peermanager=WARN
logger.record.net.i2p.router.peermanager.ProfileOrganizer=WARN
logger.record.net.i2p.router.transport=WARN
logger.minimumOnScreenLevel=ERROR
logger.record.net.i2p.crypto=ERROR
logger.record.net.i2p.router.InNetMessagePool=ERROR
logger.record.net.i2p.router.Router=ERROR
logger.record.net.i2p.router.Shitlist=ERROR
logger.record.net.i2p.router.networkdb=ERROR
logger.record.net.i2p.router.peermanager=ERROR
logger.record.net.i2p.router.peermanager.ProfileOrganizer=ERROR
logger.record.net.i2p.router.transport=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.util.I2PThread=ERROR
logger.record.net.i2p.util.LogManager=WARN
logger.record.net.i2p.util.LogWriter=WARN
logger.record.net.i2p.util.NativeBigInteger=DEBUG
logger.record.net.org.cybergarage.util.Debug=DEBUG
logger.record.net.i2p.util.LogManager=ERROR
logger.record.net.i2p.util.LogWriter=ERROR
logger.record.net.i2p.util.NativeBigInteger=ERROR
logger.record.net.org.cybergarage.util.Debug=ERROR

View File

@ -1,22 +1,20 @@
******* Please read all of the following *******
This is the first alpha release of the I2P Android app.
This is an alpha release of the I2P Android app.
WARNING - This is ALPHA SOFTWARE. It may crash your phone. Do not rely upon it for strong anonymity. Tunnels may be as short as one hop. There may be serious security holes in the app.
Minimum Android OS is 2.2 (API 8). The app is only tested on the Motorola Droid. It uses a lot of RAM. You need at least 256 MB of RAM. 512 should be much better.
Minimum Android OS is 2.2 (API 8). It uses a lot of RAM. You need at least 256 MB of RAM. 512 should be much better.
The app may use a lot of RAM even after the router has stopped and there is no icon in the notification bar. Go to Settings -> Applications -> Running Services and stop the I2P service if necessary. Or Settings -> Applications -> Manage Applications -> Running -> I2P and force stop.
The app may be moved to the SD card if you have Froyo (2.2) or higher. 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 enabled but it doesn't appear to be working.
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.
I2P's NTP is disabled for API 11 (Honeycomb) and above, as those versions include NTP support. If you have cell service, your phone or tablet should have the correct time. If you do not have cell service, ensure your device has accurate time.
The app will work best when you are not changing IPs. If you are moving around, changing WIFI nodes, or switching between mobile and WIFI networks, it won't work well.
@ -28,7 +26,7 @@ Embedded web browser
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
- Can't load cross-site images or CSS
- No POSTs to forms
@ -47,21 +45,21 @@ For eepsites and websites, problems include:
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 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 6670: irc.telecomix.i2p
* Port 6670: irc.telecomix.i2p (probably down)
* Port 6671: irc.killyourtv.i2p
Further anonymity warnings
--------------------------
* Reseeding is via http
* Exploratory and Client Tunnels are 1 hop + 0-1 hops
* Exploratory and Client Tunnels are 2 hops
* Sharing IRC and HTTP proxies on same tunnels allows for linking
* Not well-tested
* There are .i2p DNS leaks

View File

@ -2,15 +2,21 @@
# temp directory now set in Init.java
#i2p.dir.temp=/data/data/net.i2p.android.router/files/tmp
#i2p.dir.pid=/data/data/net.i2p.android.router/files/tmp
#
# 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.bufferSize=32768
router.decayingBloomFilterM=20
stat.full=false
#
# Don't run NTP client, the phone should have a valid time
#
time.disabled=true
# Tablets are not phones, turn this on. I've seen the phone not have
# 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)
#
@ -20,38 +26,53 @@ i2cp.disableInterface=true
# Todo: implement a NamingService using the android native SQLite
#
i2p.naming.impl=net.i2p.client.naming.HostsTxtNamingService
i2p.hostsfilelist=hosts.txt
#
##### Tunnels
#
router.inboundPool.backupQuantity=0
router.inboundPool.length=1
router.inboundPool.lengthVariance=1
router.inboundPool.length=2
router.inboundPool.lengthVariance=0
router.inboundPool.quantity=2
router.outboundPool.backupQuantity=0
router.outboundPool.length=1
router.outboundPool.lengthVariance=1
router.outboundPool.length=2
router.outboundPool.lengthVariance=0
router.outboundPool.quantity=2
router.maxParticipatingTunnels=0
router.sharePercentage=10
router.maxParticipatingTunnels=20
router.sharePercentage=80
#
##### Transport
#
i2np.bandwidth.inboundKBytesPerSecond=100
i2np.bandwidth.outboundKBytesPerSecond=30
i2np.bandwidth.outboundKBytesPerSecond=50
#
# NTCP
#
#i2np.ntcp.enable=false
i2np.ntcp.maxConnections=24
i2np.ntcp.enable=true
i2np.ntcp.maxConnections=32
#
# UDP disabled for now
# UDP
#
i2np.udp.enable=false
i2np.udp.maxConnections=12
i2np.udp.enable=true
i2np.udp.maxConnections=32
#
# no COMM at all!!!
#i2p.vmCommSystem=true
#
# not on android
i2np.upnp.enable=true
routerconsole.geoip.enable=false
#
# false is default but was true in 0.9.1-0_b1 release so have to set it back
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-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>

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"?>
<resources>
<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_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
xmlns:android="http://schemas.android.com/apk/res/android"
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="@string/settings_desc_bw_inbound"
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="@string/settings_desc_bw_outbound"
android:text=" KBytes/sec"
/>
<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="@string/settings_dialog_maxPartTunnels"
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="@string/settings_dialog_sharePercent"
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>

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
#
@ -5,7 +6,21 @@
# uncomment to skip
# 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
LIBFILE=$PWD/libjbigi.so
@ -16,9 +31,21 @@ then
exit 0
fi
I2PBASE=${1:-../../i2p.i2p}
export NDK=$(realpath ../../android-ndk-r5b/)
I2PBASE=${1:-../../../i2p.i2p}
#
# 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
#
@ -26,7 +53,11 @@ LEVEL=8
ARCH=arm
export SYSROOT=$NDK/platforms/android-$LEVEL/arch-$ARCH/
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 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
@ -35,7 +66,7 @@ STRIP="$NDK/toolchains/$AABI/prebuilt/$SYSTEM/bin/${BINPREFIX}strip"
#echo "CC is $CC"
JBIGI=$(realpath $I2PBASE/core/c/jbigi)
JBIGI="$I2PBASE/core/c/jbigi"
#
# GMP Version
#
@ -65,13 +96,23 @@ cd build
if [ ! -f config.status ]
then
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
echo "Building GMP..."
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
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"

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 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
# 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
MANIFEST=../AndroidManifest.xml
MANIFESTROUTER=../routerjars/AndroidManifest.xml
TMP=AndroidManifest.xml.tmp
I2PBASE=${1:-../../i2p.i2p}
@ -14,6 +25,7 @@ CORE=`grep 'public final static String VERSION' $I2PBASE/core/java/src/net/i2p/C
MAJOR=`echo $CORE | cut -d '.' -f 1`
MINOR=`echo $CORE | cut -d '.' -f 2`
RELEASE=`echo $CORE | cut -d '.' -f 3`
RELEASE=${RELEASE:-0}
ROUTERBUILD=$((`grep 'public final static long BUILD' $I2PBASE/router/java/src/net/i2p/router/RouterVersion.java | \
cut -d '=' -f 2 | \
@ -26,7 +38,7 @@ SDK=`grep 'android:minSdkVersion' $MANIFEST | \
cut -d '"' -f 2`
# don't let build number get too long
VERSIONSTRING="${CORE}-${ROUTERBUILD}_b$(($ANDROIDBUILD % 512))-API$SDK"
VERSIONSTRING="${MAJOR}.${MINOR}.${RELEASE}-${ROUTERBUILD}_b$(($ANDROIDBUILD % 512))-API$SDK"
#
# Android version code is an integer.
@ -58,4 +70,8 @@ SUBST='s/android.versionCode="[0-9]*"/android.versionCode="'${VERSIONINT}'"/'
sed "$SUBST" < $MANIFEST > $TMP
SUBST='s/android.versionName="[^"]*"/android.versionName="'${VERSIONSTRING}'"/'
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

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.FileInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import net.i2p.I2PAppContext;
import net.i2p.data.DataHelper;
import net.i2p.util.EepGet;
@ -47,7 +46,7 @@ public class EepGetFetcher implements EepGet.StatusListener {
_eepget.setWriteErrorToOutput();
//_eepget.addStatusListener(this);
}
/**
* Writes to output stream
*/
@ -62,7 +61,7 @@ public class EepGetFetcher implements EepGet.StatusListener {
if (writeErrorToStream)
_eepget.setWriteErrorToOutput();
}
public void addStatusListener(EepGet.StatusListener 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 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 headerReceived(String url, int attemptNum, String key, String val) {}

View File

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

View File

@ -1,30 +1,32 @@
package net.i2p.android.router.activity;
import android.app.ListActivity;
import android.content.Intent;
import android.net.Uri;
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.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import net.i2p.android.router.R;
import net.i2p.I2PAppContext;
import net.i2p.android.router.R;
import net.i2p.client.naming.NamingService;
public class AddressbookActivity extends ListActivity {
public class AddressbookActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_addressbook);
// Grab context if router has started, otherwise create new
// FIXME dup contexts, locking, ...
@ -39,19 +41,26 @@ public class AddressbookActivity extends ListActivity {
// get the names
NamingService ns = ctx.namingService();
// After router shutdown we get nothing... why?
Set<String> names = ns.getNames();
// set the header
TextView tv = (TextView) getLayoutInflater().inflate(R.layout.addressbook_header, null);
tv.setText(names.size() + " hosts in address book. Start typing to filter.");
ListView lv = getListView();
int sz = names.size();
if (sz > 1)
tv.setText(sz + " hosts in address book. Start typing to filter.");
else if (sz > 0)
tv.setText("1 host in address book.");
else
tv.setText("No hosts in address book, or your router is not up.");
ListView lv = (ListView) findViewById(R.id.addressbook_list);
lv.addHeaderView(tv, "", false);
lv.setTextFilterEnabled(true);
lv.setTextFilterEnabled(sz > 1);
// set the list
List<String> nameList = new ArrayList(names);
List<String> nameList = new ArrayList<String>(names);
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
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@ -63,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;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import net.i2p.android.router.R;
import net.i2p.android.router.binder.RouterBinder;
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.stat.StatManager;
public abstract class I2PActivityBase extends Activity {
public abstract class I2PActivityBase extends ActionBarActivity {
protected String _myDir;
protected boolean _isBound;
protected boolean _triedBind;
protected ServiceConnection _connection;
protected RouterService _routerService;
private SharedPreferences _sharedPrefs;
@ -41,7 +41,7 @@ public abstract class I2PActivityBase extends Activity {
@Override
public void onCreate(Bundle savedInstanceState)
{
System.err.println(this + " onCreate called");
Util.i(this + " onCreate called");
super.onCreate(savedInstanceState);
_myDir = getFilesDir().getAbsolutePath();
}
@ -49,14 +49,14 @@ public abstract class I2PActivityBase extends Activity {
@Override
public void onRestart()
{
System.err.println(this + " onRestart called");
Util.i(this + " onRestart called");
super.onRestart();
}
@Override
public void onStart()
{
System.err.println(this + " onStart called");
Util.i(this + " onStart called");
super.onStart();
_sharedPrefs = getSharedPreferences(SHARED_PREFS, 0);
if (_sharedPrefs.getBoolean(PREF_AUTO_START, DEFAULT_AUTO_START))
@ -87,28 +87,28 @@ public abstract class I2PActivityBase extends Activity {
@Override
public void onResume()
{
System.err.println(this + " onResume called");
Util.i(this + " onResume called");
super.onResume();
}
@Override
public void onPause()
{
System.err.println(this + " onPause called");
Util.i(this + " onPause called");
super.onPause();
}
@Override
public void onSaveInstanceState(Bundle outState)
{
System.err.println(this + " onSaveInstanceState called");
Util.i(this + " onSaveInstanceState called");
super.onSaveInstanceState(outState);
}
@Override
public void onStop()
{
System.err.println(this + " onStop called");
Util.i(this + " onStop called");
unbindRouter();
super.onStop();
}
@ -116,7 +116,7 @@ public abstract class I2PActivityBase extends Activity {
@Override
public void onDestroy()
{
System.err.println(this + " onDestroy called");
Util.i(this + " onDestroy called");
super.onDestroy();
}
@ -151,9 +151,11 @@ public abstract class I2PActivityBase extends Activity {
MenuItem addressbook = menu.findItem(R.id.menu_addressbook);
addressbook.setVisible(showAddressbook);
addressbook.setEnabled(showAddressbook);
boolean showReload = showAddressbook || (this instanceof PeersActivity);
MenuItem reload = menu.findItem(R.id.menu_reload);
reload.setVisible(showAddressbook);
reload.setEnabled(showAddressbook);
reload.setVisible(showReload);
reload.setEnabled(showReload);
return super.onPrepareOptionsMenu(menu);
}
@ -208,14 +210,14 @@ public abstract class I2PActivityBase extends Activity {
protected boolean startRouter() {
Intent intent = new Intent();
intent.setClassName(this, "net.i2p.android.router.service.RouterService");
System.err.println(this + " calling startService");
Util.i(this + " calling startService");
ComponentName name = startService(intent);
if (name == null)
System.err.println(this + " XXXXXXXXXXXXXXXXXXXX got from startService: " + name);
System.err.println(this + " got from startService: " + name);
Util.i(this + " XXXXXXXXXXXXXXXXXXXX got from startService: " + name);
Util.i(this + " got from startService: " + name);
boolean success = bindRouter(true);
if (!success)
System.err.println(this + " Bind router failed");
Util.i(this + " Bind router failed");
return success;
}
@ -225,25 +227,28 @@ public abstract class I2PActivityBase extends Activity {
protected boolean bindRouter(boolean autoCreate) {
Intent intent = new Intent();
intent.setClassName(this, "net.i2p.android.router.service.RouterService");
System.err.println(this + " calling bindService");
Util.i(this + " calling bindService");
_connection = new RouterConnection();
boolean success = bindService(intent, _connection, autoCreate ? BIND_AUTO_CREATE : 0);
System.err.println(this + " bindService: auto create? " + autoCreate + " success? " + success);
return success;
_triedBind = bindService(intent, _connection, autoCreate ? BIND_AUTO_CREATE : 0);
Util.i(this + " bindService: auto create? " + autoCreate + " success? " + _triedBind);
return _triedBind;
}
protected void unbindRouter() {
if (_isBound && _connection != null) {
unbindService(_connection);
_routerService = null;
_isBound = false;
}
Util.i(this + " unbindRouter called with _isBound:" + _isBound + " _connection:" + _connection + " _triedBind:" + _triedBind);
if (_triedBind && _connection != null)
unbindService(_connection);
_triedBind = false;
_connection = null;
_routerService = null;
_isBound = false;
}
protected class RouterConnection implements ServiceConnection {
public void onServiceConnected(ComponentName name, IBinder service) {
System.err.println(this + " connected to router service");
Util.i(this + " connected to router service");
RouterBinder binder = (RouterBinder) service;
RouterService svc = binder.getService();
_routerService = svc;
@ -252,7 +257,7 @@ public abstract class I2PActivityBase extends Activity {
}
public void onServiceDisconnected(ComponentName name) {
System.err.println(this + " disconnected from router service!!!!!!!");
Util.i(this + " disconnected from router service!!!!!!!");
// save memory
_routerService = null;
_isBound = false;

View File

@ -1,6 +1,5 @@
package net.i2p.android.router.activity;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
@ -9,17 +8,16 @@ import android.net.Uri;
import android.os.AsyncTask;
import android.view.Gravity;
import android.view.View;
import android.webkit.HttpAuthHandler;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import net.i2p.android.apps.EepGetFetcher;
import net.i2p.android.router.provider.CacheProvider;
import net.i2p.android.router.util.AppCache;
@ -46,7 +44,7 @@ class I2PWebViewClient extends WebViewClient {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
Util.e("Should override? " + url);
Util.d("Should override? " + url);
view.stopLoading();
Uri uri = Uri.parse(url);
@ -61,7 +59,7 @@ class I2PWebViewClient extends WebViewClient {
//reverse back to a i2p URI so we can load it here and not in ContentProvider
try {
uri = CacheProvider.getI2PUri(uri);
Util.e("Reversed content uri back to " + uri);
Util.d("Reversed content uri back to " + uri);
} catch (FileNotFoundException fnfe) {}
url = uri.toString();
}
@ -75,7 +73,7 @@ class I2PWebViewClient extends WebViewClient {
s = s.toLowerCase();
if (!(s.equals("http") || s.equals("https") ||
s.equals(CONTENT))) {
Util.e("Not loading URL " + url);
Util.d("Not loading URL " + url);
return false;
}
String h = uri.getHost();
@ -128,14 +126,14 @@ class I2PWebViewClient extends WebViewClient {
//view.loadUrl(url);
BGLoad task = new BackgroundLoad(view);
_lastTask = task;
Util.e("Fetching via web or resource: " + url);
Util.d("Fetching via web or resource: " + url);
task.execute(url);
}
return true;
}
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.setGravity(Gravity.CENTER, 0, 0);
toast.show();
@ -143,25 +141,25 @@ class I2PWebViewClient extends WebViewClient {
@Override
public void onLoadResource(WebView view, String url) {
Util.e("OLR URL: " + url);
Util.d("OLR URL: " + url);
super.onLoadResource(view, url);
}
@Override
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);
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
Util.e("OPS URL: " + url);
Util.d("OPS URL: " + url);
super.onPageStarted(view, url, favicon);
}
@Override
public void onPageFinished(WebView view, String url) {
Util.e("OPF URL: " + url);
Util.d("OPF URL: " + url);
ProgressDialog d = _lastDialog;
if (d != null && d.isShowing()) {
try {
@ -173,6 +171,12 @@ class I2PWebViewClient extends WebViewClient {
super.onPageFinished(view, url);
}
@Override
public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm) {
Util.d("ORHAR URL: " + host);
super.onReceivedHttpAuthRequest(view, handler, host, realm);
}
/******
API 11 :(
@ -186,7 +190,7 @@ class I2PWebViewClient extends WebViewClient {
void cancelAll() {
BGLoad task = _lastTask;
if (task != null) {
Util.e("Cancelling fetches");
Util.d("Cancelling fetches");
task.cancel(true);
}
}
@ -201,12 +205,12 @@ class I2PWebViewClient extends WebViewClient {
try {
//reverse back to a i2p URI so we can delete it from the AppCache
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);
} catch (FileNotFoundException fnfe) {
// this actually only deletes the row in the provider,
// 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);
}
}
@ -273,9 +277,12 @@ class I2PWebViewClient extends WebViewClient {
return Integer.valueOf(0);
}
@Override
protected void onProgressUpdate(Integer... progress) {
if (isCancelled())
return;
//if (isCancelled())
// return;
//if (progress[0].intValue() < 0) {
// _dialog = ProgressDialog.show(_view.getContext(), "Loading", "some url");
// _dialog.setOnCancelListener(this);
@ -304,7 +311,7 @@ class I2PWebViewClient extends WebViewClient {
File cacheFile = AppCache.getInstance(_view.getContext()).getCacheFile(uri);
if (cacheFile.exists()) {
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().setBlockNetworkLoads(false);
try {
@ -327,7 +334,7 @@ class I2PWebViewClient extends WebViewClient {
fetcher.addStatusListener(this);
boolean success = fetcher.fetch();
if (isCancelled()) {
Util.e("Fetch cancelled for " + url);
Util.d("Fetch cancelled for " + url);
return Integer.valueOf(0);
}
try { out.close(); } catch (IOException ioe) {}
@ -336,20 +343,20 @@ class I2PWebViewClient extends WebViewClient {
// Set as current base
Uri content = AppCache.getInstance(_view.getContext()).addCacheFile(uri, true);
if (content != null) {
Util.e("Stored cache in " + content);
Util.d("Stored cache in " + content);
} else {
AppCache.getInstance(_view.getContext()).removeCacheFile(uri);
Util.e("cache create error");
Util.d("cache create error");
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 {
_view.loadUrl(content.toString());
} catch (Exception exc) {
// CalledFromWrongThreadException
cancel(false);
}
Util.e("Fetch failed for " + url);
Util.d("Fetch failed for " + url);
} else {
// Load the error message in as a string, delete the file
String t = fetcher.getContentType();
@ -371,7 +378,7 @@ class I2PWebViewClient extends WebViewClient {
DataHelper.read(fis, data);
msg = new String(data, e);
} catch (IOException ioe) {
Util.e("WVC", ioe);
Util.d("WVC", ioe);
msg = HEADER + "I/O error" + FOOTER;
} finally {
if (fis != null) try { fis.close(); } catch (IOException ioe) {}
@ -379,7 +386,7 @@ class I2PWebViewClient extends WebViewClient {
}
AppCache.getInstance(_view.getContext()).removeCacheFile(uri);
try {
Util.e("loading error data URL: " + url);
Util.d("loading error data URL: " + url);
_view.loadDataWithBaseURL(url, msg, t, e, url);
} catch (Exception exc) {
// CalledFromWrongThreadException
@ -387,13 +394,14 @@ class I2PWebViewClient extends WebViewClient {
}
}
} catch (IOException ioe) {
Util.e("IOE for " + url, ioe);
Util.d("IOE for " + url, ioe);
} finally {
if (out != null) try { out.close(); } catch (IOException ioe) {}
}
return Integer.valueOf(0);
}
@Override
protected void onProgressUpdate(Integer... progress) {
if (isCancelled())
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.ArrayAdapter;
import android.widget.ListView;
import net.i2p.android.router.R;
public class LicenseActivity extends ListActivity {
@ -15,7 +14,7 @@ public class LicenseActivity extends ListActivity {
private static final String[] names = {
"Android Application License", "Apache 2.0",
"Router License Overview", "Blockfile", "Crypto Filters", "ElGamal / DSA",
"GPLv2", "LGPLv2.1", "GPLv3", "LGPLv3",
"GPLv2", "LGPLv2.1", "GPLv3", "LGPLv3", "FatCowIcons",
"Ministreaming",
"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.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_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};
@Override

View File

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

View File

@ -10,9 +10,8 @@ import android.os.Handler;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import java.io.File;
import java.text.DecimalFormat;
import net.i2p.android.router.R;
import net.i2p.android.router.service.RouterService;
import net.i2p.android.router.util.Util;
@ -25,21 +24,45 @@ public class MainActivity extends I2PActivityBase {
private Runnable _updater;
private Runnable _oneShotUpdate;
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_VERSION = "i2p.newVersion";
protected static final int DIALOG_NEW_INSTALL = 0;
protected static final int DIALOG_NEW_VERSION = 1;
/** Called when the activity is first created. */
@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);
// 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);
Button b = (Button) findViewById(R.id.news_button);
b.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
Intent intent = new Intent(view.getContext(), NewsActivity.class);
startActivity(intent);
@ -48,6 +71,7 @@ public class MainActivity extends I2PActivityBase {
b = (Button) findViewById(R.id.releasenotes_button);
b.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
Intent intent = new Intent(view.getContext(), TextResourceActivity.class);
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.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
Intent intent = new Intent(view.getContext(), LicenseActivity.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.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
Intent intent = new Intent(view.getContext(), WebActivity.class);
//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.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
Intent intent = new Intent(view.getContext(), WebActivity.class);
//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.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
Intent intent = new Intent(view.getContext(), WebActivity.class);
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.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
Intent intent = new Intent(view.getContext(), AddressbookActivity.class);
startActivity(intent);
@ -104,6 +133,7 @@ public class MainActivity extends I2PActivityBase {
b = (Button) findViewById(R.id.logs_button);
b.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
Intent intent = new Intent(view.getContext(), LogActivity.class);
startActivity(intent);
@ -112,6 +142,7 @@ public class MainActivity extends I2PActivityBase {
b = (Button) findViewById(R.id.error_button);
b.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
Intent intent = new Intent(view.getContext(), LogActivity.class);
intent.putExtra(LogActivity.ERRORS_ONLY, true);
@ -121,44 +152,44 @@ public class MainActivity extends I2PActivityBase {
b = (Button) findViewById(R.id.peers_button);
b.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
Intent intent = new Intent(view.getContext(), PeersActivity.class);
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.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
_startPressed = true;
RouterService svc = _routerService;
if (svc != null && _isBound) {
if(svc != null && _isBound) {
setPref(PREF_AUTO_START, true);
svc.manualStart();
} else {
(new File(_myDir, "wrapper.log")).delete();
startRouter();
}
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.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
RouterService svc = _routerService;
if (svc != null && _isBound) {
if(svc != null && _isBound) {
setPref(PREF_AUTO_START, false);
svc.manualQuit();
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();
_updater = new Updater();
_oneShotUpdate = new OneShotUpdate();
}
@Override
public void onStart()
{
public void onStart() {
super.onStart();
_handler.removeCallbacks(_updater);
_handler.removeCallbacks(_oneShotUpdate);
if (_savedStatus != null) {
if(_savedStatus != null) {
TextView tv = (TextView) findViewById(R.id.main_status_text);
tv.setText(_savedStatus);
}
@ -193,25 +216,23 @@ public class MainActivity extends I2PActivityBase {
}
@Override
public void onStop()
{
public void onStop() {
super.onStop();
_handler.removeCallbacks(_updater);
_handler.removeCallbacks(_oneShotUpdate);
}
@Override
public void onResume()
{
public void onResume() {
super.onResume();
updateOneShot();
}
@Override
public void onSaveInstanceState(Bundle outState)
{
if (_savedStatus != null)
public void onSaveInstanceState(Bundle outState) {
if(_savedStatus != null) {
outState.putString("status", _savedStatus);
}
super.onSaveInstanceState(outState);
}
@ -220,6 +241,7 @@ public class MainActivity extends I2PActivityBase {
}
private class OneShotUpdate implements Runnable {
public void run() {
updateVisibility();
updateStatus();
@ -227,175 +249,259 @@ public class MainActivity extends I2PActivityBase {
}
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() {
updateVisibility();
if (counter++ % 3 == 0)
if(counter++ % toloop == 0) {
updateStatus();
_handler.postDelayed(this, 2500);
}
//_handler.postDelayed(this, 2500);
_handler.postDelayed(this, delay);
}
}
private void updateVisibility() {
RouterService svc = _routerService;
boolean showStart = ((svc == null) || (!_isBound) || svc.canManualStart()) &&
Util.isConnected(this);
boolean showStart = ((svc == null) || (!_isBound) || svc.canManualStart())
&& Util.isConnected(this);
Button start = (Button) findViewById(R.id.router_start_button);
start.setVisibility(showStart ? View.VISIBLE : View.INVISIBLE);
boolean showStop = svc != null && _isBound && svc.canManualStop();
// Old stop but leave in memory. Always hide for now.
Button stop = (Button) findViewById(R.id.router_stop_button);
stop.setVisibility( /* showStop ? View.VISIBLE : */ View.INVISIBLE);
// Button stop = (Button) findViewById(R.id.router_stop_button);
// stop.setVisibility( /* showStop ? View.VISIBLE : */ View.INVISIBLE);
Button quit = (Button) findViewById(R.id.router_quit_button);
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() {
RouterContext ctx = getRouterContext();
TextView tv = (TextView) findViewById(R.id.main_status_text);
/***
if (!Util.isConnected(this)) {
tv.setText("No Internet connection is available");
if(!Util.isConnected(this)) {
tv.setText("Router version: " + _ourVersion + "\nNo Internet connection is available");
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 known = Math.max(ctx.netDb().getKnownRouters() - 1, 0);
int inEx = ctx.tunnelManager().getFreeTunnelCount();
int outEx = ctx.tunnelManager().getOutboundTunnelCount();
int inCl = ctx.tunnelManager().getInboundClientTunnelCount();
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();
String jobLag = DataHelper.formatDuration((long) dLag);
String msgDelay = DataHelper.formatDuration(ctx.throttle().getMessageDelay());
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 outBW = ctx.bandwidthLimiter().getSendBps() / 1024;
// control total width
DecimalFormat fmt;
if (inBW >= 1000 || outBW >= 1000)
if(inBW >= 1000 || outBW >= 1000) {
fmt = new DecimalFormat("#0");
else if (inBW >= 100 || outBW >= 100)
} else if(inBW >= 100 || outBW >= 100) {
fmt = new DecimalFormat("#0.0");
else
} else {
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 =
"ROUTER STATUS" +
"\nPeers active/known: " + active + " / " + known +
"\nExploratory Tunnels in/out: " + inEx + " / " + outEx +
"\nClient Tunnels in/out: " + inCl + " / " + outCl;
//" Pt " + part +
"ROUTER STATUS"
+ "\nNetwork: " + netstatus
+ "\nPeers active/known: " + active + " / " + known
+ "\nExploratory Tunnels in/out: " + inEx + " / " + outEx
+ "\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 =
"\nBandwidth in/out: " + fmt.format(inBW) + " / " + fmt.format(outBW) + " KBps" +
"\nMemory: " + DataHelper.formatSize(Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) +
"B / " + DataHelper.formatSize(Runtime.getRuntime().maxMemory()) + 'B' +
"\nJob Lag: " + jobLag +
"\nMsg Delay: " + msgDelay +
"\nUptime: " + uptime;
"\nBandwidth in/out: " + fmt.format(inBW) + " / " + fmt.format(outBW) + " KBps"
+ "\nData usage in/out: " + kBfmt.format(kBytesIn) + " / " + kBfmt.format(kBytesOut) + " KB"
+ "\nMemory: " + DataHelper.formatSize(Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory())
+ "B / " + DataHelper.formatSize(Runtime.getRuntime().maxMemory()) + 'B'
+ "\nJob Lag: " + jobLag
+ "\nMsg Delay: " + msgDelay
+ "\nUptime: " + uptime;
_savedStatus = status + details;
_savedStatus = "Router version: " + _ourVersion + "\n" + status + participate + details;
tv.setText(_savedStatus);
tv.setVisibility(View.VISIBLE);
} else {
// network but no router context
tv.setText("Router version: " + _ourVersion + "\n");
//tv.setVisibility(View.INVISIBLE);
RouterService svc = _routerService;
String status =
"connected? " + Util.isConnected(this) +
"\nMemory: " + DataHelper.formatSize(Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) +
"B / " + DataHelper.formatSize(Runtime.getRuntime().maxMemory()) + 'B' +
"\nhave ctx? " + (ctx != null) +
"\nhave svc? " + (svc != null) +
"\nis bound? " + _isBound +
"\nsvc state: " + (svc == null ? "null" : svc.getState()) +
"\ncan start? " + (svc == null ? "null" : svc.canManualStart()) +
"\ncan stop? " + (svc == null ? "null" : svc.canManualStop());
tv.setText(status);
tv.setVisibility(View.VISIBLE);
/**
* **
* RouterService svc = _routerService; String status = "connected? "
* + Util.isConnected(this) + "\nMemory: " +
* DataHelper.formatSize(Runtime.getRuntime().totalMemory() -
* Runtime.getRuntime().freeMemory()) + "B / " +
* DataHelper.formatSize(Runtime.getRuntime().maxMemory()) + 'B' +
* "\nhave ctx? " + (ctx != null) + "\nhave svc? " + (svc != null) +
* "\nis bound? " + _isBound + "\nsvc state: " + (svc == null ?
* "null" : svc.getState()) + "\ncan start? " + (svc == null ?
* "null" : svc.canManualStart()) + "\ncan stop? " + (svc == null ?
* "null" : svc.canManualStop()); tv.setText(status);
* tv.setVisibility(View.VISIBLE);
***
*/
}
}
private void checkDialog() {
String oldVersion = getPref(PREF_INSTALLED_VERSION, "??");
if (oldVersion.equals("??")) {
if(oldVersion.equals("??")) {
showDialog(DIALOG_NEW_INSTALL);
} else {
String currentVersion = Util.getOurVersion(this);
if (!oldVersion.equals(currentVersion))
if(!oldVersion.equals(currentVersion)) {
showDialog(DIALOG_NEW_VERSION);
}
}
}
@Override
protected Dialog onCreateDialog(int id) {
final String currentVersion = Util.getOurVersion(this);
Dialog rv = null;
AlertDialog.Builder b = new AlertDialog.Builder(this);
switch (id) {
case DIALOG_NEW_INSTALL:
b.setMessage(getResources().getText(R.string.welcome_new_install))
.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;
switch(id) {
case DIALOG_NEW_INSTALL:
b.setMessage(getResources().getText(R.string.welcome_new_install)).setCancelable(false).setPositiveButton("OK", new DialogInterface.OnClickListener() {
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);
}
});
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() {
rv = b.create();
break;
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:
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;
}

View File

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

View File

@ -2,16 +2,13 @@ package net.i2p.android.router.activity;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.MenuItem;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.TextView;
import java.io.StringWriter;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.io.StringWriter;
import net.i2p.android.router.R;
import net.i2p.android.router.service.RouterService;
import net.i2p.android.router.util.Util;
import net.i2p.router.CommSystemFacade;
public class PeersActivity extends I2PActivityBase {
@ -28,7 +25,7 @@ public class PeersActivity extends I2PActivityBase {
super.onCreate(savedInstanceState);
setContentView(R.layout.peers);
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
wv.getSettings().setUseWideViewPort(true);
_wvClient = new I2PWebViewClient(this);
@ -53,6 +50,7 @@ public class PeersActivity extends I2PActivityBase {
private void update() {
WebView wv = (WebView) findViewById(R.id.peers_webview);
wv.clearHistory(); // fixes having to hit back.
CommSystemFacade comm = getCommSystem();
String data;
if (comm != null) {
@ -61,7 +59,7 @@ public class PeersActivity extends I2PActivityBase {
try {
comm.renderStatusHTML(out, "http://thiswontwork.i2p/peers", 0);
out.append(FOOTER);
data = out.toString();
data = out.toString().replaceAll("/themes", "themes");
} catch (IOException ioe) {
data = HEADER + "Error: " + ioe + FOOTER;
}
@ -69,7 +67,11 @@ public class PeersActivity extends I2PActivityBase {
data = HEADER + "No peer data available. The router is not running." + FOOTER;
}
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
// String url = "file://" + _myDir + "/docs/";
String url = "file:///android_asset/";
wv.loadDataWithBaseURL(url, data, "text/html", "UTF-8", url);
} catch (Exception e) {
}
}
@ -80,11 +82,27 @@ public class PeersActivity extends I2PActivityBase {
if ((keyCode == KeyEvent.KEYCODE_BACK)) {
_wvClient.cancelAll();
wv.stopLoading();
if (wv.canGoBack()) {
wv.goBack();
return true;
}
// We do not want to go back, or keep history... Theere is no need to.
// What we DO want to do is exit!
//if (wv.canGoBack()) {
// wv.goBack();
// return true;
//}
}
return super.onKeyDown(keyCode, event);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
WebView wv = (WebView) findViewById(R.id.peers_webview);
switch (item.getItemId()) {
case R.id.menu_reload:
update();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}

View File

@ -1,9 +1,18 @@
package net.i2p.android.router.activity;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.Preference;
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.util.Util;
import net.i2p.router.RouterContext;
import net.i2p.util.OrderedProperties;
public class SettingsActivity extends PreferenceActivity {
@ -12,4 +21,66 @@ public class SettingsActivity extends PreferenceActivity {
super.onCreate(savedInstanceState);
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;
import android.content.res.Resources;
import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;
import android.text.method.ScrollingMovementMethod;
import android.widget.TextView;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import net.i2p.android.router.R;
import net.i2p.android.router.util.Util;
@ -45,7 +43,7 @@ public class TextResourceActivity extends I2PActivityBase {
try {
in = getResources().openRawResource(id);
int read = 0;
int read;
while ( (read = in.read(buf)) != -1)
out.write(buf, 0, read);

View File

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

View File

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

View File

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

View File

@ -9,7 +9,6 @@ import android.content.ServiceConnection;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.IBinder;
import net.i2p.android.router.binder.RouterBinder;
import net.i2p.android.router.service.RouterService;
import net.i2p.android.router.util.Util;
@ -32,13 +31,14 @@ public class I2PReceiver extends BroadcastReceiver {
intents.addAction(Intent.ACTION_TIME_CHANGED);
intents.addAction(Intent.ACTION_TIME_TICK); // once per minute, for testing
intents.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
context.registerReceiver(this, intents);
@SuppressWarnings("LeakingThisInConstructor")
Intent registerReceiver = context.registerReceiver(this, intents);
_wasConnected = Util.isConnected(context);
}
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
System.err.println("Got broadcast: " + action);
//Util.w("Got broadcast: " + action);
if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
boolean failover = intent.getBooleanExtra(ConnectivityManager.EXTRA_IS_FAILOVER, false);
@ -47,7 +47,7 @@ public class I2PReceiver extends BroadcastReceiver {
NetworkInfo other = (NetworkInfo) intent.getParcelableExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO);
/*****
System.err.println("No conn? " + noConn + " failover? " + failover +
Util.w("No conn? " + noConn + " failover? " + failover +
" info: " + info + " other: " + other);
printInfo(info);
printInfo(other);
@ -63,10 +63,10 @@ public class I2PReceiver extends BroadcastReceiver {
if (++_unconnectedCount >= 3) {
RouterService svc = _routerService;
if (_isBound && svc != null) {
System.err.println("********* Network down, already bound");
Util.w("********* Network down, already bound");
svc.networkStop();
} else {
System.err.println("********* Network down, binding to router");
Util.w("********* Network down, binding to router");
// connection will call networkStop()
bindRouter();
}
@ -81,10 +81,10 @@ public class I2PReceiver extends BroadcastReceiver {
/****
private static void printInfo(NetworkInfo ni) {
if (ni == null) {
System.err.println("Network info is null");
Util.w("Network info is null");
return;
}
System.err.println(
Util.w(
"state: " + ni.getState() +
" detail: " + ni.getDetailedState() +
" extrainfo: " + ni.getExtraInfo() +
@ -101,10 +101,10 @@ public class I2PReceiver extends BroadcastReceiver {
private boolean bindRouter() {
Intent intent = new Intent();
intent.setClassName(_context, "net.i2p.android.router.service.RouterService");
System.err.println(this + " calling bindService");
Util.w(this + " calling bindService");
_connection = new RouterConnection();
boolean success = _context.bindService(intent, _connection, 0);
System.err.println(this + " got from bindService: " + success);
Util.w(this + " got from bindService: " + success);
return success;
}
@ -123,7 +123,7 @@ public class I2PReceiver extends BroadcastReceiver {
_isBound = true;
_unconnectedCount = 0;
_wasConnected = false;
System.err.println("********* Network down, stopping router");
Util.w("********* Network down, stopping router");
_routerService.networkStop();
// this doesn't work here... TODO where to unbind
//_context.unbindService(this);
@ -132,7 +132,7 @@ public class I2PReceiver extends BroadcastReceiver {
public void onServiceDisconnected(ComponentName name) {
_isBound = false;
_routerService = null;
System.err.println("********* Receiver unbinding from router");
Util.w("********* Receiver unbinding from router");
}
}
}

View File

@ -1,27 +1,9 @@
package net.i2p.android.router.service;
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.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.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.NativeBigInteger;
import net.i2p.util.OrderedProperties;
class Init {
@ -29,205 +11,30 @@ class Init {
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 Init(Context c) {
ctx = c;
myDir = c.getFilesDir().getAbsolutePath();
_ourVersion = Util.getOurVersion(c);
}
void debugStuff() {
System.err.println("java.io.tmpdir" + ": " + System.getProperty("java.io.tmpdir"));
System.err.println("java.vendor" + ": " + System.getProperty("java.vendor"));
System.err.println("java.version" + ": " + System.getProperty("java.version"));
System.err.println("os.arch" + ": " + System.getProperty("os.arch"));
System.err.println("os.name" + ": " + System.getProperty("os.name"));
System.err.println("os.version" + ": " + System.getProperty("os.version"));
System.err.println("user.dir" + ": " + System.getProperty("user.dir"));
System.err.println("user.home" + ": " + System.getProperty("user.home"));
System.err.println("user.name" + ": " + System.getProperty("user.name"));
System.err.println("getFilesDir()" + ": " + myDir);
System.err.println("max mem" + ": " + DataHelper.formatSize(Runtime.getRuntime().maxMemory()));
System.err.println("Package" + ": " + ctx.getPackageName());
System.err.println("Version" + ": " + _ourVersion);
System.err.println("MODEL" + ": " + Build.MODEL);
System.err.println("DISPLAY" + ": " + Build.DISPLAY);
System.err.println("VERSION" + ": " + Build.VERSION.RELEASE);
System.err.println("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");
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");
File img2Dir = new File(cssDir, "images");
img2Dir.mkdir();
copyResourceToFile(R.drawable.header, "docs/themes/console/light/images/header.png");
}
deleteOldFiles();
// 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.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;
System.err.println("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);
System.err.println("Merging resource into file " + f);
} catch (IOException ioe) {
System.err.println("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);
System.err.println("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) {
System.err.println("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) {
System.err.println("New version " + _ourVersion);
props.setProperty(PROP_INSTALLED_VERSION, _ourVersion);
try {
DataHelper.storeProps(props, ctx.getFileStreamPath(CONFIG_FILE));
} catch (IOException ioe) {
System.err.println("Failed to write " + CONFIG_FILE);
}
}
return newVersion;
}
private void deleteOldFiles() {
(new File(myDir, "wrapper.log")).delete();
File tmp = new File(myDir, "tmp");
File[] files = tmp.listFiles();
if (files != null) {
for (int i = 0; i < files.length; i++) {
File f = files[i];
System.err.println("Deleting old file/dir " + f);
Util.i("Deleting old file/dir " + f);
FileUtil.rmdir(f, false);
}
}

View File

@ -1,7 +1,9 @@
package net.i2p.android.router.service;
import net.i2p.BOB.BOB;
import net.i2p.addressbook.DaemonThread;
import net.i2p.android.apps.NewsFetcher;
import net.i2p.android.router.util.Util;
import net.i2p.i2ptunnel.TunnelControllerGroup;
import net.i2p.router.Job;
import net.i2p.router.JobImpl;
@ -28,9 +30,10 @@ import net.i2p.util.I2PAppThread;
*
*/
class LoadClientsJob extends JobImpl {
private Thread _fetcherThread;
private DaemonThread _addressbook;
private Thread _BOB;
/** this is the delay to load (and start) the clients. */
private static final long LOAD_DELAY = 90*1000;
@ -57,11 +60,21 @@ class LoadClientsJob extends JobImpl {
_addressbook.start();
// add other clients here
Run_BOB bob = new Run_BOB();
_BOB = new I2PAppThread(bob, "BOB", true);
_BOB.start();
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 {
public RunI2PTunnel(RouterContext ctx) {
@ -71,18 +84,20 @@ class LoadClientsJob extends JobImpl {
public String getName() { return "Start I2P Tunnel"; };
public void runJob() {
System.err.println("Starting i2ptunnel");
Util.i("Starting i2ptunnel");
TunnelControllerGroup tcg = TunnelControllerGroup.getInstance();
int sz = tcg.getControllers().size();
System.err.println("i2ptunnel started " + sz + " clients");
Util.i("i2ptunnel started " + sz + " clients");
}
}
private class ClientShutdownHook implements Runnable {
public void run() {
System.err.println("client shutdown hook");
Util.i("client shutdown hook");
// i2ptunnel registers its own hook
if (_BOB != null)
BOB.stop();
if (_fetcherThread != null)
_fetcherThread.interrupt();
if (_addressbook != null)

View File

@ -1,19 +1,18 @@
package net.i2p.android.router.service;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.DecimalFormat;
import java.util.List;
import net.i2p.android.router.R;
import java.util.Properties;
import java.util.Random;
import net.i2p.android.router.binder.RouterBinder;
import net.i2p.android.router.receiver.I2PReceiver;
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.RouterContext;
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 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 String _myDir;
//private String _apkPath;
@ -50,7 +51,6 @@ public class RouterService extends Service {
private final Object _stateLock = new Object();
private Handler _handler;
private Runnable _updater;
private static final String SHARED_PREFS = "net.i2p.android.router";
private static final String LAST_STATE = "service.lastState";
private static final String EXTRA_RESTART = "restart";
@ -60,105 +60,267 @@ public class RouterService extends Service {
public void onCreate() {
State lastState = getSavedState();
setState(State.INIT);
System.err.println(this + " onCreate called" +
" Saved state is: " + lastState +
" Current state is: " + _state);
Util.i(this + " onCreate called"
+ " Saved state is: " + lastState
+ " Current state is: " + _state);
//(new File(getFilesDir(), "wrapper.log")).delete();
_myDir = getFilesDir().getAbsolutePath();
// init other stuff here, delete log, etc.
Init init = new Init(this);
init.debugStuff();
init.initialize();
//_apkPath = init.getAPKPath();
_statusBar = new StatusBar(this);
// kill any old one... will this work?
_statusBar.off();
// Remove stale notification icon.
_statusBar.remove();
_binder = new RouterBinder(this);
_handler = new Handler();
_updater = new Updater();
if (lastState == State.RUNNING) {
if(lastState == State.RUNNING) {
Intent intent = new Intent(this, RouterService.class);
intent.putExtra(EXTRA_RESTART, true);
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
public int onStartCommand(Intent intent, int flags, int startId) {
System.err.println(this + " onStart called" +
" Intent is: " + intent +
" Flags is: " + flags +
" ID is: " + startId +
" Current state is: " + _state);
Util.i(this + " onStart called"
+ " Intent is: " + intent
+ " Flags is: " + flags
+ " ID is: " + startId
+ " Current state is: " + _state);
boolean restart = intent != null && intent.getBooleanExtra(EXTRA_RESTART, false);
if (restart)
System.err.println(this + " RESTARTING");
synchronized (_stateLock) {
if (_state != State.INIT)
//return START_STICKY;
if(restart) {
Util.i(this + " RESTARTING");
}
synchronized(_stateLock) {
if(_state != State.INIT) //return START_STICKY;
{
return START_NOT_STICKY;
}
_receiver = new I2PReceiver(this);
if (Util.isConnected(this)) {
if (restart)
_statusBar.replace("I2P is restarting");
else
_statusBar.replace("I2P is starting up");
if(Util.isConnected(this)) {
if(restart) {
_statusBar.replace(StatusBar.ICON1, "I2P is restarting");
} else {
_statusBar.replace(StatusBar.ICON1, "I2P is starting up");
}
setState(State.STARTING);
_starterThread = new Thread(new Starter());
_starterThread.start();
} else {
_statusBar.replace("I2P is waiting for a network connection");
_statusBar.replace(StatusBar.ICON6, "I2P is waiting for a network connection");
setState(State.WAITING);
_handler.postDelayed(new Waiter(), 10*1000);
_handler.postDelayed(new Waiter(), 10 * 1000);
}
}
_handler.removeCallbacks(_updater);
_handler.postDelayed(_updater, 50);
if(!restart) {
startForeground(1337, _statusBar.getNote());
}
//return START_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 {
public void run() {
System.err.println(MARKER + this + " waiter handler" +
" Current state is: " + _state);
if (_state == State.WAITING) {
if (Util.isConnected(RouterService.this)) {
synchronized (_stateLock) {
if (_state != State.WAITING)
Util.i(MARKER + this + " waiter handler"
+ " Current state is: " + _state);
if(_state == State.WAITING) {
if(Util.isConnected(RouterService.this)) {
synchronized(_stateLock) {
if(_state != State.WAITING) {
return;
_statusBar.replace("Network connected, I2P is starting up");
}
_statusBar.replace(StatusBar.ICON1, "Network connected, I2P is starting up");
setState(State.STARTING);
_starterThread = new Thread(new Starter());
_starterThread.start();
}
return;
}
_handler.postDelayed(this, 15*1000);
_handler.postDelayed(this, 15 * 1000);
}
}
}
private class Starter implements Runnable {
public void run() {
System.err.println(MARKER + this + " starter thread" +
" Current state is: " + _state);
//System.err.println(MARKER + this + " JBigI speed test started");
Util.i(MARKER + this + " starter thread"
+ " Current state is: " + _state);
//Util.i(MARKER + this + " JBigI speed test started");
//NativeBigInteger.main(null);
//System.err.println(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);
synchronized (_stateLock) {
if (_state != State.STARTING)
synchronized(_stateLock) {
if(_state != State.STARTING) {
return;
}
setState(State.RUNNING);
List contexts = RouterContext.listContexts();
if ( (contexts == null) || (contexts.isEmpty()) )
throw new IllegalStateException("No contexts. This is usually because the router is either starting up or shutting down.");
_statusBar.update("I2P is running");
_context = (RouterContext)contexts.get(0);
List<?> contexts = RouterContext.listContexts();
if((contexts == null) || (contexts.isEmpty())) {
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");
_context = (RouterContext) contexts.get(0);
_context.router().setKillVMOnEnd(false);
Job loadJob = new LoadClientsJob(_context);
_context.jobQueue().addJob(loadJob);
@ -166,22 +328,23 @@ public class RouterService extends Service {
_context.addFinalShutdownTask(new FinalShutdownHook());
_starterThread = null;
}
System.err.println("Router.main finished");
Util.i("Router.main finished");
}
}
private class Updater implements Runnable {
public void run() {
RouterContext ctx = _context;
if (ctx != null && _state == State.RUNNING) {
if(ctx != null && _state == State.RUNNING) {
Router router = ctx.router();
if (router.isAlive())
if(router.isAlive()) {
updateStatus(ctx);
}
}
_handler.postDelayed(this, 15*1000);
_handler.postDelayed(this, 15 * 1000);
}
}
private boolean _hadTunnels;
private void updateStatus(RouterContext ctx) {
@ -196,62 +359,72 @@ public class RouterService extends Service {
double outBW = ctx.bandwidthLimiter().getSendBps() / 1024;
// control total width
DecimalFormat fmt;
if (inBW >= 1000 || outBW >= 1000)
if(inBW >= 1000 || outBW >= 1000) {
fmt = new DecimalFormat("#0");
else if (inBW >= 100 || outBW >= 100)
} else if(inBW >= 100 || outBW >= 100) {
fmt = new DecimalFormat("#0.0");
else
} else {
fmt = new DecimalFormat("#0.00");
}
String status =
"I2P " +
active + '/' + known + " peers connected";
"I2P "
+ active + '/' + known + " peers connected";
String details =
fmt.format(inBW) + '/' + fmt.format(outBW) + " KBps" +
"; Expl " + inEx + '/' + outEx +
"; Client " + inCl + '/' + outCl;
fmt.format(inBW) + '/' + fmt.format(outBW) + " KBps"
+ "; Expl " + inEx + '/' + outEx
+ "; Client " + inCl + '/' + outCl;
boolean haveTunnels = inCl > 0 && outCl > 0;
if (haveTunnels != _hadTunnels) {
if (haveTunnels)
_statusBar.replace("Client tunnels are ready");
else
_statusBar.replace("Client tunnels are down");
if(haveTunnels != _hadTunnels) {
if(haveTunnels) {
_statusBar.replace(StatusBar.ICON3, "Client tunnels are ready");
} else {
_statusBar.replace(StatusBar.ICON2, "Client tunnels are down");
}
_hadTunnels = haveTunnels;
}
_statusBar.update(status, details);
}
@Override
public IBinder onBind(Intent intent)
{
System.err.println(this + "onBind called" +
" Current state is: " + _state);
public IBinder onBind(Intent intent) {
Util.i(this + "onBind called"
+ " Current state is: " + _state);
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() {
RouterContext rv = _context;
if (rv == null)
if(rv == null) {
return null;
if (!rv.router().isAlive())
}
if(!rv.router().isAlive()) {
return null;
if (_state != State.RUNNING &&
_state != State.STOPPING &&
_state != State.MANUAL_STOPPING &&
_state != State.MANUAL_QUITTING &&
_state != State.NETWORK_STOPPING)
}
if(_state != State.RUNNING
&& _state != State.STOPPING
&& _state != State.MANUAL_STOPPING
&& _state != State.MANUAL_QUITTING
&& _state != State.NETWORK_STOPPING) {
return null;
}
return rv;
}
/** debug */
/**
* debug
*/
public String getState() {
return _state.toString();
}
@ -261,18 +434,20 @@ 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() {
System.err.println("manualStop called" +
" Current state is: " + _state);
synchronized (_stateLock) {
if (!canManualStop())
Util.i("manualStop called"
+ " Current state is: " + _state);
synchronized(_stateLock) {
if(!canManualStop()) {
return;
if (_state == State.STARTING)
}
if(_state == State.STARTING) {
_starterThread.interrupt();
if (_state == State.STARTING || _state == State.RUNNING) {
_statusBar.replace("Stopping I2P");
}
if(_state == State.STARTING || _state == State.RUNNING) {
_statusBar.replace(StatusBar.ICON4, "Stopping I2P");
Thread stopperThread = new Thread(new Stopper(State.MANUAL_STOPPING, State.MANUAL_STOPPED));
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() {
System.err.println("manualQuit called" +
" Current state is: " + _state);
synchronized (_stateLock) {
if (!canManualStop())
Util.i("manualQuit called"
+ " Current state is: " + _state);
synchronized(_stateLock) {
if(!canManualStop()) {
return;
if (_state == State.STARTING)
}
if(_state == State.STARTING) {
_starterThread.interrupt();
if (_state == State.STARTING || _state == State.RUNNING) {
_statusBar.replace("Stopping I2P");
}
if(_state == State.STARTING || _state == State.RUNNING) {
_statusBar.replace(StatusBar.ICON4, "Stopping I2P");
Thread stopperThread = new Thread(new Stopper(State.MANUAL_QUITTING, State.MANUAL_QUITTED));
stopperThread.start();
} else if (_state == State.WAITING) {
} else if(_state == State.WAITING) {
setState(State.MANUAL_QUITTING);
(new FinalShutdownHook()).run();
}
@ -302,16 +479,17 @@ 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() {
System.err.println("networkStop called" +
" Current state is: " + _state);
synchronized (_stateLock) {
if (_state == State.STARTING)
Util.i("networkStop called"
+ " Current state is: " + _state);
synchronized(_stateLock) {
if(_state == State.STARTING) {
_starterThread.interrupt();
if (_state == State.STARTING || _state == State.RUNNING) {
_statusBar.replace("Network disconnected, stopping I2P");
}
if(_state == State.STARTING || _state == State.RUNNING) {
_statusBar.replace(StatusBar.ICON4, "Network disconnected, stopping I2P");
// don't change state, let the shutdown hook do it
Thread stopperThread = new Thread(new Stopper(State.NETWORK_STOPPING, State.NETWORK_STOPPING));
stopperThread.start();
@ -325,12 +503,13 @@ public class RouterService extends Service {
}
public void manualStart() {
System.err.println("restart called" +
" Current state is: " + _state);
synchronized (_stateLock) {
if (!canManualStart())
Util.i("restart called"
+ " Current state is: " + _state);
synchronized(_stateLock) {
if(!canManualStart()) {
return;
_statusBar.replace("I2P is starting up");
}
_statusBar.replace(StatusBar.ICON1, "I2P is starting up");
setState(State.STARTING);
_starterThread = new Thread(new Starter());
_starterThread.start();
@ -338,37 +517,37 @@ public class RouterService extends Service {
}
// ******** end methods accessed from Activities and Receivers ************
/**
* Turn off the status bar.
* Unregister the receiver.
* If we were running, fire up the Stopper thread.
* Turn off the status bar. Unregister the receiver. If we were running,
* fire up the Stopper thread.
*/
@Override
public void onDestroy() {
System.err.println("onDestroy called" +
" Current state is: " + _state);
Util.i("onDestroy called"
+ " Current state is: " + _state);
_handler.removeCallbacks(_updater);
_statusBar.off();
_statusBar.remove();
I2PReceiver rcvr = _receiver;
if (rcvr != null) {
if(rcvr != null) {
synchronized(rcvr) {
try {
// throws if not registered
unregisterReceiver(rcvr);
} catch (IllegalArgumentException iae) {}
} catch(IllegalArgumentException iae) {
}
//rcvr.unbindRouter();
//_receiver = null;
}
}
synchronized (_stateLock) {
if (_state == State.STARTING)
synchronized(_stateLock) {
if(_state == State.STARTING) {
_starterThread.interrupt();
if (_state == State.STARTING || _state == State.RUNNING) {
// should this be in a thread?
_statusBar.replace("I2P is shutting down");
}
if(_state == State.STARTING || _state == State.RUNNING) {
// should this be in a thread?
_statusBar.replace(StatusBar.ICON5, "I2P is shutting down");
Thread stopperThread = new Thread(new Stopper(State.STOPPING, State.STOPPED));
stopperThread.start();
}
@ -376,16 +555,17 @@ public class RouterService extends Service {
}
/**
* Transition to the next state.
* If we still have a context, shut down the router.
* Turn off the status bar.
* Then transition to the stop state.
* Transition to the next state. If we still have a context, shut down the
* router. Turn off the status bar. Then transition to the stop state.
*/
private class Stopper implements Runnable {
private final State nextState;
private final State stopState;
/** call holding statelock */
/**
* call holding statelock
*/
public Stopper(State next, State stop) {
nextState = next;
stopState = stop;
@ -393,89 +573,103 @@ public class RouterService extends Service {
}
public void run() {
System.err.println(MARKER + this + " stopper thread" +
" Current state is: " + _state);
RouterContext ctx = _context;
if (ctx != null)
ctx.router().shutdown(Router.EXIT_HARD);
_statusBar.off();
System.err.println("********** Router shutdown complete");
synchronized (_stateLock) {
if (_state == nextState)
setState(stopState);
try {
Util.i(MARKER + this + " stopper thread"
+ " Current state is: " + _state);
RouterContext ctx = _context;
if(ctx != null) {
ctx.router().shutdown(Router.EXIT_HARD);
}
_statusBar.remove();
Util.i("********** Router shutdown complete");
synchronized(_stateLock) {
if(_state == nextState) {
setState(stopState);
}
}
} finally {
stopForeground(true);
_statusBar.remove();
}
}
}
/**
* First (early) hook.
* Update the status bar.
* Unregister the receiver.
* First (early) hook. Update the status bar. Unregister the receiver.
*/
private class ShutdownHook implements Runnable {
public void run() {
System.err.println(this + " shutdown hook" +
" Current state is: " + _state);
_statusBar.replace("I2P is shutting down");
Util.i(this + " shutdown hook"
+ " Current state is: " + _state);
_statusBar.replace(StatusBar.ICON5, "I2P is shutting down");
I2PReceiver rcvr = _receiver;
if (rcvr != null) {
if(rcvr != null) {
synchronized(rcvr) {
try {
// throws if not registered
unregisterReceiver(rcvr);
} catch (IllegalArgumentException iae) {}
} catch(IllegalArgumentException iae) {
}
//rcvr.unbindRouter();
//_receiver = null;
}
}
synchronized (_stateLock) {
synchronized(_stateLock) {
// null out to release the memory
_context = null;
if (_state == State.STARTING)
if(_state == State.STARTING) {
_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);
}
}
}
}
/**
* Second (late) hook.
* Turn off the status bar.
* Null out the context.
* If we were stopped manually, do nothing.
* If we were stopped because of no network, start the waiter thread.
* If it stopped of unknown causes or from manualQuit(), kill the Service.
* Second (late) hook. Turn off the status bar. Null out the context. If we
* were stopped manually, do nothing. 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 {
public void run() {
System.err.println(this + " final shutdown hook" +
" Current state is: " + _state);
_statusBar.off();
//I2PReceiver rcvr = _receiver;
synchronized (_stateLock) {
// null out to release the memory
_context = null;
Runtime.getRuntime().gc();
if (_state == State.STARTING)
_starterThread.interrupt();
if (_state == State.MANUAL_STOPPING) {
setState(State.MANUAL_STOPPED);
} else if (_state == State.NETWORK_STOPPING) {
// start waiter handler
setState(State.WAITING);
_handler.postDelayed(new Waiter(), 10*1000);
} else if (_state == State.STARTING || _state == State.RUNNING ||
_state == State.STOPPING) {
System.err.println(this + " died of unknown causes");
setState(State.STOPPED);
stopSelf();
} else if (_state == State.MANUAL_QUITTING) {
setState(State.MANUAL_QUITTED);
stopSelf();
public void run() {
try {
Util.i(this + " final shutdown hook"
+ " Current state is: " + _state);
//I2PReceiver rcvr = _receiver;
synchronized(_stateLock) {
// null out to release the memory
_context = null;
Runtime.getRuntime().gc();
if(_state == State.STARTING) {
_starterThread.interrupt();
}
if(_state == State.MANUAL_STOPPING) {
setState(State.MANUAL_STOPPED);
} else if(_state == State.NETWORK_STOPPING) {
// start waiter handler
setState(State.WAITING);
_handler.postDelayed(new Waiter(), 10 * 1000);
} 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() {
SharedPreferences prefs = getSharedPreferences(SHARED_PREFS, 0);
String stateString = prefs.getString(LAST_STATE, State.INIT.toString());
for (State s : State.values()) {
if (s.toString().equals(stateString))
for(State s : State.values()) {
if(s.toString().equals(stateString)) {
return s;
}
}
return State.INIT;
}
@ -495,7 +690,9 @@ public class RouterService extends Service {
saveState();
}
/** @return success */
/**
* @return success
*/
private boolean saveState() {
SharedPreferences prefs = getSharedPreferences(SHARED_PREFS, 0);
SharedPreferences.Editor edit = prefs.edit();

View File

@ -5,20 +5,24 @@ import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import java.lang.Thread.UncaughtExceptionHandler;
import net.i2p.android.router.R;
import net.i2p.android.router.activity.MainActivity;
public class StatusBar {
class StatusBar {
private final Context ctx;
private final Intent intent;
private final Notification notif;
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 ICON2 = R.drawable.ic_launcher_itoopie_330;
public static final int ICON3 = R.drawable.ic_launcher_itoopie;
public static final int ICON4 = R.drawable.ic_launcher_itoopie_120;
public static final int ICON5 = R.drawable.ic_launcher_itoopie_150;
public static final int ICON6 = R.drawable.ic_launcher_itoopie_180;
StatusBar(Context cx) {
ctx = cx;
@ -26,20 +30,23 @@ public class StatusBar {
mgr = (NotificationManager)ctx.getSystemService(ns);
Thread.currentThread().setUncaughtExceptionHandler(new CrashHandler(mgr));
int icon = R.drawable.ic_launcher_itoopie;
int icon = ICON1;
// won't be shown if replace() is called
String text = "Starting I2P";
long now = System.currentTimeMillis();
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.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
/** remove and re-add */
public void replace(String tickerText) {
public void replace(int icon, String tickerText) {
off();
notif.tickerText = tickerText;
notif.icon = icon;
notif.tickerText= tickerText;
update(tickerText);
}
@ -55,6 +62,10 @@ public class StatusBar {
}
public void off() {
//mgr.cancel(ID);
}
public void remove() {
mgr.cancel(ID);
}
@ -78,8 +89,12 @@ public class StatusBar {
} catch (Throwable ex) {}
}
System.err.println("In CrashHandler " + e);
e.printStackTrace();
e.printStackTrace(System.err);
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.Context;
import android.net.Uri;
import java.io.IOException;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
@ -15,9 +14,7 @@ import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
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
@ -62,7 +59,7 @@ public class AppCache {
private AppCache(Context ctx) {
_cacheDir = new File(ctx.getCacheDir(), DIR_NAME);
_cacheDir.mkdir();
Util.e("AppCache cache dir " + _cacheDir);
Util.d("AppCache cache dir " + _cacheDir);
_resolver = ctx.getContentResolver();
_cache = new LHM(MAX_FILES);
initialize();
@ -122,7 +119,7 @@ public class AppCache {
public Uri getCacheUri(Uri key) {
int hash = toHash(key);
// poke the LRU
Object present = null;
Object present;
synchronized(_cache) {
present = _cache.get(Integer.valueOf(hash));
}
@ -145,9 +142,9 @@ public class AppCache {
private void initialize() {
_totalSize = 0;
List<File> fileList = new ArrayList(MAX_FILES);
List<File> fileList = new ArrayList<File>(MAX_FILES);
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());
// oldest first, delete if too big or too old, else add to LHM
long now = System.currentTimeMillis();
@ -160,7 +157,7 @@ public class AppCache {
// TODO insertContent
}
}
Util.e("after init " + _cache.size() + " files totalling " + total + " bytes");
Util.d("after init " + _cache.size() + " files totalling " + total + " bytes");
}
/** oldest first */
@ -201,7 +198,7 @@ public class AppCache {
_cache.put(Integer.valueOf(hash), DUMMY);
}
} catch (IllegalArgumentException iae) {
Util.e("Huh bad file?" + iae);
Util.d("Huh bad file?" + iae);
f.delete();
}
}
@ -285,6 +282,7 @@ public class AppCache {
* on remove.
*/
private static class LHM extends LinkedHashMap<Integer, Object> {
private static final long serialVersionUID = 1L;
private final int _max;
public LHM(int max) {
@ -312,7 +310,7 @@ public class AppCache {
if (f.exists()) {
_totalSize -= f.length();
f.delete();
Util.e("AppCache deleted file " + f);
Util.d("AppCache deleted file " + f);
}
}
return rv;

View File

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

View File

@ -6,10 +6,8 @@ package net.i2p.util;
*/
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
import java.util.Queue;
/**
@ -28,7 +26,7 @@ class LogWriter implements Runnable {
private LogManager _manager;
private boolean _write;
private LogWriter() { // nop
}
@ -39,7 +37,7 @@ class LogWriter implements Runnable {
public void stopWriting() {
_write = false;
}
public void run() {
_write = true;
try {
@ -50,7 +48,7 @@ class LogWriter implements Runnable {
}
} catch (Exception e) {
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) {
t.printStackTrace();
t.printStackTrace(System.err);
} finally {
if (shouldWait) {
try {
try {
synchronized (this) {
this.wait(10*1000);
this.wait(10*1000);
}
} catch (InterruptedException ie) { // nop
}
@ -90,7 +88,7 @@ class LogWriter implements Runnable {
public String currentFile() {
return _currentFile != null ? _currentFile.getAbsolutePath() : "uninitialized";
}
private void rereadConfig() {
long now = Clock.getInstance().now();
if (now - _lastReadConfig > CONFIG_READ_ITERVAL) {
@ -122,7 +120,7 @@ class LogWriter implements Runnable {
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) {
String tag = src.getName();
int dot = tag.lastIndexOf(".");
@ -143,7 +141,7 @@ class LogWriter implements Runnable {
'[' + 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) {
String tag = src.getName();
int dot = tag.lastIndexOf(".");
@ -181,16 +179,4 @@ class LogWriter implements Runnable {
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
*/
public class SecureDirectory extends File {
private static final long serialVersionUID = 1L;
public SecureDirectory(String pathname) {
super(pathname);

View File

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

View File

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