{"id":17069385,"url":"https://github.com/nukc/qoo","last_synced_at":"2026-04-18T19:31:00.591Z","repository":{"id":149849029,"uuid":"291656231","full_name":"nukc/Qoo","owner":"nukc","description":"File Scan, Permissions Request, Easier to do things.","archived":false,"fork":false,"pushed_at":"2021-04-12T02:17:34.000Z","size":1595,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-23T10:44:28.345Z","etag":null,"topics":["files","imagepicker","permission-requests"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nukc.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-08-31T08:18:48.000Z","updated_at":"2024-02-19T10:28:26.000Z","dependencies_parsed_at":null,"dependency_job_id":"4741dbe5-213b-44ee-8489-59f58f49d4ca","html_url":"https://github.com/nukc/Qoo","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/nukc/Qoo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nukc%2FQoo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nukc%2FQoo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nukc%2FQoo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nukc%2FQoo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nukc","download_url":"https://codeload.github.com/nukc/Qoo/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nukc%2FQoo/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31982414,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-18T17:30:12.329Z","status":"ssl_error","status_checked_at":"2026-04-18T17:29:59.069Z","response_time":103,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["files","imagepicker","permission-requests"],"created_at":"2024-10-14T11:26:17.836Z","updated_at":"2026-04-18T19:31:00.565Z","avatar_url":"https://github.com/nukc.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Qoo\n\n```groovy\nimplementation 'com.github.nukc.permissionrer:permissionrer:1.0'\n\n```\n\n\u003e Scanner\n\n文件扫描，可通过 ``Path`` 或 ``Uri`` 。\n\n主要是通过实现 ``BasePathMatcher`` 或 ``BaseUriMatcher``。\n\nImage Picker Demo:\n\n\u003cimg src=\"https://raw.githubusercontent.com/nukc/Qoo/master/art/image_picker.png\" width=\"300px\"\u003e\n\n\u003e PermissionRer\n\n权限请求\n\n```kotlin\nPermissionRer.with(activity)\n    .request(Manifest.permission.READ_EXTERNAL_STORAGE)\n    .subscribe { granted, permissions -\u003e\n        if (granted) {\n            activity.startActivityForResult(\n                Intent(activity, ImagePickerActivity::class.java),\n                REQUEST_CODE\n            )\n        } else if (permissions[0].shouldShowRequestPermissionRationale) {\n            Toast.makeText(activity, R.string.tils_select_image_need_read_image_permission, Toast.LENGTH_SHORT).show()\n        }\n    }\n```\n\n\n#### 用法示例：\n\n```kotlin\nviewModelScope.launch {\n\tval fileBox = FileScanner.build(context)\n    \t.scan(ImageMatcher())\n    \t.scan(ApkMatcher())\n    \t.scan(InvalidImageMatcher(), InvalidVideoMatcher())\n    \t.setScanListener(..)\n        .start()\n}\n```\n\nScan Listener: \n\n```kotlin\ninterface OnScanListener {\n    fun onScanStart()\n\n    fun onScanning(item: BaseItem)\n\n    fun onScanEnd()\n}\n```\n\nMatcher eg:\n\n```kotlin\n/**\n * image matcher, eg: jpg, gif, png\n * @author Nukc.\n */\nopen class ImageMatcher : BaseUriMatcher\u003cImageItem\u003e() {\n\n    override fun provideUri(): Uri {\n        return MediaStore.Images.Media.EXTERNAL_CONTENT_URI\n    }\n\n    override fun provideProjection(): Array\u003cString\u003e {\n        return getProjection()\n    }\n\n    override fun provideSelection(): String? {\n        return null\n    }\n\n    override fun provideSelectionArgs(): Array\u003cString\u003e? {\n        return null\n    }\n\n    override fun provideSortOrder(): String? {\n        return \"${MediaStore.Files.FileColumns.DATE_ADDED} DESC\"\n    }\n\n    override fun fill(cur: Cursor): ImageItem {\n        val id = cur.getLong(cacheColumn[MediaStore.Images.Media._ID]!!)\n        val contentUri: Uri = ContentUris.withAppendedId(\n            MediaStore.Images.Media.EXTERNAL_CONTENT_URI,\n            id\n        )\n        return ImageItem(\n            id = id,\n            name = cur.getString(cacheColumn[MediaStore.Images.Media.DISPLAY_NAME]!!),\n            path = cur.getString(cacheColumn[MediaStore.Images.Media.DATA]!!),\n            size = cur.getLong(cacheColumn[MediaStore.Images.Media.SIZE]!!),\n            dateAdded = cur.getLong(cacheColumn[MediaStore.Images.Media.DATE_ADDED]!!),\n            dateModified = cur.getLong(cacheColumn[MediaStore.Images.Media.DATE_MODIFIED]!!),\n            mimeType = cur.getString(cacheColumn[MediaStore.Images.Media.MIME_TYPE]!!),\n            contentUri = contentUri,\n            bucketName = cur.getString(cacheColumn[MediaStore.Files.FileColumns.BUCKET_DISPLAY_NAME]!!)\n        )\n    }\n\n\n    private fun getProjection(): Array\u003cString\u003e {\n        return arrayOf(\n            MediaStore.Images.Media._ID,\n            MediaStore.Images.Media.DISPLAY_NAME,\n            MediaStore.Images.Media.SIZE,\n            MediaStore.Images.Media.MIME_TYPE,\n            MediaStore.Images.Media.DATA,\n            MediaStore.Images.Media.DATE_ADDED,\n            MediaStore.Images.Media.DATE_MODIFIED,\n            MediaStore.Files.FileColumns.BUCKET_ID,\n            MediaStore.Files.FileColumns.BUCKET_DISPLAY_NAME\n        )\n    }\n}\n```\n\n\n\n### TODO:\n\n* [x] Demo\n* [x] Image Picker\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnukc%2Fqoo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnukc%2Fqoo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnukc%2Fqoo/lists"}