Alberto
Alberto

Reputation: 728

Play a video on android device

i'm tring to display a youtube video on android. I googled but I can't find any solution to my last error:

08-16 12:05:55.950: E/MediaPlayer(2418): error (1, -2147483648)
08-16 12:05:56.274: E/MediaPlayer(2418): Error (1,-2147483648)

I added to Manifest file user permission to internet:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapp"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="17" />
    <uses-permission android:name="android.permission.INTERNET" />
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >

        <activity
            android:name="com.example.myapp.MainActivity">

            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name="com.example.myapp.MovieActivity"
            android:parentActivityName="com.example.myapp.MainActivity">

            <meta-data
            android:name="android.support.PARENT_ACTIVITY"
            android:value="com.example.myapp.MainActivity" />

            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
</application>
</manifest>

this is my MovieActivity.java:

package com.example.myapp;

import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.renderscript.Element;
import android.support.v4.app.NavUtils;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;
import android.widget.MediaController;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.VideoView;

@SuppressLint("NewApi")
public class MovieActivity extends Activity
{
@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.movie_activity);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) 
    {
        getActionBar().setDisplayHomeAsUpEnabled(true);
    }
    ImageView m_avatar = (ImageView) findViewById(R.id.Avatar);
    m_avatar.setImageResource(R.drawable.lambda);

    TextView m_pagedescription = (TextView) findViewById( R.id.pageDescription);
    m_pagedescription.setText("What do you like to do?");

    TextView m_nickname = (TextView) findViewById(R.id.nickName);
    m_nickname.setText("User");

    new MoviePlayer("http://www.youtube.com/watch?v=1FJHYqE0RDg",this).execute();
}

@Override
public boolean onOptionsItemSelected(MenuItem item) 
{
    switch (item.getItemId()) 
    {
        case android.R.id.home:
            NavUtils.navigateUpFromSameTask(this);
            return true;
    }
    return super.onOptionsItemSelected(item);
}

@Override
public boolean onCreateOptionsMenu(Menu menu)
{
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

public void btnSkip_OnClick(View v)
{
    Intent intent = new Intent(this, MainActivity.class);
    startActivity(intent);
}

public class MoviePlayer extends  AsyncTask<Void, Void, Void>
{
    ProgressBar m_progressBar;
    VideoView m_movieView;
    String m_movieUrl;
    MediaController m_mc;
    Context c;
    public MoviePlayer(final String url, Context context)
    {
        c = context;
        m_movieUrl = url;
        m_progressBar = (ProgressBar) findViewById(R.id.progressBar);
        m_movieView = (VideoView) findViewById(R.id.movie);
        m_mc = (MediaController) findViewById(R.id.mediaController);
    }

   @Override
    protected void onPreExecute()
    {
        super.onPreExecute();
        m_progressBar.setVisibility(View.VISIBLE);
        m_movieView.setVisibility(View.GONE);
    }

    @SuppressLint("NewApi")
    @Override
    protected Void doInBackground(Void... params)
    {
        try
        {
            if(m_movieUrl.isEmpty())
            {
                String url = "http://www.youtube.com/watch?v=1FJHYqE0RDg";
                m_movieUrl = getUrlVideoRTSP(url);
            }
            Log.e("Video url for playing=========>>>>>", m_movieUrl);
        }
        catch (Exception e)
        {
            Log.e("Login Soap Calling in Exception", e.toString());
        }
        return null;
    }

    @Override
    protected void onPostExecute(Void result)
    {
        super.onPostExecute(result);
        m_progressBar.setVisibility(View.GONE);
        m_movieView.setVisibility(View.VISIBLE);

        m_movieView.setVideoURI(Uri.parse(m_movieUrl));
        m_mc = new MediaController(c);
        m_movieView.setMediaController(m_mc);
        m_movieView.requestFocus();
        m_movieView.start();          
        m_mc.show();
    }

    public String getUrlVideoRTSP(String urlYoutube)
    {
        try
        {
            String gdy = "http://gdata.youtube.com/feeds/api/videos/";
            DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
            String id = extractYoutubeId(urlYoutube);
            URL url = new URL(gdy + id);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            Document doc = documentBuilder.parse(connection.getInputStream());
            Element el = (Element) doc.getDocumentElement();
            NodeList list = ((Document) el).getElementsByTagName("media:content");///media:content
            String cursor = urlYoutube;
            for (int i = 0; i < list.getLength(); i++)
            {
                Node node = list.item(i);
                if (node != null)
                {
                    NamedNodeMap nodeMap = node.getAttributes();
                    HashMap<String, String> maps = new HashMap<String, String>();
                    for (int j = 0; j < nodeMap.getLength(); j++)
                    {
                        Attr att = (Attr) nodeMap.item(j);
                        maps.put(att.getName(), att.getValue());
                    }
                    if (maps.containsKey("yt:format"))
                    {
                        String f = maps.get("yt:format");
                        if (maps.containsKey("url"))
                        {
                            cursor = maps.get("url");
                        }
                        if (f.equals("1"))
                            return cursor;
                    }
                }
            }
            return cursor;
        }
        catch (Exception ex)
        {
            Log.e("Get Url Video RTSP Exception======>>", ex.toString());
        }
        return urlYoutube;

    }

    protected String extractYoutubeId(String url) throws MalformedURLException
    {
        String id = null;
        try
        {
            String query = new URL(url).getQuery();
            if (query != null)
            {
                String[] param = query.split("&");
                for (String row : param)
                {
                    String[] param1 = row.split("=");
                    if (param1[0].equals("v"))
                    {
                        id = param1[1];
                    }
                }
            }
            else
            {
                if (url.contains("embed"))
                {
                    id = url.substring(url.lastIndexOf("/") + 1);
                }
            }
        }
        catch (Exception ex)
        {
            Log.e("Exception", ex.toString());
            }
            return id;
        }       
}
}

and finally this is my movie_activity.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" >

<ImageView
    android:id="@+id/Avatar"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:adjustViewBounds="true"
    android:contentDescription="@string/Avatar"
    android:maxHeight="80dp"
    android:maxWidth="80dp"
    android:src="@drawable/ic_launcher">
</ImageView>

<TextView
    android:id="@+id/nickName"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_alignBottom="@id/Avatar"
    android:layout_alignParentTop="true"
    android:layout_toRightOf="@id/Avatar"
    android:gravity="center_vertical"
    android:maxLength="15"
    android:paddingLeft="16dp"
    android:text="@string/nicknamePH"
    android:textAlignment="gravity"
    android:textAppearance="?android:attr/textAppearanceLarge" >
</TextView>

<View
    android:id="@+id/Ruler1"
    android:layout_width="fill_parent"
    android:layout_height="1dp"
    android:layout_below="@id/nickName"
    android:background="#000000">
</View>

<TextView
    android:id="@+id/pageDescription"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_below="@id/Ruler1"
    android:gravity="center_vertical|center_horizontal"
    android:text="@string/pageDescription"
    android:textAlignment="gravity"
    android:textAppearance="?android:attr/textAppearanceSmall">
</TextView>

<View
    android:id="@+id/Ruler2"
    android:layout_width="fill_parent"
    android:layout_height="1dp"        
    android:background="#000000"
    android:layout_below="@id/pageDescription">
</View>

<Button
    android:id="@+id/Skip"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_alignParentRight="true"
    android:onClick="btnSkip_OnClick"
    android:text="@string/skipebutton">
</Button>

<TextView
        android:id="@+id/details"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_above="@id/Skip"
        android:clickable="true"
        android:gravity="center_vertical|center_horizontal"
        android:linksClickable="true"
        android:text="@string/detailspc"
        android:textAlignment="gravity"
        android:textAppearance="?android:attr/textAppearanceLarge" >
</TextView>

<MediaController
    android:id="@+id/mediaController"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_above="@id/details" >
</MediaController>

<FrameLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_below="@id/Ruler2" android:layout_above="@id/mediaController">

    <VideoView
        android:id="@+id/movie"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">
    </VideoView>
    <!--
    <ProgressDialog
        android:id="@+id/progressDialog"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical">
    </ProgressDialog>
    -->

    <ProgressBar
        android:id="@+id/progressBar"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical|center_horizontal"
        android:contentDescription="@string/progressbar"
        android:indeterminate="true" >

        </ProgressBar>


    </FrameLayout>      

</RelativeLayout>

On emulator when i try to run video i get just: "Can't play this video." error message. I read some post that blame the video format/resolution. If you think this is my case could be so kind to provide link that's supposed to work? Error is not very explanatory of what was wrong. So maybe someone more skilled than me could help :)

Thanks in advance for any hint.

Upvotes: 1

Views: 1495

Answers (1)

Alberto
Alberto

Reputation: 728

@bofredo: no, it doesn't work even on a real device.

I found my issue. I wrote my code using Hemant Vc's code: "can't video play error display" after playing video in android

but I realized that DOM parser doesn't work, at least for me. So I wrote two implementations:

the first based on DOM as Hemant Vc's code, and the second based on XPath (I think it's simpler for these cases).

Changing at [0] with a method call to [1] or [2] the MediaPlayer switches way to get url. I think my DOM parser is ugly so I'll use XPath, but maybe some readers will be able to improve it. Biggest issue with XPath was understanding how to set up namespaces. I used Suraj's code: Multiple NameSpace in Xml Xpath value

[EDIT]: as my code came from a bigger project there could be some unused imports

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Iterator;
import javax.xml.XMLConstants;
import javax.xml.namespace.NamespaceContext;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import com.radarmeup.R;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import org.w3c.dom.Element;
import org.xml.sax.InputSource;
import android.support.v4.app.NavUtils;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;
import android.widget.MediaController;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.VideoView;

@SuppressLint("NewApi")
public class MovieActivity extends Activity
{
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.movie_activity);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) 
        {            
                getActionBar().setDisplayHomeAsUpEnabled(true);
        }                   
        new MoviePlayer("http://www.youtube.com/watch?v=1FJHYqE0RDg",this).execute();
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) 
    {
        switch (item.getItemId()) 
        {
            case android.R.id.home:
                NavUtils.navigateUpFromSameTask(this);
                return true;
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu)
    {       
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    public void btnSkip_OnClick(View v)
    {
        Intent intent = new Intent(this, MainActivity.class);
        startActivity(intent);
    }

    private class MyNamespaceContext implements NamespaceContext 
    {               
        public String getNamespaceURI(String prefix) 
        {
            if (prefix == null) {
                throw new IllegalArgumentException("No prefix provided!");
            } else if (prefix.equals("namespace")) {
                return "http://www.w3.org/2005/Atom";
            } else if (prefix.equals("media")) {
                return "http://search.yahoo.com/mrss/";
            } else if (prefix.equals("gd")) {
                return "http://schemas.google.com/g/2005";
            } else if (prefix.equals("yt")) {
                return "http://gdata.youtube.com/schemas/2007";
            } else {
                return XMLConstants.NULL_NS_URI;
            }
        }

        public String getPrefix(String namespaceURI) 
        {
            return null;
        }

        public Iterator<?> getPrefixes(String namespaceURI) 
        {
            return null;
        }
    }

    private class MoviePlayer extends  AsyncTask<Void, Void, Void>
    {
        ProgressBar m_progressBar;
        VideoView m_movieView;
        String m_movieUrl;
        MediaController m_mc;
        Context c;
        public MoviePlayer(final String url, Context context)
        {
            c = context;
            m_movieUrl = url;
            m_progressBar = (ProgressBar) findViewById(R.id.progressBar);
            m_movieView = (VideoView) findViewById(R.id.movie);
            m_mc = (MediaController) findViewById(R.id.mediaController);
        }

        @Override
        protected void onPreExecute()
        {
            super.onPreExecute();           
            m_progressBar.setVisibility(View.VISIBLE);
            m_movieView.setVisibility(View.GONE);
        }

        @SuppressLint("NewApi")
        @Override
        protected Void doInBackground(Void... params)
        {
            try
            {   
                m_movieUrl = getUrlVideoRTSPByXPath(m_movieUrl);//[0]               
                Log.e("Video url for playing =>", m_movieUrl);//here must be shown an url like rtsp://something/video.3gp
            }
            catch (Exception e)
            {
                Log.e("Login Soap Calling in Exception", e.toString());
            }
            return null;
        }

        @Override
        protected void onPostExecute(Void result)
        {
            super.onPostExecute(result);       
            m_movieView = (VideoView) findViewById(R.id.movie);        
            m_progressBar = (ProgressBar) findViewById(R.id.progressBar);
            m_mc = (MediaController) findViewById(R.id.mediaController);
            m_progressBar.setVisibility(View.GONE);
            m_movieView.setVisibility(View.VISIBLE);
            m_movieView.setVideoURI(Uri.parse(m_movieUrl));
            m_mc = new MediaController(c);          
            m_movieView.setMediaController(m_mc);
            m_movieView.requestFocus();
            m_movieView.start();          
            m_mc.show();
        }

        //[1]
        public String getUrlVideoRTSPByXPath(String urlYoutube)
        {
            String ret = "";
            try
            {       
                String gdy = "http://gdata.youtube.com/feeds/api/videos/";
                String id = extractYoutubeId(urlYoutube);
                URL url = new URL(gdy + id);
                InputSource xml = new InputSource(url.openStream()); 
                XPath xpath = XPathFactory.newInstance().newXPath();
                xpath.setNamespaceContext(new MyNamespaceContext());
                ret = xpath.evaluate("//media:content[@yt:format='1']/@url",xml);                           
            }
            catch(Exception ex)
            {
                ret = "";
                Log.e("Get Url Video RTSP Exception======>>", ex.toString());
            }
            return ret;         
        }

        //[2]
        public String getUrlVideoRTSPByDOM(String urlYoutube)
        {
            try
            {        
                String gdy = "http://gdata.youtube.com/feeds/api/videos/";
                DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
                String id = extractYoutubeId(urlYoutube);
                URL url = new URL(gdy + id);
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                Document doc = documentBuilder.parse(connection.getInputStream());
                Element el = (Element) doc.getDocumentElement();//entry
                NodeList list = el.getElementsByTagName("media:content");///media:content
                Node n;
                NamedNodeMap nnm;
                Attr a;
                String urlString = "";
                boolean found = false;
                for(int i = 0; i<list.getLength();++i)
                {//loop nodes media:content:
                    n = list.item(i);
                    if(n != null)
                    {
                        nnm = n.getAttributes();
                        for(int j=0;j<nnm.getLength();++j)
                        {//loop i-th node's attributes:
                            a = (Attr) nnm.item(j);
                            if(a.getName().equalsIgnoreCase("url"))
                                urlString = a.getValue();
                            if(a.getName().equalsIgnoreCase("yt:format") && a.getValue().equalsIgnoreCase("1"))
                            {
                                found = true;
                                break;
                            }
                            else if (a.getName().equalsIgnoreCase("yt:format") && !a.getValue().equalsIgnoreCase("1"))
                            {//wrong node => urlString cleaning:
                                urlString = "";
                            }   
                        }
                        if(found)
                        {
                            if (urlString.isEmpty())
                            {//if i didn't find url yet I have to loop again in node's attributes:
                                for(int j=0;j<nnm.getLength();++j)
                                {//loop i-th node's attributes:
                                    a = (Attr) nnm.item(j);
                                    if(a.getName().equalsIgnoreCase("url"))
                                        urlString = a.getValue();
                                }
                            }else{
                                urlYoutube = urlString;
                                break;
                            }
                        }
                    }
                }  
            }
            catch (Exception ex)
            {
                Log.e("Get Url Video RTSP Exception======>>", ex.toString());
            }
            return urlYoutube;
        }   

        protected String extractYoutubeId(String url) throws MalformedURLException
        {
            String id = null;
            try
            {
                String query = new URL(url).getQuery();
                if (query != null)
                {
                    String[] param = query.split("&");
                    for (String row : param)
                    {
                        String[] param1 = row.split("=");
                        if (param1[0].equals("v"))
                        {
                            id = param1[1];
                        }
                    }
                }
                else
                {
                    if (url.contains("embed"))
                    {
                        id = url.substring(url.lastIndexOf("/") + 1);
                    }
                }
            }
            catch (Exception ex)
            {
                Log.e("Exception", ex.toString());
            }
            return id;
        }
    }
}

I hope it can be useful for someone else.

Upvotes: 1

Related Questions