简体   繁体   中英

Streaming live video from Raspberry Pi to my Android App but getting security exception

I would like to stream live video to my android app. I am using the motion service to stream live video from my raspberry pi's camera (small usb connected camera). I have it setup for port 8082 so I can successfully type in (exampled IP) " http://74.220.185.125:8082 " from any browser and see my video streaming. However, when I use this in my code for my app using the videoView I get an Exception thrown each time.

MainActivity:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //Starting video
        piVideo = (VideoView) findViewById(R.id.piVidView);

        try{
            piVideo.setVideoURI(Uri.parse("http://74.220.185.125:8082/"));
        } catch (Exception e){
            Log.e("Error found here->", e.getMessage());
            e.printStackTrace();
        }
        piVideo.requestFocus();
        piVideo.start();

        piVideo.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
            @Override

            public void onPrepared(MediaPlayer mp) {
                piVideo.start();
            }
        });


    }

Each time, I get this same error:

03-08 12:46:49.258 1412-1412/com.me.blah.app D/MediaPlayer: setDataSource IOException | SecurityException happend : 
                                                                         java.io.FileNotFoundException: No content provider: http://74.220.185.125:8082/
                                                                             at android.content.ContentResolver.openTypedAssetFileDescriptor(ContentResolver.java:1141)
                                                                             at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:991)
                                                                             at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:914)
                                                                             at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1121)
                                                                             at android.widget.VideoView.openVideo(VideoView.java:371)
                                                                             at android.widget.VideoView.access$2100(VideoView.java:71)
                                                                             at android.widget.VideoView$7.surfaceCreated(VideoView.java:652)
                                                                             at android.view.SurfaceView.updateWindow(SurfaceView.java:712)
                                                                             at android.view.SurfaceView$3.onPreDraw(SurfaceView.java:209)
                                                                             at android.view.ViewTreeObserver.dispatchOnPreDraw(ViewTreeObserver.java:1014)
                                                                             at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2510)
                                                                             at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1437)
                                                                             at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7397)
                                                                             at android.view.Choreographer$CallbackRecord.run(Choreographer.java:920)
                                                                             at android.view.Choreographer.doCallbacks(Choreographer.java:695)
                                                                             at android.view.Choreographer.doFrame(Choreographer.java:631)
                                                                             at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:906)
                                                                             at android.os.Handler.handleCallback(Handler.java:739)
                                                                             at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                             at android.os.Looper.loop(Looper.java:158)
                                                                             at android.app.ActivityThread.main(ActivityThread.java:7229)
                                                                             at java.lang.reflect.Method.invoke(Native Method)
                                                                             at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
                                                                             at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)

I have INTERNET enabled in my manifest file:

"uses-permission android:name="android.permission.INTERNET"

I have tried rstp:// and http:// and both still end up with the same exception being thrown. Can anyone see where I this exception could being caused from?

So I actually found this simple solution about a week or so ago after searching & asking for roughly two weeks, and I noticed there were many other people asking the same questions or looking for a simple answer and I wanted to share what worked for me.

My search lead me to using a videoView, but from my understanding the videoView is searching for a specific file and/or a specific streaming file type that would normally be created on your remote server. However the motion service did not readily provide the file nor the details I was looking for, but the ip address definitely worked in a normal browser so I tried a webView instead, adjusted my pixel ratio on my raspberry pi in the motion.conf file, and played with the dimensions of my webView and it worked perfectly fine. The code was a lot easier than the examples I kept seeing and this is what I used:

String piAddr = "http://10.0.0.116:8081/"

mWebView = (WebView) findViewById(R.id.activity_main_webview);
mWebView.loadUrl(piAddr);

NOTE: I am running a python script that starts the motion service on my raspberry pi and it seems that the timing between the app requesting the raspberry pi motion service port and the motion service actually starting up is slightly off, so throughout my code I just repeat the following line periodically to verify my video is streaming successfully.

Additionally, the webView has a scroll bar automatically so if you cannot see the entire video (with the timer at the bottom) you can always tweak your video dimensions on the pi in the motion.conf file.

Is there a way you can provide the working solution? Currently working on a project where I need to access the live stream in an android app so we can run a CNN model on it. I have tried looking for it all over. This is where I got my original code from https://supercheatsblog.blogspot.com/2015/05/play-stream-video-from-raspberry-pi-on.html and the stream setup from here https://pimylifeup.com/raspberry-pi-webcam-server/ . After looking at the suggested solution, I am planning on making these changes:-

MainActivity.java 
public class MainActivity extends AppCompatActivity {

EditText addrField;
Button btnConnect;
WebView streamView;
MediaController mediaController;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    addrField = (EditText)findViewById(R.id.addr);
    btnConnect = (Button)findViewById(R.id.connect);
    streamView = (WebView)findViewById(R.id.streamview);

    btnConnect.setOnClickListener(new OnClickListener(){

        @Override
        public void onClick(View v) {
            String s = addrField.getEditableText().toString();
            playStream(s);
        }});

}

private void playStream(String src){
    Uri UriSrc = Uri.parse(src);
    if(UriSrc == null){
        Toast.makeText(MainActivity.this,
                "UriSrc == null", Toast.LENGTH_LONG).show();
    }else{
        streamView.loadUrl(src);

        Toast.makeText(MainActivity.this,
                "Connect: " + src,
                Toast.LENGTH_LONG).show();
    }
}

@Override
protected void onDestroy() {
    super.onDestroy();
    streamView.destroy();
}

}

And my activity_main.xml to be something like this

    <?xml version="1.0" encoding="utf-8"?>

<LinearLayout 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"
android:orientation="vertical">

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal"
    android:text="Streaming App"
    android:textStyle="bold" />
<EditText
    android:id="@+id/addr"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="http://192.168.43.120:8081/" />
<Button
    android:id="@+id/connect"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="Connect" />
<WebView
    android:id="@+id/streamview"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />


</LinearLayout>

Just so I have everything covered, this is what my manifest file looks like

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.testnetrabenchside">
    <uses-permission android:name="android.permission.BLUETOOTH"/>
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

    <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">
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:theme="@style/AppTheme.NoActionBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

</manifest>

I am thinking about changing the width and height of the WebView based on the width and height of the stream. Should this be enough? Am I missing anything??

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM