我在Realm
的上使用TabbedLayout
。 Floating Action Button
上的fragment
将使用Dialog
包装器在CameraKit
上启动默认的相机应用。
我使用了示例here。
我在MainActivity上这样声明:
package com.example.app
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.viewpager.widget.ViewPager
import com.example.app.ui.main.SectionsPagerAdapter
import com.google.android.material.tabs.TabLayout
import io.realm.Realm
import io.realm.RealmConfiguration
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val sectionsPagerAdapter = SectionsPagerAdapter(this, supportFragmentManager)
val viewPager: ViewPager = findViewById(R.id.view_pager)
viewPager.adapter = sectionsPagerAdapter
val tabs: TabLayout = findViewById(R.id.tabs)
tabs.setupWithViewPager(viewPager)
Realm.init(this)
val configuration = RealmConfiguration.Builder()
.name("my.db")
.deleteRealmIfMigrationNeeded()
.schemaVersion(0)
.build()
Realm.setDefaultConfiguration(configuration)
}
}
列表片段:
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager
import com.google.android.material.floatingactionbutton.FloatingActionButton
import io.realm.Realm
import io.realm.RealmResults
import kotlinx.android.synthetic.main.fragment_list.*
class ListFragment : Fragment(), ListRecyclerAdapter.OnListListener {
private lateinit var layoutManager : LinearLayoutManager
lateinit var adapter : ListRecyclerAdapter
private lateinit var list : ArrayList<ListRealmObject>
lateinit var fab : FloatingActionButton
private var
realm = Realm.getDefaultInstance()
private var results : RealmResults<ListRealmObject> =
realm.where<ListRealmObject>(ListRealmObject::class.java).findAll()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_list, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
fab = fab
}
override fun onResume() {
super.onResume()
layoutManager = LinearLayoutManager(activity)
listRecyclerView.layoutManager = layoutManager
fab.setOnClickListener {
startActivity(Intent(activity, ListActivity::class.java))
/* val nextFrag = ListFragment()
requireActivity().supportFragmentManager.beginTransaction()
.replace(R.id.fragment_list_layout, nextFrag, "findThisFragment")
.addToBackStack(null)
.commit()*/
}
getAllFarmers()
}
companion object {
@JvmStatic
fun newInstance() =
ListFragment().apply {
arguments = Bundle().apply {
}
}
}
private fun getAllList() {
list = ArrayList()
listRecyclerView.adapter = ListRecyclerAdapter(activity, results, this)
listRecyclerView.adapter!!.notifyDataSetChanged()
}
override fun onListClick(position: Int) {
Log.d("ListClick", "onListClick : ${results[position]}")
val selectedList = results[position]
val intent = Intent(context, ListUpdateActivity::class.java)
if (selectedList != null) {
intent.putExtra("farmer", selectedList.getID())
startActivity(intent)
}
}
}
AddActivity
:
import android.Manifest
import android.app.AlertDialog
import android.app.DatePickerDialog
import android.content.DialogInterface
import android.content.pm.PackageManager
import android.os.Bundle
import android.os.Environment
import android.text.Editable
import android.text.TextWatcher
import android.view.View
import android.widget.*
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.core.view.forEach
import com.bumptech.glide.Glide
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.camerakit.CameraKitView
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.google.android.material.snackbar.Snackbar
import io.realm.Realm
import kotlinx.android.synthetic.main.activity_add.*
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import java.util.*
class AddActivity : AppCompatActivity() {
private val ALL_PERMISSIONS = 1
private var relativeLocation : String = ""
private var relative
FileName : String = ""
private fun openCameraDialog() {
//Inflating the AlertDialog
val alertDialog: AlertDialog.Builder = AlertDialog.Builder(this@AddActivity)
val inflater = layoutInflater
val dialogView: View = inflater.inflate(R.layout.camera_view, null)
alertDialog.setView(dialogView)
//CameraView UI
val screen: AlertDialog = alertDialog.create()
val cameraKitView: CameraKitView = dialogView.findViewById(R.id.cameraKitView)
val fabCapture: FloatingActionButton = dialogView.findViewById(R.id.fabCapture)
val fabDone: FloatingActionButton = dialogView.findViewById(R.id.fabDone)
val fabRepeat: FloatingActionButton = dialogView.findViewById(R.id.fabRepeat)
val imageView: ImageView = dialogView.findViewById(R.id.imgView)
//Handler
// val image: Array<File?> = arrayOf<File?>(null)
var image : File? = null
//We start the camera
cameraKitView.onStart()
//Capturing action
fabCapture.setOnClickListener {
cameraKitView.captureImage { cameraKitView, bytes ->
val folder =
File(relativeLocation)
if (!folder.exists()) folder.mkdirs()
/*image[0] =
File("${folder.absoluteFile}${File.separator}$relativeFileName.jpg")*/
image =
File("${folder.absoluteFile}${File.separator}${relativeFileName}_${getDate(System.currentTimeMillis(), "MM/dd/yyyy hh:mm:ss.SSS")}.jpg")
// if (image[0]?.exists()!!) image[0]?.delete()
if (image?.exists()!!) image?.delete()
val outputStream: FileOutputStream?
try {
// outputStream = FileOutputStream(image[0]?.path, false)
outputStream = FileOutputStream(image?.path, false)
outputStream.write(bytes)
outputStream.flush()
outputStream.close()
Glide.with(this@AddActivity)
//.load(image[0])
.load(image)
.skipMemoryCache(true)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.into(imageView)
cameraKitView.visibility = View.GONE
imageView.visibility = View.VISIBLE
fabCapture.visibility = View.GONE
fabDone.visibility = View.VISIBLE
fabRepeat.visibility = View.VISIBLE
} catch (e: IOException) {
e.printStackTrace()
}
}
}
//Recapturing
fabRepeat.setOnClickListener {
imageView.visibility = View.GONE
cameraKitView.visibility = View.VISIBLE
fabRepeat.visibility = View.GONE
fabDone.visibility = View.GONE
fabCapture.visibility = View.VISIBLE
}
//Done, let's display it in the imgViewAddActivity
fabDone.setOnClickListener {
pix = image
if (image!= null) Glide.with(this@AddActivity)
.load(image)
.skipMemoryCache(true)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.into(pixImageView)
screen.dismiss()
}
//To let us start new capturing
screen.setOnDismissListener(DialogInterface.OnDismissListener {
cameraKitView.stopVideo()
cameraKitView.onStop()
})
//Display the dialog
screen.show()
}
private fun checkPermissions() {
//Permissions we need
val permissions = arrayOf(
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.CAMERA
)
//Permissions that we will ask for
val needed_permissions: ArrayList<String> = ArrayList()
//Check which is not granted yet
for (permission in permissions) {
if (ContextCompat.checkSelfPermission(this@AddActivity, permission) !=
PackageManager.PERMISSION_GRANTED
) {
needed_permissions.add(permission)
}
}
//Ask for multiple not granted permissions
if (needed_permissions.isNotEmpty()) ActivityCompat.requestPermissions(
this@AddActivity,
needed_permissions.toArray(arrayOfNulls<String>(needed_permissions.size)),
ALL_PERMISSIONS
) else openCameraDialog()
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
//called when user presses ALLOW or DENY from Permission Request Popup
if (requestCode == ALL_PERMISSIONS) {
if (grantResults.isNotEmpty() &&
(grantResults[0]
+ grantResults[1]
+ grantResults[2]) == PackageManager.PERMISSION_GRANTED
) {
//This method will open the popup (dialog) cameraview
openCameraDialog()
} else {
Toast.makeText(
this@AddActivity,
"All permissions need to be granted",
Toast.LENGTH_LONG
)
.show()
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_add)
relativeLocation =
"${Environment.getExternalStorageDirectory()}/MyFolder"
pixImageView.setOnClickListener { checkPermissions() }
val realm = Realm.getDefaultInstance()
realm.executeTransaction {
val list = RealmObject()
list.pix = pix.toString()
}
finish()
}
}
}
现在,总体来说,该应用可以在minifyEnabled = false
上正常运行。我可以添加和删除记录并将其显示在RecyclerView
上,但仍可以拍照。即使我设置了minifyEnabled = true
,该应用程序仍然可以运行。除了当我点击pixImageView时。这是唯一因minifyEnabled = true
而崩溃的事情。应该注意的是,启动checkPermissions()
时,它与Realm无关,它只需要征求许可并启动默认摄像机,而是得到以下信息:
2020-07-19 09:30:24.207 2486-2486/? E/Zygote: isWhitelistProcess - Process is Whitelisted
2020-07-19 09:30:24.208 2486-2486/? E/Zygote: accessInfo : 1
2020-07-19 09:30:24.925 2486-2486/com.example.app E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.app, PID: 2486
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.app/com.example.app.MainActivity}: androidx.fragment.app.Fragment$e: Unable to instantiate fragment com.example.app.l: calling Fragment constructor caused an exception
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3092)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3235)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1926)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:6990)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1445)
Caused by: androidx.fragment.app.Fragment$e: Unable to instantiate fragment com.example.app.l: calling Fragment constructor caused an exception
at androidx.fragment.app.Fragment.S(:620)
at androidx.fragment.app.g.b(:57)
at androidx.fragment.app.n$e.a(:448)
at androidx.fragment.app.v.<init>(:86)
at androidx.fragment.app.n.c1(:2614)
at androidx.fragment.app.i.w(:198)
at androidx.fragment.app.e.onCreate(:237)
at androidx.appcompat.app.d.onCreate(:106)
at com.example.app.MainActivity.onCreate(:14)
at android.app.Activity.performCreate(Activity.java:7326)
at android.app.Activity.performCreate(Activity.java:7317)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3072)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3235)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1926)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:6990)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1445)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Constructor.newInstance0(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
at androidx.fragment.app.Fragment.S(:602)
at androidx.fragment.app.g.b(:57)
at androidx.fragment.app.n$e.a(:448)
at androidx.fragment.app.v.<init>(:86)
at androidx.fragment.app.n.c1(:2614)
at androidx.fragment.app.i.w(:198)
at androidx.fragment.app.e.onCreate(:237)
at androidx.appcompat.app.d.onCreate(:106)
at com.example.app.MainActivity.onCreate(:14)
at android.app.Activity.performCreate(Activity.java:7326)
at android.app.Activity.performCreate(Activity.java:7317)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3072)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3235)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1926)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:6990)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1445)
Caused by: java.lang.IllegalStateException: Call `Realm.init(Context)` before calling this method.
at io.realm.o.S(:402)
at com.example.app.l.<init>(:23)
at java.lang.reflect.Constructor.newInstance0(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
at androidx.fragment.app.Fragment.S(:602)
at androidx.fragment.app.g.b(:57)
at androidx.fragment.app.n$e.a(:448)
at androidx.fragment.app.v.<init>(:86)
at androidx.fragment.app.n.c1(:2614)
at androidx.fragment.app.i.w(:198)
at androidx.fragment.app.e.onCreate(:237)
at androidx.appcompat.app.d.onCreate(:106)
at com.example.app.MainActivity.onCreate(:14)
at android.app.Activity.performCreate(Activity.java:7326)
at android.app.Activity.performCreate(Activity.java:7317)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3072)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3235)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1926)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:6990)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1445)
我已经尝试在所有类上使用@Keep
批注,但无济于事。