Libstreaming - use VLC as a RTSP client - java

I'm trying to use VLC as a RTSP client. The RTSP server is based on the libstreaming library. I'm using the code provided by the 1rst example:
// Sets the port of the RTSP server to 1234
Editor editor = PreferenceManager.getDefaultSharedPreferences(this).edit();
editor.putString(RtspServer.KEY_PORT, String.valueOf(1234));
editor.commit();
// Configures the SessionBuilder
SessionBuilder.getInstance()
.setSurfaceView(mSurfaceView)
.setPreviewOrientation(90)
.setContext(getApplicationContext())
.setAudioEncoder(SessionBuilder.AUDIO_NONE)
.setVideoEncoder(SessionBuilder.VIDEO_H264);
// Starts the RTSP server
this.startService(new Intent(this,RtspServer.class));
The android app starts; I try to access the stream using VLC (open a stream) and this URL:
rtsp://192.168.43.250:1234
The device is connected to the same network (I can ping it), but nothing happens in the android App and VLC displays a "connection failed" window.
Any idea where the problem is? Maybe a bad URL, but I can't found any detailled example of this situation.

It throws null pointer, check the logcat.
you have to provide the url as rtsp://ip:1234?h264=200-20-320-240
200 - buf
20 - fps
320 - resolution w
240 - resolution h

I had similar problems. Here is my solution.
Make sure you have imported the library as an imported module through android studio
Give your manifest the permission to use the resources needed
Use this code for you MainActivity:
public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback, RtspServer.CallbackListener, Session.Callback{
private final static String TAG = "MainActivity";
private SurfaceView mSurfaceView;
private Session mSession;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
mSurfaceView = (SurfaceView) findViewById(R.id.surface);
// Sets the port of the RTSP server to 1234
SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(this).edit();
editor.putString( RtspServer.KEY_PORT, String.valueOf(1234));
editor.commit();
// Configures the SessionBuilder
mSession = SessionBuilder.getInstance()
.setCallback(this)
.setSurfaceView((net.majorkernelpanic.streaming.gl.SurfaceView) mSurfaceView)
.setPreviewOrientation(90)
.setContext(getApplicationContext())
.setAudioEncoder(SessionBuilder.AUDIO_AAC)
.setAudioQuality(new AudioQuality(8000, 16000))
.setVideoEncoder(SessionBuilder.VIDEO_H264)
//.setVideoQuality(new VideoQuality(320,240,20,500000))
.build();
mSurfaceView.getHolder().addCallback(this);
((net.majorkernelpanic.streaming.gl.SurfaceView) mSurfaceView).setAspectRatioMode(net.majorkernelpanic.streaming.gl.SurfaceView.ASPECT_RATIO_PREVIEW);
String ip, port, path;
// Starts the RTSP server
this.startService(new Intent(this,RtspServer.class));
Log.d("test", "1");
mSession.startPreview(); //camera preview on phone surface
mSession.start();
}
#Override
public void onResume()
{
super.onResume();
mSession.stopPreview();
}
#Override
public void onDestroy()
{
super.onDestroy();
mSession.release();
mSurfaceView.getHolder().removeCallback(this);
}
//region ----------------------------------implement methods required
#Override
public void onError(RtspServer server, Exception e, int error) {
Log.e("Server", e.toString());
}
#Override
public void onMessage(RtspServer server, int message) {
Log.e("Server", "unkown message");
}
#Override
public void onBitrateUpdate(long bitrate) {
}
#Override
public void onSessionError(int reason, int streamType, Exception e) {
}
#Override
public void onPreviewStarted() {
}
#Override
public void onSessionConfigured() {
}
#Override
public void onSessionStarted() {
}
#Override
public void onSessionStopped() {
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
//endregion
}
using VLC player open the open network stream and type
rtsp://the ip of android device:1234 <--this port is hard coded so don't change

When I worked with libstreaming & VLC I spent a lot of time with the same problem. The solution for me was to use other VLC version. For example, it worked for me on vlc ver. 1.0.5, but many other versions didn't play the stream.

))) the first example is a server (for the author of the library, the server is someone who accepts the stream and does not give)
you need to use 2 or 3 example ...
2 example is good because you only need a VLK player ...
find out your Ip (cmd-> ipconfig) (it's important to understand that the device must have an external ip address or is in the same network)
Specify the received ip address of the PC in mEditText (mSession.setDestination ();)
After launching the application, press the start button. The studio in the logs will return the contents to create the sdp format file (TAG, mSession.getSessionDescription ());
create a falix for example 1.sdp edit it by specifying the contents of getSessionDescription (remove extra spaces)
huge minutes then that we need to specify the ip of the one we want to send the stream to ...
 now the main thing! in any of the examples it does not turn out to simply enter rtsp: //192.168.43.250: 1234 and get the video !!! - 0)))))))
 
 In the Session class, you'll find mOrigin = "127.0.0.1"; ok SessionBuilder .... .setOrigin ("192.xxx.xxx.xx")
 Further your logic may suggest that you only need to find the port and maybe you will find SessionBuilder Session build () video.setDestinationPorts (5006);
 but this is not the port)))
 in this library there is no rtsp server implementation (I'm writing a server since it means that we want to raise the server for ip cam on the device)
 
 you can find the hint in the RtspClient class (pay attention to the author of the library, this is the one who gives it) and there the author writes to us
 
 * RFC 2326.
 * A basic and asynchronous RTSP client.
 RTSP client compatible with Wowza.
 * It implements Digest Access Authentication according to RFC 2069.

Related

Discovering all services on the network using jmDNS on Android

I'm using the jmdns.jar from this project https://github.com/twitwi/AndroidDnssdDemo in my Android project.
I'm currently trying to find all services on my network. I can't use Android NSD, so please avoid suggesting it as a solution.
protected Object doInBackground(Object[] params) {
try {
WifiManager wifi = (WifiManager) getActivity().getSystemService(Context.WIFI_SERVICE);
final InetAddress deviceIpAddress = InetAddress.getByName(Formatter.formatIpAddress(wifi.getConnectionInfo().getIpAddress()));
multicastLock = wifi.createMulticastLock(getClass().getName());
multicastLock.setReferenceCounted(true);
multicastLock.acquire();
jmDNS = JmDNS.create(deviceIpAddress, "Android Device Discovery");
jmDNS.addServiceListener("_http._tcp.local.", new ServiceListener() {//_services._dns-sd._udp _http._tcp.local. _workstation._tcp.local.
#Override
public void serviceAdded(ServiceEvent serviceEvent) {
jmDNS.requestServiceInfo("", "", 1000);
}
#Override
public void serviceRemoved(ServiceEvent serviceEvent) {
}
#Override
public void serviceResolved(ServiceEvent serviceEvent) {
System.out.println(serviceEvent.getInfo().getHostAddress());
System.out.println(serviceEvent.getInfo().getName());
}
});
}catch(IOException e) {
Log.e(TAG, e.getMessage(), e);
}
}
The above code gives me the address and name of a printer on my network. That's great. What I would like is a TYPE that will catch all the services being broadcasted on my network. Android NSD had a _services._dns-sd._udpthat could be used for the type of service and find all services on the network. This doesn't work with jmDNS. I can't find anything in the limited documentation about this.
Do I need to go through and add all the service types myself? That is not a very clean solution.
I have the proper perms in my AndroidManifest.
Try adding the dot at the end, my jmdns app crashed without it..
Also try adding the .local. by yourself with the service type.

Unable to get the shared with me files with the Google Drive Api using Filters.sharedWithMe()

I have some files in my Google Drive that others have shared with me and I would like to be able to query them. Unfortunately the MetadataBuffer' result count is 0
This is the code:
private GoogleApiClient mGoogleApiClient;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
mGoogleApiClient = new GoogleApiClient.Builder(this).addApi(com.google.android.gms.drive.Drive.API)
.addScope(com.google.android.gms.drive.Drive.SCOPE_FILE).addConnectionCallbacks(this)
.addOnConnectionFailedListener(this).build();
}
#Override
protected void onStart() {
super.onStart();
mGoogleApiClient.connect();
}
#Override
public void onConnected(Bundle arg0) {
Query query = new Query.Builder().addFilter(Filters.sharedWithMe()).build();
Drive.DriveApi.query(mGoogleApiClient, query).setResultCallback(metadataCallback);
}
private ResultCallback<DriveApi.MetadataBufferResult> metadataCallback =
new ResultCallback<DriveApi.MetadataBufferResult>() {
#Override
public void onResult(DriveApi.MetadataBufferResult result) {
if (!result.getStatus().isSuccess()) {
Log.d(TAG, "Problem while retrieving results");
return;
}
MetadataBuffer buffer = result.getMetadataBuffer();
if(buffer != null) {
int cnt = buffer.getCount();
Log.d(TAG, "BUFFER COUNT: " + cnt);
for(int i = 0; i < cnt; i++) {
Metadata meta = buffer.get(i);
Log.d(TAG, meta.getTitle());
}
buffer.close();
}
}
};
....................
I am using the new Google Drive and I also tried moving some shared files from the Incoming Folder into the My Drive root. Still nothing.
I would appreciate any help and suggestions.
As said also on unable to query the files "shared with me" from google drive using Google drive api android , at the moment drive apis let you access only data in drive made by your app.
you can verify by yourself by changing
Query query = new Query.Builder().addFilter(Filters.sharedWithMe()).build();
in
Query query = new Query.Builder().build();
and you see only one folder, named "App Data"
to access other files you need to use drive java api, as told in https://developers.google.com/drive/android/auth#connecting_and_authorizing_the_google_drive_android_api
Note: The Google Drive Android API currently only supports drive.file and drive.appfolder
authorization scopes. If your application requires additional permissions or features not
yet available in the Drive Android API, you must use the Google APIs Java Client.

Sending Email Using apache commons mail package from android

I am new to android. I am developing the new app with email sending option. To send a mail I have used gmail configurations host "smtp.gmail.com", port 465 with SSL true. To send an email I have apache commons API. OnTouch event mail sending method will call. Whenever touch button it shows following errors,
Error : Could not find class 'javax.naming.InitialContext', referenced from method org.apache.commons.mail.Email.setMailSessionFromJNDI
Warning: VFY: unable to resolve new-instance 955 (Ljavax/naming/InitialContext;) in Lorg/apache/commons/mail/Email;
Warning : org.apache.commons.mail.EmailException: Sending the email to the following server failed : smtp.gmail.com:465
I have added uses-permission android:name="android.permission.INTERNET" in my manifest file.
Can i use all java files in android ?
My email code executed correctly as a stand alone java program.
Here is an example of what I am doing in an app. I have an app that has its own email account that sends an email to the user when they fill out a form and press the submit button.
Important make sure you have the libSMTP.jar file referenced in your app. I am using this library for the following code. Here is the following code being used, take from it what you'd like, hope this is useful:
Imports needed:
import org.apache.commons.net.smtp.SMTPClient;
import org.apache.commons.net.smtp.SMTPReply;
import org.apache.commons.net.smtp.SimpleSMTPHeader;
Submit button to make the request to send email
submit.setOnClickListener(new OnClickListener()
{
public void onClick(View v)
{
//-- Submit saves data to sqlite db, but removed that portion for this demo...
//-- Executes an new task to send an automated email to user when they fill out a form...
new sendEmailTask().execute();
}
}
});
Email task to be preformed on seperate thread:
private class sendEmailTask extends AsyncTask<Void, Void, Void>
{
#Override
protected void onPostExecute(Void result)
{
}
#Override
protected void onPreExecute()
{
}
#SuppressLint("ParserError")
#Override
protected Void doInBackground(Void... params)
{
try {
//--Note the send format is as follows: send(from, to, subject line, body message)
send("myAppName#gmail.com", "emailToSendTo#gmail.com", "Form Submitted", "You submitted the form.");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
Send function being used:
public void send(String from, String to, String subject, String text) throws IOException
{
SMTPClient client = new SMTPClient("UTF-8");
client.setDefaultTimeout(60 * 1000);
client.setRequireStartTLS(true); // requires STARTTLS
//client.setUseStartTLS(true); // tries STARTTLS, but falls back if not supported
client.setUseAuth(true); // use SMTP AUTH
//client.setAuthMechanisms(authMechanisms); // sets AUTH mechanisms e.g. LOGIN
client.connect("smtp.gmail.com", 587);
checkReply(client);
//--Note the following format is as follows: client.login("localhost", (...your email account being used to send email from...), (...your email accounts password ...));
client.login("localhost", "myAppName#gmail.com", "...myAppName email account password...");
checkReply(client);
client.setSender(from);
checkReply(client);
client.addRecipient(to);
checkReply(client);
Writer writer = client.sendMessageData();
if (writer != null)
{
SimpleSMTPHeader header = new SimpleSMTPHeader(from, to, subject);
writer.write(header.toString());
writer.write(text);
writer.close();
client.completePendingCommand();
checkReply(client);
}
client.logout();
client.disconnect();
}
Check reply function being used:
private void checkReply(SMTPClient sc) throws IOException
{
if (SMTPReply.isNegativeTransient(sc.getReplyCode()))
{
sc.disconnect();
throw new IOException("Transient SMTP error " + sc.getReplyCode());
}
else if (SMTPReply.isNegativePermanent(sc.getReplyCode()))
{
sc.disconnect();
throw new IOException("Permanent SMTP error " + sc.getReplyCode());
}
}
From Apache Commons Net 3.3, you can just drop the jar in your classpath and start using the AuthenticationSMTPClient : http://blog.dahanne.net/2013/06/17/sending-a-mail-in-java-and-android-with-apache-commons-net/

Android 2.3.4 - Http Live Streaming

I'm working on this project for a client and we're supposed to stream audio from a server onto a device running Android Gingerbread. To retrieve the stream, the Android client needs to make a request for a variant playlist, and then make a request for the playlist itself (the one with URIs that point to the TS file chunks themselves). Once that's done, the client app decrypts the chunks and sends them to the platform for playback.
The problem I'm having revolves around the security part. Our client(the company in question) uses a proprietary encryption scheme that serves the keys for decrypting the TS file chunks ahead of time through an HTTP request instead of following the HLS spec and serving the key files through URI(s) listed in the index files themselves. As far as I can tell, the Android Mediaplayer framework has the ability to find these key files and generate/find the appropriate IVs for decryption IF the key file URIs are in the index files.
Unfortunately, what this all means is that I can't decrypt the file chunks and play back the stream without gaps between each segment -- I accomplish this by making HTTP GET requests for each segment, downloading them to internal storage, applying decrypting, and then playing them back using the following code:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
File dir = new File(TS_FILE_DIR);
String [] files = dir.list();
mTsFiles = new ArrayList<File>();
for (String file : files) {
String path = TS_FILE_DIR + file;
mTsFiles.add(new File(path));
}
mMediaController = new MediaController(this);
mVideoView = (VideoView)findViewById(R.id.video_view_1);
mVideoView.setVideoPath(mTsFiles.get(0).getAbsolutePath());
mVideoView.setMediaController(mMediaController);
mVideoView.setOnPreparedListener(new OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
mp.start();
}
});
mVideoView.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
mp.pause();
mp.reset();
if (mIndex < mTsFiles.size()) {
mIndex++;
try {
mp.setDataSource(mTsFiles.get(mIndex).getAbsolutePath());
mp.prepareAsync();
}
catch (Exception e) {
e.printStackTrace();
}
}
}
});
}
I've tried:
1) Using 2 mediaplayers and switching between the 2, but it doesn't work at all
2) Staring at the source code for ICS to get an idea of how this all works, but its very complex and I'm not well versed in c++
Is there anything I missed?

Android/Java -- Post simple text to Facebook wall?

I'm trying to integrate posting to one's wall from within my app. I already have an area where the user can save his/her username and password (encrypted). I would like my program to recall the saved username and password, pass that to Facebook for authentication, and then allow the app to post simple text (maybe a link too) to the user's wall.
That said, I've read everything on the developer pages at Facebook (the api looks completely foreign to me... I've never done any type of web app development before... just desktop apps), and experimented with the Java libraries here but to be honest, I don't understand any of the various implementations. Some claim to be simple to use, but apparently they are all way above my head.
I've even tried messing with the official Facebook Android SDK, but that uses a webview interface, and I can't pass in the username and password for easy authentication. Plus, I'm still clueless as to how to post to the wall even after correct authentication.
Please help.
Thanks.
Oh, btw I already have a Facebook API key and Application ID.
[UPDATE 1]
For further clarification:
If I use the following code snippet with the official Facebook Android SDK http://github.com/facebook/facebook-android-sdk what should I do next (after the user has logged-in)? This is unclear to me.
Facebook facebookClient = new Facebook();
facebookClient.authorize(this, "[APP ID]", new String[] {"publish_stream", "read_stream", "offline_access"}, this);
where "this" is an Activity that implements a DialogListener, and "[APP ID]" is my Facebook application ID.
Thanks.
[UPDATE 2]
I found a solution (see below), though the only thing missing is the ability to auto-populate the login text boxes with the data I have stored in the app. The official Facebook Android SDK may not allow for this. I'll keep looking into it.
I figured it out, with Tom's help (thanks). The key was creating a dialog with the "stream.publish" API call, using the Facebook Android SDK. Here are the steps:
Download the official Facebook Android SDK : http://github.com/facebook/facebook-android-sdk
Import the project files into Eclipse.
Export the project as a *.jar file. (this might cause a conflict)
[UPDATE]
Facebook recently updated the source code and I noticed the icon file caused resource id conflicts with my projects (Android 1.5+). My solution is to forget about exporting as a jar. Instead, copy the Facebook "com" folder directly into your app's "src" folder (i.e. "com.facebook.android" should be a package in your app... right alongside your source files). If you already have a "com" folder in your "src" folder, don't worry about any dialog boxes that appear about overwriting files, none of your source files should be overwritten. Go back into Eclipse, and refresh the "src" folder and "com.facebook.android" should now be listed as a package. Copy one of the included Facebook icons to your app's "drawable" folder and refresh that as well. Eclipse will complain about the "FbDialog.java" file... just add an import pointing to your app's "R" file to the header of that file (e.g. if your app's package name is "com.android.myapp," then add this: "import com.android.myapp.R;"). Go to #5 if you needed to do this.
Add the .jar file to your project's build path
Look at the following simplified example code:
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.LinearLayout;
import com.facebook.android.*;
import com.facebook.android.Facebook.DialogListener;
public class FacebookActivity extends Activity implements DialogListener,
OnClickListener
{
private Facebook facebookClient;
private LinearLayout facebookButton;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
this.setContentView(R.layout.test);//my layout xml
facebookButton = (LinearLayout)this.findViewById(R.id.Test_Facebook_Layout);
}
#Override
public void onComplete(Bundle values)
{
if (values.isEmpty())
{
//"skip" clicked ?
return;
}
// if facebookClient.authorize(...) was successful, this runs
// this also runs after successful post
// after posting, "post_id" is added to the values bundle
// I use that to differentiate between a call from
// faceBook.authorize(...) and a call from a successful post
// is there a better way of doing this?
if (!values.containsKey("post_id"))
{
try
{
Bundle parameters = new Bundle();
parameters.putString("message", "this is a test");// the message to post to the wall
facebookClient.dialog(this, "stream.publish", parameters, this);// "stream.publish" is an API call
}
catch (Exception e)
{
// TODO: handle exception
System.out.println(e.getMessage());
}
}
}
#Override
public void onError(DialogError e)
{
System.out.println("Error: " + e.getMessage());
}
#Override
public void onFacebookError(FacebookError e)
{
System.out.println("Error: " + e.getMessage());
}
#Override
public void onCancel()
{
}
#Override
public void onClick(View v)
{
if (v == facebookButton)
{
facebookClient = new Facebook();
// replace APP_API_ID with your own
facebookClient.authorize(this, APP_API_ID,
new String[] {"publish_stream", "read_stream", "offline_access"}, this);
}
}
}
AsyncFacebookRunner mAsyncRunner;
Facebook facebook =new Facebook("Your app id");
btnLogin.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
facebook.authorize(FbdemoActivity.this, new String[]{ "user_photos,publish_checkins,publish_actions,publish_stream"},new DialogListener() {
#Override
public void onComplete(Bundle values) {
}
#Override
public void onFacebookError(FacebookError error) {
}
#Override
public void onError(DialogError e) {
}
#Override
public void onCancel() {
}
});
}
});
public void postOnWall(String msg) {
Log.d("Tests", "Testing graph API wall post");
try {
String response = facebook.request("me");
Bundle parameters = new Bundle();
parameters.putString("message", msg);
parameters.putString("description", "test test test");
response = facebook.request("me/feed", parameters,
"POST");
Log.d("Tests", "got response: " + response);
if (response == null || response.equals("") ||
response.equals("false")) {
Log.v("Error", "Blank response");
}
} catch(Exception e) {
e.printStackTrace();
}
Here is an objective answer to your new question, "What do I do next?"
A quick look at the source code leads me to believe this is what you do:
Check this URL for the REST (http://en.wikipedia.org/wiki/Representational_State_Transfer) API methods you can use to leave a comment/post:
http://developers.facebook.com/docs/reference/rest/
Specifically this: http://developers.facebook.com/docs/reference/rest/links.post
Check out lines 171 through 295 of Facebook.java
http://github.com/facebook/facebook-android-sdk/blob/master/facebook/src/com/facebook/android/Facebook.java
To see how to use the API to make these requests.
You'll probably want this method (it's overloaded, see the code).
/**
* Make a request to Facebook's old (pre-graph) API with the given
* parameters. One of the parameter keys must be "method" and its value
* should be a valid REST server API method.
*
* See http://developers.facebook.com/docs/reference/rest/
*
* Note that this method blocks waiting for a network response, so do not
* call it in a UI thread.
*
* Example:
* <code>
* Bundle parameters = new Bundle();
* parameters.putString("method", "auth.expireSession");
* String response = request(parameters);
* </code>
*
* #param parameters
* Key-value pairs of parameters to the request. Refer to the
* documentation: one of the parameters must be "method".
* #throws IOException
* if a network error occurs
* #throws MalformedURLException
* if accessing an invalid endpoint
* #throws IllegalArgumentException
* if one of the parameters is not "method"
* #return JSON string representation of the response
*/
public String request(Bundle parameters)
To those who have problems, in the new facebook(); , the string is you App_id, and just delete the APP_ID in the authorized call.
Don't know why the error message is shown, but I guess that facebook updated the facebook SDK.

Categories