External sharing improvements
Improve NewPipe's share on some devices + fix crash when no browser is set on some devices Catching ActivityNotFoundException when trying to open the default browser Use an ACTION_CHOOSER intent and put as an extra intent the intent to open an URI / share an URI when no default app is set. Add a LinkHelper class which set a custom action when clicking web links in the description of a content. This class also helps to implement a confirmation dialog when trying to open web links in an external app.
This commit is contained in:
parent
b73eb9438d
commit
a57fd69fb4
|
@ -146,16 +146,20 @@ public class AboutActivity extends AppCompatActivity {
|
|||
aboutBinding.appVersion.setText(BuildConfig.VERSION_NAME);
|
||||
|
||||
aboutBinding.githubLink.setOnClickListener(nv ->
|
||||
openUrlInBrowser(context, context.getString(R.string.github_url)));
|
||||
openUrlInBrowser(context, context.getString(R.string.github_url),
|
||||
false));
|
||||
|
||||
aboutBinding.donationLink.setOnClickListener(v ->
|
||||
openUrlInBrowser(context, context.getString(R.string.donation_url)));
|
||||
openUrlInBrowser(context, context.getString(R.string.donation_url),
|
||||
false));
|
||||
|
||||
aboutBinding.websiteLink.setOnClickListener(nv ->
|
||||
openUrlInBrowser(context, context.getString(R.string.website_url)));
|
||||
openUrlInBrowser(context, context.getString(R.string.website_url),
|
||||
false));
|
||||
|
||||
aboutBinding.privacyPolicyLink.setOnClickListener(v ->
|
||||
openUrlInBrowser(context, context.getString(R.string.privacy_policy_url)));
|
||||
openUrlInBrowser(context, context.getString(R.string.privacy_policy_url),
|
||||
false));
|
||||
|
||||
return aboutBinding.getRoot();
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@ import android.os.Bundle;
|
|||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.provider.Settings;
|
||||
import android.text.util.Linkify;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
|
@ -96,6 +95,7 @@ import org.schabi.newpipe.util.Constants;
|
|||
import org.schabi.newpipe.util.DeviceUtils;
|
||||
import org.schabi.newpipe.util.ExtractorHelper;
|
||||
import org.schabi.newpipe.util.ImageDisplayConstants;
|
||||
import org.schabi.newpipe.util.LinkHelper;
|
||||
import org.schabi.newpipe.util.ListHelper;
|
||||
import org.schabi.newpipe.util.Localization;
|
||||
import org.schabi.newpipe.util.NavigationHelper;
|
||||
|
@ -112,10 +112,7 @@ import java.util.Objects;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import icepick.State;
|
||||
import io.noties.markwon.Markwon;
|
||||
import io.noties.markwon.linkify.LinkifyPlugin;
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.rxjava3.core.Single;
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable;
|
||||
import io.reactivex.rxjava3.disposables.Disposable;
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers;
|
||||
|
@ -1233,26 +1230,17 @@ public final class VideoDetailFragment
|
|||
}
|
||||
|
||||
if (description.getType() == Description.HTML) {
|
||||
disposables.add(Single.just(description.getContent())
|
||||
.map(descriptionText ->
|
||||
HtmlCompat.fromHtml(descriptionText,
|
||||
HtmlCompat.FROM_HTML_MODE_LEGACY))
|
||||
.subscribeOn(Schedulers.computation())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(spanned -> {
|
||||
videoDescriptionView.setText(spanned);
|
||||
videoDescriptionView.setVisibility(View.VISIBLE);
|
||||
}));
|
||||
LinkHelper.createLinksFromHtmlBlock(requireContext(), description.getContent(),
|
||||
videoDescriptionView, HtmlCompat.FROM_HTML_MODE_LEGACY);
|
||||
videoDescriptionView.setVisibility(View.VISIBLE);
|
||||
} else if (description.getType() == Description.MARKDOWN) {
|
||||
final Markwon markwon = Markwon.builder(requireContext())
|
||||
.usePlugin(LinkifyPlugin.create())
|
||||
.build();
|
||||
markwon.setMarkdown(videoDescriptionView, description.getContent());
|
||||
LinkHelper.createLinksFromMarkdownText(requireContext(), description.getContent(),
|
||||
videoDescriptionView);
|
||||
videoDescriptionView.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
//== Description.PLAIN_TEXT
|
||||
videoDescriptionView.setAutoLinkMask(Linkify.WEB_URLS);
|
||||
videoDescriptionView.setText(description.getContent(), TextView.BufferType.SPANNABLE);
|
||||
LinkHelper.createLinksFromPlainText(requireContext(), description.getContent(),
|
||||
videoDescriptionView);
|
||||
videoDescriptionView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
package org.schabi.newpipe.fragments.list.channel;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
@ -188,8 +186,7 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo>
|
|||
private void openRssFeed() {
|
||||
final ChannelInfo info = currentInfo;
|
||||
if (info != null) {
|
||||
final Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(info.getFeedUrl()));
|
||||
startActivity(intent);
|
||||
ShareUtils.openUrlInBrowser(requireContext(), info.getFeedUrl(), false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,6 @@ import android.view.Menu;
|
|||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
|
@ -207,8 +206,7 @@ public class ErrorActivity extends AppCompatActivity {
|
|||
openPrivacyPolicyDialog(this, "EMAIL"));
|
||||
|
||||
activityErrorBinding.errorReportCopyButton.setOnClickListener(v -> {
|
||||
ShareUtils.copyToClipboard(this, buildMarkdown());
|
||||
Toast.makeText(this, R.string.msg_copied, Toast.LENGTH_SHORT).show();
|
||||
ShareUtils.copyToClipboard(this, buildMarkdown());
|
||||
});
|
||||
|
||||
activityErrorBinding.errorReportGitHubButton.setOnClickListener(v ->
|
||||
|
@ -246,11 +244,7 @@ public class ErrorActivity extends AppCompatActivity {
|
|||
goToReturnActivity();
|
||||
break;
|
||||
case R.id.menu_item_share_error:
|
||||
final Intent intent = new Intent();
|
||||
intent.setAction(Intent.ACTION_SEND);
|
||||
intent.putExtra(Intent.EXTRA_TEXT, buildJson());
|
||||
intent.setType("text/plain");
|
||||
startActivity(Intent.createChooser(intent, getString(R.string.share_dialog_title)));
|
||||
ShareUtils.shareUrl(this, getString(R.string.error_report_title), buildJson());
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
|
@ -273,10 +267,10 @@ public class ErrorActivity extends AppCompatActivity {
|
|||
.putExtra(Intent.EXTRA_SUBJECT, ERROR_EMAIL_SUBJECT)
|
||||
.putExtra(Intent.EXTRA_TEXT, buildJson());
|
||||
if (i.resolveActivity(getPackageManager()) != null) {
|
||||
startActivity(i);
|
||||
ShareUtils.openContentInApp(context, i);
|
||||
}
|
||||
} else if (action.equals("GITHUB")) { // open the NewPipe issue page on GitHub
|
||||
ShareUtils.openUrlInBrowser(this, ERROR_GITHUB_ISSUE_URL);
|
||||
ShareUtils.openUrlInBrowser(this, ERROR_GITHUB_ISSUE_URL, false);
|
||||
}
|
||||
|
||||
})
|
||||
|
|
|
@ -69,7 +69,8 @@ public class CommentTextOnTouchListener implements View.OnTouchListener {
|
|||
handled = handleUrl(v.getContext(), (URLSpan) link[0]);
|
||||
}
|
||||
if (!handled) {
|
||||
link[0].onClick(widget);
|
||||
ShareUtils.openUrlInBrowser(v.getContext(),
|
||||
((URLSpan) link[0]).getURL(), false);
|
||||
}
|
||||
} else if (action == MotionEvent.ACTION_DOWN) {
|
||||
Selection.setSelection(buffer,
|
||||
|
|
|
@ -365,8 +365,8 @@ public final class ExtractorHelper {
|
|||
}
|
||||
}
|
||||
|
||||
metaInfoTextView.setText(HtmlCompat.fromHtml(stringBuilder.toString(),
|
||||
HtmlCompat.FROM_HTML_SEPARATOR_LINE_BREAK_HEADING));
|
||||
LinkHelper.createLinksFromHtmlBlock(context, stringBuilder.toString(),
|
||||
metaInfoTextView, HtmlCompat.FROM_HTML_SEPARATOR_LINE_BREAK_HEADING);
|
||||
metaInfoTextView.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
metaInfoTextView.setVisibility(View.VISIBLE);
|
||||
metaInfoSeparator.setVisibility(View.VISIBLE);
|
||||
|
|
|
@ -0,0 +1,116 @@
|
|||
package org.schabi.newpipe.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.text.style.ClickableSpan;
|
||||
import android.text.style.URLSpan;
|
||||
import android.text.util.Linkify;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.core.text.HtmlCompat;
|
||||
|
||||
import io.noties.markwon.Markwon;
|
||||
import io.noties.markwon.linkify.LinkifyPlugin;
|
||||
|
||||
public final class LinkHelper {
|
||||
private LinkHelper() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create web links for contents with an HTML description.
|
||||
* <p>
|
||||
* This will call
|
||||
* {@link LinkHelper#changeIntentsOfDescriptionLinks(Context, CharSequence, TextView)}
|
||||
* after linked the URLs with {@link HtmlCompat#fromHtml(String, int)}.
|
||||
*
|
||||
* @param context the context to use
|
||||
* @param htmlBlock the htmlBlock to be linked
|
||||
* @param textView the TextView to set the htmlBlock linked
|
||||
* @param htmlCompatFlag the int flag to be set when {@link HtmlCompat#fromHtml(String, int)}
|
||||
* will be called
|
||||
*/
|
||||
public static void createLinksFromHtmlBlock(final Context context,
|
||||
final String htmlBlock,
|
||||
final TextView textView,
|
||||
final int htmlCompatFlag) {
|
||||
changeIntentsOfDescriptionLinks(context, HtmlCompat.fromHtml(htmlBlock, htmlCompatFlag),
|
||||
textView);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create web links for contents with a plain text description.
|
||||
* <p>
|
||||
* This will call
|
||||
* {@link LinkHelper#changeIntentsOfDescriptionLinks(Context, CharSequence, TextView)}
|
||||
* after linked the URLs with {@link TextView#setAutoLinkMask(int)} and
|
||||
* {@link TextView#setText(CharSequence, TextView.BufferType)}.
|
||||
*
|
||||
* @param context the context to use
|
||||
* @param plainTextBlock the block of plain text to be linked
|
||||
* @param textView the TextView to set the plain text block linked
|
||||
*/
|
||||
public static void createLinksFromPlainText(final Context context,
|
||||
final String plainTextBlock,
|
||||
final TextView textView) {
|
||||
textView.setAutoLinkMask(Linkify.WEB_URLS);
|
||||
textView.setText(plainTextBlock, TextView.BufferType.SPANNABLE);
|
||||
changeIntentsOfDescriptionLinks(context, textView.getText(), textView);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create web links for contents with a markdown description.
|
||||
* <p>
|
||||
* This will call
|
||||
* {@link LinkHelper#changeIntentsOfDescriptionLinks(Context, CharSequence, TextView)}
|
||||
* after creating an {@link Markwon} object and using
|
||||
* {@link Markwon#setMarkdown(TextView, String)}.
|
||||
*
|
||||
* @param context the context to use
|
||||
* @param markdownBlock the block of markdown text to be linked
|
||||
* @param textView the TextView to set the plain text block linked
|
||||
*/
|
||||
public static void createLinksFromMarkdownText(final Context context,
|
||||
final String markdownBlock,
|
||||
final TextView textView) {
|
||||
final Markwon markwon = Markwon.builder(context).usePlugin(LinkifyPlugin.create()).build();
|
||||
markwon.setMarkdown(textView, markdownBlock);
|
||||
changeIntentsOfDescriptionLinks(context, textView.getText(), textView);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change links generated by libraries in the description of a content to a custom link action.
|
||||
* <p>
|
||||
* Instead of using an ACTION_VIEW intent in the description of a content, this method will
|
||||
* parse the CharSequence and replace all current web links with
|
||||
* {@link ShareUtils#openUrlInBrowser(Context, String, Boolean)}.
|
||||
* <p>
|
||||
* This method is required in order to intercept links and maybe, show a confirmation dialog
|
||||
* before opening a web link.
|
||||
*
|
||||
* @param context the context to use
|
||||
* @param chars the CharSequence to be parsed
|
||||
* @param textView the TextView in which the converted CharSequence will be applied
|
||||
*/
|
||||
private static void changeIntentsOfDescriptionLinks(final Context context,
|
||||
final CharSequence chars,
|
||||
final TextView textView) {
|
||||
final SpannableStringBuilder textBlockLinked = new SpannableStringBuilder(chars);
|
||||
final URLSpan[] urls = textBlockLinked.getSpans(0, chars.length(), URLSpan.class);
|
||||
|
||||
for (final URLSpan span : urls) {
|
||||
final ClickableSpan clickableSpan = new ClickableSpan() {
|
||||
public void onClick(final View view) {
|
||||
ShareUtils.openUrlInBrowser(context, span.getURL(), false);
|
||||
}
|
||||
};
|
||||
textBlockLinked.setSpan(clickableSpan, textBlockLinked.getSpanStart(span),
|
||||
textBlockLinked.getSpanEnd(span), textBlockLinked.getSpanFlags(span));
|
||||
textBlockLinked.removeSpan(span);
|
||||
}
|
||||
|
||||
textView.setText(textBlockLinked);
|
||||
textView.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
}
|
||||
}
|
|
@ -246,16 +246,14 @@ public final class NavigationHelper {
|
|||
|
||||
public static void resolveActivityOrAskToInstall(final Context context, final Intent intent) {
|
||||
if (intent.resolveActivity(context.getPackageManager()) != null) {
|
||||
context.startActivity(intent);
|
||||
ShareUtils.openContentInApp(context, intent);
|
||||
} else {
|
||||
if (context instanceof Activity) {
|
||||
new AlertDialog.Builder(context)
|
||||
.setMessage(R.string.no_player_found)
|
||||
.setPositiveButton(R.string.install, (dialog, which) -> {
|
||||
final Intent i = new Intent();
|
||||
i.setAction(Intent.ACTION_VIEW);
|
||||
i.setData(Uri.parse(context.getString(R.string.fdroid_vlc_url)));
|
||||
context.startActivity(i);
|
||||
ShareUtils.openUrlInBrowser(context,
|
||||
context.getString(R.string.fdroid_vlc_url), false);
|
||||
})
|
||||
.setNegativeButton(R.string.cancel, (dialog, which)
|
||||
-> Log.i("NavigationHelper", "You unlocked a secret unicorn."))
|
||||
|
@ -568,27 +566,14 @@ public final class NavigationHelper {
|
|||
return getOpenIntent(context, url, service.getServiceId(), linkType);
|
||||
}
|
||||
|
||||
private static Uri openMarketUrl(final String packageName) {
|
||||
return Uri.parse("market://details")
|
||||
.buildUpon()
|
||||
.appendQueryParameter("id", packageName)
|
||||
.build();
|
||||
}
|
||||
|
||||
private static Uri getGooglePlayUrl(final String packageName) {
|
||||
return Uri.parse("https://play.google.com/store/apps/details")
|
||||
.buildUpon()
|
||||
.appendQueryParameter("id", packageName)
|
||||
.build();
|
||||
}
|
||||
|
||||
private static void installApp(final Context context, final String packageName) {
|
||||
try {
|
||||
// Try market:// scheme
|
||||
context.startActivity(new Intent(Intent.ACTION_VIEW, openMarketUrl(packageName)));
|
||||
ShareUtils.openUrlInBrowser(context, "market://details?id=" + packageName, false);
|
||||
} catch (final ActivityNotFoundException e) {
|
||||
// Fall back to google play URL (don't worry F-Droid can handle it :)
|
||||
context.startActivity(new Intent(Intent.ACTION_VIEW, getGooglePlayUrl(packageName)));
|
||||
ShareUtils.openUrlInBrowser(context,
|
||||
"https://play.google.com/store/apps/details?id=" + packageName, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package org.schabi.newpipe.util;
|
||||
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
|
@ -21,22 +22,80 @@ public final class ShareUtils {
|
|||
* Open the url with the system default browser.
|
||||
* <p>
|
||||
* If no browser is set as default, fallbacks to
|
||||
* {@link ShareUtils#openInDefaultApp(Context, String)}
|
||||
* {@link ShareUtils#openInDefaultApp(Context, Intent)}
|
||||
*
|
||||
* @param context the context to use
|
||||
* @param url the url to browse
|
||||
* @param httpDefaultBrowserTest the boolean to set if the
|
||||
* test for the default browser will be for HTTP protocol
|
||||
* or for the created intent
|
||||
*/
|
||||
public static void openUrlInBrowser(final Context context, final String url,
|
||||
final Boolean httpDefaultBrowserTest) {
|
||||
final String defaultPackageName;
|
||||
final Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url))
|
||||
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
if (httpDefaultBrowserTest) {
|
||||
defaultPackageName = getDefaultBrowserPackageName(context);
|
||||
} else {
|
||||
defaultPackageName = getDefaultAppPackageName(context, intent);
|
||||
}
|
||||
|
||||
if (defaultPackageName.equals("android")) {
|
||||
// no browser set as default (doesn't work on some devices)
|
||||
openInDefaultApp(context, intent);
|
||||
} else {
|
||||
try {
|
||||
intent.setPackage(defaultPackageName);
|
||||
context.startActivity(intent);
|
||||
} catch (final ActivityNotFoundException e) {
|
||||
// not a browser but an app chooser because of OEMs changes
|
||||
intent.setPackage(null);
|
||||
openInDefaultApp(context, intent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the url with the system default browser.
|
||||
* <p>
|
||||
* If no browser is set as default, fallbacks to
|
||||
* {@link ShareUtils#openInDefaultApp(Context, Intent)}
|
||||
* <p>
|
||||
* This call {@link ShareUtils#openUrlInBrowser(Context, String, Boolean)} with true
|
||||
* for the boolean parameter
|
||||
*
|
||||
* @param context the context to use
|
||||
* @param url the url to browse
|
||||
*/
|
||||
**/
|
||||
public static void openUrlInBrowser(final Context context, final String url) {
|
||||
final String defaultBrowserPackageName = getDefaultBrowserPackageName(context);
|
||||
openUrlInBrowser(context, url, true);
|
||||
}
|
||||
|
||||
if (defaultBrowserPackageName.equals("android")) {
|
||||
// no browser set as default
|
||||
openInDefaultApp(context, url);
|
||||
/**
|
||||
* Open a content with the system default browser.
|
||||
* <p>
|
||||
* If no app is set as default, fallbacks to
|
||||
* {@link ShareUtils#openInDefaultApp(Context, Intent)}
|
||||
*
|
||||
* @param context the context to use
|
||||
* @param intent the intent of the file to open
|
||||
*/
|
||||
public static void openContentInApp(final Context context, final Intent intent) {
|
||||
final String defaultAppPackageName = getDefaultAppPackageName(context, intent);
|
||||
|
||||
if (defaultAppPackageName.equals("android")) {
|
||||
// no app set as default (doesn't work on some devices)
|
||||
openInDefaultApp(context, intent);
|
||||
} else {
|
||||
final Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url))
|
||||
.setPackage(defaultBrowserPackageName)
|
||||
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
context.startActivity(intent);
|
||||
try {
|
||||
intent.setPackage(defaultAppPackageName);
|
||||
context.startActivity(intent);
|
||||
} catch (final ActivityNotFoundException e) {
|
||||
// not an app to open a file but an app chooser because of OEMs changes
|
||||
intent.setPackage(null);
|
||||
openInDefaultApp(context, intent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -45,20 +104,38 @@ public final class ShareUtils {
|
|||
* <p>
|
||||
* If no app is set as default, it will open a chooser
|
||||
*
|
||||
* @param context the context to use
|
||||
* @param url the url to browse
|
||||
* @param context the context to use
|
||||
* @param viewIntent the intent to open
|
||||
*/
|
||||
private static void openInDefaultApp(final Context context, final String url) {
|
||||
final Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
|
||||
context.startActivity(Intent.createChooser(
|
||||
intent, context.getString(R.string.share_dialog_title))
|
||||
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
|
||||
private static void openInDefaultApp(final Context context, final Intent viewIntent) {
|
||||
final Intent intent = new Intent(Intent.ACTION_CHOOSER);
|
||||
intent.putExtra(Intent.EXTRA_INTENT, viewIntent);
|
||||
intent.putExtra(Intent.EXTRA_TITLE, context.getString(R.string.open_with));
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default app package name.
|
||||
* <p>
|
||||
* If no app is set as default, it will return "android".
|
||||
* <p>
|
||||
* Note: it doesn't return "android" on some devices because some OEMs changed the app chooser.
|
||||
*
|
||||
* @param context the context to use
|
||||
* @param intent the intent to get default app
|
||||
* @return the package name of the default app, or the app chooser if there's no default
|
||||
*/
|
||||
private static String getDefaultAppPackageName(final Context context, final Intent intent) {
|
||||
return context.getPackageManager().resolveActivity(intent,
|
||||
PackageManager.MATCH_DEFAULT_ONLY).activityInfo.packageName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default browser package name.
|
||||
* <p>
|
||||
* If no browser is set as default, it will return "android"
|
||||
* Note: it doesn't return "android" on some devices because some OEMs changed the app chooser.
|
||||
*
|
||||
* @param context the context to use
|
||||
* @return the package name of the default browser, or "android" if there's no default
|
||||
|
@ -66,8 +143,8 @@ public final class ShareUtils {
|
|||
private static String getDefaultBrowserPackageName(final Context context) {
|
||||
final Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://"))
|
||||
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
final ResolveInfo resolveInfo = context.getPackageManager().resolveActivity(
|
||||
intent, PackageManager.MATCH_DEFAULT_ONLY);
|
||||
final ResolveInfo resolveInfo = context.getPackageManager().resolveActivity(intent,
|
||||
PackageManager.MATCH_DEFAULT_ONLY);
|
||||
return resolveInfo.activityInfo.packageName;
|
||||
}
|
||||
|
||||
|
@ -79,13 +156,15 @@ public final class ShareUtils {
|
|||
* @param url the url to share
|
||||
*/
|
||||
public static void shareUrl(final Context context, final String subject, final String url) {
|
||||
final Intent intent = new Intent(Intent.ACTION_SEND);
|
||||
intent.setType("text/plain");
|
||||
intent.putExtra(Intent.EXTRA_SUBJECT, subject);
|
||||
intent.putExtra(Intent.EXTRA_TEXT, url);
|
||||
context.startActivity(Intent.createChooser(
|
||||
intent, context.getString(R.string.share_dialog_title))
|
||||
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
|
||||
final Intent shareIntent = new Intent(Intent.ACTION_SEND);
|
||||
shareIntent.setType("text/plain");
|
||||
shareIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
|
||||
shareIntent.putExtra(Intent.EXTRA_TEXT, url);
|
||||
final Intent intent = new Intent(Intent.ACTION_CHOOSER);
|
||||
intent.putExtra(Intent.EXTRA_INTENT, shareIntent);
|
||||
intent.putExtra(Intent.EXTRA_TITLE, context.getString(R.string.share_dialog_title));
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -100,14 +179,11 @@ public final class ShareUtils {
|
|||
ContextCompat.getSystemService(context, ClipboardManager.class);
|
||||
|
||||
if (clipboardManager == null) {
|
||||
Toast.makeText(context,
|
||||
R.string.permission_denied,
|
||||
Toast.LENGTH_LONG).show();
|
||||
Toast.makeText(context, R.string.permission_denied, Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
|
||||
clipboardManager.setPrimaryClip(ClipData.newPlainText(null, text));
|
||||
Toast.makeText(context, R.string.msg_copied, Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
Toast.makeText(context, R.string.msg_copied, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package us.shandian.giga.ui.adapter;
|
|||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.NotificationManager;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Color;
|
||||
|
@ -44,6 +45,7 @@ import org.schabi.newpipe.report.ErrorActivity;
|
|||
import org.schabi.newpipe.report.ErrorInfo;
|
||||
import org.schabi.newpipe.report.UserAction;
|
||||
import org.schabi.newpipe.util.NavigationHelper;
|
||||
import org.schabi.newpipe.util.ShareUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
|
@ -346,10 +348,9 @@ public class MissionAdapter extends Adapter<ViewHolder> implements Handler.Callb
|
|||
if (BuildConfig.DEBUG)
|
||||
Log.v(TAG, "Mime: " + mimeType + " package: " + BuildConfig.APPLICATION_ID + ".provider");
|
||||
|
||||
Uri uri = resolveShareableUri(mission);
|
||||
final Uri uri = resolveShareableUri(mission);
|
||||
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(Intent.ACTION_VIEW);
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.setDataAndType(uri, mimeType);
|
||||
intent.addFlags(FLAG_GRANT_READ_URI_PERMISSION);
|
||||
|
||||
|
@ -363,7 +364,7 @@ public class MissionAdapter extends Adapter<ViewHolder> implements Handler.Callb
|
|||
//mContext.grantUriPermission(packageName, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
|
||||
if (intent.resolveActivity(mContext.getPackageManager()) != null) {
|
||||
mContext.startActivity(intent);
|
||||
ShareUtils.openContentInApp(mContext, intent);
|
||||
} else {
|
||||
Toast.makeText(mContext, R.string.toast_no_player, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
@ -372,12 +373,23 @@ public class MissionAdapter extends Adapter<ViewHolder> implements Handler.Callb
|
|||
private void shareFile(Mission mission) {
|
||||
if (checkInvalidFile(mission)) return;
|
||||
|
||||
Intent intent = new Intent(Intent.ACTION_SEND);
|
||||
intent.setType(resolveMimeType(mission));
|
||||
intent.putExtra(Intent.EXTRA_STREAM, resolveShareableUri(mission));
|
||||
intent.addFlags(FLAG_GRANT_READ_URI_PERMISSION);
|
||||
final Intent shareIntent = new Intent(Intent.ACTION_SEND);
|
||||
shareIntent.setType(resolveMimeType(mission));
|
||||
shareIntent.putExtra(Intent.EXTRA_STREAM, resolveShareableUri(mission));
|
||||
shareIntent.addFlags(FLAG_GRANT_READ_URI_PERMISSION);
|
||||
final Intent intent = new Intent(Intent.ACTION_CHOOSER);
|
||||
intent.putExtra(Intent.EXTRA_INTENT, shareIntent);
|
||||
intent.putExtra(Intent.EXTRA_TITLE, mContext.getString(R.string.share_dialog_title));
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
|
||||
mContext.startActivity(Intent.createChooser(intent, null));
|
||||
try {
|
||||
intent.setPackage("android");
|
||||
mContext.startActivity(intent);
|
||||
} catch (final ActivityNotFoundException e) {
|
||||
// falling back to OEM chooser if Android's system chooser was removed by the OEM
|
||||
intent.setPackage(null);
|
||||
mContext.startActivity(intent);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -651,4 +651,5 @@
|
|||
<string name="notification_colorize_summary">Demander à Android de personnaliser la couleur de la notification en fonction de la couleur principale de la miniature (noter que cela n’est pas disponible sur tous les appareils)</string>
|
||||
<string name="show_thumbnail_title">Afficher la miniature</string>
|
||||
<string name="show_thumbnail_summary">Utiliser la miniature pour l\'arrière-plan de l’écran de verrouillage et les notifications</string>
|
||||
<string name="open_with">Ouvrir avec</string>
|
||||
</resources>
|
|
@ -11,6 +11,7 @@
|
|||
<string name="fdroid_vlc_url" translatable="false">https://f-droid.org/repository/browse/?fdfilter=vlc&fdid=org.videolan.vlc</string>
|
||||
<string name="open_in_browser">Open in browser</string>
|
||||
<string name="open_in_popup_mode">Open in popup mode</string>
|
||||
<string name="open_with">Open with</string>
|
||||
<string name="share">Share</string>
|
||||
<string name="download">Download</string>
|
||||
<string name="controls_download_desc">Download stream file</string>
|
||||
|
|
|
@ -12,21 +12,20 @@
|
|||
lines="253,325"/>
|
||||
|
||||
<suppress checks="FinalParameters"
|
||||
files="ListHelper.java"
|
||||
lines="281,313"/>
|
||||
files="ListHelper.java"
|
||||
lines="281,313"/>
|
||||
|
||||
<suppress checks="EmptyBlock"
|
||||
files="ContentSettingsFragment.java"
|
||||
lines="227,245"/>
|
||||
files="ContentSettingsFragment.java"
|
||||
lines="227,245"/>
|
||||
|
||||
<!-- org.schabi.newpipe.streams -->
|
||||
<suppress checks="LineLength"
|
||||
files="WebMWriter.java"
|
||||
lines="156,158"/>
|
||||
files="WebMWriter.java"
|
||||
lines="156,158"/>
|
||||
|
||||
<suppress checks="FileLength"
|
||||
files="Player.java"/>
|
||||
files="Player.java"/>
|
||||
|
||||
<suppress checks="FileLength"
|
||||
files="VideoDetailFragment.java"/>
|
||||
files="VideoDetailFragment.java"/>
|
||||
</suppressions>
|
||||
|
|
Loading…
Reference in New Issue