Commit 555f4f68 authored by Mygod's avatar Mygod

Refine #609

parent e99a0eaa
...@@ -39,34 +39,27 @@ ...@@ -39,34 +39,27 @@
package com.github.shadowsocks package com.github.shadowsocks
import android.content.{Intent, DialogInterface} import android.content.{DialogInterface, Intent}
import android.graphics.Color import android.graphics.Color
import android.graphics.drawable.ColorDrawable import android.graphics.drawable.ColorDrawable
import android.nfc.{NdefMessage, NfcAdapter} import android.nfc.{NdefMessage, NfcAdapter}
import android.os.{Parcelable, Bundle} import android.support.v7.app.{AlertDialog, AppCompatActivity}
import android.support.v7.app.{AppCompatActivity, AlertDialog} import android.text.TextUtils
import android.view.WindowManager import android.view.WindowManager
import com.github.shadowsocks.utils.Parser import com.github.shadowsocks.utils.Parser
class ParserActivity extends AppCompatActivity { class ParserActivity extends AppCompatActivity {
override def onCreate(savedInstanceState: Bundle) { override def onNewIntent(intent: Intent) {
super.onCreate(savedInstanceState) super.onNewIntent(intent)
} val sharedStr = intent.getAction match {
case Intent.ACTION_VIEW => intent.getData.toString
case NfcAdapter.ACTION_NDEF_DISCOVERED =>
override def onResume() { val rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES)
super.onResume() if (rawMsgs != null && rawMsgs.nonEmpty)
var sharedStr = "" new String(rawMsgs(0).asInstanceOf[NdefMessage].getRecords()(0).getPayload) else null
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent.getAction)) { case _ => null
val rawMsgs = getIntent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES)
if (rawMsgs != null) {
val msg = rawMsgs(0).asInstanceOf[NdefMessage]
val records = msg.getRecords
sharedStr = new String(records(0).getPayload)
}
} else if (Intent.ACTION_VIEW.equals(getIntent.getAction)) {
sharedStr = getIntent.getData.toString
} }
if (TextUtils.isEmpty(sharedStr)) return
val profiles = Parser.findAll(sharedStr) val profiles = Parser.findAll(sharedStr)
if (profiles.isEmpty) { if (profiles.isEmpty) {
finish() finish()
...@@ -79,9 +72,9 @@ class ParserActivity extends AppCompatActivity { ...@@ -79,9 +72,9 @@ class ParserActivity extends AppCompatActivity {
.setPositiveButton(android.R.string.yes, ((_, _) => .setPositiveButton(android.R.string.yes, ((_, _) =>
profiles.foreach(ShadowsocksApplication.profileManager.createProfile)): DialogInterface.OnClickListener) profiles.foreach(ShadowsocksApplication.profileManager.createProfile)): DialogInterface.OnClickListener)
.setNegativeButton(android.R.string.no, null) .setNegativeButton(android.R.string.no, null)
.setMessage(sharedStr) .setMessage(profiles.mkString("\n"))
.create() .create()
dialog.setOnDismissListener((dialog: DialogInterface) => finish()) // builder method was added in API 17 dialog.setOnDismissListener((_: DialogInterface) => finish()) // builder method was added in API 17
dialog.show() dialog.show()
} }
......
...@@ -3,8 +3,8 @@ package com.github.shadowsocks ...@@ -3,8 +3,8 @@ package com.github.shadowsocks
import java.nio.charset.Charset import java.nio.charset.Charset
import android.content._ import android.content._
import android.nfc.{NdefRecord, NdefMessage, NfcEvent, NfcAdapter}
import android.nfc.NfcAdapter.CreateNdefMessageCallback import android.nfc.NfcAdapter.CreateNdefMessageCallback
import android.nfc.{NdefMessage, NdefRecord, NfcAdapter, NfcEvent}
import android.os.{Bundle, Handler} import android.os.{Bundle, Handler}
import android.support.v7.app.{AlertDialog, AppCompatActivity} import android.support.v7.app.{AlertDialog, AppCompatActivity}
import android.support.v7.widget.RecyclerView.ViewHolder import android.support.v7.widget.RecyclerView.ViewHolder
...@@ -13,7 +13,7 @@ import android.support.v7.widget.helper.ItemTouchHelper ...@@ -13,7 +13,7 @@ import android.support.v7.widget.helper.ItemTouchHelper
import android.support.v7.widget.helper.ItemTouchHelper.SimpleCallback import android.support.v7.widget.helper.ItemTouchHelper.SimpleCallback
import android.support.v7.widget.{DefaultItemAnimator, LinearLayoutManager, RecyclerView, Toolbar} import android.support.v7.widget.{DefaultItemAnimator, LinearLayoutManager, RecyclerView, Toolbar}
import android.text.style.TextAppearanceSpan import android.text.style.TextAppearanceSpan
import android.text.{TextUtils, SpannableStringBuilder, Spanned} import android.text.{SpannableStringBuilder, Spanned, TextUtils}
import android.view.{LayoutInflater, MenuItem, View, ViewGroup} import android.view.{LayoutInflater, MenuItem, View, ViewGroup}
import android.widget.{CheckedTextView, ImageView, LinearLayout, Toast} import android.widget.{CheckedTextView, ImageView, LinearLayout, Toast}
import com.github.shadowsocks.aidl.IShadowsocksServiceCallback import com.github.shadowsocks.aidl.IShadowsocksServiceCallback
...@@ -25,10 +25,8 @@ import net.glxn.qrgen.android.QRCode ...@@ -25,10 +25,8 @@ import net.glxn.qrgen.android.QRCode
import scala.collection.mutable.ArrayBuffer import scala.collection.mutable.ArrayBuffer
/** class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClickListener with ServiceBoundContext
* @author Mygod with CreateNdefMessageCallback {
*/
class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClickListener with ServiceBoundContext with CreateNdefMessageCallback{
private class ProfileViewHolder(val view: View) extends RecyclerView.ViewHolder(view) with View.OnClickListener { private class ProfileViewHolder(val view: View) extends RecyclerView.ViewHolder(view) with View.OnClickListener {
var item: Profile = _ var item: Profile = _
private val text = itemView.findViewById(android.R.id.text1).asInstanceOf[CheckedTextView] private val text = itemView.findViewById(android.R.id.text1).asInstanceOf[CheckedTextView]
...@@ -37,10 +35,10 @@ class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClickListe ...@@ -37,10 +35,10 @@ class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClickListe
{ {
val shareBtn = itemView.findViewById(R.id.share) val shareBtn = itemView.findViewById(R.id.share)
shareBtn.setOnClickListener(_ => { shareBtn.setOnClickListener(_ => {
val url = Parser.generate(item) val url = item.toString
if (nfcAdapter != null && nfcAdapter.isEnabled) { if (nfcAdapter != null && nfcAdapter.isEnabled) {
nfcAdapter.setNdefPushMessageCallback(ProfileManagerActivity.this,ProfileManagerActivity.this) nfcAdapter.setNdefPushMessageCallback(ProfileManagerActivity.this, ProfileManagerActivity.this)
nfcShareItem = url nfcShareItem = url.getBytes(Charset.forName("UTF-8"))
} }
val image = new ImageView(ProfileManagerActivity.this) val image = new ImageView(ProfileManagerActivity.this)
image.setLayoutParams(new LinearLayout.LayoutParams(-1, -1)) image.setLayoutParams(new LinearLayout.LayoutParams(-1, -1))
...@@ -58,14 +56,11 @@ class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClickListe ...@@ -58,14 +56,11 @@ class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClickListe
.setMessage(R.string.share_message) .setMessage(R.string.share_message)
.setTitle(R.string.share) .setTitle(R.string.share)
.create() .create()
dialog.setOnDismissListener(_ => if (nfcAdapter != null && nfcAdapter.isEnabled)
nfcAdapter.setNdefPushMessageCallback(null, ProfileManagerActivity.this))
dialog.show() dialog.show()
dialog.setOnDismissListener((dialog : DialogInterface) => {
if (nfcAdapter != null && nfcAdapter.isEnabled) {
nfcAdapter.setNdefPushMessageCallback(null,ProfileManagerActivity.this)
}
})
}) })
shareBtn.setOnLongClickListener((v: View) => { shareBtn.setOnLongClickListener(_ => {
Utils.positionToast(Toast.makeText(ProfileManagerActivity.this, R.string.share, Toast.LENGTH_SHORT), shareBtn, Utils.positionToast(Toast.makeText(ProfileManagerActivity.this, R.string.share, Toast.LENGTH_SHORT), shareBtn,
getWindow, 0, Utils.dpToPx(ProfileManagerActivity.this, 8)).show getWindow, 0, Utils.dpToPx(ProfileManagerActivity.this, 8)).show
true true
...@@ -163,8 +158,8 @@ class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClickListe ...@@ -163,8 +158,8 @@ class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClickListe
private var undoManager: UndoSnackbarManager[Profile] = _ private var undoManager: UndoSnackbarManager[Profile] = _
private lazy val clipboard = getSystemService(Context.CLIPBOARD_SERVICE).asInstanceOf[ClipboardManager] private lazy val clipboard = getSystemService(Context.CLIPBOARD_SERVICE).asInstanceOf[ClipboardManager]
private var nfcAdapter : NfcAdapter = _ private var nfcAdapter: NfcAdapter = _
private var nfcShareItem : String = _ private var nfcShareItem: Array[Byte] = _
override def onCreate(savedInstanceState: Bundle) { override def onCreate(savedInstanceState: Bundle) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
...@@ -181,9 +176,8 @@ class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClickListe ...@@ -181,9 +176,8 @@ class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClickListe
toolbar.setOnMenuItemClickListener(this) toolbar.setOnMenuItemClickListener(this)
nfcAdapter = NfcAdapter.getDefaultAdapter(this) nfcAdapter = NfcAdapter.getDefaultAdapter(this)
if (nfcAdapter != null && nfcAdapter.isEnabled) { if (nfcAdapter != null && nfcAdapter.isEnabled)
nfcAdapter.setNdefPushMessageCallback(null,ProfileManagerActivity.this) nfcAdapter.setNdefPushMessageCallback(null, ProfileManagerActivity.this)
}
ShadowsocksApplication.profileManager.setProfileAddedListener(profilesAdapter.add) ShadowsocksApplication.profileManager.setProfileAddedListener(profilesAdapter.add)
val profilesList = findViewById(R.id.profilesList).asInstanceOf[RecyclerView] val profilesList = findViewById(R.id.profilesList).asInstanceOf[RecyclerView]
...@@ -239,15 +233,15 @@ class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClickListe ...@@ -239,15 +233,15 @@ class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClickListe
override def onActivityResult(requestCode: Int, resultCode: Int, data: Intent) { override def onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
val scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, data) val scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, data)
if (scanResult != null && !TextUtils.isEmpty(scanResult.getContents)) if (scanResult != null) {
Parser.findAll(scanResult.getContents).foreach(ShadowsocksApplication.profileManager.createProfile) val contents = scanResult.getContents
if (!TextUtils.isEmpty(contents))
Parser.findAll(contents).foreach(ShadowsocksApplication.profileManager.createProfile)
}
} }
def createNdefMessage(nfcEvent: NfcEvent): NdefMessage = { def createNdefMessage(nfcEvent: NfcEvent) =
val ndefRecord = new NdefRecord(NdefRecord.TNF_ABSOLUTE_URI,nfcShareItem.getBytes(Charset.forName("US-ASCII")),Array[Byte](),nfcShareItem.getBytes(Charset.forName("US-ASCII"))) new NdefMessage(Array(new NdefRecord(NdefRecord.TNF_ABSOLUTE_URI, nfcShareItem, Array[Byte](), nfcShareItem)))
val ndefMessage = new NdefMessage(Array[NdefRecord](ndefRecord))
ndefMessage
}
def onMenuItemClick(item: MenuItem): Boolean = item.getItemId match { def onMenuItemClick(item: MenuItem): Boolean = item.getItemId match {
case R.id.scan_qr_code => case R.id.scan_qr_code =>
...@@ -276,7 +270,7 @@ class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClickListe ...@@ -276,7 +270,7 @@ class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClickListe
case R.id.action_export => case R.id.action_export =>
ShadowsocksApplication.profileManager.getAllProfiles match { ShadowsocksApplication.profileManager.getAllProfiles match {
case Some(profiles) => case Some(profiles) =>
clipboard.setPrimaryClip(ClipData.newPlainText(null, profiles.map(Parser.generate).mkString("\n"))) clipboard.setPrimaryClip(ClipData.newPlainText(null, profiles.mkString("\n")))
Toast.makeText(this, R.string.action_export_msg, Toast.LENGTH_SHORT).show Toast.makeText(this, R.string.action_export_msg, Toast.LENGTH_SHORT).show
case _ => Toast.makeText(this, R.string.action_export_err, Toast.LENGTH_SHORT).show case _ => Toast.makeText(this, R.string.action_export_err, Toast.LENGTH_SHORT).show
} }
......
...@@ -39,6 +39,9 @@ ...@@ -39,6 +39,9 @@
package com.github.shadowsocks.database package com.github.shadowsocks.database
import java.util.Locale
import android.util.Base64
import com.j256.ormlite.field.{DataType, DatabaseField} import com.j256.ormlite.field.{DataType, DatabaseField}
class Profile { class Profile {
...@@ -95,4 +98,7 @@ class Profile { ...@@ -95,4 +98,7 @@ class Profile {
@DatabaseField @DatabaseField
var userOrder: Long = _ var userOrder: Long = _
override def toString = "ss://" + Base64.encodeToString("%s:%s@%s:%d".formatLocal(Locale.ENGLISH,
method, password, host, remotePort).getBytes, Base64.NO_PADDING | Base64.NO_WRAP)
} }
...@@ -39,8 +39,6 @@ ...@@ -39,8 +39,6 @@
package com.github.shadowsocks.utils package com.github.shadowsocks.utils
import java.util.Locale
import android.util.{Base64, Log} import android.util.{Base64, Log}
import com.github.shadowsocks.database.Profile import com.github.shadowsocks.database.Profile
...@@ -48,9 +46,6 @@ object Parser { ...@@ -48,9 +46,6 @@ object Parser {
val TAG = "ShadowParser" val TAG = "ShadowParser"
private val pattern = "(?i)ss://([A-Za-z0-9+-/=_]+)".r private val pattern = "(?i)ss://([A-Za-z0-9+-/=_]+)".r
def generate (profile: Profile): String = "ss://" + Base64.encodeToString("%s:%s@%s:%d".formatLocal(Locale.ENGLISH,
profile.method, profile.password, profile.host, profile.remotePort).getBytes, Base64.NO_PADDING | Base64.NO_WRAP)
def findAll(data: CharSequence) = pattern.findAllMatchIn(data).map(m => try { def findAll(data: CharSequence) = pattern.findAllMatchIn(data).map(m => try {
val content = new String(Base64.decode(m.group(1), Base64.NO_PADDING), "UTF-8") val content = new String(Base64.decode(m.group(1), Base64.NO_PADDING), "UTF-8")
val methodIdx = content.indexOf(':') val methodIdx = content.indexOf(':')
......
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