Commit 69c18e80 authored by Max Lv's avatar Max Lv

update

parent 1a67a3c1

Too many changes to show.

To preserve performance only 1000 of 1000+ files are displayed.

......@@ -12,20 +12,9 @@ tests/gen
tests/local.properties
NUL
gen_*
libs/armeabi/ip6tables
libs/armeabi/iptables
libs/armeabi/obfsproxy
libs/armeabi/pdnsd
libs/armeabi/polipo
libs/armeabi/redsocks
libs/armeabi/shadowsocks
libs/x86/ip6tables
libs/x86/iptables
libs/x86/obfsproxy
libs/x86/pdnsd
libs/x86/polipo
libs/x86/redsocks
libs/x86/shadowsocks
*.class
*.o
local.sbt
#Intellij IDEA
*.iml
......@@ -33,3 +22,19 @@ libs/x86/shadowsocks
*.iws
.idea/
out/
#NDK
src/main/libs/armeabi/ip6tables
src/main/libs/armeabi/iptables
src/main/libs/armeabi/obfsproxy
src/main/libs/armeabi/pdnsd
src/main/libs/armeabi/polipo
src/main/libs/armeabi/redsocks
src/main/libs/armeabi/shadowsocks
src/main/libs/x86/ip6tables
src/main/libs/x86/iptables
src/main/libs/x86/obfsproxy
src/main/libs/x86/pdnsd
src/main/libs/x86/polipo
src/main/libs/x86/redsocks
src/main/libs/x86/shadowsocks
[submodule "jni/shadowsocks"]
path = jni/shadowsocks
url = https://github.com/madeye/shadowsocks-libev.git
language: java
language: scala
before_install:
- sudo apt-get update
- sudo apt-get install libc6-dev-i386
......@@ -14,4 +14,8 @@ before_install:
install:
- sudo pip install python-swiftclient
script:
- mvn clean install -DTRAVIS=true
- wget https://raw.github.com/paulp/sbt-extras/master/sbt
- chmod u+x ./sbt
- cp local.sbt.example local.sbt
- ./sbt android:package-release
- ./sbt deploy
This diff is collapsed.
......@@ -11,53 +11,21 @@ A [shadowsocks](http://shadowsocks.org) client for Android, powered by amazing n
## PREREQUISITES
* JDK 1.6+
* Maven 3.0.3+
* SBT 0.12.3+
* Android SDK r17+
* Android NDK r8+
* Local maven dependencies
```bash
git clone https://github.com/mosabua/maven-android-sdk-deployer.git
pushd maven-android-sdk-deployer
export ANDROID_HOME=/path/to/android/sdk
mvn install -P 4.1
popd
```
* Build native dependecies
```bash
ndk-build
cp libs/armeabi/pdnsd assets/
```
* Android NDK r8d+
## BUILD
* Create your key following the instructions at
http://developer.android.com/guide/publishing/app-signing.html#cert
* Create a profile in your settings.xml file in ~/.m2 like this
```xml
<settings>
<profiles>
<profile>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<sign.keystore>/absolute/path/to/your.keystore</sign.keystore>
<sign.alias>youralias</sign.alias>
<sign.keypass>keypass</sign.keypass>
<sign.storepass>storepass</sign.storepass>
</properties>
</profile>
</profiles>
</settings>
```
* Create your key following the instructions at http://developer.android.com/guide/publishing/app-signing.html#cert
* Put your key in ~/.keystore
* Create local.sbt from local.sbt.example with your own key alias
* Invoke the building like this
```bash
mvn clean install
# Optional
./build-ndk.sh
# Build
sbt android:prepare-market
```
#!/bin/bash
cd src/main
ndk-build
for app in ip6tables iptables obfsproxy pdnsd polipo redsocks shadowsocks
do
cp libs/armeabi/$app assets/arm/
cp libs/x86/$app assets/x86/
mv libs/armeabi/$app assets/arm/
mv libs/x86/$app assets/x86/
done
javacOptions in Compile ++= Seq("-source", "1.6", "-target", "1.6")
javacOptions in doc ++= Seq("-source", "1.6")
libraryDependencies ++= Seq(
"com.google.android" % "support-v4" % "r12",
"com.google.android.analytics" % "analytics" % "2.0beta4"
)
libraryDependencies ++= Seq(
"com.actionbarsherlock" % "actionbarsherlock" % "4.2.0" artifacts(Artifact("actionbarsherlock", "apklib", "apklib")),
"net.saik0.android.unifiedpreference" % "unifiedpreference" % "0.0.2" artifacts(Artifact("unifiedpreference", "apklib", "apklib")),
"org.jraf" % "android-switch-backport" % "1.0" artifacts(Artifact("android-switch-backport", "apklib", "apklib")),
"de.keyboardsurfer.android.widget" % "crouton" % "1.7"
)
Subproject commit 3ed7551ce18147740ad1e1113d9d4ca2c01e4248
import org.scalasbt.androidplugin.AndroidKeys._
keyalias in Android := "travis"
This diff is collapsed.
import sbt._
import sbt.Keys._
import org.scalasbt.androidplugin._
import org.scalasbt.androidplugin.AndroidKeys._
object App {
val version = "1.4.0"
}
object General {
val settings = Defaults.defaultSettings ++ Seq (
name := "shadowsocks",
version := App.version,
versionCode := 22,
scalaVersion := "2.9.2",
compileOrder := CompileOrder.JavaThenScala,
platformName in Android := "android-16",
resolvers += "madeye-maven" at "http://madeye-maven-repository.googlecode.com/git",
resolvers += "central-maven" at "http://repo.maven.apache.org/maven2"
)
val pgOptions = Seq("-keep class android.support.v4.app.** { *; }",
"-keep interface android.support.v4.app.** { *; }",
"-keep class com.actionbarsherlock.** { *; }",
"-keep interface com.actionbarsherlock.** { *; }",
"-keep class org.jraf.android.backport.** { *; }",
"-keep class com.github.shadowsocks.** { *; }",
"-keepattributes *Annotation*").mkString(" ")
val proguardSettings = Seq (
useProguard in Android := true,
proguardOption in Android := pgOptions
)
lazy val fullAndroidSettings =
General.settings ++
AndroidProject.androidSettings ++
TypedResources.settings ++
proguardSettings ++
AndroidManifestGenerator.settings ++
AndroidMarketPublish.settings ++ Seq (
cachePasswords in Android := true,
libraryDependencies += "org.scalatest" %% "scalatest" % "1.8" % "test"
)
}
object AndroidBuild extends Build {
val deploy = TaskKey[Unit]("deploy", "deploy to the build server")
val deployTask = deploy := {
"./deploy target shadowsocks-" + App.version + ".apk" !;
println("Deploy successfully")
}
lazy val main = Project (
"shadowsocks",
file("."),
settings = General.fullAndroidSettings ++ Seq(deployTask)
)
}
// resolvers += Resolver.url("scalasbt releases", new URL("http://scalasbt.artifactoryonline.com/scalasbt/sbt-plugin-releases"))(Resolver.ivyStylePatterns)
resolvers += Resolver.url("scalasbt releases", new URL("http://scalasbt.artifactoryonline.com/scalasbt/sbt-plugin-snapshots"))(Resolver.ivyStylePatterns)
addSbtPlugin("org.scala-sbt" % "sbt-android-plugin" % "0.6.3-20130429-SNAPSHOT")
addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.4.0")
This diff is collapsed.
/* Shadowsocks - A shadowsocks client for Android
* Copyright (C) 2012 <max.c.lv@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*
* ___====-_ _-====___
* _--^^^#####// \\#####^^^--_
* _-^##########// ( ) \\##########^-_
* -############// |\^^/| \\############-
* _/############// (@::@) \\############\_
* /#############(( \\// ))#############\
* -###############\\ (oo) //###############-
* -#################\\ / VV \ //#################-
* -###################\\/ \//###################-
* _#/|##########/\######( /\ )######/\##########|\#_
* |/ |#/\#/\#/\/ \#/\##\ | | /##/\#/ \/\#/\#/\#| \|
* ` |/ V V ` V \#\| | | |/#/ V ' V V \| '
* ` ` ` ` / | | | | \ ' ' ' '
* ( | | | | )
* __\ | | | | /__
* (vvv(VVV)(VVV)vvv)
*
* HERE BE DRAGONS
*
*/
package com.github.shadowsocks;
import android.R;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.widget.ImageView;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.HashMap;
import java.util.Stack;
public class ImageLoader {
final int stub_id = R.drawable.sym_def_app_icon;
PhotosQueue photosQueue = new PhotosQueue();
PhotosLoader photoLoaderThread = new PhotosLoader();
// the simplest in-memory cache implementation. This should be replaced with
// something like SoftReference or BitmapOptions.inPurgeable(since 1.6)
private HashMap<Integer, Bitmap> cache = new HashMap<Integer, Bitmap>();
private File cacheDir;
private Context context;
public ImageLoader(Context c) {
// Make the background thead low priority. This way it will not affect
// the UI performance
photoLoaderThread.setPriority(Thread.NORM_PRIORITY - 1);
context = c;
// Find the dir to save cached images
cacheDir = context.getCacheDir();
}
public void clearCache() {
// clear memory cache
cache.clear();
// clear SD cache
File[] files = cacheDir.listFiles();
for (File f : files)
f.delete();
}
// decodes image and scales it to reduce memory consumption
private Bitmap decodeFile(File f) {
try {
// decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f), null, o);
// Find the correct scale value. It should be the power of 2.
final int REQUIRED_SIZE = 70;
int width_tmp = o.outWidth, height_tmp = o.outHeight;
int scale = 1;
while (true) {
if (width_tmp / 2 < REQUIRED_SIZE || height_tmp / 2 < REQUIRED_SIZE) break;
width_tmp /= 2;
height_tmp /= 2;
scale *= 2;
}
// decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
} catch (FileNotFoundException ignored) {
}
return null;
}
public void DisplayImage(int uid, Activity activity, ImageView imageView) {
if (cache.containsKey(uid)) {
imageView.setImageBitmap(cache.get(uid));
} else {
queuePhoto(uid, activity, imageView);
imageView.setImageResource(stub_id);
}
}
private Bitmap getBitmap(int uid) {
// I identify images by hashcode. Not a perfect solution, good for the
// demo.
String filename = String.valueOf(uid);
File f = new File(cacheDir, filename);
// from SD cache
Bitmap b = decodeFile(f);
if (b != null) return b;
// from web
try {
BitmapDrawable icon = (BitmapDrawable) Utils.getAppIcon(context, uid);
return icon.getBitmap();
} catch (Exception ex) {
return null;
}
}
private void queuePhoto(int uid, Activity activity, ImageView imageView) {
// This ImageView may be used for other images before. So there may be
// some old tasks in the queue. We need to discard them.
photosQueue.Clean(imageView);
PhotoToLoad p = new PhotoToLoad(uid, imageView);
synchronized (photosQueue.photosToLoad) {
photosQueue.photosToLoad.push(p);
photosQueue.photosToLoad.notifyAll();
}
// start thread if it's not started yet
if (photoLoaderThread.getState() == Thread.State.NEW) photoLoaderThread.start();
}
public void stopThread() {
photoLoaderThread.interrupt();
}
// Used to display bitmap in the UI thread
class BitmapDisplayer implements Runnable {
Bitmap bitmap;
ImageView imageView;
public BitmapDisplayer(Bitmap b, ImageView i) {
bitmap = b;
imageView = i;
}
@Override
public void run() {
if (bitmap != null) {
imageView.setImageBitmap(bitmap);
} else {
imageView.setImageResource(stub_id);
}
}
}
class PhotosLoader extends Thread {
@Override
public void run() {
try {
while (true) {
// thread waits until there are any images to load in the
// queue
if (photosQueue.photosToLoad.size() == 0) {
synchronized (photosQueue.photosToLoad) {
photosQueue.photosToLoad.wait();
}
}
if (photosQueue.photosToLoad.size() != 0) {
PhotoToLoad photoToLoad;
synchronized (photosQueue.photosToLoad) {
photoToLoad = photosQueue.photosToLoad.pop();
}
Bitmap bmp = getBitmap(photoToLoad.uid);
cache.put(photoToLoad.uid, bmp);
Object tag = photoToLoad.imageView.getTag();
if (tag != null && ((Integer) tag) == photoToLoad.uid) {
BitmapDisplayer bd = new BitmapDisplayer(bmp, photoToLoad.imageView);
Activity a = (Activity) photoToLoad.imageView.getContext();
a.runOnUiThread(bd);
}
}
if (Thread.interrupted()) break;
}
} catch (InterruptedException e) {
// allow thread to exit
}
}
}
// stores list of photos to download
class PhotosQueue {
private final Stack<PhotoToLoad> photosToLoad = new Stack<PhotoToLoad>();
// removes all instances of this ImageView
public void Clean(ImageView image) {
synchronized (photosToLoad) {
for (int j = 0; j < photosToLoad.size(); ) {
if (photosToLoad.get(j).imageView == image) {
photosToLoad.remove(j);
} else {
++j;
}
}
}
}
}
// Task for the queue
private class PhotoToLoad {
public int uid;
public ImageView imageView;
public PhotoToLoad(int u, ImageView i) {
uid = u;
imageView = i;
}
}
}
This diff is collapsed.
/* Shadowsocks - A shadowsocks client for Android
* Copyright (C) 2012 <max.c.lv@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*
* ___====-_ _-====___
* _--^^^#####// \\#####^^^--_
* _-^##########// ( ) \\##########^-_
* -############// |\^^/| \\############-
* _/############// (@::@) \\############\_
* /#############(( \\// ))#############\
* -###############\\ (oo) //###############-
* -#################\\ / VV \ //#################-
* -###################\\/ \//###################-
* _#/|##########/\######( /\ )######/\##########|\#_
* |/ |#/\#/\#/\/ \#/\##\ | | /##/\#/ \/\#/\#/\#| \|
* ` |/ V V ` V \#\| | | |/#/ V ' V V \| '
* ` ` ` ` / | | | | \ ' ' ' '
* ( | | | | )
* __\ | | | | /__
* (vvv(VVV)(VVV)vvv)
*
* HERE BE DRAGONS
*
*/
package com.github.shadowsocks;
import android.app.Application;
import com.google.analytics.tracking.android.EasyTracker;
public class ShadowsocksApplication extends Application {
private static String sTmpDir;
public static String getTmpDir() {
return sTmpDir;
}
@Override
public void onCreate() {
EasyTracker.getInstance().setContext(this);
sTmpDir = getCacheDir().getAbsolutePath();
}
}
This diff is collapsed.
This diff is collapsed.
package com.github.shadowsocks.preferences;
import android.content.Context;
import android.preference.EditTextPreference;
import android.util.AttributeSet;
public class SummaryEditTextPreference extends EditTextPreference {
private CharSequence mDefaultSummary;
public SummaryEditTextPreference(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mDefaultSummary = getSummary();
}
public SummaryEditTextPreference(Context context, AttributeSet attrs) {
super(context, attrs);
mDefaultSummary = getSummary();
}
public SummaryEditTextPreference(Context context) {
super(context);
}
@Override
public void setSummary(CharSequence summary) {
if (summary.toString().isEmpty()) {
super.setSummary(mDefaultSummary);
} else {
super.setSummary(summary);
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.github.shadowsocks"
android:installLocation="auto"
android:versionCode="21"
android:versionName="1.3.9">
package="com.github.shadowsocks">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
......@@ -20,12 +16,13 @@
android:targetSdkVersion="16"/>
<application
android:name=".ShadowsocksApplication"
android:name="com.github.shadowsocks.ShadowsocksApplication"
android:hardwareAccelerated="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name">
<activity
android:name=".Shadowsocks"
android:name="com.github.shadowsocks.Shadowsocks"
android:label="@string/app_name"
android:theme="@style/Theme.GAEProxy"
android:launchMode="singleTask">
......@@ -34,8 +31,9 @@
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:name=".AppManager"
android:name="com.github.shadowsocks.AppManager"
android:theme="@style/Theme.GAEProxy"
android:label="@string/app_name">
<intent-filter>
......@@ -45,10 +43,10 @@
</activity>
<service
android:name=".ShadowsocksService"
android:name="com.github.shadowsocks.ShadowsocksService"
android:enabled="true"/>
<receiver android:name=".ShadowsocksReceiver">
<receiver android:name="com.github.shadowsocks.ShadowsocksReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.ACTION_SHUTDOWN"/>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment