I have written a code that open a file like pdf. For that I used intent like the below one:
public void openFile(Context context, File file) {
String typeFile = "application/pdf";
if (file.exists()) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), typeFile);
PackageManager pm = context.getPackageManager();
Intent sendIntent = new Intent(Intent.ACTION_VIEW);
sendIntent.setType(typeFile);
Intent openInChooser = Intent.createChooser(intent, "Choose");
List<ResolveInfo> resInfo = pm.queryIntentActivities(sendIntent, 0);
if (resInfo.size() > 0) {
try {
context.startActivity(openInChooser);
} catch (Throwable throwable) {
Toast.makeText(context, "No application found which can open the file", Toast.LENGTH_SHORT).show();
// PDF apps are not installed
}
} else {
Toast.makeText(context, "No application found which can open the file", Toast.LENGTH_SHORT).show();
}
}
}
My problem is when I run this code on Android 10 and 11, the Toast in else is executed but in older versions these codes work correctly.
So what should I do to open file in Android 10 and 11?
Your app should be crashing on Android 7.0+ with a FileUriExposedException. You need to get rid of Uri.fromFile() and switch to FileProvider.
Also, you can get rid of queryIntentActivities(). You do not need it, partly because there should always be a chooser, and partly because you have the try/catch block to catch the ActivityNotFoundException if there is no chooser for some strange reason. If your reason for queryIntentActivities() is to avoid an empty chooser, stop creating a chooser — the OS will add one automatically if one is appropriate. Alternatively, for Android 11+, you will need to deal with package visibility rules to be able to call queryIntentActivities(). See this and this for more.
I believe that the original APK Expansion Library was slightly over-engineered. And not support android Oreo.
First:
I'm trying to use Google's Downloader Library and Application Licensing Service since my app is going to use APK Expansion.
I read guide from https://developer.android.com/google/play/expansion-files#java and https://kitefaster.com/2017/02/15/expansion-apk-files-android-studio/,Everything is going well. But error.expansion.downloader does not exist. I did everything as guide
enter image description here , enter image description here , enter image description here
Final
, I have used lib from git-hub https://github.com/bolein/better-apk-expansion
But it always status IDownloaderClient.STATE_FAILED_FETCHING_URL when download OBB file and it not support Android Oreo with error toast Developer warning for package Failed to post notification on channel .
Code download OBB file:
if (!expansionFilesDelivered()) {
try {
Intent launchIntent = SampleDownloaderActivity.this
.getIntent();
Intent intentToLaunchThisActivityFromNotification = new Intent(
SampleDownloaderActivity
.this, SampleDownloaderActivity.this.getClass());
intentToLaunchThisActivityFromNotification.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_CLEAR_TOP);
intentToLaunchThisActivityFromNotification.setAction(launchIntent.getAction());
if (launchIntent.getCategories() != null) {
for (String category : launchIntent.getCategories()) {
intentToLaunchThisActivityFromNotification.addCategory(category);
}
}
// Build PendingIntent used to open this activity from
// Notification
PendingIntent pendingIntent = PendingIntent.getActivity(
SampleDownloaderActivity.this,
0, intentToLaunchThisActivityFromNotification,
PendingIntent.FLAG_UPDATE_CURRENT);
// Request to start the download
int startResult = DownloaderClientMarshaller.startDownloadServiceIfRequired(this,
pendingIntent, SampleDownloaderService.class);
if (startResult != DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED) {
// The DownloaderService has started downloading the files,
// show progress
initializeDownloadUI();
return;
} // otherwise, download not needed so we fall through to
// starting the movie
} catch (NameNotFoundException e) {
Log.e(LOG_TAG, "Cannot find own package! MAYDAY!");
e.printStackTrace();
}
} else {
validateXAPKZipFiles();
}
I hope somebody give me a solution, please.
Try moving to the latest expansion code from Github. Google haven't updated their docs yet. The code is at: https://github.com/google/play-apk-expansion
I really don't know your problem, but my below code is using play-apk-expansion and working fine.
just note that when using emulator to use google play supported Image.
void check_apkx(){
if (!expansionFilesDelivered()) {
try {
Intent launchIntent = MainActivity.this.getIntent();
Intent intentToLaunchThisActivityFromNotification = new Intent(
MainActivity.this, MainActivity.this.getClass());
intentToLaunchThisActivityFromNotification.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_CLEAR_TOP);
intentToLaunchThisActivityFromNotification.setAction(launchIntent.getAction());
if (launchIntent.getCategories() != null) {
for (String category : launchIntent.getCategories()) {
intentToLaunchThisActivityFromNotification.addCategory(category);
}
}
// Build PendingIntent used to open this activity from
// Notification
PendingIntent pendingIntent = PendingIntent.getActivity(
MainActivity.this,
0, intentToLaunchThisActivityFromNotification,
PendingIntent.FLAG_UPDATE_CURRENT);
// Request to start the download
DownloaderClientMarshaller.startDownloadServiceIfRequired(this,
pendingIntent, SampleDownloaderService.class);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
} else {
// validateXAPKZipFiles();
}
I am experiencing some trouble with opening files on Android O (api 26).
In Android O when I tab the notification after successfull download, nothing happens (notification just gets deleted), however when I do the same in in api 25 the file opens as it should be and it works.
Debugging points out the the method canOpenFile always returns false on api 26.
Did I overlook something?
Any help is appreciated, many thx.
Notification code:
public void finishedNotification(int id, String appName, String urlPath, boolean success) {
initSoundChannels(this);
NotificationCompat.Builder notification = new NotificationCompat.Builder(this, "default");
notification.setContentTitle(appName)
.setContentText(success ? "Successfully downloaded" : "Download failed - file deleted")
.setSmallIcon(R.mipmap.ic_noti)
.setWhen(System.currentTimeMillis())
.setColor(mApplication_.getInstance().getResources().getColor(R.color.apps_color))
.setLargeIcon(BitmapFactory.decodeResource(mApplication_.getInstance().getResources(), R.mipmap.ic_launcher))
.setOngoing(false)
.setPriority(Notification.PRIORITY_HIGH)
.setAutoCancel(true);
if (success) {
if (canOpenFile(urlPath)) { // ALWAYS false on API26??
PendingIntent openFile = PendingIntent.getActivity(getApplicationContext(),
ACTION_OPEN_FILE.hashCode() + id,
openFile(urlPath),
PendingIntent.FLAG_CANCEL_CURRENT);
notification.setContentIntent(openFile);
} else { // being executed on api 26
PendingIntent openDownloads = PendingIntent.getBroadcast(getApplicationContext(),
ACTION_OPEN_DOWNLOADS.hashCode() + id,
new Intent(ACTION_OPEN_FILE),
PendingIntent.FLAG_CANCEL_CURRENT);
notification.setContentIntent(openDownloads);
}
} else {
Intent cancelIntent = new Intent(ACTION_FILE_CANCEL);
cancelIntent.putExtra("id", id);
PendingIntent cancel = PendingIntent.getBroadcast(mApplication_.getInstance(),
ACTION_FILE_CANCEL.hashCode() + id,
cancelIntent,
PendingIntent.FLAG_CANCEL_CURRENT);
notification.setContentIntent(cancel);
}
Notification builtNotification = notification.build();
getNotificationManager().notify(id, builtNotification);
}
Openfile Intent:
private Intent openFile(String urlPath) {
File file = new File(urlPath);
Intent target = new Intent(Intent.ACTION_VIEW);
MimeTypeMap mime = MimeTypeMap.getSingleton();
String ext = file.getName().substring(file.getName().lastIndexOf(".") + 1);
String type = mime.getMimeTypeFromExtension(ext);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Uri uri = FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID + ".provider", file);
target.setDataAndType(uri, type);
target.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_GRANT_READ_URI_PERMISSION);
} else {
Uri uri = Uri.fromFile(file);
target.setDataAndType(uri, type);
target.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
return target;
}
CanOpenfile:
private boolean canOpenFile(String urlPath) {
PackageManager pm = getPackageManager();
File file = new File(urlPath);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.fromFile(file));
ResolveInfo info = pm.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
return info != null;
}
I see two issues that may be contributing to your problems.
First, you are using implicit broadcasts (action strings instead of component names), to what would appear to be your own app. That was never a particularly good idea from a security standpoint, and on Android 8.0+, implicit broadcasts are banned in general. So, replace new Intent(ACTION_OPEN_FILE) with new Intent(this, WhateverTheReceiverClassIs.class).setAction(ACTION_OPEN_FILE), where WhateverTheReceiverClassIs is whatever your BroadcastReceiver class is.
Second, canOpenFile() is using Uri.fromFile(), giving you a file scheme on the Uri. Since the file scheme was banned in general on Android 7.0, it is entirely possible that there is no app that offers an <intent-filter> for it on your Android 8.0 test environment. Moreover, that code does not match openFile(). Generate the Uri once and use it for both scenarios.
My application evokes the android PackageManager when a file is chosen and the user is presented with a choice of applications to handle how the file should be dealt with. I want to limit this choice to Bluetooth. Currently Bluetooth comes up as the first option which is fine and this all works. I was wondering if its possible to only present the user with this single option.
case REQUEST_FILE_SELECT:
if (requestCode == REQUEST_FILE_SELECT) {
// Get the Uri of the selected file
Uri uri = data.getData();
Log.d(TAG, "File Uri: " + uri.toString());
// Get the path
String path = null;
try {
path = FileUtils.getPath(this, uri);
} catch (URISyntaxException e) {
e.printStackTrace();
}
Log.d(TAG, "File Path: " + path);
// Get the file instance
File mFile = new File(path);
// Evoke the file chooser
List<Intent> targetedShareIntents = new ArrayList<Intent>();
Intent shareIntent = new Intent(
android.content.Intent.ACTION_SEND);
shareIntent.setType("*/*");
// Evoke the package manager
List<ResolveInfo> resInfo = getPackageManager()
.queryIntentActivities(shareIntent,
PackageManager.GET_ACTIVITIES);
if (!resInfo.isEmpty()) {
for (ResolveInfo resolveInfo : resInfo) {
String packageName = resolveInfo.activityInfo.packageName;
if (packageName.equals("com.android.bluetooth")) {
Intent targetedShareIntent = new Intent(
android.content.Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_STREAM,
Uri.fromFile(mFile));
targetedShareIntent.setPackage(packageName);
targetedShareIntents.add(targetedShareIntent);
startActivity(Intent.createChooser(shareIntent,
"Share File"));
}
}
}
}
Solution: find out which apps does the device support for your intent, find the one that is bluetooh, invoke it directly.
This article answers your question:
http://tsicilian.wordpress.com/2012/11/06/bluetooth-data-transfer-with-android/
From the article:
We can see that the BT application is among those handlers. We could of course let the user pick that application from the list and be done with it. But if we feel we should be a tad more user-friendly, we need to go further and start the application ourselves, instead of simply displaying it in a midst of other unnecessary options…But how?
One way to do that would be to use Android’s PackageManager this way:
//list of apps that can handle our intent
PackageManager pm = getPackageManager();
List appsList = pm.queryIntentActivities( intent, 0);
if(appsList.size() > 0 {
// proceed
}
The above PackageManager method returns the list we saw earlier of all activities susceptible to handle our file transfer intent, in the form of a list of ResolveInfo objects that encapsulate information we need:
//select bluetooth
String packageName = null;
String className = null;
boolean found = false;
for(ResolveInfo info: appsList){
packageName = info.activityInfo.packageName;
if( packageName.equals("com.android.bluetooth")){
className = info.activityInfo.name;
found = true;
break;// found
}
}
if(! found){
Toast.makeText(this, R.string.blu_notfound_inlist,
Toast.LENGTH_SHORT).show();
// exit
}
We now have the necessary information to start BT ourselves:
//set our intent to launch Bluetooth
intent.setClassName(packageName, className);
startActivity(intent);
What we did was to use the package and its corresponding class retrieved earlier. Since we are a curious bunch, we may wonder what the class name for the “com.android.bluetooth” package is. This is what we would get if we were to print it out: com.broadcom.bt.app.opp.OppLauncherActivity. OPP stands for Object Push Profile, and is the Android component allowing to wirelessly share files.
Also in the article, how to enable the bluetooth from your application.
I'm developing an Android app and am interested to know how you can update the app user's status from within the app using Android's share intents.
Having looked through Facebook's SDK it appears that this is easy enough to do, however I'm keen to allow the user to do it via the regular Share Intent pop up window? seen here:
I have tried the usual share intent code, however this no longer appears to work for Facebook.
public void invokeShare(Activity activity, String quote, String credit) {
Intent shareIntent = new Intent(android.content.Intent.ACTION_SEND);
shareIntent.setType("text/plain");
shareIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, activity.getString(R.string.share_subject));
shareIntent.putExtra(android.content.Intent.EXTRA_TEXT, "Example text");
activity.startActivity(Intent.createChooser(shareIntent, activity.getString(R.string.share_title)));
}
UPDATE:
Having done more digging, it looks as though it's a bug with Facebook's app that has yet to be resolved! (facebook bug) For the mean time it looks like I'm just going to have to put up with the negative "Sharing doesn't work!!!" reviews. Cheers Facebook :*(
Apparently Facebook no longer (as of 2014) allows you to customise the sharing screen, no matter if you are just opening sharer.php URL or using Android intents in more specialised ways. See for example these answers:
"Sharer.php no longer allows you to customize."
"You need to use Facebook Android SDK or Easy Facebook Android SDK to share."
Anyway, using plain Intents, you can still share a URL, but not any default text with it, as billynomates commented. (Also, if you have no URL to share, just launching Facebook app with empty "Write Post" (i.e. status update) dialog is equally easy; use the code below but leave out EXTRA_TEXT.)
Here's the best solution I've found that does not involve using any Facebook SDKs.
This code opens the official Facebook app directly if it's installed, and otherwise falls back to opening sharer.php in a browser. (Most of the other solutions in this question bring up a huge "Complete action using…" dialog which isn't optimal at all!)
String urlToShare = "https://stackoverflow.com/questions/7545254";
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
// intent.putExtra(Intent.EXTRA_SUBJECT, "Foo bar"); // NB: has no effect!
intent.putExtra(Intent.EXTRA_TEXT, urlToShare);
// See if official Facebook app is found
boolean facebookAppFound = false;
List<ResolveInfo> matches = getPackageManager().queryIntentActivities(intent, 0);
for (ResolveInfo info : matches) {
if (info.activityInfo.packageName.toLowerCase().startsWith("com.facebook.katana")) {
intent.setPackage(info.activityInfo.packageName);
facebookAppFound = true;
break;
}
}
// As fallback, launch sharer.php in a browser
if (!facebookAppFound) {
String sharerUrl = "https://www.facebook.com/sharer/sharer.php?u=" + urlToShare;
intent = new Intent(Intent.ACTION_VIEW, Uri.parse(sharerUrl));
}
startActivity(intent);
(Regarding the com.facebook.katana package name, see MatheusJardimB's comment.)
The result looks like this on my Nexus 7 (Android 4.4) with Facebook app installed:
The Facebook application does not handle either the EXTRA_SUBJECT or EXTRA_TEXT fields.
Here is bug link: https://developers.facebook.com/bugs/332619626816423
Thanks #billynomates:
The thing is, if you put a URL in the EXTRA_TEXT field, it does
work. It's like they're intentionally stripping out any text.
The usual way
The usual way to create what you're asking for, is to simply do the following:
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_TEXT, "The status update text");
startActivity(Intent.createChooser(intent, "Dialog title text"));
This works without any issues for me.
The alternative way (maybe)
The potential problem with doing this, is that you're also allowing the message to be sent via e-mail, SMS, etc. The following code is something I'm using in an application, that allows the user to send me an e-mail using Gmail. I'm guessing you could try to change it to make it work with Facebook only.
I'm not sure how it responds to any errors or exceptions (I'm guessing that would occur if Facebook is not installed), so you might have to test it a bit.
try {
Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
String[] recipients = new String[]{"e-mail address"};
emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, recipients);
emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "E-mail subject");
emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, "E-mail text");
emailIntent.setType("plain/text"); // This is incorrect MIME, but Gmail is one of the only apps that responds to it - this might need to be replaced with text/plain for Facebook
final PackageManager pm = getPackageManager();
final List<ResolveInfo> matches = pm.queryIntentActivities(emailIntent, 0);
ResolveInfo best = null;
for (final ResolveInfo info : matches)
if (info.activityInfo.packageName.endsWith(".gm") ||
info.activityInfo.name.toLowerCase().contains("gmail")) best = info;
if (best != null)
emailIntent.setClassName(best.activityInfo.packageName, best.activityInfo.name);
startActivity(emailIntent);
} catch (Exception e) {
Toast.makeText(this, "Application not found", Toast.LENGTH_SHORT).show();
}
I found out you can only share either Text or Image, not both using Intents. Below code shares only Image if exists, or only Text if Image does not exits. If you want to share both, you need to use Facebook SDK from here.
If you use other solution instead of below code, don't forget to specify package name com.facebook.lite as well, which is package name of Facebook Lite. I haven't test but com.facebook.orca is package name of Facebook Messenger if you want to target that too.
You can add more methods for sharing with WhatsApp, Twitter ...
public class IntentShareHelper {
/**
* <b>Beware,</b> this shares only image if exists, or only text if image does not exits. Can't share both
*/
public static void shareOnFacebook(AppCompatActivity appCompatActivity, String textBody, Uri fileUri) {
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_TEXT,!TextUtils.isEmpty(textBody) ? textBody : "");
if (fileUri != null) {
intent.putExtra(Intent.EXTRA_STREAM, fileUri);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setType("image/*");
}
boolean facebookAppFound = false;
List<ResolveInfo> matches = appCompatActivity.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo info : matches) {
if (info.activityInfo.packageName.toLowerCase().startsWith("com.facebook.katana") ||
info.activityInfo.packageName.toLowerCase().startsWith("com.facebook.lite")) {
intent.setPackage(info.activityInfo.packageName);
facebookAppFound = true;
break;
}
}
if (facebookAppFound) {
appCompatActivity.startActivity(intent);
} else {
showWarningDialog(appCompatActivity, appCompatActivity.getString(R.string.error_activity_not_found));
}
}
public static void shareOnWhatsapp(AppCompatActivity appCompatActivity, String textBody, Uri fileUri){...}
private static void showWarningDialog(Context context, String message) {
new AlertDialog.Builder(context)
.setMessage(message)
.setNegativeButton(context.getString(R.string.close), new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
})
.setCancelable(true)
.create().show();
}
}
For getting Uri from File, use below class:
public class UtilityFile {
public static #Nullable Uri getUriFromFile(Context context, #Nullable File file) {
if (file == null)
return null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
try {
return FileProvider.getUriForFile(context, "com.my.package.fileprovider", file);
} catch (Exception e) {
e.printStackTrace();
return null;
}
} else {
return Uri.fromFile(file);
}
}
// Returns the URI path to the Bitmap displayed in specified ImageView
public static Uri getLocalBitmapUri(Context context, ImageView imageView) {
Drawable drawable = imageView.getDrawable();
Bitmap bmp = null;
if (drawable instanceof BitmapDrawable) {
bmp = ((BitmapDrawable) imageView.getDrawable()).getBitmap();
} else {
return null;
}
// Store image to default external storage directory
Uri bmpUri = null;
try {
// Use methods on Context to access package-specific directories on external storage.
// This way, you don't need to request external read/write permission.
File file = new File(context.getExternalFilesDir(Environment.DIRECTORY_PICTURES), "share_image_" + System.currentTimeMillis() + ".png");
FileOutputStream out = new FileOutputStream(file);
bmp.compress(Bitmap.CompressFormat.PNG, 90, out);
out.close();
bmpUri = getUriFromFile(context, file);
} catch (IOException e) {
e.printStackTrace();
}
return bmpUri;
}
}
For writing FileProvider, use this link: https://github.com/codepath/android_guides/wiki/Sharing-Content-with-Intents
Here is what I did (for text). In the code, I copy whatever text is needed to clipboard. The first time an individual tries to use the share intent button, I pop up a notification that explains if they wish to share to facebook, they need to click 'Facebook' and then long press to paste (this is to make them aware that Facebook has BROKEN the android intent system). Then the relevant information is in the field. I might also include a link to this post so users can complain too...
private void setClipboardText(String text) { // TODO
int sdk = android.os.Build.VERSION.SDK_INT;
if(sdk < android.os.Build.VERSION_CODES.HONEYCOMB) {
android.text.ClipboardManager clipboard = (android.text.ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
clipboard.setText(text);
} else {
android.content.ClipboardManager clipboard = (android.content.ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
android.content.ClipData clip = android.content.ClipData.newPlainText("text label",text);
clipboard.setPrimaryClip(clip);
}
}
Below is a method for dealing w/prior versions
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_item_share:
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("text/plain");
shareIntent.putExtra(Intent.EXTRA_TEXT, "text here");
ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE); //TODO
ClipData clip = ClipData.newPlainText("label", "text here");
clipboard.setPrimaryClip(clip);
setShareIntent(shareIntent);
break;
}
return super.onOptionsItemSelected(item);
}
In Lollipop (21), you can use Intent.EXTRA_REPLACEMENT_EXTRAS to override the intent for Facebook specifically (and specify a link only)
https://developer.android.com/reference/android/content/Intent.html#EXTRA_REPLACEMENT_EXTRAS
private void doShareLink(String text, String link) {
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("text/plain");
Intent chooserIntent = Intent.createChooser(shareIntent, getString(R.string.share_via));
// for 21+, we can use EXTRA_REPLACEMENT_EXTRAS to support the specific case of Facebook
// (only supports a link)
// >=21: facebook=link, other=text+link
// <=20: all=link
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
shareIntent.putExtra(Intent.EXTRA_TEXT, text + " " + link);
Bundle facebookBundle = new Bundle();
facebookBundle.putString(Intent.EXTRA_TEXT, link);
Bundle replacement = new Bundle();
replacement.putBundle("com.facebook.katana", facebookBundle);
chooserIntent.putExtra(Intent.EXTRA_REPLACEMENT_EXTRAS, replacement);
} else {
shareIntent.putExtra(Intent.EXTRA_TEXT, link);
}
chooserIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(chooserIntent);
}
Seems in version 4.0.0 of Facebook so many things has changed. This is my code which is working fine. Hope it helps you.
/**
* Facebook does not support sharing content without using their SDK however
* it is possible to share URL
*
* #param content
* #param url
*/
private void shareOnFacebook(String content, String url)
{
try
{
// TODO: This part does not work properly based on my test
Intent fbIntent = new Intent(Intent.ACTION_SEND);
fbIntent.setType("text/plain");
fbIntent.putExtra(Intent.EXTRA_TEXT, content);
fbIntent.putExtra(Intent.EXTRA_STREAM, url);
fbIntent.addCategory(Intent.CATEGORY_LAUNCHER);
fbIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
fbIntent.setComponent(new ComponentName("com.facebook.katana",
"com.facebook.composer.shareintent.ImplicitShareIntentHandler"));
startActivity(fbIntent);
return;
}
catch (Exception e)
{
// User doesn't have Facebook app installed. Try sharing through browser.
}
// If we failed (not native FB app installed), try share through SEND
String sharerUrl = "https://www.facebook.com/sharer/sharer.php?u=" + url;
SupportUtils.doShowUri(this.getActivity(), sharerUrl);
}
This solution works aswell. If there is no Facebook installed, it just runs the normal share-dialog. If there is and you are not logged in, it goes to the login screen. If you are logged in, it will open the share dialog and put in the "Share url" from the Intent Extra.
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_TEXT, "Share url");
intent.setType("text/plain");
List<ResolveInfo> matches = getMainFragmentActivity().getPackageManager().queryIntentActivities(intent, 0);
for (ResolveInfo info : matches) {
if (info.activityInfo.packageName.toLowerCase().contains("facebook")) {
intent.setPackage(info.activityInfo.packageName);
}
}
startActivity(intent);
Here is something I did which open Facebook App with Link
shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setComponent(new ComponentName("com.facebook.katana",
"com.facebook.katana.activity.composer.ImplicitShareIntentHandler"));
shareIntent.setType("text/plain");
shareIntent.putExtra(Intent.EXTRA_TEXT, videoUrl);
public void invokeShare(Activity activity, String quote, String credit) {
Intent shareIntent = new Intent(android.content.Intent.ACTION_SEND);
shareIntent.setType("text/plain");
shareIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, activity.getString(R.string.share_subject));
shareIntent.putExtra(android.content.Intent.EXTRA_TEXT, "Example text");
shareIntent.putExtra("com.facebook.platform.extra.APPLICATION_ID", activity.getString(R.string.app_id));
activity.startActivity(Intent.createChooser(shareIntent, activity.getString(R.string.share_title)));
}
Facebook does not allow to share plain text data with Intent.EXTRA_TEXT but You can share text+link with facebook messanger using this, this works fine for me
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, text+url link);
sendIntent.setType("text/plain");
sendIntent.setPackage("com.facebook.orca");
startActivity(sendIntent);
The easiest way that I could find to pass a message from my app to facebook was programmatically copy to the clipboard and alert the user that they have the option to paste. It saves the user from manually doing it; my app is not pasting but the user might.
...
if (app.equals("facebook")) {
// overcome fb 'putExtra' constraint;
// copy message to clipboard for user to paste into fb.
ClipboardManager cb = (ClipboardManager)
getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("post", msg);
cb.setPrimaryClip(clip);
// tell the to PASTE POST with option to stop showing this dialogue
showDialog(this, getString(R.string.facebook_post));
}
startActivity(appIntent);
...