diff --git a/src/main/res/menu/app_manager_menu.xml b/src/main/res/menu/app_manager_menu.xml
new file mode 100644
index 00000000..f6a20e01
--- /dev/null
+++ b/src/main/res/menu/app_manager_menu.xml
@@ -0,0 +1,8 @@
+
diff --git a/src/main/res/values-zh/strings.xml b/src/main/res/values-zh/strings.xml
index cd059227..c89c2154 100755
--- a/src/main/res/values-zh/strings.xml
+++ b/src/main/res/values-zh/strings.xml
@@ -88,4 +88,11 @@
- 绕过局域网及中国大陆地址
+ 导出至剪贴板
+ 从剪贴板导入
+ 导出成功
+ 导出失败
+ 导入成功
+ 导入失败
+
diff --git a/src/main/res/values/colors.xml b/src/main/res/values/colors.xml
index 0b4a3cf9..89f7d8d6 100644
--- a/src/main/res/values/colors.xml
+++ b/src/main/res/values/colors.xml
@@ -4,6 +4,7 @@
#ff5e5e5e
#17170443
+ #FFFFFF
#000000
#646464
#c8c8c8
@@ -11,4 +12,4 @@
#00000000
#FF555555
-
\ No newline at end of file
+
diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml
index 6bd9bd7d..4e51f063 100755
--- a/src/main/res/values/strings.xml
+++ b/src/main/res/values/strings.xml
@@ -86,6 +86,12 @@
Flush DNS Cache
Flushing
Add Profile
+ Export to Clipboard
+ Import from Clipboard
+ Successfully export!
+ Failed to export.
+ Successfully import!
+ Failed to import.
Add this Shadowsocks Profile?
diff --git a/src/main/res/values/styles_shadow.xml b/src/main/res/values/styles_shadow.xml
index 3c845499..b76e2abe 100755
--- a/src/main/res/values/styles_shadow.xml
+++ b/src/main/res/values/styles_shadow.xml
@@ -29,10 +29,10 @@
- @drawable/cab_background_top_shadow
- @drawable/cab_background_bottom_shadow
- @style/ActionButton.CloseMode.Shadow
-
-
+
- @style/Theme.Shadow.Widget
-
+ - @style/m_textAppearanceLargePopupMenu
+ - @style/m_textAppearanceSmallPopupMenu
+
+
+
+
@@ -77,6 +85,9 @@
-
\ No newline at end of file
+
diff --git a/src/main/scala/com/github/shadowsocks/AppManager.scala b/src/main/scala/com/github/shadowsocks/AppManager.scala
index 4e478901..5d3ae5b2 100644
--- a/src/main/scala/com/github/shadowsocks/AppManager.scala
+++ b/src/main/scala/com/github/shadowsocks/AppManager.scala
@@ -40,6 +40,8 @@
package com.github.shadowsocks
import android.app.{Activity, ProgressDialog}
+import android.content.ClipboardManager
+import android.content.ClipData
import android.content.Context
import android.content.SharedPreferences
import android.content.pm.PackageManager
@@ -47,6 +49,8 @@ import android.graphics.{Bitmap, PixelFormat}
import android.os.Bundle
import android.os.Handler
import android.preference.PreferenceManager
+import android.view.Menu
+import android.view.MenuItem
import android.view.View
import android.view.View.OnClickListener
import android.view.ViewGroup
@@ -115,7 +119,7 @@ class AppManager extends Activity with OnCheckedChangeListener with OnClickListe
var appsLoaded: Boolean = false
def loadApps(context: Context): Array[ProxiedApp] = {
- val prefs: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
+ val prefs = PreferenceManager.getDefaultSharedPreferences(context)
val proxiedAppString = prefs.getString(Key.proxied, "")
val proxiedApps = proxiedAppString.split('|').sortWith(_ < _)
@@ -218,6 +222,48 @@ class AppManager extends Activity with OnCheckedChangeListener with OnClickListe
}
}
+ protected override def onOptionsItemSelected(item: MenuItem): Boolean = {
+ val clipboard = getSystemService(Context.CLIPBOARD_SERVICE).asInstanceOf[ClipboardManager]
+ val prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext)
+ item.getItemId match {
+ case R.id.action_export =>
+ val proxiedAppString = prefs.getString(Key.proxied, "")
+ val clip = ClipData.newPlainText(Key.proxied, proxiedAppString)
+ clipboard.setPrimaryClip(clip)
+ Toast.makeText(this, R.string.action_export_msg, Toast.LENGTH_SHORT).show()
+ return true
+ case R.id.action_import =>
+ if (clipboard.hasPrimaryClip) {
+ val clipdata = clipboard.getPrimaryClip
+ val label = clipdata.getDescription.getLabel
+ if (label == Key.proxied) {
+ val proxiedAppSequence = clipdata.getItemAt(0).getText
+ if (proxiedAppSequence != null) {
+ val proxiedAppString = proxiedAppSequence.toString
+ if (!proxiedAppString.isEmpty) {
+ Toast.makeText(this, R.string.action_import_msg, Toast.LENGTH_SHORT).show()
+ prefs.edit.putString(Key.proxied, proxiedAppString).commit()
+ // Restart activity
+ val intent = getIntent
+ finish()
+ startActivity(intent)
+ return true
+ }
+ }
+ }
+ }
+ Toast.makeText(this, R.string.action_import_err, Toast.LENGTH_SHORT).show()
+ return false
+ }
+ super.onOptionsItemSelected(item)
+ }
+
+ protected override def onCreateOptionsMenu(menu: Menu): Boolean = {
+ val inflater = getMenuInflater()
+ inflater.inflate(R.menu.app_manager_menu, menu)
+ return super.onCreateOptionsMenu(menu)
+ }
+
protected override def onCreate(savedInstanceState: Bundle) {
super.onCreate(savedInstanceState)
@@ -239,7 +285,7 @@ class AppManager extends Activity with OnCheckedChangeListener with OnClickListe
ImageLoader.getInstance().init(config)
val bypassSwitch = findViewById(R.id.bypassSwitch).asInstanceOf[Switch]
- val prefs: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(getBaseContext)
+ val prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext)
bypassSwitch.setOnCheckedChangeListener(new OnCheckedChangeListener {
def onCheckedChanged(button: CompoundButton, checked: Boolean) {
prefs.edit().putBoolean(Key.isBypassApps, checked).commit()
@@ -261,7 +307,7 @@ class AppManager extends Activity with OnCheckedChangeListener with OnClickListe
def saveAppSettings(context: Context) {
if (apps == null) return
- val prefs: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
+ val prefs = PreferenceManager.getDefaultSharedPreferences(this)
val proxiedApps = new StringBuilder
apps.foreach(app =>
if (app.proxied) {