diff --git a/.gitignore b/.gitignore index e6380b23..97eb74f9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ *.iml .gradle +/gradle.properties /local.properties /.idea/caches /.idea/libraries diff --git a/README.md b/README.md index 2cfd89b9..39716f2f 100644 --- a/README.md +++ b/README.md @@ -18,57 +18,107 @@ ![图片](https://github.com/devzwy/open_nsfw_android/blob/dev/img/demopic.png) -### 开始使用(从1.3.9版本开始,依赖从JetPack移动到Maven仓库,可直接在项目中依赖,无需添加jetpack支持) +### 开始使用 (已从jCenter仓库迁移到Maven,注:新版本需要手动下载[nsfw.tflite](https://github.com/devzwy/open_nsfw_android/blob/dev/app/src/main/assets/nsfw.tflite)模型初始化使用) -- 开启tflite文件支持 +- [下载模型文件,并放入assets目录下](https://github.com/devzwy/open_nsfw_android/blob/dev/app/src/main/assets/nsfw.tflite) -``` - android { - aaptOptions { - noCompress "tflite" - } - } -``` -- 引入依赖(lastVersion更换为最新版本,最新版本为右边图片中的数字👉[ ![Download](https://api.bintray.com/packages/devzwy/maven/nsfw/images/download.svg) ](https://bintray.com/devzwy/maven/nsfw/_latestVersion)) +- 开启tflite文件读取支持(解决模型放在assets目录下无法读取的问题。如果模型不放在assets目录下可跳过该步骤) ``` - //可选 快速初始化扫描器,可免去初始化代码 - implementation 'com.zwy.nsfw:nsfw_initializer:lastVersion' - //必须 扫描器核心文件 - implementation 'com.zwy.nsfw:nsfw:lastVersion' - //必须 tensorflow 支持库 - implementation 'org.tensorflow:tensorflow-lite:2.1.0' - implementation 'org.tensorflow:tensorflow-lite-gpu:2.1.0' -``` +android { -- 初始化 + ... -[模型下载](https://github.com/devzwy/open_nsfw_android/blob/dev/app/src/main/assets/nsfw.tflite) + aaptOptions { + noCompress "tflite" + } +} +``` +- 引入依赖 ``` - //方式一,将模型文件放在Assets根目录下并命名为nsfw.tflite - NSFWHelper.init(context = this@Application) + dependencies { + ... + implementation 'io.github.devzwy:nsfw:1.5.1' + } - //方式二,适用于产品对apk大小控制严格,无法将模型文件直接放在apk中,可在用户打开Apk后台静默下载后指定模型路径进行初始化 - NSFWHelper.init(modelPath = "模型文件存放路径") +``` - //方式三,将模型文件放在Assets根目录下并命名为nsfw.tflite,引用该库可免去初始化代码 - implementation 'com.zwy.nsfw:nsfw_initializer:lastVersion' +- 初始化(建议在Application中进行) ``` -- 使用: + class KtApp : Application() { + override fun onCreate() { + super.onCreate() + + //开启日志输出,可选 + NSFWHelper.openDebugLog() + + //扫描前必须初始化 + NSFWHelper.initHelper( + context = this) + + //初始化api原型 + /* NSFW初始化函数 内部日志默认关闭,调试环境可使用openDebugLog()开启日志*/ + fun initHelper( + context: Context, //建议传入application,传入activity可能会有内存泄漏 + modelPath: String? = null,//模型文件路径,为空时将默认从Assets下读取 + isOpenGPU: Boolean = true, //是否开启GPU扫描加速,部分机型兼容不友好的可关闭。默认开启 + numThreads: Int = 4 //扫描数据时内部分配的线程 默认4 + ) + } + } ``` - //val mNSFWScoreBean:NSFWScoreBean = File.getNSFWScore() - //val mNSFWScoreBean:NSFWScoreBean = Bitmap.getNSFWScore() - //val mNSFWScoreBean:NSFWScoreBean = NSFWHelper.getNSFWScore(bitmap) +- 支持的api列表,带返回值的为同步,传入函数的为异步: + +>> [NSFWHelper.getNSFWScore(file: File): NSFWScoreBean]() +>> [getNSFWScore(file: File, onResult: ((NSFWScoreBean) -> Unit))]() +>> [getNSFWScore(filePath: String): NSFWScoreBean]() +>> [getNSFWScore(filePath: String, onResult: ((NSFWScoreBean) -> Unit))]() +>> [getNSFWScore(bitmap: Bitmap): NSFWScoreBean]() +>> [getNSFWScore(bitmap: Bitmap, onResult: ((NSFWScoreBean) -> Unit))]() + +- 识别结果说明 +``` mNSFWScoreBean.sfw ... 非涉黄数值 数值越大约安全 mNSFWScoreBean.nsfw ... 涉黄数值 数值越大约危险 mNSFWScoreBean.timeConsumingToLoadData ... 装载数据耗时 单位ms mNSFWScoreBean.timeConsumingToScanData ... 扫描图片耗时 单位ms ``` +- 调用参考 + +``` + //异步方式 + NSFWHelper.getNSFWScore(item.bitmap) { + this.text = + "nsfw:${it.nsfwScore}\nsfw:${it.sfwScore}\n扫描耗时:${it.timeConsumingToScanData} ms" + if (it.nsfwScore > 0.7) { + this.setBackgroundColor(Color.parseColor("#C1FF0000")) + } else if (it.nsfwScore > 0.5) { + this.setBackgroundColor(Color.parseColor("#C1FF9800")) + } else { + this.setBackgroundColor(Color.parseColor("#803700B3")) + } + } + + //同步方式 + NSFWHelper.getNSFWScore(item.bitmap).let { + this.text = + "nsfw:${it.nsfwScore}\nsfw:${it.sfwScore}\n扫描耗时:${it.timeConsumingToScanData} ms" + if (it.nsfwScore > 0.7) { + this.setBackgroundColor(Color.parseColor("#C1FF0000")) + } else if (it.nsfwScore > 0.5) { + this.setBackgroundColor(Color.parseColor("#C1FF9800")) + } else { + this.setBackgroundColor(Color.parseColor("#803700B3")) + } + } + +``` + ### 安卓手机直接[点我安装](http://d.6short.com/q9cv) ### 扫码下载 diff --git a/app/build.gradle b/app/build.gradle index c08bce76..e8e59499 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -27,6 +27,7 @@ android { } } + aaptOptions { noCompress "tflite" } @@ -61,4 +62,5 @@ dependencies { // implementation project(path: ':nsfw_initializer') implementation project(path: ':nsfw') +// implementation 'io.github.devzwy:nsfw:1.5.0' } diff --git a/app/src/androidTest/java/com/zww/sample/ExampleInstrumentedTest.kt b/app/src/androidTest/java/com/zww/sample/ExampleInstrumentedTest.kt deleted file mode 100644 index 440f90ec..00000000 --- a/app/src/androidTest/java/com/zww/sample/ExampleInstrumentedTest.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.zww.sample - -import androidx.test.platform.app.InstrumentationRegistry -import androidx.test.ext.junit.runners.AndroidJUnit4 - -import org.junit.Test -import org.junit.runner.RunWith - -import org.junit.Assert.* - -/** - * Instrumented test, which will execute on an Android device. - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -@RunWith(AndroidJUnit4::class) -class ExampleInstrumentedTest { - @Test - fun useAppContext() { - // Context of the app under test. - val appContext = InstrumentationRegistry.getInstrumentation().targetContext - assertEquals("com.zww.sample", appContext.packageName) - } -} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 9d66117c..69ad1e58 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,17 +2,10 @@ - - - - - - () { - @Override - public Unit invoke() { - Toast.makeText(JavaApp.this, "初始化成功", Toast.LENGTH_SHORT).show(); - return null; - } - }, new Function1() { - @Override - public Unit invoke(String s) { - Toast.makeText(JavaApp.this, s, Toast.LENGTH_SHORT).show(); - return null; - } - }); - } -} diff --git a/app/src/main/java/com/zww/sample/KtApp.kt b/app/src/main/java/com/zww/sample/KtApp.kt index a9ba199b..d97dfac0 100644 --- a/app/src/main/java/com/zww/sample/KtApp.kt +++ b/app/src/main/java/com/zww/sample/KtApp.kt @@ -4,19 +4,24 @@ import android.app.Application import android.widget.Toast import io.github.devzwy.nsfw.NSFWHelper -class KtApp:Application() { +class KtApp : Application() { override fun onCreate() { super.onCreate() + + //开启日志输出,可选 NSFWHelper.openDebugLog() + + //扫描前必须初始化 NSFWHelper.initHelper( - context = this, - modelPath = "${this.filesDir.path}/nsfw.tflite", - isOpenGPU = true, - onInitError = { - Toast.makeText(this, it, Toast.LENGTH_SHORT).show() - }, - onInitSuccess = { - Toast.makeText(this, "初始化成功", Toast.LENGTH_SHORT).show() - }) + context = this) + + //初始化api原型 + /* NSFW初始化函数 内部日志默认关闭,调试环境可使用openDebugLog()开启日志*/ +// fun initHelper( +// context: Context, //建议传入application,传入activity可能会有内存泄漏 +// modelPath: String? = null,//模型文件路径,为空时将默认从Assets下读取 +// isOpenGPU: Boolean = true, //是否开启GPU扫描加速,部分机型兼容不友好的可关闭。默认开启 +// numThreads: Int = 4 //扫描数据时内部分配的线程 默认4 +// ) } } \ No newline at end of file diff --git a/app/src/main/java/com/zww/sample/MainActivity.kt b/app/src/main/java/com/zww/sample/MainActivity.kt index f774e205..70ee1fca 100644 --- a/app/src/main/java/com/zww/sample/MainActivity.kt +++ b/app/src/main/java/com/zww/sample/MainActivity.kt @@ -26,6 +26,8 @@ class MainActivity : BaseActivity() { .diskCacheStrategy(DiskCacheStrategy.ALL) .into(holder.getView(R.id.iv)) holder.getView(R.id.tv).apply { + + //异步方式 NSFWHelper.getNSFWScore(item.bitmap) { this.text = "nsfw:${it.nsfwScore}\nsfw:${it.sfwScore}\n扫描耗时:${it.timeConsumingToScanData} ms" @@ -38,8 +40,8 @@ class MainActivity : BaseActivity() { } } - -// item.nsfwScoreBean.let { +// //同步方式 +// NSFWHelper.getNSFWScore(item.bitmap).let { // this.text = // "nsfw:${it.nsfwScore}\nsfw:${it.sfwScore}\n扫描耗时:${it.timeConsumingToScanData} ms" // if (it.nsfwScore > 0.7) { @@ -50,6 +52,7 @@ class MainActivity : BaseActivity() { // this.setBackgroundColor(Color.parseColor("#803700B3")) // } // } + } } diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index 912980c8..00000000 --- a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index eca70cfe..00000000 --- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index eca70cfe..00000000 --- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a571e600..00000000 Binary files a/app/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 61da551c..00000000 Binary files a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index c41dd285..00000000 Binary files a/app/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index db5080a7..00000000 Binary files a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 15ac6817..00000000 Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index b216f2d3..00000000 Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index f25a4197..00000000 Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index e96783cc..00000000 Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/app/src/main/res/xml/network_security_config.xml b/app/src/main/res/xml/network_security_config.xml deleted file mode 100644 index 2439f15c..00000000 --- a/app/src/main/res/xml/network_security_config.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/app/src/test/java/com/zww/sample/ExampleUnitTest.kt b/app/src/test/java/com/zww/sample/ExampleUnitTest.kt deleted file mode 100644 index f912f63c..00000000 --- a/app/src/test/java/com/zww/sample/ExampleUnitTest.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.zww.sample - -import org.junit.Test - -import org.junit.Assert.* - -/** - * Example local unit test, which will execute on the development machine (host). - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -class ExampleUnitTest { - @Test - fun addition_isCorrect() { - assertEquals(4, 2 + 2) - } -} \ No newline at end of file diff --git a/build.gradle b/build.gradle index 7b576e9d..ca1ba1b8 100644 --- a/build.gradle +++ b/build.gradle @@ -1,16 +1,14 @@ buildscript { - ext.kotlin_version = '1.3.72' - ext.libVersion = '1.5.0' + ext.kotlin_version = '1.4.32' + ext.libVersion = '1.5.1' repositories { + mavenCentral() jcenter() google() - mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:4.0.0' + classpath 'com.android.tools.build:gradle:4.1.2' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.3' - classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' classpath "org.jetbrains.dokka:dokka-gradle-plugin:0.9.18" } } diff --git a/gradle.properties b/gradle.properties index aa410575..6c9cf518 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,4 +2,9 @@ org.gradle.jvmargs=-Xmx1536m kotlin.code.style=official kotlin.coroutines=enable android.useAndroidX=true -android.enableJetifier=true \ No newline at end of file +android.enableJetifier=true +signing.keyId=EFDF121D +### 创建密钥时的密码 +signing.password=Aa112211.... +### .gpg文件的路径 +signing.secretKeyRingFile=/Users/zhaowenwen/.gnupg/secring.gpg \ No newline at end of file diff --git a/nsfw/build.gradle b/nsfw/build.gradle index f07974c7..a3ab5fe0 100644 --- a/nsfw/build.gradle +++ b/nsfw/build.gradle @@ -1,23 +1,18 @@ apply plugin: 'com.android.library' apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' -//apply plugin: 'com.github.dcendents.android-maven' -//apply plugin: 'com.jfrog.bintray' apply plugin: 'org.jetbrains.dokka' -apply plugin: 'maven-publish' - - -group 'com.zwy.nsfw' -version "$libVersion" +apply plugin: 'maven' +apply plugin: 'signing' android { compileSdkVersion 30 buildToolsVersion "30.0.2" defaultConfig { - minSdkVersion 21 + minSdkVersion 16 targetSdkVersion 30 - versionCode 139 + versionCode 151 versionName "$libVersion" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" @@ -31,14 +26,14 @@ android { } } - sourceSets { - main { - java { - include '**/*.java' - include '**/*.kt' - } - } - } +// sourceSets { +// main { +// java { +// include '**/*.java' +// include '**/*.kt' +// } +// } +// } } dependencies { @@ -55,132 +50,60 @@ dependencies { } -//version = "$libVersion" -//group = "com.zwy.nsfw" -//publish { -// userOrg = 'devzwy' -// repoName = 'maven' -// artifactId = 'nsfw' -// desc = 'android端离线鉴黄库' -// website = 'https://github.com/devzwy' -//} -// -//tasks.withType(Javadoc) {//防止编码问题 -// options.addStringOption('Xdoclint:none', '-quiet') -// options.addStringOption('encoding', 'UTF-8') -// options.addStringOption('charSet', 'UTF-8') -//} -def siteUrl = 'https://github.com/devzwy/open_nsfw_android' // 项目的主页(可以写自己的库的GitHub地址) -def gitUrl = 'https://github.com/devzwy/open_nsfw_android.git' // Git仓库的url -group = "io.github.devzwy" // (**慎重填写**)这里是groupId ,必须填写 一般填你唯一的包名,对应com.squareup.okhttp3:okhttp:3.4.1中的com.squareup.okhttp3部分 - - Properties properties = new Properties() properties.load(project.rootProject.file('local.properties').newDataInputStream()) def lUsername = properties.getProperty("username") def lPassword = properties.getProperty("password") -publishing { +group="io.github.devzwy" +version="$libVersion" + +uploadArchives { + repositories { + mavenDeployer { + beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } + + repository(url: "https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/") { + authentication(userName: lUsername, password: lPassword) + } + pom.project { + name 'nsfw' + packaging 'jar' + description 'android端离线鉴黄库' + url 'https://github.com/devzwy/open_nsfw_android' + + scm { + connection 'scm:git:https://github.com/devzwy/open_nsfw_android.git' + developerConnection 'scm:git:https://github.com/devzwy/open_nsfw_android.git' + url 'https://github.com/devzwy/open_nsfw_android' + } - publications { - // 推送 - publishMyProjectMiniexcel(MavenPublication) { - // 编译jar包 -// from components.java -// // 打包源码 -// artifact generateSourcesJar -// // javadoc -// artifact generateJavadoc - pom { - name = "nsfw" - description = "android端离线鉴黄库" - url = "https://github.com/devzwy/open_nsfw_android" licenses { license { - name = "The Apache License, Version 2.0" - url = "http://www.apache.org/licenses/LICENSE-2.0.txt" + name 'The Apache License, Version 2.0' + url 'http://www.apache.org/licenses/LICENSE-2.0.txt' } } + developers { developer { - id = "devzwy" - name = "devzwy" - email = "dev_zwy@aliyun.com" + id 'nsfw' + name 'dev_zwy' + email 'dev_zwy@aliyun.com' } } - scm { - connection = gitUrl - developerConnection = gitUrl - url = siteUrl - } } } } - // 到 https://oss.sonatype.org/#nexus-search; 搜索是否上传成功 - //Properties properties = new Properties() -//properties.load(project.rootProject.file('local.properties').newDataInputStream()) -//bintray { -// user = properties.getProperty("bintray.username") //读取 local.properties 文件里面的 bintray.user -// key = properties.getProperty("bintray.password") //读取 local.properties 文件里面的 bintray.apikey -// configurations = ['archives'] - - - repositories { - - //configurations = ['archives'] - // 发布Release版本可在版本号后面带上'-RELEASE',也可不带 - maven { +} - name 'Release' - url 'https://oss.sonatype.org/service/local/staging/deploy/maven2' - credentials { - username = lUsername - password = lPassword - } - } - // 发布Snapshot快照版本必须在版本号后面加上'-SNAPSHOT' -// maven { -// name = 'Snapshot' -// url = 'https://oss.sonatype.org/content/repositories/snapshots' -// credentials { -// username = "${NEXUS_USERNAME}" -// password = "${NEXUS_PASSWORD}" -// } -// } - } +signing { + sign configurations.archives } -//install { -// repositories.mavenInstaller { -// pom { -// project { -// packaging 'aar' -// name 'nsfw' //项目名字 -// url siteUrl -// licenses { -// license { -// name = 'The Apache Software License, Version 2.0' -// url = 'http://www.apache.org/licenses/LICENSE-2.0.txt' -// } -// } -// developers { -// developer { -// id 'z' //填写开发者的一些基本信息 -// name 'Jason' //填写开发者的一些基本信息 -// email 'dev_zwy@aliyun.com' //填写开发者的一些基本信息 -// } -// } -// scm { -// connection gitUrl -// developerConnection gitUrl -// url siteUrl -// } -// } -// } -// } -//} + task generateSourcesJar(type: Jar) { group = 'jar' from android.sourceSets.main.java.srcDirs @@ -215,19 +138,3 @@ artifacts { archives generateSourcesJar //sourcesJar } -//Properties properties = new Properties() -//properties.load(project.rootProject.file('local.properties').newDataInputStream()) -//bintray { -// user = properties.getProperty("bintray.user") //读取 local.properties 文件里面的 bintray.user -// key = properties.getProperty("bintray.apikey") //读取 local.properties 文件里面的 bintray.apikey -// configurations = ['archives'] -// pkg { -// repo = "maven" //(**慎重填写**)这里填写在bintray中自己新建仓库的名字 -// name = "nsfw" //(**慎重填写**)发布到JCenter上的项目名字,必须填写,对应com.squareup.okhttp3:okhttp:3.4.1中的okhttp -// websiteUrl = siteUrl -// vcsUrl = gitUrl -// licenses = ["Apache-2.0"] -// publish = true -// desc = 'android端离线鉴黄库' -// } -//} diff --git a/nsfw/src/main/AndroidManifest.xml b/nsfw/src/main/AndroidManifest.xml index e1dd25d9..8bedd48b 100644 --- a/nsfw/src/main/AndroidManifest.xml +++ b/nsfw/src/main/AndroidManifest.xml @@ -1,3 +1,3 @@ + package="io.github.devzwy.nsfw"> \ No newline at end of file diff --git a/nsfw/src/main/java/io/github/devzwy/nsfw/NSFWHelper.kt b/nsfw/src/main/java/io/github/devzwy/nsfw/NSFWHelper.kt index 36d837c4..9203bdd4 100644 --- a/nsfw/src/main/java/io/github/devzwy/nsfw/NSFWHelper.kt +++ b/nsfw/src/main/java/io/github/devzwy/nsfw/NSFWHelper.kt @@ -1,6 +1,7 @@ package io.github.devzwy.nsfw -import android.app.Application +import android.content.Context +import android.content.res.AssetFileDescriptor import android.graphics.Bitmap import android.graphics.BitmapFactory import android.graphics.Color @@ -13,16 +14,16 @@ import java.io.ByteArrayOutputStream import java.io.File import java.io.FileInputStream import java.io.FileNotFoundException -import java.lang.Exception import java.nio.ByteBuffer import java.nio.ByteOrder import java.nio.channels.FileChannel import java.text.DecimalFormat + object NSFWHelper { /*为空时表示未初始化SDK*/ - private var nsfwApplication: Application? = null + private var nsfwApplication: Context? = null /*扫描器*/ private lateinit var mInterpreter: Interpreter @@ -43,22 +44,17 @@ object NSFWHelper { * [modelPath] 模型文件路径,为空时将默认从Assets下读取 * [isOpenGPU] 是否开启GPU扫描加速,部分机型兼容不友好的可关闭。默认开启 * [numThreads] 扫描数据时内部分配的线程 默认4 - * [onInitSuccess] 初始化成功的回调 - * [onInitError] 初始化失败的回调,携带一个string */ fun initHelper( - context: Application, + context: Context, modelPath: String? = null, isOpenGPU: Boolean = true, - numThreads: Int = 4, - onInitSuccess: (() -> Unit)? = null, - onInitError: ((String) -> Unit)? = null + numThreads: Int = 4 ) { nsfwApplication?.let { logD("NSFWHelper已初始化,自动跳过本次初始化!") - onInitError?.let { it1 -> it1("请勿重复初始化") } return } @@ -72,6 +68,7 @@ object NSFWHelper { logD("未传入模型路径,尝试从Assets下读取'nsfw.tflite'模型文件") //指定模型为空时默认寻找assets目录下名称为nsfw.tflite的模型 try { + mInterpreter = Interpreter( nsfwApplication!!.assets.openFd("nsfw.tflite") .let { fileDescriptor -> @@ -82,15 +79,13 @@ object NSFWHelper { ) }, options ) - } catch (e: Exception) { + } catch (mFileNotFoundException: FileNotFoundException) { nsfwApplication = null logE("未从Assets下成功读取'nsfw.tflite'模型") - onInitError?.let { it("未从Assets下成功读取'nsfw.tflite'模型") } - - return + throw NSFWException("未从Assets下成功读取'nsfw.tflite'模型") } logD("从Assets下加载模型文件成功!") @@ -121,17 +116,13 @@ object NSFWHelper { nsfwApplication = null logE("模型配置错误,读取失败") - onInitError?.let { it("未能正确读取到模型文件 '${modelPath}'") } - - - return + throw NSFWException("未能正确读取到模型文件 '${modelPath}'") } } } logD("NSFWHelper初始化成功!${if (isOpenGPU) "GPU加速已成功开启" else "GPU加速未开启"}") - onInitSuccess?.let { it() } } @@ -169,12 +160,7 @@ object NSFWHelper { * 同步扫描文件NSFW数值 */ fun getNSFWScore(file: File): NSFWScoreBean { - - nsfwApplication?.let { - return getNSFWScore(BitmapFactory.decodeFile(file.path)) - } - - throw NSFWUnInitException() + return getNSFWScore(BitmapFactory.decodeFile(file.path)) } @@ -183,10 +169,6 @@ object NSFWHelper { */ fun getNSFWScore(file: File, onResult: ((NSFWScoreBean) -> Unit)) { - if (nsfwApplication == null) { - throw NSFWUnInitException() - } - GlobalScope.launch(Dispatchers.IO) { getNSFWScore(BitmapFactory.decodeFile(file.path)).let { result -> withContext(Dispatchers.Main) { @@ -194,18 +176,14 @@ object NSFWHelper { } } } + } /** * 同步扫描文件NSFW数值 */ fun getNSFWScore(filePath: String): NSFWScoreBean { - - nsfwApplication?.let { - return getNSFWScore(BitmapFactory.decodeFile(filePath)) - } - throw NSFWUnInitException() - + return getNSFWScore(BitmapFactory.decodeFile(filePath)) } @@ -214,10 +192,6 @@ object NSFWHelper { */ fun getNSFWScore(filePath: String, onResult: ((NSFWScoreBean) -> Unit)) { - if (nsfwApplication == null) { - throw NSFWUnInitException() - } - GlobalScope.launch(Dispatchers.IO) { getNSFWScore(BitmapFactory.decodeFile(filePath)).let { result -> withContext(Dispatchers.Main) { @@ -225,6 +199,7 @@ object NSFWHelper { } } } + } /** @@ -268,7 +243,7 @@ object NSFWHelper { } } } - throw NSFWUnInitException() + throw NSFWException("请调用NSFWHelper.init(...)函数后再试!") } @@ -289,10 +264,6 @@ object NSFWHelper { // # 使用index关键字喂入模型 // # 删除所有单维度的条目 // # 输出扫描结果 - if (nsfwApplication == null) { - logE("未初始化") - throw NSFWUnInitException() - } GlobalScope.launch(Dispatchers.IO) { getNSFWScore(bitmap).let { result -> diff --git a/nsfw/src/main/java/io/github/devzwy/nsfw/utils.kt b/nsfw/src/main/java/io/github/devzwy/nsfw/utils.kt index f69cebf7..ea038fa4 100644 --- a/nsfw/src/main/java/io/github/devzwy/nsfw/utils.kt +++ b/nsfw/src/main/java/io/github/devzwy/nsfw/utils.kt @@ -24,6 +24,6 @@ fun Boolean.assetBoolean(onTrue: ()-> Unit,onFalse: ()-> Unit){ if (this) onTrue() else onFalse() } -class NSFWUnInitException:Exception("请调用NSFWHelper.init(...)函数后再试!") +class NSFWException(str:String):Exception(str) data class CovertBitmapResultBean(val imgData: ByteBuffer,val exceTime:Long)