Reputation: 544
Is it possible in current state of NativeScript to create an app which listens for share intents on Android?
What I would like to achieve is for example having a website opened in my web browser on Android, tap on share and see my NativeScript app on the list of share targets.
I did accomplish this on a native Android app but can't get it to work in a NativeScript app. I've messed with the AndroidManifest.xml to add
<action android:name="android.intent.action.SEND"></action>
<category android:name="android.intent.category.DEFAULT"></category>
into intent-filter but this did not help. My app does not show up in the list of share targets.
Upvotes: 5
Views: 2411
Reputation: 159
As none of this answers are correct in 2023, with nativescript 7+ the way it works is
add the intent filter like mentioned already:
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
</intent-filter>
listen to the activityNewIntentEvent. This is the only way to retrieve the incoming intent and extract the extra:
if (isAndroid) {
Application.android.on(AndroidApplication.activityNewIntentEvent, function (args: AndroidActivityNewIntentEventData) {
console.log('Event : ' + args.intent);
});
}
Upvotes: 1
Reputation: 663
In case if anyone is looking for most recent NS7 and NS8 compatible version, this works for me and for Android. This is tested on drawer template app from NS8. Javascript part is for home-page.js , just replace it's content with code below.
Imports are different for NS7 and NS8, which gets people confused.
App_Resources/Android/src/main/AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="__PACKAGE__"
android:versionCode="10000"
android:versionName="1.0">
<supports-screens
android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
android:xlargeScreens="true"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<application
android:name="com.tns.NativeScriptApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<activity
android:name="com.tns.NativeScriptActivity"
android:label="@string/title_activity_kimera"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|smallestScreenSize|screenLayout|locale|uiMode"
android:theme="@style/LaunchScreenTheme">
<meta-data android:name="SET_THEME_ON_LAUNCH" android:resource="@style/AppTheme" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
</intent-filter>
</activity>
<activity android:name="com.tns.ErrorReportActivity"/>
</application>
</manifest>
home/home-page.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const Observable = require("@nativescript/core").Observable;
const application = require("@nativescript/core/application");
import { Application } from '@nativescript/core'
import { HomeViewModel } from './home-view-model'
var vm = new Observable();
export function onNavigatingTo(args) {
const page = args.object
page.bindingContext = new HomeViewModel();
page.bindingContext = vm;
vm.set("sharedText", "Waiting for intent...");
if (application.android) {
application.android.on(application.AndroidApplication.activityCreatedEvent, function (args) {
var activity = args.activity;
console.log(activity);
vm.set("sharedText", "Intend data received");
// Get intent, action and MIME type
var intent = activity.getIntent();
var action = intent.getAction();
var type = intent.getType();
if (android.content.Intent.ACTION_SEND === action && type != null) {
if (type.startsWith("text/")) {
handleSendText(intent); // Handle text being sent
}
else if (type.startsWith("image/")) {
handleSendImage(intent); // Handle single image being sent
}
}
else if (android.content.Intent.ACTION_SEND_MULTIPLE === action && type != null) {
if (type.startsWith("image/")) {
handleSendMultipleImages(intent); // Handle multiple images being sent
}
}
else {
// Handle other intents, such as being started from the home screen
}
});
}
}
function handleSendText(intent) {
if (application.android) {
var sharedText = intent.getStringExtra(android.content.Intent.EXTRA_TEXT);
if (sharedText != null) {
// Update UI to reflect text being shared
console.log("sharedText: ", sharedText);
console.log("Text received!");
// set timeout - enough to update UI after app loading
setTimeout(func, 1000);
function func() {
vm.set("sharedText", sharedText);
}
}
}
}
function handleSendImage(intent) {
if (application.android) {
var imageUri = intent.getParcelableExtra(android.content.Intent.EXTRA_STREAM);
if (imageUri != null) {
// Update UI to reflect image being shared
console.log("Image received!");
var appContext = application.android.context;
var bitmap = android.provider.MediaStore.Images.Media.getBitmap(appContext.getContentResolver(), imageUri);
console.log("bitmap: ", bitmap);
vm.set("bitmap", bitmap);
}
}
}
function handleSendMultipleImages(intent) {
if (application.android) {
var imageUris = intent.getParcelableArrayListExtra(android.content.Intent.EXTRA_STREAM);
if (imageUris != null) {
// Update UI to reflect multiple images being shared
console.log("imageUris: ", imageUris);
console.log("Multiple images received!");
}
}
}
export function onDrawerButtonTap(args) {
const sideDrawer = Application.getRootView()
sideDrawer.showDrawer()
}
Upvotes: 0
Reputation: 329
I've been searching for a solution to this question myself and found all of the others answers here very helpful.
Yet, I'm a noob (only two days in) for NativeScript and couldn't actually get where and how to implement all the code bits together to work.
By using the answers here I could continue my search and found a finished GITHUB EXAMPLE: NickIliev/nativescript-receiving-shared-content
For other freshmen (or freshwoman) looking for a finished example go to the repo and explore the code in /demo/app/
directory. It was helpful for me and I'll hope it will help you too.
Upvotes: 3
Reputation: 23
First update your AndroidManifest.xml in app/App_Resources/AndroidManifest.xml
Add following intent-filter like below
<application android:name="com.tns.NativeScriptApplication" android:allowBackup="true" android:icon="@drawable/icon" android:label="@string/app_name"
android:theme="@style/AppTheme"> <activity android:name="com.tns.NativeScriptActivity"
android:label="@string/title_activity_kimera" android:configChanges="keyboardHidden|orientation|screenSize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> </intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.APP_BROWSER" />
<data android:mimeType="text/plain" />
<data android:mimeType="image/*" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.APP_BROWSER" />
<data android:mimeType="image/*" />
</intent-filter>
</activity> <activity android:name="com.tns.ErrorReportActivity"/> </application>
Then Add following lines of code in your app.js
application.android.on(application.AndroidApplication.activityResumedEvent, function (args) {
console.log("Event: " + args.eventName + ", Activity: " + args.activity);
var a = args.activity;
try {
var Intent_1 = android.content.Intent;
var actionSend = Intent_1.ACTION_SEND;
var actionSendMultiple = Intent_1.ACTION_SEND_MULTIPLE;
var argIntent = a.getIntent();
var argIntentAction = argIntent.getAction();
var argIntentType = argIntent.getType();
console.log(" ~~~~ Intent is ~~~~ :" + new String(argIntent.getAction()).valueOf());
String.prototype.startsWith = function (str) {
return this.substring(0, str.length) === str;
};
if (new String(argIntentAction).valueOf() === new String(Intent_1.ACTION_SEND).valueOf()) {
if (new String(argIntentType).valueOf() === new String("text/plain").valueOf()) {
console.dump(cbParseTextAndUrl(argIntent));
}
else if (argIntentType.startsWith("image/")) {
console.log(cbParseImageUrl(argIntent));
}
}
else if (new String(argIntentAction).valueOf() === new String(Intent_1.ACTION_SEND_MULTIPLE).valueOf()) {
if (argIntentType.startsWith("image/")) {
var Uri = cbParseMultipleImageUrl(argIntent);
if (Uri !== null) {
var Uris = JSON.parse(Uri);
console.log(Uris);
}
}
}
function cbParseTextAndUrl(argIntent) {
var Patterns = android.util.Patterns;
//let Matcher = java.util.regex.Matcher;
var ListUrl = [];
var text = argIntent.getStringExtra(Intent_1.EXTRA_TEXT);
if (new String().valueOf() !== "null") {
var Matcher = Patterns.WEB_URL.matcher(text);
while (Matcher.find()) {
var url = Matcher.group();
ListUrl.push(url);
}
return { "text": text, "listUrl": ListUrl };
}
}
function cbParseImageUrl(argIntent) {
var imageUri = argIntent.getParcelableExtra(Intent_1.EXTRA_STREAM);
if (imageUri != null) {
// Update UI to reflect image being shared
return imageUri;
}
}
function cbParseMultipleImageUrl(argIntent) {
var imageUris = argIntent.getParcelableArrayListExtra(Intent_1.EXTRA_STREAM);
if (imageUris != null) {
// Update UI to reflect image being shared
return JSON.stringify(imageUris.toString());
}
}
}
catch (e) {
console.log(e);
}
});
Now you can share your content from 3rd party app to your app.
Upvotes: 1
Reputation: 9670
In addition to the intent-filter you have to add in your AppManifest.xml make sure that you rebuild your app (livesync option may not reflect changes in AppManifest.xml)
Here is an NativeScript implementation for basic share
var app = require("application");
function onShare() {
var sharingIntent = new android.content.Intent(android.content.Intent.ACTION_SEND);
sharingIntent.setType("text/plain");
var shareBody = "Here is the share content body";
sharingIntent.addFlags(android.content.Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
sharingIntent.addFlags(android.content.Intent.FLAG_ACTIVITY_NEW_TASK | android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
sharingIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "Subject Here");
sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, shareBody);
app.android.context.startActivity(sharingIntent);
}
exports.onShare = onShare;
Upvotes: 2
Reputation: 1486
NativeScript should support this scenario out of the box. Here's what my AndroidManifest in app/App_resources/Android
of a default bootstrapped application looks like:
<activity
android:name="com.tns.NativeScriptActivity"
android:label="@string/title_activity_kimera"
android:configChanges="keyboardHidden|orientation|screenSize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
</activity>
edit: Very simple implementation to send intent to any of my other application:
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.setType("text/plain");
sendIntent.putExtra("string", "the data Im sending you");
Intent chooser = Intent.createChooser(sendIntent, "Share with ");
if (sendIntent.resolveActivity(getPackageManager()) != null) {
startActivity(chooser);
}
}
});
Upvotes: 2