Share video to viber via intents in android not working - android

I googled a lot but no success.
I want to share a video file in my App via this code:
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("video/mp4"); //or even video mpeg not working!
intent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + outputFileInformation.getFullPath()));
startActivity(Intent.createChooser(intent, getString(R.string.share)));
And I tried some other codes, But for in sharing list if I choose Viber, After selecting recipient nothing happens, Screen flashes and nothing happens.
(I must say sharing image/png has no issue.
I really need to get this work soon.
I could easily share that video from gallery without any issue but now working in my app... .

I manged to make it work.
I must make an Uri in another way, here is the code i used for making Uri from a video file path (you could change it for Images as well)
public static Uri getVideoContentUri(Context context, File imageFile) {
String filePath = imageFile.getAbsolutePath();
Cursor cursor = context.getContentResolver().query(
MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
new String[] { MediaStore.Video.Media._ID },
MediaStore.Video.Media.DATA + "=? ",
new String[] { filePath }, null);
if (cursor != null && cursor.moveToFirst()) {
int id = cursor.getInt(cursor
.getColumnIndex(MediaStore.MediaColumns._ID));
Uri baseUri = Uri.parse("content://media/external/video/media");
return Uri.withAppendedPath(baseUri, "" + id);
} else {
if (imageFile.exists()) {
ContentValues values = new ContentValues();
values.put(MediaStore.Video.Media.DATA, filePath);
return context.getContentResolver().insert(
MediaStore.Video.Media.EXTERNAL_CONTENT_URI, values);
} else {
return null;
}
}
}

Related

Android : use of mediaStore with pdf file

I try to use media store to store a pdf download (in Environment.DIRECTORY_DOWNLOADS) from a private network and to show it. I want the user to be able to choose the application to show it.
In my code, I have difficulty to define the file path "dataFile"
Can you give advice, thanks
Laurent
String fileType="application/pdf";
String filetxt="Choose pdf Application";
final Intent intent = new Intent(Intent.ACTION_VIEW)
.setDataAndType(dataFile, fileType);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
Intent intentChooser = Intent.createChooser(intent,filetxt);
context.startActivity(intentChooser);
dataFile should be URI, which can be easily created from File (or its path)
File file = new File(pathToFile);
Uri dataFile = Uri.parse(file.toString()); // or strightly pass pathToFile here
My solution after several tests :
String[] projections = new String[]{
MediaStore.DownloadColumns._ID,
};
String selection =MediaStore.Files.FileColumns.DISPLAY_NAME+"=?";
String[] selectionArgs = new String[]{newLocalpath};
Cursor cursor = context.getContentResolver().query(
MediaStore.Downloads.EXTERNAL_CONTENT_URI,
projections,
selection,
selectionArgs,
null
);
Uri uri=null;
int docIndex = cursor.getColumnIndexOrThrow(MediaStore.DownloadColumns._ID);
if (cursor.moveToNext()==true) {
uri = ContentUris.withAppendedId(MediaStore.Downloads.EXTERNAL_CONTENT_URI, cursor.getInt(docIndex));
}
if (uri!=null) {
try {
String fileType="application/pdf";
String filetxt="Choose pdf Application";
final Intent intent = new Intent(Intent.ACTION_VIEW)
.setDataAndType(uri, fileType);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Intent intentChooser = Intent.createChooser(intent,filetxt);
intentChooser.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intentChooser);
} catch (Exception e) {
Log.d("application", "error starting download file: " + e.toString());
}

Share Video From Android App

Ours is a video hosting portal where users can upload and earn from their videos based on the views they get. We have recently launched an Android App and trying to integrate Share button to each video. Here is the code what we have placed
Intent intent = new Intent();
try {
URL url = new URL("https://www.clipsnow.com/videos/images/thumbnails/230/10493.jpg");
Bitmap image = BitmapFactory.decodeStream(url.openConnection().getInputStream());
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setAction(Intent.ACTION_SEND);
intent.setData(Uri.parse("https://www.clipsnow.com"));
intent.putExtra(Intent.EXTRA_TEXT,msg);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_STREAM, getImageUri(v.getContext(), image));
intent.setType("image/*");
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
v.getContext().startActivity(Intent.createChooser(intent, "Share Video"));
} catch (Exception e) {
e.printStackTrace();
}
When we share any video with this, only thumbnail image is getting shared along with the video title. But, we need the video URL will get shared and when user tap on the URL, user will be taken to our app.
How can we do that?
This worked with me. Give a try!
File videoFile = new File(filePath);
Uri videoURI = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
? FileProvider.getUriForFile(mContext, mContext.getPackageName(), videoFile)
: Uri.fromFile(videoFile);
ShareCompat.IntentBuilder.from(getActivity())
.setStream(videoURI)
.setType("video/mp4")
.setChooserTitle("Share video...")
.startChooser();
You should download video first. Then you can share with using ACTION_SEND.
String path = ""; //should be local path of downloaded video
ContentValues content = new ContentValues(4);
content.put(MediaStore.Video.VideoColumns.DATE_ADDED,
System.currentTimeMillis() / 1000);
content.put(MediaStore.Video.Media.MIME_TYPE, "video/mp4");
content.put(MediaStore.Video.Media.DATA, path);
ContentResolver resolver = getApplicationContext().getContentResolver();
Uri uri = resolver.insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, content);
Intent sharingIntent = new Intent(Intent.ACTION_SEND);
sharingIntent.setType("video/*");
sharingIntent.putExtra(Intent.EXTRA_SUBJECT, "Hey this is the video subject");
sharingIntent.putExtra(Intent.EXTRA_TEXT, "Hey this is the video text");
sharingIntent.putExtra(Intent.EXTRA_STREAM,uri);
startActivity(Intent.createChooser(sharingIntent,"Share Video");
I guess, all the other solutions are obsolete. Here is the working solution for sharing the video to any platform (Youtube, Gmail, Hangout, Whatsapp etc),
startActivity(
Intent.createChooser(
Intent().setAction(Intent.ACTION_SEND)
.setType("video/*")
.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
.putExtra(
Intent.EXTRA_STREAM,
getVideoContentUri(this, File(currentVideo.videoPath))
), resources.getString(R.string.share_video)
)
)
Below is the getVideoContentUri method,
/**
* Return the URI for a file. This URI is used for
* sharing of video.
* NOTE: You cannot share a file by file path.
*
* #param context Context
* #param videoFile File
* #return Uri?
*/
fun getVideoContentUri(context: Context, videoFile: File): Uri? {
var uri: Uri? = null
val filePath = videoFile.absolutePath
val cursor = context.contentResolver.query(
MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
arrayOf(MediaStore.Video.Media._ID),
MediaStore.Video.Media.DATA + "=? ",
arrayOf(filePath), null)
if (cursor != null && cursor.moveToFirst()) {
val id = cursor.getInt(cursor
.getColumnIndex(MediaStore.MediaColumns._ID))
val baseUri = Uri.parse("content://media/external/video/media")
uri = Uri.withAppendedPath(baseUri, "" + id)
} else if (videoFile.exists()) {
val values = ContentValues()
values.put(MediaStore.Video.Media.DATA, filePath)
uri = context.contentResolver.insert(
MediaStore.Video.Media.EXTERNAL_CONTENT_URI, values)
}
closeCursor(cursor)
return uri
}
To send the video in android 10 and above use this. I used this to send the video from local storage to WhatsApp.
public void shareVideo(String filepath)
{
Intent shareintent=new Intent("android.intent.action.SEND");
shareintent.setType("video/mp4");
shareintent.putExtra("android.intent.extra.STREAM",
Uri.parse(filepath));
startActivity(Intent.createChooser(shareintent,"share"));
}

What's the correct way to form the URI to the video file I intend to send to Whatsapp?

I've been trying to send videos to Instagram and Whatsapp using the following code:
private void createShareIntent(String type, shareVectorList svList){
// Create the new Intent using the 'Send' action.
Intent share = new Intent(Intent.ACTION_SEND);
// Set the MIME type
share.setType(type);
// Create the URI from the media
File media = new File(pathName);
Uri uri = Uri.fromFile(media); //This is the part I'm confused about
// Add the URI to the Intent.
share.putExtra(Intent.EXTRA_STREAM, uri);
switch(svList)
{
case INSTAGRAM:
share.setPackage("com.instagram.android");
break;
case WHATSAPP:
share.setPackage("com.whatsapp");
break;
default:
break;
}
// Broadcast the Intent.
startActivity(Intent.createChooser(share, "Share to"));
}
When I send the video to Instagram, it uploads fine. When I send the video to Whatsapp, however, it just shows a black screen where the video editing part is supposed to be.
When I look at the Android logs, it states a FileNotFoundException.
Someone told me it's because of the malformed URI, or the URI pointing to some file that doesn't exist.
I tried using Uri.parse("file://" + pathName), but it still nets me the same Exception.
I tried getting the URI from the ContentResolver's query with the following code:
public Uri retrieveUriFromVideoPath(String pathName) {
File file = new File(pathName);
Cursor cursor = getContentResolver().query(
MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
new String[] { MediaStore.Video.Media._ID },
MediaStore.Video.Media.DATA + "=? ",
new String[] { pathName }, null);
if (cursor != null && cursor.moveToFirst()) {
int id = cursor.getInt(cursor.getColumnIndex(MediaStore.Video.VideoColumns._ID));
cursor.close();
return Uri.withAppendedPath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "" + id);
} else {
if (file.exists()) {
ContentValues values = new ContentValues();
values.put(MediaStore.Video.Media.DATA, pathName);
return getContentResolver().insert(
MediaStore.Video.Media.EXTERNAL_CONTENT_URI, values);
} else {
return null;
}
}
}
However it just returns mecontent://media/external/images/media/<video_file_id>, and the same Exception pops up.
My questions:
How should I form the URI that refers to the video I intend to share to Whatsapp?
If that video is in a custom folder I generate, would the same method work?
What if the file name contains whitespaces?
Turns out what did the trick was using a FileProvider instead.
I added the following in the Manifest:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.example.thisFileProvider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/path_to_this_app_directory_permanent" />
</provider>
And for the URI I'll just have to do this: Uri uri = FileProvider.getUriForFile(this, "com.example.thisFileProvider", media);
I frankly can't believe it took me this long to figure it out.

Android MediaStore can't get inserted image data

I have image editing app with image export function. Previously I tryed to export it directly by passing file path uri to ACTION_SEND intent. Something like:
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file));
shareIntent.setType("image/*");
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(Intent.createChooser(shareIntent, getString(R.string.export)));
But not all apps can correctly parse such intent. So now I first prepare uri by adding image to android's MediaStore:
shareUri = Uri.parse(MediaStore.Images.Media.insertImage(getContentResolver(),
file.getAbsolutePath(), file.getName(), projectName));
...and then passing shareUri to intent. Now all apps can correctly process this intent, but one problem appear - each time when user exports image its copy added to android MediaStore(even if image path and name the same).
I trying to determine is image already added to mediastore by following code:
Cursor c = getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null, MediaStore.Images.Media.DATA + "=?",
new String[] { filePath }, null);
if (c.getCount() > 0 && c.moveToFirst()) {
shareUri = Uri.withAppendedPath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
"" + c.getInt(c.getColumnIndex(MediaStore.Images.Media._ID)));
c.close();
} else {
shareUri = Uri.parse(MediaStore.Images.Media.insertImage(getContentResolver(),
file.getAbsolutePath(), file.getName(), projectName));
}
...but c.getCount() always == 0. Even if I copy saved uri from MediaStore.Images.Media.insertImage and query it directly by
Cursor c = getContentResolver().query(savedUri, null, null, null);
How I can detect is image file already in MediaStore?
Found solution: not using MediaStore.Images.Media.insertImage to add file to gallery but doing similar by MediaScannerConnection:
MediaScannerConnection.scanFile(
getApplicationContext(),
new String[]{file.getAbsolutePath()},
new String[]{"image/*"},
new OnScanCompletedListener() {
#Override
public void onScanCompleted(String path, Uri uri) {
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
shareIntent.setType("image/*");
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(Intent.createChooser(shareIntent, getString(R.string.export)));
}
});

Share Intent does not work for uploading video to youtube

I am trying to share a video that is being created and stored on external sdcard whose path has been obtained by.
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES).getAbsolutePath()
I am using SEND_INTENT as follows:
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
shareIntent.setType("video/mp4");
shareIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "My Subject");
shareIntent.putExtra(android.content.Intent.EXTRA_TEXT,"My Text");
shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse(video_path));
startActivityForResult(Intent.createChooser(shareIntent, "Share Your Video"),SHARE_INTENT);
Problem:
While I share through gmail, it shows me compose window with video attached. But no size being shown of the video and when you either send or cancel the window, gmail will crash with inputstream NPE on contentresolver.
In case of youtube, it says you cannot upload videos from cloud service, my video clearly resides on the device.
In case of facebook, it is silently discarded. This works fine with wassup. :-)
Any ideas how to get this to work?
EDIT:
Video Path:
/storage/emulated/0/Movies/MyFolder/my-video_1378253389208.mp4
UPDATE
By adding file:/// suffix, gmail and facebook works fine.
Youtube is still cribbing about "Videos cannot be uploaded from cloud services".
The reason Youtube fails and others work is because it checks to see if it is a media file. It only thinks it is a media file if it has been scanned. Run the code below and it should work. It will also show up in the gallery. How to upload a temp file I do not know.
void publishScan() {
//mVidFnam: "/mnt/sdcard/DCIM/foo/vid_20131001_123738.3gp" (or such)
MediaScannerConnection.scanFile(this, new String[] { mVidFnam }, null,
new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
Log.d(TAG, "onScanCompleted uri " + uri);
}
});
}
Based on Johan vdH's answer, the following code works on many sharing apps including Youtube, Facebook, WhatsApp and so on.
Path should be absolute path of video file. for eg. "/mnt/sdcard/DCIM/foo/vid_20131001_123738.3gp"
public void shareVideo(final String title, String path) {
MediaScannerConnection.scanFile(getActivity(), new String[] { path },
null, new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
Intent shareIntent = new Intent(
android.content.Intent.ACTION_SEND);
shareIntent.setType("video/*");
shareIntent.putExtra(
android.content.Intent.EXTRA_SUBJECT, title);
shareIntent.putExtra(
android.content.Intent.EXTRA_TITLE, title);
shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
shareIntent
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
context.startActivity(Intent.createChooser(shareIntent,
getString(R.string.str_share_this_video)));
}
});
}
In addition to Johan vdH's answer, the Uri used in
shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
Must be the one obtained from
public void onScanCompleted(String path, Uri uri)
Getting the Uri by
Uri uri = Uri.fromFile(new File(video_path));
Will not work. Youtube seems to like content:// but not file://
The best and easy method method to Share video on youtube, Use Provider to get Video Uri in Devices with Api >=24
private void VideoShareOnYoutube(String videoPath) {
try {
String csYoutubePackage = "com.google.android.youtube";
Intent intent = getPackageManager().getLaunchIntentForPackage(csYoutubePackage);
if (intent != null && !videoPath.isEmpty()) {
Intent share = new Intent(Intent.ACTION_SEND);
share.setPackage(csYoutubePackage);
Uri contentUri;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
contentUri = FileProvider.getUriForFile(context, context.getApplicationContext().getPackageName() + ".my.package.name.provider", new File(videoPath));
}
else
{
contentUri = Uri.fromFile(new File(videoPath));
}
share.setType("video/*");
share.putExtra(Intent.EXTRA_STREAM, contentUri);
startActivity(share);
} else {
Common.showToast("Youtube app not installed!", activty);
}
} catch (Exception e) {
Log.e(TAG, "Youtubeexeption() :" + e.getMessage());
}
}
with this code you can try.
public void makeVideo(String nameVideo){
String type = "video/*";
// /storage/emulated/0/nameVideo.mp4
// if you have other path is necessary you change the path
String mediaPath = Environment.getExternalStorageDirectory() + File.separator + nameVideo;
createIntent(type, mediaPath);
}
private void createIntent(String type, String mediaPath) {
// Create the new Intent using the 'Send' action.
Intent share = new Intent(Intent.ACTION_SEND);
// Set the MIME type
share.setType(type);
// Create the URI from the media
File media = new File(mediaPath);
Uri uri = Uri.fromFile(media);
// Add the URI to the Intent.
share.putExtra(Intent.EXTRA_STREAM, uri);
// Broadcast the Intent.
startActivity(Intent.createChooser(share, "Share to"));
}
more information https://instagram.com/developer/mobile-sharing/android-intents/
Just a heads up as this caught me out when trying to share a video to Facebook via Intent Chooser that worked fine with Gmail and a few other Intents -
If there are spaces or other characters that get encoded to %20 for space for example, Facebook won't find the video if you try to play it.
I was using Video - 27 Apr 2016 - 16:59 pm.mp4 for instance, and spaces and colons were replaced, breaking the link inside Facebook. A thumbnail of the video would show when composing the share in Facebook, so I thought it was OK, but if you clicked to play it, it would say the file could not be found / played.
No such problem with Gmail, it sent and was playable once retrieved from email.
Here is the working solution for sharing videos, (code is in kotlin)
startActivity(
Intent.createChooser(
Intent().setAction(Intent.ACTION_SEND)
.setType("video/*")
.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
.putExtra(
Intent.EXTRA_STREAM,
getVideoContentUri(this, File(currentVideo.videoPath))
), resources.getString(R.string.share_video)
)
)
don't forget to add the following method,
/**
* Return the URI for a file. This URI is used for
* sharing of video.
* NOTE: You cannot share a file by file path.
*
* #param context Context
* #param videoFile File
* #return Uri?
*/
fun getVideoContentUri(context: Context, videoFile: File): Uri? {
var uri: Uri? = null
val filePath = videoFile.absolutePath
val cursor = context.contentResolver.query(
MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
arrayOf(MediaStore.Video.Media._ID),
MediaStore.Video.Media.DATA + "=? ",
arrayOf(filePath), null)
if (cursor != null && cursor.moveToFirst()) {
val id = cursor.getInt(cursor
.getColumnIndex(MediaStore.MediaColumns._ID))
val baseUri = Uri.parse("content://media/external/video/media")
uri = Uri.withAppendedPath(baseUri, "" + id)
} else if (videoFile.exists()) {
val values = ContentValues()
values.put(MediaStore.Video.Media.DATA, filePath)
uri = context.contentResolver.insert(
MediaStore.Video.Media.EXTERNAL_CONTENT_URI, values)
}
closeCursor(cursor)
return uri
}
Happy Codng :)

Categories

Resources