Implement plugin interface in mobile app

This commit is contained in:
Mygod
2017-01-16 22:30:26 +08:00
parent c54745e241
commit 0ffae32a44
9 changed files with 136 additions and 103 deletions
@@ -1,8 +1,13 @@
package com.github.shadowsocks.plugin
import java.io.{File, FileNotFoundException, FileOutputStream, IOException}
import android.content.pm.PackageManager
import android.content.{BroadcastReceiver, Intent}
import android.content.{BroadcastReceiver, ContentResolver, Intent}
import android.net.Uri
import com.github.shadowsocks.ShadowsocksApplication.app
import com.github.shadowsocks.utils.CloseUtils.autoClose
import com.github.shadowsocks.utils.IOUtils
import scala.collection.JavaConverters._
@@ -22,4 +27,53 @@ object PluginManager {
})
cachedPlugins
}
// the following parts are meant to be used by :bg
@throws[Throwable]
def initPlugin(id: String): String = {
if (id.isEmpty) return null
var throwable: Throwable = null
try initNativePlugin(id) match {
case null =>
case path => return path
} catch {
case t: Throwable => if (throwable == null) throwable = t
}
// add other plugin types here
throw if (throwable == null)
new FileNotFoundException(app.getString(com.github.shadowsocks.R.string.plugin_unknown, id)) else throwable
}
@throws[IOException]
@throws[IndexOutOfBoundsException]
@throws[AssertionError]
private def initNativePlugin(id: String): String = {
val builder = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(PluginInterface.getAuthority(id))
val cr = app.getContentResolver
val cursor = cr.query(builder.build(), Array(PluginInterface.COLUMN_PATH), null, null, null)
if (cursor != null) {
var initialized = false
val pluginDir = new File(app.getFilesDir, "plugin")
if (cursor.moveToFirst()) {
IOUtils.deleteRecursively(pluginDir)
if (!pluginDir.mkdirs()) throw new FileNotFoundException("Unable to create plugin directory")
val pluginDirPath = pluginDir.getAbsolutePath + '/'
do {
val path = cursor.getString(0)
val file = new File(pluginDir, path)
assert(file.getAbsolutePath.startsWith(pluginDirPath))
autoClose(cr.openInputStream(builder.path(path).build()))(in =>
autoClose(new FileOutputStream(file))(out => IOUtils.copy(in, out)))
if (path == id) initialized = true
} while (cursor.moveToNext())
}
if (!initialized) throw new IndexOutOfBoundsException("Plugin entry binary not found")
new File(pluginDir, id).getAbsolutePath
} else null
}
}