I'm working on an Android application in Android Studio and I'm struggling to get my new fragment to display. In the logcat I see an error but I'm not sure what it means and can't find the answer to this issue anywhere else. I'm not sure if I'm making other errors in trying to set up this fragment.
I've tried only adding the fragment programmatically but found other examples on YouTube of adding the fragment to XML so I've tried that too and it didn't work either. I've been trying to work this out for days so any help would be greatly appreciated.
I tried starting the new fragment using fragmentTransaction.add and fragmentTransaction.replace with no difference.
Here is the main class
public class Dashboard extends AppCompatActivity {
Button menuButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dashboard);
menuButton = (Button) findViewById(R.id.menu_button);
menuButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startClassMenu();
}
});
}
public void startClassMenu(){
Fragment classMenuFragment = new ClassMenuFragment();
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.class_menu_fragment_place, classMenuFragment);
fragmentTransaction.commit();
}
}
Here is the main class xml
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginStart="0dp"
android:layout_marginLeft="0dp"
android:layout_marginTop="0dp"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
android:theme="?attr/actionBarTheme" />
<Button
android:id="#+id/menu_button"
android:layout_width="40dp"
android:layout_height="34dp"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginStart="21dp"
android:layout_marginLeft="21dp"
android:layout_marginTop="82dp"
android:background="#drawable/icon_blue_menu" />
<Button
android:id="#+id/home_button"
android:layout_width="40dp"
android:layout_height="38dp"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_marginTop="6dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:background="#drawable/home_icon" />
<Button
android:id="#+id/settings_button"
android:layout_width="37dp"
android:layout_height="33dp"
android:layout_alignBottom="#+id/menu_button"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_marginEnd="100dp"
android:layout_marginRight="100dp"
android:layout_marginBottom="72dp"
android:background="#drawable/icon_settings" />
<fragment
android:id="#+id/class_menu_fragment_place"
android:name="teamingenium.ingeniummobileapplication.fragments.ClassMenuFragment"
android:layout_width="177dp"
android:layout_height="187dp"
android:layout_alignEnd="#+id/menu_button"
android:layout_alignParentTop="true"
android:layout_marginTop="135dp"
android:layout_marginEnd="-127dp" />
Here is the fragment Java class
public class ClassMenuFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View view = inflater.inflate(R.layout.fragment_class_menu, container, false);
return view;
}
}
And here is the fragment xml class
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".fragments.ClassMenuFragment"
android:id="#+id/fragment_class_menu">
<TextView
android:id="#+id/fragment_class_menu_text_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:text="Fragment Started" />
</FrameLayout>
Here is the error from logcat
2018-12-29 20:09:48.405 1925-1925/system_process E/LoadedApk: Unable to instantiate appComponentFactory
java.lang.ClassNotFoundException: Didn't find class "android.support.v4.app.CoreComponentFactory" on path: DexPathList[[],nativeLibraryDirectories=[/system/priv-app/GoogleSdkSetup/lib/x86, /system/lib, /system/lib]]
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:134)
at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
at android.app.LoadedApk.createAppFactory(LoadedApk.java:226)
at android.app.LoadedApk.updateApplicationInfo(LoadedApk.java:338)
at android.app.ActivityThread.handleDispatchPackageBroadcast(ActivityThread.java:5388)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1733)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at com.android.server.SystemServer.run(SystemServer.java:454)
at com.android.server.SystemServer.main(SystemServer.java:294)
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:838)
refer to this link fragment;
As you use <fragment in your layout xml, you have no need to invoke startClassMenu() ,just to delete the startClassMenu() method and try again.
Try other two methods:
1, try to use android.app.Fragment and android.app.FragmentManager and android.app.Activity instead of using support library.
2, try to add -keep public class * extends android.support.v4.** in your proguard-rules.pro file
Try these
After checking this "DexPathList", it is definitely due to dexes.
multidex increases the number of methods
The Dalvik Executable specification limits the total number of methods that can be referenced within a single DEX file to 65,536
This error can be caused due to using both androidx and legacy android support libraries
Just open project structure and go to Dependencies and select All Modules and check is there any library which contains android.support
Just replace that with androidx version for that library
If still that issue exists then
Try these to fix this issue
dependencies {
def multidex_version = "2.0.1"
implementation "androidx.multidex:multidex:$multidex_version"
}
in the latest versions of android studio, just REMOVE these lines if it is there inside the manifest file
<application
...
tools:replace="android:appComponentFactory" // REMOVE THIS
android:appComponentFactory="androidx" // REMOVE THIS
>
Check for this line
defaultConfig {
...
multiDexEnabled true
}
Add this line in your MainActivity.kt
class MyApplication : Application() {
override fun attachBaseContext(base: Context) {
super.attachBaseContext(base)
MultiDex.install(this) //ADD THIS
}
}
Add this in your proguard-rules.pro file
-keep class com.example.** { *; }
Verify in this
buildTypes {
dev{
minifyEnabled false
}
release {
minifyEnabled true
}
}
In latest version of android studio there is no instant run disable options
Now android studio requires jdk versions above 8 so NO NEED TO ADDING THIS
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}
Related
My Build keeps crashing on App build. I followed two different ways to implement a lottie animation as a splash screen animation. Using a ConstraintLayout, this is my code.
activity_main.xml:
<ImageView
android:id="#+id/app_bg"
android:layout_width="500dp"
android:layout_height="1110dp"
android:scaleType="centerCrop"
android:src="#drawable/app_bg"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.501"
android:contentDescription="#string/app_name" />
<com.airbnb.lottie.LottieAnimationView
android:id="#+id/animationView"
android:layout_width="100dp"
android:layout_height="100dp"
app:lottie_autoPlay="true"
app:lottie_loop="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true"
android:layout_marginStart="32dp"
android:layout_marginTop="32dp"
android:layout_marginEnd="32dp"
android:layout_marginBottom="32dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
In my MainActivity.kt:
package com.dv202.ibot
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.airbnb.lottie.LottieDrawable
import com.dv202.ibot.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
setupAnim()
}
private fun setupAnim() {
binding.animationView.setAnimation(R.raw.lf30_editor_x9ijtq5k)
binding.animationView.repeatCount = LottieDrawable.INFINITE
binding.animationView.playAnimation()
binding.animationView.repeatCount = 5
}
}
My Gradle BuildType Module has been synced
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
I have png images for a backgroud and app logo in my drawable too :) Not sure what I'm missing or why the app build keeps crashing...
Can anyone please offer some assistance. I am new to learning Android Studio/kotlin, and just trying to get an animated splashscreen going
I'm learning to develop android app using kotlin. I have an app written using web technologies and I want to port it on android. I've created a simple layout where I have some input field that are needed to connect to the IP cam I need to display.
I've found this repo on github and I'm trying to implement it in my app but I don't know how to proceed.
How I can correctly implement the library I need and how I pass the data from the layout to the main file of the app so I can connect when the button is clicked? I want to create something similar to the screen of the repository I'm using to connect to the ip cam.
I've added the gradle plugin in my build.gradle file
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
}
android {
compileSdk 31
defaultConfig {
applicationId "com.example.onvif_camview"
minSdk 19
targetSdk 31
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
}
dependencies {
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'com.squareup.okhttp3:okhttp:3.10.0'
implementation 'com.rvirin.onvif:onvifcamera:1.1.6'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}
In my MainActivity.kt file I have added the needed code. but I get some error notice
Unresolved reference: OnvifDevice
package com.example.onvif_camview
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
currentDevice = OnvifDevice("IP_ADDRESS:PORT", "login", "pwd")
currentDevice.listener = this
currentDevice.getDeviceInformation()
}
// Called by the SDK each time a request is performed on the camera, when the result is parsed
override fun requestPerformed(response: OnvifResponse) {
Log.d("ONVIF", "Request ${response.request.type} performed.")
Log.d("ONVIF","Succeeded: ${response.success},
message: ${response.parsingUIMessage}")
if (response.request.type == GetDeviceInformation) {
currentDevice.getProfiles()
} else if (response.request.type == GetProfiles) {
currentDevice.getStreamURI()
} else if (response.request.type == GetStreamURI) {
Log.d("ONVIF", "Stream URI retrieved: ${currentDevice.rtspURI}")
}
}
}
in my layout I have this code
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<EditText
android:id="#+id/login"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:hint="Username"
android:inputType="textPersonName"
android:text="Username"
tools:layout_editor_absoluteX="91dp"
tools:layout_editor_absoluteY="189dp" />
<EditText
android:id="#+id/IP_ADDRESS:PORT"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:hint="IP_ADDRESS"
android:inputType="textPersonName"
android:text="Indirizzo IP"
tools:layout_editor_absoluteX="91dp"
tools:layout_editor_absoluteY="129dp" />
<EditText
android:id="#+id/pwd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:hint="Password"
android:inputType="textPersonName"
android:text="Password"
tools:layout_editor_absoluteX="92dp"
tools:layout_editor_absoluteY="252dp" />
<Button
android:id="#+id/button"
android:layout_width="209dp"
android:layout_height="43dp"
android:text="CONNETTI"
tools:layout_editor_absoluteX="93dp"
tools:layout_editor_absoluteY="314dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
place cursor somewhere in the middle of OnvifDevice(... and some hint should appear allowing importing dependency. you can press Alt+Enter for autoimport then
also you haven't implemented needed interface OnvifListener and didn't declared onvifDevice anywhere...
class MainActivity : AppCompatActivity(), OnvifListener {
lateinit onvifDevice:OnvifDevice
override fun onCreate(savedInstanceState: Bundle?) {
... rest of code
it should also be imported as above
Navigation from my BottomNavigationView isn't working correctly and I'm stumped.
When I first open the app, it works fine. I click a button in the BottomNavigationView and the corresponding fragment is displayed.
I start seeing the bug after I navigate from fragment A to fragment B using a "go to B" button on fragment A. From then on, when I click the A button in the BottomNavigationView, B is displayed.
Things I've tried:
I overrode all the fragment lifecycle callbacks in A (onCreate(), onCreateView(), onViewCreated(), onViewStateRestored(), onStart(), onResume()). I put breakpoints in each. None are hit when in the buggy state.
I created a new app with the Android template for Bottom Navigation Activity, and reproduced the bug there. The only thing I changed was to add a button on fragment A that navigates to fragment B.
I'm new to both Android and stack overflow so let me know if I'm doing anything silly. Thanks in advance for any help!
Here's the code that reproduces the bug. (Fragment A is the HomeFragment)
HomeFragment.kt
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.findNavController
import androidx.navigation.fragment.findNavController
import com.example.myapplication.R
import com.example.myapplication.databinding.FragmentHomeBinding
class HomeFragment : Fragment() {
private var _binding: FragmentHomeBinding? = null
// This property is only valid between onCreateView and
// onDestroyView.
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
val homeViewModel =
ViewModelProvider(this).get(HomeViewModel::class.java)
_binding = FragmentHomeBinding.inflate(inflater, container, false)
val root: View = binding.root
val textView: TextView = binding.textHome
homeViewModel.text.observe(viewLifecycleOwner) {
textView.text = it
}
return root
}
// This is the code I added
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.button.setOnClickListener {view ->
view.findNavController().navigate(HomeFragmentDirections.actionNavigationHomeToNavigationDashboard())
}
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
fragment_home.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.home.HomeFragment">
<TextView
android:id="#+id/text_home"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:textAlignment="center"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<!-- I added this button -->
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Dashboard"
app:layout_constraintTop_toBottomOf="#id/text_home"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
mobile_navigation.xml
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/mobile_navigation"
app:startDestination="#+id/navigation_home">
<fragment
android:id="#+id/navigation_home"
android:name="com.example.myapplication.ui.home.HomeFragment"
android:label="#string/title_home"
tools:layout="#layout/fragment_home" >
<!-- I added this action -->
<action
android:id="#+id/action_navigation_home_to_navigation_dashboard"
app:destination="#id/navigation_dashboard" />
</fragment>
<fragment
android:id="#+id/navigation_dashboard"
android:name="com.example.myapplication.ui.dashboard.DashboardFragment"
android:label="#string/title_dashboard"
tools:layout="#layout/fragment_dashboard" />
<fragment
android:id="#+id/navigation_notifications"
android:name="com.example.myapplication.ui.notifications.NotificationsFragment"
android:label="#string/title_notifications"
tools:layout="#layout/fragment_notifications" />
</navigation>
MainActivity.kt (didn't modify this)
package com.example.myapplication
import android.os.Bundle
import com.google.android.material.bottomnavigation.BottomNavigationView
import androidx.appcompat.app.AppCompatActivity
import androidx.navigation.findNavController
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.setupActionBarWithNavController
import androidx.navigation.ui.setupWithNavController
import com.example.myapplication.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val navView: BottomNavigationView = binding.navView
val navController = findNavController(R.id.nav_host_fragment_activity_main)
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
val appBarConfiguration = AppBarConfiguration(
setOf(
R.id.navigation_home, R.id.navigation_dashboard, R.id.navigation_notifications
)
)
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
}
}
activity_main.xml (didn't modify this)
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="?attr/actionBarSize">
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/nav_view"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="0dp"
android:layout_marginStart="0dp"
android:background="?android:attr/windowBackground"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:menu="#menu/bottom_nav_menu" />
<fragment
android:id="#+id/nav_host_fragment_activity_main"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:layout_constraintBottom_toTopOf="#id/nav_view"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="#navigation/mobile_navigation" />
</androidx.constraintlayout.widget.ConstraintLayout>
Top level build.gradle
// Top-level build file where you can add configuration options common to all sub-projects/modules.
// I added everything within the buildscript block
buildscript {
repositories {
google()
}
dependencies {
classpath("androidx.navigation:navigation-safe-args-gradle-plugin:2.4.1")
}
}
plugins {
id 'com.android.application' version '7.1.2' apply false
id 'com.android.library' version '7.1.2' apply false
id 'org.jetbrains.kotlin.android' version '1.6.10' apply false
}
task clean(type: Delete) {
delete rootProject.buildDir
}
build.gradle (app)
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
// I added this line
id 'androidx.navigation.safeargs.kotlin'
}
android {
compileSdk 31
defaultConfig {
applicationId "com.example.myapplication"
minSdk 26
targetSdk 31
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
buildFeatures {
viewBinding true
}
}
dependencies {
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.5.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.4.1'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.1'
implementation 'androidx.navigation:navigation-fragment-ktx:2.4.1'
implementation 'androidx.navigation:navigation-ui-ktx:2.4.1'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}
I figured it out. The fix is to add the last three lines to the action tag in mobile_navigation.xml:
<action
android:id="#+id/action_navigation_home_to_navigation_dashboard"
app:destination="#id/navigation_dashboard"
app:restoreState="true"
app:popUpTo="#id/navigation_home"
app:popUpToSaveState="true"
/>
More information about why this works: https://developer.android.com/guide/navigation/multi-back-stacks#nav-xml
I have searched for a lot of solutions to this problem but none of them worked for me.
Finally, I have found a lazy hack that can "fix" this "bug". I have already tested this solution for a while and no issues have been found so far.
Note: this is NOT an official way to fix this issue. I suggest NOT to use this solution UNTIL none of the solutions worked for you.
Solution:
Replace this line:
navController.navigate(R.id.navigation_dashboard);
with this line:
findViewById(R.id.nav_view).findViewById(R.id.navigation_dashboard).performClick();
R.id.nav_view is the id of the BottomNavigationView component. It could be inside your activity_main.xml.
R.id.navigation_dashboard is the id of the fragment that you want to navigate to. It could be inside your res/navigation/mobile_navigation.xml or res/navigation/nav_graph.xml.
I'm on Android Studio 3.4, and using Material Design.
When I add a button to the layout i'm getting a java.lang.ClassCastException#11378fc8 and i can't use anymore the layout editor until I remove the button.
I have already tried to "invalidate/restart", to rebuild, to clean and build.
This is my tree structure :
Tree structure
Build.Gradle :
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
defaultConfig {
applicationId "fr.aurelien.test_dessin_android"
minSdkVersion 24
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.0.0-beta01'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.legacy:legacy-support-v4:1.0.0-beta01'
implementation 'com.google.android.material:material:1.1.0-alpha06'
implementation 'com.google.code.gson:gson:2.8.5'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.1.0-alpha4'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0-alpha4'
}
Class cast exception :
java.lang.IllegalArgumentException: java.lang.ClassCastException#126d0c4
at sun.reflect.GeneratedMethodAccessor1380.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at android.animation.PropertyValuesHolder_Delegate.callMethod(PropertyValuesHolder_Delegate.java:108)
at android.animation.PropertyValuesHolder_Delegate.nCallFloatMethod(PropertyValuesHolder_Delegate.java:143)
at android.animation.PropertyValuesHolder.nCallFloatMethod(PropertyValuesHolder.java)
at android.animation.PropertyValuesHolder.access$400(PropertyValuesHolder.java:38)
at android.animation.PropertyValuesHolder$FloatPropertyValuesHolder.setAnimatedValue(PropertyValuesHolder.java:1387)
at android.animation.ObjectAnimator.animateValue(ObjectAnimator.java:990)
at android.animation.ValueAnimator.setCurrentFraction(ValueAnimator.java:674)
at android.animation.ValueAnimator.start(ValueAnimator.java:1071)
at android.animation.ValueAnimator.start(ValueAnimator.java:1088)
at android.animation.ObjectAnimator.start(ObjectAnimator.java:852)
at android.animation.ValueAnimator.startWithoutPulsing(ValueAnimator.java:1081)
at android.animation.AnimatorSet.handleAnimationEvents(AnimatorSet.java:1142)
at android.animation.AnimatorSet.doAnimationFrame(AnimatorSet.java:1046)
at android.animation.AnimationHandler.doAnimationFrame(AnimationHandler.java:146)
at android.animation.AnimationHandler.access$100(AnimationHandler.java:37)
at android.animation.AnimationHandler$1.doFrame(AnimationHandler.java:54)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:947)
at android.view.Choreographer.doCallbacks(Choreographer.java:761)
at android.view.Choreographer_Delegate.doFrame(Choreographer_Delegate.java:66)
at com.android.layoutlib.bridge.impl.RenderSessionImpl.renderAndBuildResult(RenderSessionImpl.java:563)
at com.android.layoutlib.bridge.impl.RenderSessionImpl.render(RenderSessionImpl.java:425)
at com.android.layoutlib.bridge.BridgeRenderSession.render(BridgeRenderSession.java:120)
at com.android.ide.common.rendering.api.RenderSession.render(RenderSession.java:151)
at com.android.ide.common.rendering.api.RenderSession.render(RenderSession.java:133)
at com.android.tools.idea.rendering.RenderTask.lambda$null$8(RenderTask.java:755)
at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1590)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
MainActivity :
package fr.aurelien.test_dessin_android;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.frameLayout, new SimpleFragment());
fragmentTransaction.commit();
}
}
Fragment class :
package fr.aurelien.test_dessin_android;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class SimpleFragment extends Fragment {
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View retView = inflater.inflate(R.layout.fragment_layout, container, false);
return retView;
}
}
Manifest.xml :
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="fr.aurelien.test_dessin_android">
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme.default">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
XML code :
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="70dp"
android:layout_marginTop="16dp"
android:text="TextView"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="#+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="55dp"
android:layout_marginTop="31dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/textView"
app:srcCompat="#mipmap/ic_launcher" />
<Button
android:id="#+id/button5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Button"
app:layout_constraintTop_toTopOf="parent"
tools:layout_editor_absoluteX="189dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
It's a bug in Android Studio. You can track it here, it's apparently fixed for 3.5.2 https://issuetracker.google.com/issues/132316448
Have you tried using androidx.appcompat.widget.AppCompatButton instead of Button?
If you want to use material components you need to change your default theme in styles.xml from Theme.AppCompat to Theme.MaterialComponents.
Don't forget to add this
implementation 'com.google.android.material:material:1.1.0' in your app level build.gradle
Can someone help me on this? In my test I want to check if the login button is displayed on the StartPage.
I've been struggling with this error for a while today and I don't know how it should be resolved.What am I missing here?
Maybe this problem is somehow similar to this question:
Espresso test fails with java.lang.String cannot be cast to com.abc.events.databinding.SponsorDetailBinding
android.view.InflateException: Binary XML file line #6: Error inflating class fragment
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:770)
at android.view.LayoutInflater.inflate(LayoutInflater.java:483)
at android.view.LayoutInflater.inflate(LayoutInflater.java:415)
at android.view.LayoutInflater.inflate(LayoutInflater.java:366)
at android.support.v7.app.AppCompatDelegateImplV7.setContentView(AppCompatDelegateImplV7.java:256)
at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:109)
at io.turbela.turbela.login.view.StartActivity.onCreate(StartActivity.java:16)
at android.app.Activity.performCreate(Activity.java:6289)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1119)
at android.support.test.runner.MonitoringInstrumentation.callActivityOnCreate(MonitoringInstrumentation.java:532)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2655)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2767)
at android.app.ActivityThread.access$900(ActivityThread.java:177)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1449)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:5951)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1400)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1195)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void io.turbela.turbela.databinding.FragmentStartBinding.setViewModel(io.turbela.turbela.login.viewmodel.DispatchViewModel)' on a null object reference
at io.turbela.turbela.StartActivityFragment.onCreateView(StartActivityFragment.java:34)
at android.app.Fragment.performCreateView(Fragment.java:2114)
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:875)
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1060)
at android.app.FragmentManagerImpl.addFragment(FragmentManager.java:1162)
at android.app.FragmentManagerImpl.onCreateView(FragmentManager.java:2131)
at android.app.Activity.onCreateView(Activity.java:5610)
at android.support.v4.app.BaseFragmentActivityHoneycomb.onCreateView(BaseFragmentActivityHoneycomb.java:34)
at android.support.v4.app.FragmentActivity.onCreateView(FragmentActivity.java:79)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:740)
... 20 more
LoginTest.java
#RunWith(AndroidJUnit4.class)
public class LoginTest {
#Rule
public ActivityTestRule<StartActivity> mActivityRule = new ActivityTestRule(StartActivity.class);
#Test
public void displayLoginPage() {
onView(withId(R.id.login_button)).check(matches(isDisplayed()));
}
}
StartActivity.java
public class StartActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_start);
}
...onCreateOptionsMenu(...
...onOptionsItemSelected(...
}
activity_start.xml
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fragment"
class="io.turbela.turbela.StartActivityFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
StartActivityFragment.java
public class StartActivityFragment extends Fragment {
public StartActivityFragment() {
}
public static StartActivityFragment newInstance(){
Bundle args = new Bundle();
args.putString("key", "value");
StartActivityFragment fragment = new StartActivityFragment();
fragment.setArguments(args);
return fragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
FragmentStartBinding binding = DataBindingUtil.inflate(inflater, R.layout.fragment_start, container, false);
binding.setViewModel(new DispatchViewModel());
return binding.getRoot();
}
}
fragment_start.xml
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="viewModel" type="io.turbela.turbela.login.viewmodel.DispatchViewModel" />
</data>
<RelativeLayout
style="#android:style/Theme.Holo"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin">
<Button
android:id="#+id/login_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_alignParentTop="true"
android:layout_marginTop="128dp"
android:onClick="#{viewModel.onClickLogin}"
android:text="#string/login" />
</RelativeLayout>
</layout>
DispatchViewModel.java
public class DispatchViewModel extends BaseObservable{
public View.OnClickListener onClickLogin() {
//loginWithEmail
return v -> Log.d("H", "onClickLogin");
}
}
build.gradle
apply plugin: 'com.android.application'
apply plugin: 'me.tatarka.retrolambda'
android {
compileSdkVersion 23
buildToolsVersion "22.0.1"
defaultConfig {
applicationId "io.turbela.turbela"
minSdkVersion 15
targetSdkVersion 23
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
dataBinding{
enabled = true
}
packagingOptions {
exclude 'LICENSE.txt'
}
lintOptions {
abortOnError false
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:cardview-v7:23.1.1'
compile 'com.android.support:appcompat-v7:23.1.1'
compile 'com.parse:parse-android:1.12.0'
compile 'com.parse.bolts:bolts-android:1.3.0'
compile 'com.facebook.android:facebook-android-sdk:4.8.1'
compile 'com.parse:parsefacebookutils-v4-android:1.10.3#aar'
androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2'
androidTestCompile 'com.android.support.test:runner:0.5'
}
There is android:name attribute missing from <fragment> tag in your activity_start.xml
As per the docs, you must include it.
So your activity.start.xml should look like this:
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fragment"
android:name="io.turbela.turbela.StartActivityFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
Note:
The class= attribute you are trying to use is for custom Views as in here