Can we embed activity inside composable, so for example, when navigate to that composable its shows the activity content inside it(and not just start activity outside the composable), That what i succeed so far, but its just show the activity and not embed it
@Composable
fun MyContent() {
val context = LocalContext.current
val intent = Intent(context, MyActivity::class.java)
context.startActivity(intent)
}
The activity
class WebViews : ComponentActivity() {
var webView: WebView? = null
private var mUploadMessage: ValueCallback<Uri>? = null
var uploadMessage: ValueCallback<Array<Uri>>? = null
val REQUEST_SELECT_FILE = 100
private val FILECHOOSER_RESULTCODE = 1
var url = "http://example.com"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_web_views)
webView = findViewById<View>(R.id.webView) as WebView
webView!!.settings.javaScriptEnabled = true
webView!!.loadUrl(url)
webView!!.webViewClient = xWebViewClient()
webView!!.webChromeClient = object : WebChromeClient() {
// For 3.0 Devices (Start)
// onActivityResult attached before constructor
protected fun openFileChooser(
uploadMsg: ValueCallback<Uri>?, acceptType: String?
) {
mUploadMessage = uploadMsg
val i = Intent(Intent.ACTION_GET_CONTENT)
i.addCategory(Intent.CATEGORY_OPENABLE)
i.type = "image/*"
startActivityForResult(Intent.createChooser(i, "File Browser"), FILECHOOSER_RESULTCODE)
}
// For Lollipop 5.0 Devices
override fun onShowFileChooser(
mWebView: WebView?,
filePathCallback: ValueCallback<Array<Uri>>?,
fileChooserParams: WebChromeClient.FileChooserParams
): Boolean {
if (uploadMessage != null) {
uploadMessage!!.onReceiveValue(null)
uploadMessage = null
}
uploadMessage = filePathCallback
var intent: Intent? = null
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
intent = fileChooserParams.createIntent()
}
try {
startActivityForResult(intent, REQUEST_SELECT_FILE)
} catch (e: ActivityNotFoundException) {
uploadMessage = null
return false
}
return true
}
//For Android 4.1 only
protected fun openFileChooser(
uploadMsg: ValueCallback<Uri>?,
acceptType: String?,
capture: String?
) {
mUploadMessage = uploadMsg
val intent = Intent(Intent.ACTION_GET_CONTENT)
intent.addCategory(Intent.CATEGORY_OPENABLE)
intent.type = "image/*"
startActivityForResult(Intent.createChooser(intent, "File Browser"), FILECHOOSER_RESULTCODE)
}
protected fun openFileChooser(uploadMsg: ValueCallback<Uri>?) {
mUploadMessage = uploadMsg
val i = Intent(Intent.ACTION_GET_CONTENT)
i.addCategory(Intent.CATEGORY_OPENABLE)
i.type = "image/*"
startActivityForResult(Intent.createChooser(i, "File Chooser"), FILECHOOSER_RESULTCODE)
}
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, intent: Intent?) {
super.onActivityResult(requestCode, resultCode, intent)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (requestCode == REQUEST_SELECT_FILE) {
if (uploadMessage == null) return
uploadMessage!!.onReceiveValue(
WebChromeClient.FileChooserParams.parseResult(
resultCode,
intent
)
)
uploadMessage = null
}
} else if (requestCode == FILECHOOSER_RESULTCODE) {
if (null == mUploadMessage) return
// Use MainActivity.RESULT_OK if you're implementing WebView inside Fragment
// Use RESULT_OK only if you're implementing WebView inside an Activity
// val result: Uri? =
// if (intent == null || resultCode != WebViews.RESULT_OK) null else intent.data
// mUploadMessage.onReceiveValue(result)
mUploadMessage = null
}
}
private class xWebViewClient : WebViewClient() {
override fun shouldOverrideUrlLoading(view: WebView, url: String?): Boolean {
if (url != null) {
view.loadUrl(url)
}
return true
}
}
}
Is there a way to make it work as composable? Thanks
CodePudding user response:
Can we embed activity inside composable
Not really.
If the activity you are trying to start is from some third-party app, or is yours but is not written in Compose UI, the best that you can do is try activity embedding on Android 12L and higher.
If the activity that you are trying to start is your own, and it itself is built in Compose UI, you could get rid of that activity and navigate to its composable.
CodePudding user response:
You can try to reference the activity through an extenstion function:
inline fun <reified Activity : ComponentActivity> Context.getActivity(): Activity? {
return when (this) {
is Activity -> this
else -> {
var context = this
while (context is ContextWrapper) {
context = context.baseContext
if (context is Activity) return context
}
null
}
}
}
Usage:
@Composable
fun YourComposable() {
val activity = LocalContext.current.getActivity<MainActivity>()
}
CodePudding user response:
I think a good way of approaching your solution is just to hoist the open of the webview outside your composable
Example
class MainActivity() {
setContent {
YourComposable(param1, param2) {
openWebViewCallBack
}
}
}
@Composable
fun YourComposable(param1:Int, param2:String, onWebViewOpen: (url:String) -> Unit) { ... }