目录
readme
本篇IDEA插件开发中使用的是kotlin语言
API
获取插件version
import com.intellij.openapi.extensions.PluginId
import com.intellij.ide.plugins.PluginManagerCore
val pluginId = PluginId.getId("idString")
val pluginVersion = PluginManagerCore.getPlugin(pluginId)?.version.toString()
获取IDEA版本
if (ApplicationInfo.getInstance().build.baselineVersion <= 211) { }
常用功能
读取Json文件关键字
fun getVersionAndUrlFromJson(url: String): Pair<String, String> {
val connection = URL(url).openConnection() as HttpURLConnection
connection.requestMethod = "GET"
connection.connectTimeout = 10000//设置读取超时
connection.readTimeout = 10000
val jsonString = connection.inputStream.bufferedReader().use { it.readText() }
val json = Json { ignoreUnknownKeys = true }
val jsonElement = json.parseToJsonElement(jsonString).jsonObject
val jetbrains = jsonElement["jetbrains"]?.jsonObject
//读取二级关键字
val version = jetbrains?.get("jetbrains_version")?.jsonPrimitive?.content ?: ""
val pluginUrl = jetbrains?.get("jetbrains_url")?.jsonPrimitive?.content ?: ""
return Pair(version, pluginUrl)
}
获取用户的本地某个路径
val userHome = System.getProperty("user.home")//用户目录
var pluginZipPath = Paths.get(userHome, "fittencode.zip").toString()//拼接
kt协程
runBlocking {
//会阻塞主线程
}
GlobalScope.launch {
//使用的是DefaultDispatcher,会自动切换到后台线程
//子线程中此处不可以做UI操作,不绑定生命周期
}
GlobalScope.launch(Dispatchers.Main) {
//使协程依托于主线程中,此时可以更新UI等操作
}
GlobalScope.launch(Dispatchers.IO) {
//效果与CoroutineScope一样
}
CoroutineScope(Dispatchers.IO).launch {
//比较推荐
}
回调函数
import java.util.function.Consumer
val callback: Consumer<PluginInstallCallbackData> = Consumer {
//执行后之后的回调操作
}
通知板块(重启)
fun notify(project: Project) {
val title = "title"
val notificationType = NotificationType.INFORMATION // 通知类型,可以选择不同的类型
val content = "通知内容。点击 <a href='doSomething'>这里</a> 来执行操作。"
val listener = object : NotificationListener {
override fun hyperlinkUpdate(notification: Notification, event: HyperlinkEvent) {
if (event.eventType == HyperlinkEvent.EventType.ACTIVATED) {
if (event.eventType == HyperlinkEvent.EventType.ACTIVATED && event.description == "name") {
val application = ApplicationManager.getApplication() as ApplicationImpl
application.invokeLater {
application.restart(6, ArrayUtil.EMPTY_STRING_ARRAY)
}
}
}
}
}
val notification = Notification("plugin_id", title, content, notificationType, listener)
Notifications.Bus.notify(notification, project)
}
从本地安装插件
//版本在211之前
fun installFromDiskOldVersion(project: Project, file: Path, callback: Consumer<PluginInstallCallbackData>) : Boolean{
val installFromDiskMethod = ReflectUtil.getMethod(
PluginInstaller::class.java,
"installFromDisk",
*arrayOf(InstalledPluginsTableModel::class.java, Path::class.java, Consumer::class.java, Component::class.java))
if (installFromDiskMethod == null) {
println("Method not found: installFromDisk")
return false
} else {
installFromDiskMethod.isAccessible = true
val tableModel = InstalledPluginsTableModel(project)
val ret = installFromDiskMethod.invoke(null as Any?, tableModel, file, callback, null)
return true
}
}
//211之后
fun installFromDiskNewVersion(project: Project, file: File, callback: Consumer<PluginInstallCallbackData>) : Boolean{
try {
val pluginEnablerClass = ReflectUtil.classForName("com.intellij.ide.plugins.PluginEnabler") as Class<*>
val pluginEnabler = ReflectUtil.getStaticField<Any>(pluginEnablerClass, "HEADLESS")
val tableModel = InstalledPluginsTableModel(project)
var installFromDiskMethod = ReflectUtil.getMethod(
PluginInstaller::class.java, "installFromDisk", *arrayOf(
InstalledPluginsTableModel::class.java, pluginEnablerClass, File::class.java, JComponent::class.java, Consumer::class.java))
if (installFromDiskMethod != null) {
installFromDiskMethod.isAccessible = true
val ret = installFromDiskMethod.invoke(null, tableModel, pluginEnabler, file, null, callback)
println("ret: $ret")
return true
}
installFromDiskMethod = ReflectUtil.getMethod(
PluginInstaller::class.java, "installFromDisk", *arrayOf(
InstalledPluginsTableModel::class.java, pluginEnablerClass, File::class.java, Project::class.java, JComponent::class.java, Consumer::class.java))
if (installFromDiskMethod != null) {
installFromDiskMethod.isAccessible = true
val ret = installFromDiskMethod.invoke(null, tableModel, pluginEnabler, file, project, null, callback)
return true
}
} catch (e: Exception) {
println("2.Error.cause: ${e.cause?.message}")
}
println("Method not found: installFromDisk")
return false
}
反射函数
object ReflectUtil {
private val classMap = ConcurrentHashMap<String, Class<*>>()
fun getMethod(clazz: Class<*>, methodName: String?, vararg parameterTypes: Class<*>?): Method? {
var targetClass: Class<*>? = clazz
do {
var method: Method? = null
try {
method = clazz.getDeclaredMethod(methodName, *parameterTypes)
} catch (var6: NoSuchMethodException) {
}
if (method != null) {
return method
}
targetClass = targetClass!!.superclass
} while (targetClass != null && targetClass != Any::class.java)
return null
}
@Throws(ClassNotFoundException::class)
fun classForName(className: String): Class<*>? {
var target = classMap[className]
if (target == null) {
target = Class.forName(className)
classMap[className] = target
}
return target
}
@Throws(NoSuchFieldException::class, IllegalAccessException::class)
fun <T> getStaticField(targetClass: Class<*>, fieldName: String): T {
val field: Field = targetClass.getDeclaredField(fieldName)
field.isAccessible = true
return field.get(null) as T
}
}