Android YouTube API: Can't reinitialize YouTubePlayerFragment with new YouTube video - android

I am trying to load a different video into a YoutubePlayer fragment when a button is clicked. My button has an onclick listener of testClick. When I click the button, I get the following exception: "UsupportedExeception: no views can be added on top of player". The initialize method also isn't being called when I initialize the new video from my onclick method. How can I a new YouTubeVideo to be loaded into the previously used YouTubePlayerFragment, and how I can get the initialize method to be called from my onClick method?
public class ExersizeListActivity extends Activity implements
YouTubePlayer.OnInitializedListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_exersize_list);
}
public void testClick(View v) {
//new YouTube Fragment to replace old one
YouTubePlayerFragment youTubePlayerFragment=YouTubePlayerFragment.newInstance();
youTubePlayerFragment.initialize(YoutubeAPIKey.API_KEY, this);
FragmentManager fragManager=getFragmentManager();
FragmentTransaction fragmentTransaction=fragManager.beginTransaction();
fragmentTransaction.replace(R.id.youtube_fragment, youTubePlayerFragment);
fragmentTransaction.commit();
}
#Override
public void onInitializationFailure(Provider arg0,
YouTubeInitializationResult arg1) {
Log.e(null, "it bombed");
}
//not being called, and in current state would reinitialize with the same video
#Override
public void onInitializationSuccess(Provider arg0,
YouTubePlayer youtubePlayer, boolean arg2) {
youtubePlayer.cueVideo("YNKehLXpLRI");
}
}
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<fragment
android:id="#+id/youtube_fragment"
android:name="com.google.android.youtube.player.YouTubePlayerFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:id="#+id/randomizeButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Randomize!"
android:layout_below="#+id/youtube_fragment"
android:onClick="testClick"/>
</RelativeLayout>

Rather than defining the fragment in the xml layout file with the <fragment> tag, define a FrameLayout container, necessary when changing fragments dinamically at runtime:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<FrameLayout
android:id="#+id/youtube_fragment"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:id="#+id/randomizeButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Randomize!"
android:layout_below="#+id/youtube_fragment"
android:onClick="testClick"/>
</RelativeLayout>
You will need to add the first YouTubeVideoFragment in onCreate() with a FragmentTransaction, and when the user clicks the button, the code you already have in testClick() should work.

Related

Display several youtube video in an activity

I got an Article object that I want to display in my Activity. An article can have:
-Text(s) : 1 at least or several
-Image(s) : 0 or several
-Video(s) : 0 or several
Each element can be anywhere in the article for example :
-Text / Image / Text / Video
-Video / Image / Video / Text
- etc...
After parsing my article, I add programmatically the content I need: TextView, ImageView, or VideoView(youtube or jwplayer). Actually it works for image and text, but I don't know how I can add several youtube video in a same activity:
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.post);
linearLayout = (LinearLayout) findViewById(R.id.llayout_article);
// Get article to display it
Intent intent = getIntent();
Article article = intent.getParcelableExtra("articleDetails");
//add ImageView & TextView
for (View view : article.getContentSplitInViews(this)) {
this.linearLayout.addView(view);
}
YouTubePlayerSupportFragment frag =
(YouTubePlayerSupportFragment) getSupportFragmentManager().findFragmentById(R.id.youtube_fragment);
src="g2mmUzNSeDM";
frag.initialize(apiKey, this);
YouTubePlayerSupportFragment frag2 =
(YouTubePlayerSupportFragment) getSupportFragmentManager().findFragmentById(R.id.youtube_fragment2);
src = "nCgQDjiotG0";
frag2.initialize(apiKey, this);
}
#Override
public void onInitializationSuccess(YouTubePlayer.Provider provider, YouTubePlayer youTubePlayer, boolean wasRestored) {
if (!wasRestored) {
youTubePlayer.setPlayerStyle(YouTubePlayer.PlayerStyle.DEFAULT);
youTubePlayer.loadVideo(src);
youTubePlayer.play();
}
}
#Override
public void onInitializationFailure(YouTubePlayer.Provider provider, YouTubeInitializationResult youTubeInitializationResult) {
// YouTube error
String errorMessage = youTubeInitializationResult.toString();
Toast.makeText(getApplicationContext(), errorMessage, Toast.LENGTH_LONG).show();
Log.d("errorMessage:", errorMessage);
}
My current xml:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:id="#+id/scrollViewId"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<LinearLayout
android:id="#+id/llayout_article"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:orientation="vertical">
<fragment
android:name="com.google.android.youtube.player.YouTubePlayerSupportFragment"
android:id="#+id/youtube_fragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<fragment
android:name="com.google.android.youtube.player.YouTubePlayerSupportFragment"
android:id="#+id/youtube_fragment2"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
</ScrollView>
Later I want to add programmaticaly the fragment tag in my XML for each video found in the Article Object.
Actually, there is 2 players in my activity, but only one is playing the video, and action in every players (play/pause/full screen) will do the same thing in the 2 players.
First of all you have to distinguish from two providers by id in onInitializationSuccess().
If the provider is the frag1, call youTubePlayer.loadVideo("g2mmUzNSeDM")
else if the provider is the frag2, call youTubePlayer.loadVideo("nCgQDjiotG0")
(You can add YouTubePlayerView programmatically to your layout if your activity extends YoutubeBaseActivity)

Trouble editing TextView within Fragment

So I am still fairly new to working with Android Studio and everything in it. I have been stuck on trying to get fragments to communicate directly with each other. Here I'm simply just trying to set the TextView text element within one of my fragments. I have looked for hours and tried a lot, but I'm not sure what to do. Also, I am implementing my fragments through code in a FrameLayout.
Here is my fragment whose text value I'm trying to edit:
public class ReceivingFrag extends Fragment {
TextView sender;
public void updateText(String text) {
sender.setText(text);
}
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.frag_sender, container, false);
sender = (TextView) v.findViewById(R.id.sender);
return v;
}
}
I believe my root problem is that getView() and sender both return Null. I also understand that fragments are not technically views, but rather aid in the layout of views and ViewGroups. Any help is appreciated.
Not sure if it helps, but this is the method that calls the updateText() method within the ReceivingFrag class.
public void sendText(String text){
ReceivingFrag frag = new ReceivingFrag();
getSupportFragmentManager().beginTransaction().add(R.id.receiving_container, frag).commit();
getSupportFragmentManager().executePendingTransactions()
frag.updateText(text);
}
**Edit:
This is my MainActivity class that is calling and creating the Fragment:
public class MainActivity extends AppCompatActivity implements SendingFragment.TextClicked {
private static final String TAG = MainActivity.class.getSimpleName();
public final static String EXTRA_MESSAGE = "com.example.myfirstapp.MESSAGE";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String[] myStringArray = {"Hello", "Nice To See You", "Bye"};
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, myStringArray);
ListView listView = (ListView) findViewById(R.id.mobile_list);
listView.setAdapter(adapter);
sendText("Hello");
}
#Override
public void sendText(String text){
ReceivingFrag frag = new ReceivingFrag();
getSupportFragmentManager().beginTransaction().add(R.id.receiving_container, frag).commit();
getSupportFragmentManager().executePendingTransactions();
frag.updateText(text);
}}
**Edit 2:
This is the MainActivity layout file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/apk/tools"
xmlns:tools2="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="1">
<EditText android:id="#+id/edit_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="#string/edit_message"
android:layout_weight="1" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="sendMessage"
android:text="#string/button_send"/>
</LinearLayout>
<ListView android:id="#+id/mobile_list"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<FrameLayout
android:id="#+id/receiving_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"></FrameLayout></LinearLayout>
And this is the layout for the Fragment:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/sender"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/frag_sender"
android:background="#color/gray"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"/></LinearLayout>
Solution:
So as mentioned below, the runtime error was fixed by adding
#Override
protected void onResume() {
super.onResume();
sendText("hello");
}
to the MainActivity class. After reading from https://developer.android.com/guide/components/fragments.html#Lifecycle
I think the statement
"Once the activity reaches the resumed state, you can freely add and remove fragments to the activity. Thus, only while the activity is in the resumed state can the lifecycle of a fragment change independently."
best explains the situation and why the error initially occurred.
If you instead put the sendText() in your onResume() like this,
#Override
protected void onResume() {
super.onResume();
sendText("Hello");
}
It will not give you the Null Pointer Exception. The fragment is still null when you call on it from onCreate().
Change your Fragment to this:
public class ReceivingFrag extends Fragment {
private TextView sender;
public void updateText(String text) {
sender.setText(text);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.frag_sender, container, false);
sender = (TextView) v.findViewById(R.id.sender);
return v;
}
}
and in your activity, before calling the updateText method, make sure the fragment transaction has executed by doing:
public void sendText(String text){
ReceivingFrag frag = new ReceivingFrag();
getSupportFragmentManager().beginTransaction().add(R.id.receiving_container, frag).commit();
getSupportFragmentManager().executePendingTransactions();
frag.updateText(text);
}

Hide/Show Button in Fragment from Activity

i am trying to hide/show Button in fragment from Activity but it give me following exception.
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
Home Activity
public class HomeActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
CategoryFragment frag=(CategoryFragment) activity.getSupportFragmentManager()
.findFragmentByTag("cat_frag");
Button newDesigns= (Button) frag.getView().findViewById(R.id.new_designs);
newDesigns.setVisibility(View.VISIBLE);
}
}
Category Fragment
public class CategoryFragment extends Fragment{
Button newDesigns;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_category, null);
newDesigns= (Button) v.findViewById(R.id.new_designs);
}
}
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#CCCCCC">
<TextView
android:id="#+id/list_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:background="#drawable/shape_logo_bg"
android:gravity="center"
android:padding="5dp"
android:textColor="#android:color/white"
android:textSize="18sp" />
<Button
android:id="#+id/new_designs"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/list_name"
android:background="#color/edit_button_color"
android:padding="10dp"
android:text="#string/new_designs"
android:textColor="#color/btn_text_color"
android:layout_centerHorizontal="true"
android:layout_marginTop="5dp"
android:visibility="gone"
/>
</RelativeLayout>
Code is too large to be posted here. Thats why i have only posted the code where i am finding an issue.
I am able to get newDesigns BUTTON instance.What is shocking for me is if try to play with button instance (VISIBLE/GONE) it gives me above mentioned exception.
Help is appreciated.
You shouldn't play with a view of the Fragment while you are in a Activity directly. You will not know what the view's state will be and this can potentially lead to issues you can't even think of(beleive me i faced many). To interact with the activity's views, make an interface:
public interface AccessFragmentViews{
public void setVisibilityForButton(boolean bool);
//any other methods that you need
}
Now implement this inside the fragment class and override the method.
class YourFragment implements AccessFragmentViews{
.
.
public void serVisibilityForButton(boolean shouldHide){
if(shouldHide){
yourButton.setVisibility(View.GONE);
}else{
yourButton.setVisibility(View.VISIBLE);
}
}
}
Now you can interact safely with the views of the fragment within a activity using this interface. Make sure that the fragment is alive before doing so though ;) accessing child's view are prone to WindowLeakedExceptions and illegalstateexceptions
In the activity use it as follows:
you can get the fragment reference by either finding it by its tag or by using the reference you used to create the fragment
//NOTE: it is very very dangerous to do the accessing on a fragment views from an activity
//first the alive check then the logic
if(yourFragmentReference!=null){
((AccessFragmentViews)yourFragmentReference).setVisibilityForButton(true);// or false if you want to make it visible
}
Add a method in your fragment class
public void changeButtonVisibility(boolean visibility){
if(visibility){
newDesigns.setVisibility(View.VISIBLE);
}else{
newDesigns.setVisibilty(View.GONE);
}
}
and in your activity class
add this line
public class HomeActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
CategoryFragment frag=(CategoryFragment) activity.getSupportFragmentManager()
.findFragmentByTag("cat_frag");
frag.changeButtonVisibility(true);
}
}

Android: Can't get YouTube Player API work inside of a fragment

I'm trying to get my app to play a YouTube video in a fragment, as This Official Documentation said that you can play YouTube videos in fragments.
But i can't get it done.
This is my code:
SingleArticleFragment:
public class SingleArticleFragment extends YouTubePlayerSupportFragment implements
YouTubePlayer.OnInitializedListener {
public static final String API_KEY = "my api key";
public static final String YOUTUBE_VIDEO_CODE = "_oEA18Y8gM0";
// YouTube player view
private YouTubePlayerView youTubeView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.article, container, false);
return v;
}
#Override
public void onViewCreated (View view, Bundle savedInstanceState) {
youTubeView = (YouTubePlayerView) getActivity().findViewById(R.id.youtube_view);
// Initializing video player with developer key
youTubeView.initialize(API_KEY, this);
}
#Override
public void onInitializationSuccess(YouTubePlayer.Provider provider, YouTubePlayer youTubePlayer, boolean b) {
if (!b) {
// loadVideo() will auto play video
// Use cueVideo() method, if you don't want to play it automatically
youTubePlayer.cueVideo(YOUTUBE_VIDEO_CODE);
// Hiding player controls
youTubePlayer.setPlayerStyle(YouTubePlayer.PlayerStyle.CHROMELESS);
}
}
#Override
public void onInitializationFailure(YouTubePlayer.Provider provider, YouTubeInitializationResult youTubeInitializationResult) {
if (youTubeInitializationResult.isUserRecoverableError()) {
youTubeInitializationResult.getErrorDialog(getActivity(), 1).show();
} else {
String errorMessage = "There was an error initializing the YouTubePlayer";
Toast.makeText(getActivity(), errorMessage, Toast.LENGTH_LONG).show();
}
}
}
And this is article.xml:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent"
android:background="#color/white">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="wrap_content"
android:orientation="vertical">
<!-- Cover Video -->
<com.google.android.youtube.player.YouTubePlayerView
android:id="#+id/youtube_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="30dp" />
<!-- Article Cover Photo -->
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/single_article_cover_photo"
android:layout_gravity="center"
android:adjustViewBounds="true"
android:layout_weight=".14"/>
<!-- Article Title -->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/single_article_title"
android:layout_gravity="center"
android:textColor="#color/black"
android:textSize="20sp"
android:textStyle="bold"
android:padding="10dp"
android:layout_weight=".14"/>
</LinearLayout>
</ScrollView>
LogCat Errors:
android.view.InflateException: Binary XML file line #11: Error inflating class com.google.android.youtube.player.YouTubePlayerView
.
.
.
Caused by: java.lang.IllegalStateException: A YouTubePlayerView can only be created with an Activity which extends YouTubeBaseActivity as its context.
So what LogCat is telling me: YouTube only works in Activities!, but android documentation says otherwise.
Can anybody help here please ?
Thanks in advance.
You are mixing two different approaches.
You can either use a YouTubePlayerView together with a YouTubeBaseActivity or you can simply use a YouTubePlayerFragment/YouTubePlayerSupportFragment. Using a YouTubePlayerView inside a YouTubePlayerFragment is simply wrong.
If you use the first approach (view + activity), you need to place the view in your XML and then set the YouTubePlayer to play inside that view.
If you use the second approach, you simply need to load the fragment in an appropriate container, initialize the YouTubePlayer and play the video.
SOLUTION 1
Remove the YouTubePlayerView from your XML and your code and replace it with a FrameLayout that will contain the YouTubeSupportFragment. Then, use a ChildFragmentManager to load the YouTubeSupportFragment inside that FrameLayout.
SOLUTION 2
Simply make your Activity extend the YouTubeBaseActivity, leave everything else as it is.

YouTube Android fragment flickering

I'm embedding Youtube videos in my Android app using the official SDK. Problem is, the screen gets flickered(black color background for <0.5 seconds) each time a video is initialized.
XML:
<LinearLayout
android:id="#+id/youTube"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/cardui"
android:orientation="vertical"
android:paddingBottom="10dp"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:paddingTop="5dp"
android:visibility="visible"
tools:visibility="visible">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:layout_marginTop="5dp"
android:fontFamily="sans-serif-light"
android:paddingBottom="5dp"
android:paddingLeft="10dp"
android:text="Watch video"
android:textAppearance="?android:attr/textAppearanceLarge" />
<!-- This is where Youtube fragment will be added -->
</LinearLayout>
Youtube Fragment Code:
public static class PlayerYouTubeFrag extends YouTubePlayerSupportFragment {
private String videoId;
public static PlayerYouTubeFrag newInstance(String videoId) {
PlayerYouTubeFrag playerYouTubeFrag = new PlayerYouTubeFrag();
Bundle bundle = new Bundle();
bundle.putString("videoId", videoId);
playerYouTubeFrag.setArguments(bundle);
return playerYouTubeFrag;
}
#Override
public View onCreateView(LayoutInflater layoutInflater, ViewGroup viewGroup, Bundle bundle) {
init();
return super.onCreateView(layoutInflater, viewGroup, bundle);
}
private void init() {
videoId = getArguments().getString("videoId");
initialize(youtubeKey, new YouTubePlayer.OnInitializedListener() {
#Override
public void onInitializationSuccess(YouTubePlayer.Provider provider, YouTubePlayer youTubePlayer, boolean b) {
youtubePlayer = youTubePlayer;
youtubePlayer.setOnFullscreenListener(new YouTubePlayer.OnFullscreenListener() {
#Override
public void onFullscreen(boolean b) {
isFullScreen = b;
}
});
if (!b) {
youtubePlayer.cueVideo(videoId);
youtubePlayer.setPlayerStyle(YouTubePlayer.PlayerStyle.MINIMAL);
}
}
#Override
public void onInitializationFailure(YouTubePlayer.Provider provider, YouTubeInitializationResult youTubeInitializationResult) {
Log.d(TAG, "Player initialization failed");
}
});
}
}
And finally, adding the Fragment to layout:
mYoutubePlayerFragment = PlayerYouTubeFrag.newInstance(videoId);
getSupportFragmentManager().beginTransaction().setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN).add(R.id.youTube, mYoutubePlayerFragment).commit();
(findViewById(R.id.youTube)).setVisibility(View.VISIBLE);
Okay, this is because of a weird bug in YouTubeSupportFragment and I'm not the first to notice it. You can get around this, by adding an empty SurfaceView.
Read more here:
http://code.google.com/p/gdata-issues/issues/detail?id=4722
The bug is still present, the solution of just adding the SurfaceView with android:width and android:height 0dp didn't solve my problem. Instead, I had to add the SurfaceView in my Layout xml
<SurfaceView
android:id="#+id/surface"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" />
and had to set the visibility of the SurfaceView to visible in code while adding the youtube fragment.
findViewById(R.id.surface).setVisibility(View.VISIBLE);
getSupportFragmentManager().beginTransaction().replace(your_holder_id, youTubePlayerFragment).commit();
Hope this helps better.

Categories

Resources