diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml index 14c0bb78..dfb8ced2 100644 --- a/src/main/AndroidManifest.xml +++ b/src/main/AndroidManifest.xml @@ -66,7 +66,8 @@ android:name=".ProfileManagerActivity" android:label="@string/profiles" android:parentActivityName=".Shadowsocks" - android:exported="false"> + android:exported="false" + android:launchMode="singleTask"> @@ -76,7 +77,8 @@ + android:parentActivityName=".Shadowsocks" + android:launchMode="singleTask"/> @@ -61,7 +54,6 @@ android:title="@string/feature_cat"> diff --git a/src/main/scala/com/github/shadowsocks/ParserActivity.scala b/src/main/scala/com/github/shadowsocks/ParserActivity.scala index 1900a27f..6d24af45 100644 --- a/src/main/scala/com/github/shadowsocks/ParserActivity.scala +++ b/src/main/scala/com/github/shadowsocks/ParserActivity.scala @@ -44,33 +44,33 @@ import android.content.DialogInterface import android.graphics.Color import android.graphics.drawable.ColorDrawable import android.os.Bundle -import android.preference.PreferenceManager import android.view.WindowManager -import com.github.shadowsocks.database.{Profile, ProfileManager} import com.github.shadowsocks.utils.Parser class ParserActivity extends Activity { override def onCreate(savedInstanceState: Bundle) { super.onCreate(savedInstanceState) - showAsPopup(this) val data = getIntent.getData.toString - new AlertDialog.Builder(this) + val profile = Parser.parse(data) + if (profile.isEmpty) { // ignore + finish() + return + } + showAsPopup(this) + val dialog = new AlertDialog.Builder(this) .setTitle(R.string.add_profile_dialog) .setCancelable(false) .setPositiveButton(android.R.string.yes, ((dialog: DialogInterface, id: Int) => { - Parser.parse(data) match { - case Some(profile) => addProfile(profile) - case _ => // ignore - } + ShadowsocksApplication.profileManager.createOrUpdateProfile(profile.get) dialog.dismiss() }): DialogInterface.OnClickListener) .setNegativeButton(android.R.string.no, ((dialog: DialogInterface, id: Int) => { dialog.dismiss() - finish() }): DialogInterface.OnClickListener) .setMessage(data) .create() - .show() + dialog.setOnDismissListener((dialog: DialogInterface) => finish()) // builder method was added in API 17 + dialog.show() } def showAsPopup(activity: Activity) { @@ -82,13 +82,4 @@ class ParserActivity extends Activity { activity.getWindow.setAttributes(params.asInstanceOf[android.view.WindowManager.LayoutParams]) activity.getWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)) } - - def addProfile(profile: Profile) { - val profileManager = - new ProfileManager(PreferenceManager.getDefaultSharedPreferences(getBaseContext), - ShadowsocksApplication.dbHelper) - profileManager.createOrUpdateProfile(profile) - profileManager.reload(profile.id) - } - } diff --git a/src/main/scala/com/github/shadowsocks/ProfileManagerActivity.scala b/src/main/scala/com/github/shadowsocks/ProfileManagerActivity.scala index 1f2d9583..8bbebe0c 100644 --- a/src/main/scala/com/github/shadowsocks/ProfileManagerActivity.scala +++ b/src/main/scala/com/github/shadowsocks/ProfileManagerActivity.scala @@ -61,7 +61,7 @@ class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClickListe } def onClick(v: View) = { - ShadowsocksApplication.profileId(item.id) + ShadowsocksApplication.switchProfile(item.id) finish } } @@ -82,10 +82,8 @@ class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClickListe removedSnackbar.dismiss commitRemoves val pos = getItemCount - if (ShadowsocksApplication.profileManager.createOrUpdateProfile(item)) { - profiles += item - notifyItemInserted(pos) - } + profiles += item + notifyItemInserted(pos) } def remove(pos: Int) { @@ -126,6 +124,7 @@ class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClickListe toolbar.inflateMenu(R.menu.add_profile_methods) toolbar.setOnMenuItemClickListener(this) + ShadowsocksApplication.profileManager.setProfileAddedListener(profilesAdapter.add) val profilesList = findViewById(R.id.profilesList).asInstanceOf[RecyclerView] profilesList.setLayoutManager(new LinearLayoutManager(this)) profilesList.setItemAnimator(new DefaultItemAnimator) @@ -147,13 +146,14 @@ class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClickListe override def onDestroy { super.onDestroy + ShadowsocksApplication.profileManager.setProfileAddedListener(null) profilesAdapter.commitRemoves } override def onActivityResult(requestCode: Int, resultCode: Int, data: Intent) { val scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, data) if (scanResult != null) Parser.parse(scanResult.getContents) match { - case Some(profile) => profilesAdapter.add(profile) + case Some(profile) => ShadowsocksApplication.profileManager.createOrUpdateProfile(profile) case _ => // ignore } } @@ -168,7 +168,7 @@ class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClickListe true case R.id.manual_settings => ShadowsocksApplication.profileManager.reload(-1) - ShadowsocksApplication.profileId(ShadowsocksApplication.profileManager.save.id) + ShadowsocksApplication.switchProfile(ShadowsocksApplication.profileManager.save.id) finish true case _ => false diff --git a/src/main/scala/com/github/shadowsocks/Shadowsocks.scala b/src/main/scala/com/github/shadowsocks/Shadowsocks.scala index 853cef0f..1aa91273 100644 --- a/src/main/scala/com/github/shadowsocks/Shadowsocks.scala +++ b/src/main/scala/com/github/shadowsocks/Shadowsocks.scala @@ -55,12 +55,12 @@ import android.support.v4.content.ContextCompat import android.support.v7.app.AppCompatActivity import android.support.v7.widget.Toolbar import android.util.Log -import android.view.{View, ViewGroup, ViewParent} +import android.view.{ViewGroup, View, ViewParent} import android.widget._ import com.github.jorgecastilloprz.FABProgressCircle import com.github.shadowsocks.aidl.{IShadowsocksService, IShadowsocksServiceCallback} import com.github.shadowsocks.database._ -import com.github.shadowsocks.preferences.{NumberPickerPreference, DropDownPreference, PasswordEditTextPreference, SummaryEditTextPreference} +import com.github.shadowsocks.preferences.{DropDownPreference, NumberPickerPreference, PasswordEditTextPreference, SummaryEditTextPreference} import com.github.shadowsocks.utils._ import com.google.android.gms.ads.{AdRequest, AdSize, AdView} @@ -197,6 +197,7 @@ class Shadowsocks private lazy val preferences = getFragmentManager.findFragmentById(android.R.id.content).asInstanceOf[ShadowsocksSettings] + private var adView: AdView = _ private lazy val greyTint = ContextCompat.getColorStateList(this, R.color.material_blue_grey_700) private lazy val greenTint = ContextCompat.getColorStateList(this, R.color.material_green_700) @@ -349,22 +350,7 @@ class Shadowsocks override def onCreate(savedInstanceState: Bundle) { super.onCreate(savedInstanceState) - - // Initialize the profile - currentProfile = { - ShadowsocksApplication.currentProfile getOrElse currentProfile - } - ShadowsocksApplication.profileManager.load(currentProfile.id) - setContentView(R.layout.layout_main) - if (ShadowsocksApplication.proxy == "198.199.101.152") { - val adView = new AdView(this) - adView.setAdUnitId("ca-app-pub-9097031975646651/7760346322") - adView.setAdSize(AdSize.SMART_BANNER) - preferences.getView.asInstanceOf[ViewGroup].addView(adView, 0) - adView.loadAd(new AdRequest.Builder().build()) - } - // Initialize action bar val toolbar = findViewById(R.id.toolbar).asInstanceOf[Toolbar] toolbar.setTitle(getString(R.string.screen_name)) @@ -429,7 +415,8 @@ class Shadowsocks case Some(profile) => profile // updated case None => // removed val profiles = ShadowsocksApplication.profileManager.getAllProfiles.getOrElse(List[Profile]()) - ShadowsocksApplication.profileId(if (profiles.isEmpty) -1 else profiles.head.id) + if (profiles.isEmpty) ShadowsocksApplication.profileManager.createDefault() + else ShadowsocksApplication.switchProfile(profiles.head.id) } updatePreferenceScreen() @@ -437,14 +424,6 @@ class Shadowsocks serviceStop() } - def addProfile(profile: Profile) { - currentProfile = profile - ShadowsocksApplication.profileManager.createOrUpdateProfile(currentProfile) - ShadowsocksApplication.profileManager.reload(currentProfile.id) - - updatePreferenceScreen() - } - protected override def onPause() { super.onPause() ShadowsocksApplication.profileManager.save @@ -509,6 +488,14 @@ class Shadowsocks } private def updatePreferenceScreen() { + if (ShadowsocksApplication.proxy == "198.199.101.152" && adView == null) { + adView = new AdView(this) + adView.setAdUnitId("ca-app-pub-9097031975646651/7760346322") + adView.setAdSize(AdSize.SMART_BANNER) + preferences.getView.asInstanceOf[ViewGroup].addView(adView, 0) + adView.loadAd(new AdRequest.Builder().build()) + } + val profile = currentProfile for (name <- Shadowsocks.PROXY_PREFS) { val pref = preferences.findPreference(name) diff --git a/src/main/scala/com/github/shadowsocks/ShadowsocksApplication.scala b/src/main/scala/com/github/shadowsocks/ShadowsocksApplication.scala index f63114e0..a267eb1b 100644 --- a/src/main/scala/com/github/shadowsocks/ShadowsocksApplication.scala +++ b/src/main/scala/com/github/shadowsocks/ShadowsocksApplication.scala @@ -77,12 +77,14 @@ object ShadowsocksApplication { .build()) def profileId = settings.getInt(Key.profileId, -1) - def profileId(i: Int) = { - settings.edit.putInt(Key.profileId, i).apply - profileManager.load(i) - } + def profileId(i: Int) = settings.edit.putInt(Key.profileId, i).apply def proxy = settings.getString(Key.proxy, "") def currentProfile = profileManager.getProfile(profileId) + + def switchProfile(id: Int) = { + profileId(id) + profileManager.load(id) + } } class ShadowsocksApplication extends Application { diff --git a/src/main/scala/com/github/shadowsocks/database/ProfileManager.scala b/src/main/scala/com/github/shadowsocks/database/ProfileManager.scala index 2370153f..fd2cda35 100644 --- a/src/main/scala/com/github/shadowsocks/database/ProfileManager.scala +++ b/src/main/scala/com/github/shadowsocks/database/ProfileManager.scala @@ -46,9 +46,13 @@ import com.github.shadowsocks.utils.Key class ProfileManager(settings: SharedPreferences, dbHelper: DBHelper) { + var profileAddedListener: Profile => Any = _ + def setProfileAddedListener(listener: Profile => Any) = this.profileAddedListener = listener + def createOrUpdateProfile(profile: Profile): Boolean = { try { dbHelper.profileDao.createOrUpdate(profile) + if (profileAddedListener != null) profileAddedListener(profile) true } catch { case ex: Exception => @@ -163,4 +167,15 @@ class ProfileManager(settings: SharedPreferences, dbHelper: DBHelper) { updateProfile(profile) profile } + + def createDefault(): Profile = { + val profile = new Profile { + name = "Default" + host = "198.199.101.152" + remotePort = 443 + password = "u1rRWTssNv0p" + } + createOrUpdateProfile(profile) + profile + } } diff --git a/src/main/scala/com/github/shadowsocks/preferences/NatSwitchPreference.scala b/src/main/scala/com/github/shadowsocks/preferences/NatSwitchPreference.scala index 0d9e34ba..4471c329 100644 --- a/src/main/scala/com/github/shadowsocks/preferences/NatSwitchPreference.scala +++ b/src/main/scala/com/github/shadowsocks/preferences/NatSwitchPreference.scala @@ -22,5 +22,6 @@ final class NatSwitchPreference(context: Context, attrs: AttributeSet) extends S setSummary(R.string.nat_summary_no_root) } - override def onGetDefaultValue(a: TypedArray, index: Int) = ShadowsocksApplication.isVpnEnabled.asInstanceOf[AnyRef] + override def onGetDefaultValue(a: TypedArray, index: Int) = + (!ShadowsocksApplication.isVpnEnabled).asInstanceOf[AnyRef] }