WebExtensions: How to send a message to content script? (Android) - android

I just noticed that the tabs API is only available for the desktop not for Android. In the past I have used this code to send messages to my content scripts:
sendMsgToTabs(msg) {
return browser.tabs.query({}).then(tabs => {
let msgPromises = []
for (let tab of tabs) {
let msgPromise = browser.tabs.sendMessage(tab.id, msg)
msgPromises.push(msgPromise)
}
return Promise.all(msgPromises)
})
}
But how am I supposed to do that when the tabs API is not available?
I mean the only thing I can think of is to constantly send empty messages from the content scripts to the background script and whenever the background script has new information then it can send a direct response to one of these messages. But that sounds horribly inefficient. There must be a better way, right?

As of Firefox 54, use .tabs.sendMessage()
As of Firefox 54, the tabs API is supported on Firefox for Android.
Alternative for versions of Firefox prior to Firefox 54.
The storage API is stated as supported in Firefox for Android. Thus, while I have not tested it, a method you could use to send data to content script would be to save a value using chrome.storage.local.set(). By listening to the chrome.storage.onChanged event in your content script(s), you can then be notified of that data being stored/changed. This will provide an event driven way to send a message (i.e. stored data) to the content script.
In order to differentiate between receiving the data in different tabs, you will need to establish a protocol for what the data you save means. This could be as simple as just a particular saved key/value meaning that all content scripts should send a message to the background script to get more information, or more complex where you send/store something like:
{
contentScriptMessage: {
tab: 14,
frame: 1234,
message: 'Some data'
}
}
In each content script's chrome.storage.onChanged listener, it can then ignore any changes that are not to the tab/frame in which it is running.
This methodology will require fleshing out as you try to implement it. Hopefully, at least part of the chrome.tabs API will be implemented for Android in the near future.

Related

Read and update json file data every second

I am reading a JSON file from a web server and want to update my data every second. I am changing my style sheet with the data of JSON file.
I apply this course in ionic 3.
public level;
public sensor;
constructor(public navCtrl: NavController , public peopleData:PeopleDataProvider) {
peopleData.getPeople().subscribe(waterlevel => {
this.level = (waterlevel.val/1000)*100;
this.levelStyles = {height: (waterlevel.val/1000)*100+'%' };
Can anyone tell me how to update this code every second?
It all depends on the web API that you are using. If it supports websockets, then your life will be much easier as you do not need to poll data every second. Just do a google search "How to get real-time updates from a web end point supporting websockets in android?".
If your web APi is an http, then you will have to poll every second (which is not recommended and is a bad practice). In this situation you can use a third-party service like streamdata.io to convert your http web api in to something that pushes update to your JSON file using Server Sent Events (SSE).
Here's in an example on their website how to use it in android projects:
android-server-sent-events

How to send a notification to specific platform?

I want to send two different notifications to Android and iOS. I want to send a notification message to iOS, this way iOS displays a nice notification. For Android I want to send a data message, this way I can handle the notification on Android and also in the background (because I don't get a callback in the background and want to handle it myself).
I looked through the docs, but couldn't find anything about sending to a specific platform. How do I do that?
Also other suggestions on how to do this are welcome, but keep in mind that I specifically want to handle the notification myself through a callback on Android (onMessageReceived)
Update: A recent feature was added for FCM that gives an option to provide specific params for specific platforms, called Platform Overrides:
Customizing a message across platforms
Messages sent by the FCM v1 HTTP protocol can contain two types of JSON key pairs:
a common set of keys to be interpreted by all app instances that receive the message.
platform-specific blocks of keys interpreted only by app instances running on the specified platform.
Platform-specific blocks give you flexibility to customize messages for different platforms to ensure that they are handled correctly when received. In many scenarios, it makes sense to use both common keys and platform-specific keys in a given message.
When to use common keys
Whenever you're targeting app instances on all platforms — iOS, Android, and web
When you are sending messages to topics
The common keys that are interpreted by all app instances regardless of platform are message.notification.title, message.notification.body, and message.data.
When to use platform-specific keys
When you want to send fields only to particular platforms
To send platform-specific fields in addition to the common keys
Whenever you want to send values to specific platforms only, don't use common keys; use platform-specific key blocks. For example, to send a notification to only iOS and web but not Android, you must use two separate blocks of keys, one for iOS and one for web.
When you are sending messages with specific delivery options, use platform-specific keys to set them. You can specify different values per platform if you want; but even when you want to set essentially the same value across platforms, you must use platform-specific keys. This is because each platform may interpret the value slightly differently — for example, time-to-live is set on Android as an expiration time in seconds, while on iOS it is set as an expiration date.
Example: notification message with platform-specific delivery options
The following v1 send request sends a common notification title and content to all platforms, but also sends some platform-specific overrides. Specifically, the request:
sets a long time-to-live for Android and Web platforms, while setting the APNs (iOS) message priority to a low setting
sets the appropriate keys to define the result of a user tap on the notification on Android and iOS — click_action, and category, respectively.
{
"message":{
"token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"notification":{
"title":"Match update",
"body":"Arsenal goal in added time, score is now 3-0"
},
"android":{
"ttl":"86400s",
"notification"{
"click_action":"OPEN_ACTIVITY_1"
}
},
"apns": {
"headers": {
"apns-priority": "5",
},
"payload": {
"aps": {
"category": "NEW_MESSAGE_CATEGORY"
}
}
},
"webpush":{
"headers":{
"TTL":"86400"
}
}
}
}
See the HTTP v1 reference documentation for complete detail on the keys available in platform-specific blocks in the message body. For more information about building send requests that contain the message body, see Build Send Requests.
I remember answering a similar question before but cant seem to find it. There is currently no option to specify which platform a message would be sent. The simplest way you could do this is by using Topics Messaging.
Everytime the token is generated for the first time, you determine from your client app the Platform type and subscribe them to the corresponding topic (e.g. topics/(Android/iOS)_<Your App Name>), then sned the messages as needed.
It's also good to keep track of the registration tokens from your Server, if you're using Firebase DB, you could put them inside a node:
/pushTokens
/android
/{userId} : string
/ios
/{userid}: string
This would let you check from your backend side and adjust your payload as needed when sending single messages.
I was facing same issue with Android Development. We used Laravel on backend side.
On backend side, developer has to maintain different scenario for both platforms.
In Android :
FCM::sendTo($tokens, $option, null, $data);
Here, null is passed as a notification builder. When you pass null in notification and create databuilder($data), you can receive message in onMessageReceived method when app in background.
For iOS :
FCM::sendTo($tokens, $option, $notification, $data);
Here, you can pass notification builder in $notification. So, iOS device can also get notification.

Create a middle BackEnd for a Mobile app

I am developing a mobile app on Android.
I download a lot of information from the backend via REST API.
For example for obtain the information about a contract I use the api the following request:
GET /contracts/01212314.json
It return a json with many fields
{
"conto_contrattuale": "01212314",
"intestatario": "Dennis D'Amico",
"utilizzo": "COTTURA + PROD. ACQUA 7 GG",
"codice_settore_merceologico": "E1",
"settore_merceologico": "ELETTRICITA",
"codice_societa_vendita": "Z016",
"societa_vendita": "Estra Energie S.r.l.",
"fornitura_indirizzo": "Via Palermo",
"fornitura_civico": "20",
"fornitura_precisazione": "Rosso",
"fornitura_cap": "59100",
"fornitura_comune": "Prato"
"rid": false,
"fatt_elettronica": true,
"fatt_email": "andrea.bettarini#devise.it",
"fatture_scadute": 1,
}
But I am only interested to the field : "fornitura_indirizzo"
I can't modify the backend and the API.
So I think to create a new middle backend that fetch the info from the actual backend and exposes a call only for the field "fornitura_indirizzo".
How can I do?
Is it possible on google cloud platform? and is it free?
Thank you for your consideration.
You can put a file on your server that fetches the data en then recreates a partial array and echo that in json.
Example:
$contract = Json_decode("/contracts/xxxx.json", true);
$needed_info = $contract["fornitura_indirizzo"];
Echo json_encode($needed_info);
I can't access to the server and modify. I can only send request.
I apologise if I misunderstand your goals here, but why bother with creating this new back end for your app. You could simply call the existing back end and ignore the unneeded information. Either way, that existing back end has to send all that info somewhere for every request your mobile app performs. You're also adding more latency to the request since it has to go through your back end first.
I can see this being worth it though if your goal is to minimize the data downloaded by the mobile app when it does a request.

Alternative to having secret URLs that are called externally

I have several actions in my application (ASP.NET MVC) that are not intended to be called by browser clients, but from other external applications of my property, such as the Azure Scheduler and my mobile applications (Android)
For these actions to work as expected, a secret parameter and value must be passed.
public ActionResult SendPendingMessages(string secret = "")
{
if (!secret.Equals("hardcoded_secret"))
return null;
// Real stuff here...
}
The above action is called by my scheduler every 30 minutes and sends scheduled messages.
Other example:
public ActionResult DownloadUndownloadedMessages(string secret = "")
{
if (!secret.Equals("hardcoded_secret"))
return null;
// Real stuff here...
}
The above action is called by my android application.
It fetches unread messages.
From these external applications, I always use HTTPS, so I´m sure the hardcoded password (and the URL itself) is secret.
I don't like what I'm doing here. It gives me a bad feeling.
To name a few problems with this approach:
The hardcoded secret is a long term secret.
If other developer works on these external applications, they will know the secret URL
I don´t like that these actions can be called by just knowing the URL. I want to have something more solid than just hiding the URL.
The question is, finally:
What is the most correct way of achieving this purpose?
If a developer works at, for example, WhatsApp, and he´s fired. Can he call WhatsApp server´s actions with the knowledge he got from seeing the WhatsApp client app?
I think that your best approach is follow the WebAPI path and implements one of the answers the post bellow provides:
How to secure an ASP.NET Web API

How to use a server to store/receive data?

I am wondering what is required to setup a server so that you can store data on it, and then have an application send requests to it to store and receive data. More specifically, I am working on an Android application where a user will generate data and then that should be stored on a server so other users can access it. But I do not know how setting up a server to be capable of this works. I have worked on Android applications in the past that sends requests (put, post, get, etc) to a server, but that back end was already set up for me. Any info or resources about setting this up would be great.
There are many, many different ways to accomplish this.
Since you're already working with a Google technology, Android - you could start by creating a Google App Engine project. Following the tutorials you can get started setting up a simple back end solution that will store data for you and you can make requests to it for that data.
Another advantage to this for you is that you don't have to learn how to install software on a server and all the dependencies that arise from that, etc. Simply set up a new account and push-button deploy through Eclipse or command line.
And since you've used Java in Android, you can use JAva for Google App Engine (GAE) too!
Getting started: http://code.google.com/appengine/docs/java/gettingstarted/introduction.html
You can try ready to use BAAS/PAAS services to store your data, e.g. QuickBlox for Android http://quickblox.com/developers/Android, where you can manipulate with your data with few strings
QBLocation location = new QBLocation();
location.setLatitude(35.0);
location.setLongitude(53.0);
location.setStatus("I'm at this place");
String someImportantString = "Dr. Henry Walton Indiana Jones";
QBLocations.createLocation(location, new QBCallbackImpl() {
#Override
public void onComplete(Result result, Object context) {
// retrieve context object inside callback
String passedContextObject = (String) context;
System.out.println(passedContextObject);
// do stuff with result
}
}, someImportantString);
All logic of data exchange with server is encapsulated in framework.

Categories

Resources