In an Android app, upon clicking on a menu button, MainActivity is supposed to replace an ImageView fragment with a WebView fragment. Instead, it throws:
java.lang.ClassCastException: android.widget.ImageView cannot be cast to android.view.ViewGroup
In Eclipse I cleaned the project, deleted the R file, checked the XML files as suggested in other threads, but no luck.
If you could help, much appreciated.
public class MainActivity extends FragmentActivity implements PhotoFragment.Callbacks {
[...]
public void onButtonInfoClicked(int index) {
WebFragment web_f = WebFragment.newInstance(1, "Web Fragment");
web_f.setIndex(index);
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.addToBackStack(null);
fragmentTransaction.replace(R.id.photoView, web_f);
fragmentTransaction.commit();
}
fragment_photo.xml
<ImageView
android:id="#+id/photoView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="top"
android:scaleType="fitXY" />
web_view.xml
<WebView
android:id="#+id/webView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="top"
android:scaleType="fitXY" />
I found where the problem was.
I was trying to pass the resource id of the ImageView (R.id.photoView) used to build the fragment, not the actual fragment. Since this fragment was not created from a layout, I need to use its object reference and pass its containerViewId instead:
// fragment previously created in MainActivity:
PhotoFragment f = PhotoFragment.newInstance();
So to fix the problem I substituted:
fragmentTransaction.replace(R.id.photoView, web_f);
with:
fragmentTransaction.replace(((ViewGroup)f.getView().getParent()).getId() , web_f);
Related
I have to make a simple application for school but for some reason my app keeps crashing on the following error:
System services not available to Activities before onCreate()
After a bit of debugging i found out that it crashes on the ArrayAdapter creation. I tried a lot of things but for some reason it keeps on crashing with the same error.
I already tried a lot of things including:
- running it in the MainActivity (which yielded the best results)
- running it directly in the onCreate()
- running it in the onViewCreated()
- and a few other places...
I wanted to make a simple friends app where people can enter their data in my phone, nothing to amazing. I need to retrieve the data from a url, i used myjson.org to create a simple json (that's the assignment). All the data i get is receive from the url is correct and the list is also complete. I just don't know how to attach it to the list...
package com.vb.vriendenboekje8.ui.home
import android.app.Activity
import android.content.Context
import android.os.AsyncTask
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ArrayAdapter
import android.widget.ListView
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import com.vb.vriendenboekje8.MainActivity
import com.vb.vriendenboekje8.R
import kotlinx.android.synthetic.main.fragment_home.*
import kotlinx.android.synthetic.main.fragment_home.view.*
import org.json.JSONArray
import org.json.JSONObject
import java.net.URL
class HomeFragment : Fragment()
{
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View?
{
val view = inflater.inflate(R.layout.fragment_home, container, false)
var lstFriends : ListView = view.findViewById(R.id.lstFriends)
LoadJsonTask(lstFriends).execute("<url to json here>")
return view
}
class LoadJsonTask(lstFriends : ListView) : AsyncTask<String, Void, String>()
{
var lstFriends : ListView
init
{
this.lstFriends = lstFriends
}
//load http request and get Json data
override fun doInBackground(vararg params: String?) : String
{
var json : String
val stringURL = params[0]
json = URL(stringURL).readText()
return json
}
override fun onPostExecute(result: String?)
{
super.onPostExecute(result)
val friendsJson = JSONArray(result)
var friendsList : MutableList<String> = mutableListOf()
//clear the friends list
friendsList.clear()
//add names to list
for (i in 0..(friendsJson.length()-1))
{
val friend : JSONObject = friendsJson[i] as JSONObject
friendsList.add(friend.get("Naam") as String)
}
val adapter = ArrayAdapter<String>(FragmentActivity(), android.R.layout.simple_list_item_1, friendsList) //where the app crashes
this.lstFriends.setAdapter(adapter)
}
}
}
my fragment layout:
<?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:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="#+id/lstFriends"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
full error:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.vb.vriendenboekje8, PID: 31342
java.lang.IllegalStateException: System services not available to Activities before onCreate()
at android.app.Activity.getSystemService(Activity.java:6649)
at android.view.LayoutInflater.from(LayoutInflater.java:284)
at android.widget.ArrayAdapter.<init>(ArrayAdapter.java:216)
at android.widget.ArrayAdapter.<init>(ArrayAdapter.java:210)
at android.widget.ArrayAdapter.<init>(ArrayAdapter.java:196)
at com.vb.vriendenboekje8.ui.home.HomeFragment$LoadJsonTask.onPostExecute(HomeFragment.kt:76)
at com.vb.vriendenboekje8.ui.home.HomeFragment$LoadJsonTask.onPostExecute(HomeFragment.kt:39)
at android.os.AsyncTask.finish(AsyncTask.java:755)
at android.os.AsyncTask.access$900(AsyncTask.java:192)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:772)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7682)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:516)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
If anyone has any ideas or sees something i do wrong please let me know.
PS im new to kotlin and android development
I have an app that works with Xamarin Forms, I need to add a feature to show a youtube player (play and pause). It will be only for Android users at least for now.
I think that WebView is not an option that works for me because I need to automatically play a video and pass to the next one with no delay or the minimum possible.
I seach this on SO and Google, but I didn't get a useful to now, for example
Xamarin + Android + Binding YouTube video player compile errors
I can't even understand how he getted to that code
Youtube player for xamarin forms He show a link to github IOS only and nobody answer
https://blog.nishanil.com/2014/08/14/youtube-android-player-for-xamarin-android/ This apparently works, I didn't try because it's for Xamarin but no Xamarin Forms
I think that WebView is not an option that works for me because I need to automatically play a video and pass to the next one with no delay or the minimum possible.
If you want to do this, I suggest you can use com.google.android.youtube.player.YouTubePlayerView to do this. You can follow the steps to create demo.
Download the latest YouTubeAndroidPlayerApi.jar from here.
Create a Android Java binding library project.Once the project is created right click “Jars” folder -> Add existing item-> Add the YouTubeAndroidPlayerApi.jar,lick on the properties of the YouTubeAndroidPlayerApi.jar and mark the BuildAction as “EmbeddedJar”.
3.Create a new Xamarin Android project,reference the Library project we created,add “Internet” permission to the application.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<com.google.android.youtube.player.YouTubePlayerView
android:id="#+id/youtube_view"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
public class MainActivity : YouTubeBaseActivity, IYouTubePlayerOnInitializedListener
{
private int RECOVERY_DIALOG_REQUEST = 1;
public void OnInitializationFailure(IYouTubePlayerProvider provider, YouTubeInitializationResult errorReason)
{
if (errorReason.IsUserRecoverableError)
{
errorReason.GetErrorDialog(this, RECOVERY_DIALOG_REQUEST).Show();
}
else
{
String errorMessage = String.Format(
GetString(Resource.String.ErrorMessage), errorReason.ToString());
Toast.MakeText(this, errorMessage, ToastLength.Long).Show();
}
}
public void OnInitializationSuccess(IYouTubePlayerProvider p0, IYouTubePlayer yPlayer, bool p2)
{
if(!p2)
{
//load list video
yPlayer.CueVideos(DevConstants.list);
}
//load single video
//yPlayer.LoadVideo(DevConstants.VIDEO_ID);
}
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.activity_main);
YouTubePlayerView youTubeView = FindViewById<YouTubePlayerView>(Resource.Id.youtube_view);
youTubeView.Initialize(DevConstants.DEVELOPER_KEY, this);
}
}
public static class DevConstants
{
public static string DEVELOPER_KEY = "your developer key";
public static string VIDEO_ID = "DHHY8m3rEzU";
public static List<string> list = new List<string>()
{
"DHHY8m3rEzU","luDyX0kYzY4"
};
}
If you still have some issue, please try to add this line in Tramsforms Metadata.xml
<remove-node path="/api/package[#name='com.google.android.youtube.player']/class[#name='YouTubeThumbnailView']/method[#name='finalize' and count(parameter)=0]" />
More detailed info, please take a look:
https://poojargaonkar.wordpress.com/2015/08/13/playing-youtube-videos-in-xamarin-android-app-part-2/
More feature, you can take a look:
https://blog.nishanil.com/2014/08/14/youtube-android-player-for-xamarin-android/
There are a lot of answers of this questions but technically my question is different, I've read some documentation and agreed we should not use multiple fragments in only one activity , we should use multiple activities with multiple fragments depend on project requirement or UI specification ,
so architecture of my application is
1. BaseActivity and all activities extends from that
2. BaseFragment and all Fragments extends from that
my Code:
in BaseActivity I've made following functions
public void replaceFragment(int containerViewId, Fragment fragment, String fragmentTag, boolean addToBackStack) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(containerViewId, fragment, fragmentTag);
if(addToBackStack)
fragmentTransaction.addToBackStack(fragmentTag);
if(fragmentTag.matches("") && addToBackStack)
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
To Add Fragment in Framelayout
public void addFragment(int containerViewId, Fragment fragment, String fragmentTag, boolean addToBackStack, boolean isPending) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(containerViewId, fragment, fragmentTag);
if(addToBackStack)
fragmentTransaction.addToBackStack(fragmentTag);
if(fragmentTag.matches("") && addToBackStack)
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
if(isPending)
fragmentManager.executePendingTransactions();
}
Back Press Functionality
public void popBackStackImmediate() {
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.popBackStackImmediate();
}
Get Total Fragments
public List<Fragment> fragmentList(){
return getSupportFragmentManager().getFragments();
}
and the flow is
FragmentA (add) -> FragmentB (replace) ->
QUETSION 1 : why totalFragments are showing 2 ? while I've replaced FragmentB to A
QUESTION 2: when i press back button still showing 2 Fragments and how may i remove from stack ?
Question 3: FragmentB is visible but FragmentA fragment life cycle working too ..means onResume and onCreate funcations are calling too strange but true dont know why
Question 1: You have not removed any fragment therefore the fragment count is 2. When you replace a fragment, you are replacing it in the fragment container, not it's instance.
Question 2: Once you add a fragment to the backstack, it means you will navigate back to it once you hit the back button. Still, your fragment manager fragment count will still be 2 since no fragment was removed. If you want to remove it the following code will do the trick:
getSupportFragmentManager().beginTransaction().remove(yourFragment).commit();
Question 3: Once you replace fragment A with fragment B, fragment A will still be active and will call it's onPause, onDestroy and onDestroyView, if you bring it back to the container it starts it's lifecycle from onCreateView, that meaning that running onResume is normal, however onCreate is not.
In my app, I have both SupportMapFragment as well as PlaceAutocompleteFragment and the layout, fragment_map is:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<fragment
android:id="#+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.FragmentB">
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="#+id/card_view"
android:layout_gravity="top"
android:layout_margin="5dp"
android:layout_width="340dp"
android:layout_height="40dp"
card_view:cardCornerRadius="4dp">
<fragment
android:id="#+id/place_autocomplete_fragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:name="com.google.android.gms.location.places.ui.PlaceAutocompleteFragment" />
</android.support.v7.widget.CardView>
</fragment>
</LinearLayout>
And in my FragmentB, I use them like so:
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container,
#Nullable Bundle savedInstanceState) {
// don't recreate fragment every time
if (supportMapFragment == null && view == null) {
view = inflater.inflate(R.layout.fragment_map, container, false);
supportMapFragment = (SupportMapFragment) this.getChildFragmentManager()
.findFragmentById(R.id.map);
//when successful, calls onMapReady()
supportMapFragment.getMapAsync(this);
}
//Place fragment
autocompleteFragment = (PlaceAutocompleteFragment) getActivity().
getFragmentManager().findFragmentById(R.id.place_autocomplete_fragment);
// Register a listener to receive callbacks when a place has been selected or an error has occurred
autocompleteFragment.setOnPlaceSelectedListener(this);
return view;
}
I run into two issues:
camera doesn't move to the selected place, even though I can get the marker to that location
map fragment takes me back to my current location
I am certain I am running into fragment lifecycle issue but I am not sure if I should replace map fragment with place fragment and add it to the backstack whenever onPlaceSelected() is selected.
I added logs for every fragment lifecycle call and noticed that onResume the map fragment overrides the place fragment because I check if the map client is connected or not so, adding this check, if (!autocompleteFragment.isVisible()) {
//if p
if (!mGoogleApiClient.isConnecting() &&
!mGoogleApiClient.isConnected())
{
mGoogleApiClient.connect();
Log.d(TAG, "onResume(), called mGoogleApiClient.connect()");
}
} ensured place fragment had focus and hence the camera moved to the selected Places location.
I am using YouTubePlayerSupportFragment and after a second it stops playing.
If I move the slider it again starts to show a movie image and sound but stops again after less then a second. It almost looks as if the movie is not streaming and buffering but view is showing the movie controls and the image.
I am using the default video mode and here is my fragment class:
public class PlayerYouTubeFrag extends YouTubePlayerSupportFragment {
String developerKey = "dev_key";
private YouTubePlayer activePlayer;
public static PlayerYouTubeFrag newInstance(String url) {
PlayerYouTubeFrag playerYouTubeFrag = new PlayerYouTubeFrag();
Bundle bundle = new Bundle();
bundle.putString("url", url);
playerYouTubeFrag.setArguments(bundle);
playerYouTubeFrag.init();
return playerYouTubeFrag;
}
private void init() {
initialize(developerKey, new OnInitializedListener() {
#Override
public void onInitializationFailure(Provider arg0, YouTubeInitializationResult arg1) {
System.out.println("PlyerYouTubeFrag initialization failure");
}
#Override
public void onInitializationSuccess(YouTubePlayer.Provider provider, YouTubePlayer player, boolean wasRestored) {
activePlayer = player;
if (getArguments().getString("url") != null) {
if (wasRestored) {
activePlayer.play();
} else {
activePlayer.loadVideo(getArguments().getString("url"), 0);
}
}
}
});
}
}
I am using viewpager for other fragments and here is the section of my main activity in my getItem() call where I create the fragment and return it:
if(ft3 ==null)
ft3 = PlayerYouTubeFrag.newInstance(video_id);
for my main activity I use this xml
<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
I am using 1.2.2 of the youtube api
I am running on 5.1 of android and have tried the newest and older youtube player. I have read about this might be happening for others and is pointed to being a API issue but I am not sure.
Any ideas I am willing to try.
I had the same problem and after few hours I finally found a solution. The problem is the view is probably not at the top of the layout where you want to put this youtubePlayerFragment.
That is why the video is cut after 1 second. To solve that you need to be sure that the place where you want to add the youtubeFragment is the top of the layout.
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.96"
android:paddingTop="5dp"
android:id="#+id/youtubeFragment">
</FrameLayout>
I do not really understand why you cannot invoke youtubePlayerFragment where you want. Perhaps to avoid some programmers to hide some parts of the video (for example artificially displaying sound without the view which is not legal following the conditions of use)...
You cannot use youtubePlayerFragment as the view overlaps the youtubePlayerView, Youtube docs recommend to use another approach for overlaying views.
Please follow the steps in this guide for ActionBarDemoActivity
https://github.com/youtube/yt-android-player