Are websocket, playing audio in background, and storing files locally possible in KaiOS app? - kaios

I am planning to develop a chat and voice messaging app in KaiOS, but want to make sure whether these things are possible in KaiOS:
web sockets in background (can receive the data when app is not opened)
playing audio in background without user interaction
storing files locally

Web Sockets : Web sockets can work only if the app is at foreground. You can use window.MozWebSocket or websock.js.
If you want to do any data exchange activity in background, then make use of push notification, serviceworker and indexed db/cache API.
Storing files : Yes you can read and write files
To read,
var sdcard = navigator.getDeviceStorage('sdcard');
var request = sdcard.get("fileName");
request.onsuccess = function () {
var fileObject = this.result;
};
request.onerror = function () {
console.warn("Unable to get the file: " + this.error);
};
To write,
var sdcard = navigator.getDeviceStorage("sdcard");
var request = sdcard.addNamed("file data", "test.txt");
request.onsuccess = function () {
var name = this.result;
console.log('File "' + name + '" successfully wrote !!');
};
request.onerror = function () {
console.warn('Unable to write the file: ' + this.error);
}

Background WebSockets aren't supposed by any browser, or on KaiOS. You can use Web Push to receive push notifications in the background.
Background audio playback is supported
Files can be read and saved locally using the Device Storage API

Related

UWP MediaPlayer : Play encrypted HLS stream by passing the key from app

I am looking for a way to play the encrypted HLS streams in UWP MediaElement , I am able to play the url that has key url given but I need to pass the key from app, not from the key url.
#EXT-X-KEY:METHOD=AES-128,URI="stream.m3u8.key",IV=0x00000000000000000000000000000000
IF the key file is present the below code works fine.
async private void InitializeAdaptiveMediaSource(System.Uri uri)
{
AdaptiveMediaSourceCreationResult result = await AdaptiveMediaSource.CreateFromUriAsync(uri);
if (result.Status == AdaptiveMediaSourceCreationStatus.Success)
{
ams = result.MediaSource;
mediaPlayerElement.SetMediaPlayer(new Windows.Media.Playback.MediaPlayer());
mediaPlayerElement.MediaPlayer.Source = MediaSource.CreateFromAdaptiveMediaSource(ams);
mediaPlayerElement.MediaPlayer.AutoPlay = true;
mediaPlayerElement.Stretch = Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT.Stretch.Uniform;
ams.InitialBitrate = ams.AvailableBitrates.Max<uint>();
//Register for download requests
ams.DownloadRequested += DownloadRequested;
////Register for download failure and completion events
//ams.DownloadCompleted += DownloadCompleted;
//ams.DownloadFailed += DownloadFailed;
////Register for bitrate change events
//ams.DownloadBitrateChanged += DownloadBitrateChanged;
//ams.PlaybackBitrateChanged += PlaybackBitrateChanged;
////Register for diagnostic event
//ams.Diagnostics.DiagnosticAvailable += DiagnosticAvailable;
}
else
{
//// Handle failure to create the adaptive media source
//MyLogMessageFunction($"Adaptive source creation failed: {uri} - {result.ExtendedError}");
}
}
But I want to pass the key from my app to decrypt the video and play in the MediaElement.Any help regarding this is greatly appriciated.

How to upload files to firebase storage from google drive using Apps Script?

I need some users to be able to upload files to firebase storage, but they're non tech-savvy, so I will let them upload to drive first, and mirror drive from storage. The thing is, I can't figure out how without having to host a server; google apps scripts can't access firebase storage easily (it can access both firebase databases though) and I need a server to use the google drive API, which could be done using firebase cloud functions, but I wonder if there is an easier alternative.
An image file can be uploaded to firebase storage using Apps Script.
There are 4 critical things that need to be done:
Enable the "Google Cloud Storage JSON API"
Get the "bucket" name of your Firebase Storage
Add the "https://www.googleapis.com/auth/devstorage.read_write" scope to the appsscript.json manifest file, along with all other scopes already needed.
Enable "Write" access in your Firebase storage rules
You will need to get an OAuth token, but you don't need an OAuth library.
Enable the "Google Cloud Storage JSON API"
This needs to be done for the Google account that will be uploading the file. The solution described here is for uploading a file where the Apps Script project, and the Firebase Storage are owned by the same Google Account.
Go to your Google Cloud Platform - From the code editor choose, "Resources" and "Cloud Platform project" - Click something in the dialog box to go to your Cloud Platform. Find the "API's and Services" section. Click "Enable API's and Services" Search "JSON" Enable the "Google Cloud Storage JSON API" service.
Get the "bucket" name of your Firebase Storage
Go to your Firebase Storage settings. Look for "gs://your-bucket-name.appsspot.com" That is your bucket name. Don't include the "gs://" The bucket name needs to have the "appspot.com" part on the end.
Add the "https://www.googleapis.com/auth/devstorage.read_write" scope to the appsscript.json manifest file
From the script editor, choose "File" and "Project Properties" and click the "Scopes" tab. Copy out all the existing scopes, and paste them somewhere so that you can get them back.
From the script editor, choose "View" and "Show Manifest file." Click on the appsscript.json file to open it. Add all existing scopes, plus the "https://www.googleapis.com/auth/devstorage.read_write" scope to the manifest file.
Manifest file to look like this, except with your time zone and scopes.
{
"timeZone": "America/New_York",
"dependencies": {
},
"webapp": {
"access": "ANYONE_ANONYMOUS",
"executeAs": "USER_DEPLOYING"
},
"exceptionLogging": "STACKDRIVER",
"oauthScopes": [
"https://mail.google.com/",
"https://www.googleapis.com/auth/drive",
"https://www.googleapis.com/auth/script.container.ui",
"https://www.googleapis.com/auth/script.external_request",
"https://www.googleapis.com/auth/script.scriptapp",
"https://www.googleapis.com/auth/spreadsheets",
"https://www.googleapis.com/auth/userinfo.email",
"https://www.googleapis.com/auth/devstorage.read_write"
]
}
Enable "Write" access in your Firebase storage rules
allow read, write: if request.auth != null;
Get the OAuth token:
You can get the OAuth token with:
ScriptApp.getOAuthToken();
So, you don't need an OAuth library, you don't need any SDK, you don't need to do anything with client side code, you don't need special information from a firebase service account or the legacy Database Secret.
The Code:
This code uploads an image file from Google Drive to firebase Storage
Note! Any file over 5MB may need something a little different.
function uploadToFirebaseStorage(po) {
try{
var blob,bucketName,bytes,fileID,fileName,folderName,
oA_Tkn,options,pathAndName,response,result,url;
/* See
https://cloud.google.com/storage/docs/uploading-objects?authuser=0
for REST API information
*/
/*
Firebase uses the Google Cloud Storage API
*/
bucketName = "your-bucket-name.appspot.com";
folderName = "folder_name";
fileName = "file_name";
pathAndName = folderName + "/" + fileName;
fileID = po.fileId;
//curl "https://www.googleapis.com/upload/storage/v1/b/[BUCKET_NAME]/o?uploadType=media&name=[OBJECT_NAME]"
url = 'https://www.googleapis.com/upload/storage/v1/b/' + bucketName + '/o?uploadType=media&name=' + pathAndName;
blob = DriveApp.getFileById(fileID).getBlob();
//Logger.log('blob.getContentType(): ' + blob.getContentType())
bytes = blob.getBytes();
//Logger.log('bytes: ' + bytes)
oA_Tkn = ScriptApp.getOAuthToken();
options = {
method: "POST",//curl -X POST
muteHttpExceptions: true,
contentLength: bytes.length,
contentType: blob.getContentType(),//curlv-H "Content-Type: [OBJECT_CONTENT_TYPE]"
payload: bytes,
headers: {//curl -H "Authorization: Bearer [OAUTH2_TOKEN]"
Authorization: 'Bearer ' + oA_Tkn
}
}
response = UrlFetchApp.fetch(url, options);
result = JSON.parse(response.getContentText());
Logger.log(JSON.stringify(result, null, 2));
/*
A successful return object looks like:
{
"kind": "storage#object",
"id": "bucket-name.appspot.com/online_store/file_name/abc123",
"selfLink": "https://www.googleapis.com/storage/v1/b/bucket-name.appspot.com/o/online_store%2FAAA_Test",
"name": "folder_Name/file_name",
"bucket": "bucket-name.appspot.com",
"generation": "abc123",
"metageneration": "1",
"contentType": "image/jpeg",
"timeCreated": "2018-10-24T00:47:33.435Z",
"updated": "2018-10-24T00:47:33.435Z",
"storageClass": "STANDARD",
"timeStorageClassUpdated": "2018-10-24T00:47:33.435Z",
"size": "950012",
"md5Hash": "abc123==",
"mediaLink": "https://www.googleapis.com/download/storage/v1/b/bucket-name.appspot.com/o/some_name%2FAAA_Test?generation=abc123&alt=media",
"crc32c": "kIY6Qg==",
"etag": "nwrfwfn="
}
*/
}catch(e) {
Logger.log(e.message + "\n\n" + e.stack)
}
}
function testFB_Upload() {
uploadToFirebaseStorage({fileId:"Put image file ID here"});
}
When the code is run for the first time, if the user has not enabled the API, there is a link provided in the extended error message in the response. So, you could modify the code to get the Cloud Console link from the error response. That link goes directly to the correct Cloud Console API, so the user doesn't need to know how to navigate their Cloud Console in order to find the correct API.
How to get the download url after the image has been uploaded
<head>
<title>Your Site Name</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Firebase App is always required and must be first -->
<script src="https://www.gstatic.com/firebasejs/5.5.7/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/5.5.7/firebase-auth.js"></script>
<script src="https://www.gstatic.com/firebasejs/5.5.7/firebase-storage.js"></script>
<script>
// Initialize Firebase
//Open the project - click Project Overview - Click the </> icon
var config = {
apiKey: "abc123",//Web API key in project settings
authDomain: "your_name.firebaseapp.com",
//databaseURL: "https://<DATABASE_NAME>.firebaseio.com",
projectId: "myID",//In Project Settings
storageBucket: "myDomain.appspot.com"
};
firebase.initializeApp(config);
</script>
</head>
window.srchForFile = function(po) {//client side code in a script tag
//This function is called from a success handler AFTER the file has
//originally been uploaded
try{
/*
po - parameters object - {fileID:'123ABC',folderName:'name_here'}
po.fileID - the ID of the original file that was uploaded
po.folderName - the name of the firebase folder to search
*/
/*
This code assumes that the firebase SDK has been loaded and that the
firebase class is available
*/
var fileID,fileName,imagesRef,spaceRef;
fileID = po.fileId;
fileName = "IMG_" + fileID;//The file name to search for which must
//be exactly the same as the file just uploaded - make sure to use
//a naming convention that is consistent
if (!STORAGE_REF) {
STORAGE_REF = firebase.storage().ref();//firebase SDK must be loaded
}
imagesRef = STORAGE_REF.child(po.folderName);
//console.log('imagesRef: ' + imagesRef);
spaceRef = imagesRef.child(fileName);// Points to the file name
//console.log('spaceRef: ' + spaceRef);
spaceRef.getDownloadURL().then(function(url) {
//console.log('File available at: ' + url);
if (!url) {
url = false;
}
nextStepAfterFileSrch(url);//Now run another function
}).catch(function(error) {//There was an error
// Handle any errors here
nextStepAfterFileSrch(false);
}
);
//DO NOT HAVE ANY CODE HERE OR IT WILL RUN BEFORE THE ABOVE CODE IS
//DONE
} catch(e) {
showErrMsg(e.message);//client side error handling
}
}

Read CollectionFS file from server's filesystem when hosted on meteor.com

Im trying let the user Upload a txt file and then let him click a button "analyze" and then perform some analysis.
I have the app working locally, Im using FS.Collection and FileSystem however I had several problems deploying to meteor.com. Here is my collection:
FS.debug = true;
Uploads = new FS.Collection('uploads', {
stores: [new FS.Store.FileSystem('uploads')]
});
and here is how I try to read the uploaded file:
var fs = Npm.require('fs');
var readedFile = fs.readFileSync(process.env.PWD+'/.meteor/local/cfs/files/uploads/+file.copies.uploads.key, 'utf-8');
The above works in local but not after I deploy to meteor.com, in the debug messages I see something like this: Error: ENOENT, no such file or directory
So I do not know how to read the file when the app is deployed, how would you do it?, or do you think I should deploy the app to Amazon EC2? Im afraid to deploy to amazon and have the same problem...
Short example of using http to download a file that was uploaded via collectionFS.
var file = Uploads.findOne({ _id: myId }); // or however you find it
HTTP.get(file.url(),function(err,result){
// this will be async obviously
if ( err ) console.log("Error "+err+" downloading file"+myId);
else {
var content = result.content; // the contents of the file
// now do something with it
}
});
Note that you must meteor add http to get access to the http package.
This is probably the package you want:
https://github.com/tomitrescak/meteor-uploads
it has a nice UI too and much less trouble than FSCollection.

Load a webpage that requires basic authentication in a Windows 8 App

How would you load an external site that requires basic authentication inside an iframe in a Windows 8 HTML/JavaScript app?
I've found that you can't use URLs of the form http://username:password#host/.
In order to load the URL I was trying to load, I had to use a webview or x-ms-webview and invoke it's navigateWithHttpRequestMessage function in order to pass the basic authentication header.
This resulted in the following code structure:
function ready(element, options) {
var webview = document.querySelector('[data-hook~="camera"]');
webview.navigateWithHttpRequestMessage(buildRequest());
}
function buildRequest() {
var username = 'username',
password = 'password',
Crypto = Windows.Security.Cryptography,
Http = Windows.Web.Http,
request,
buffer,
token;
request = new Http.HttpRequestMessage(
Http.HttpMethod.get,
new Windows.Foundation.Uri('http://ipcamera/'));
buffer = Crypto.CryptographicBuffer.convertStringToBinary(
[username, password].join(':'),
Crypto.BinaryStringEncoding.utf8);
token = Crypto.CryptographicBuffer.encodeToBase64String(buffer);
request.headers.authorization = new Http.Headers.HttpCredentialsHeaderValue('basic', token);
return request;
}
The caveat to this is that none of the DOM ready events seem to fire, so if you need to interact with the external site, you'll have to play with timers.

Worklight 6.2 - Broadcast notification not being sent

We are trying to run the sample app for push notifications with some modification to get it to send out a broadcast notification, but it is not getting sent.
We have modified the PushBackendEmulator code as well. The emulator invokes the submitBroadCastNotification procedure successfully and the following result is returned:
Server response :: /-secure-{"result":"Notification sent to all
users","isSuccessful":true}/
However, it appears the WL.Server.sendMessage method is not sending the message and returns. I am not able to see the server side logs either after a thorough search on the liberty server except for the messages.log on the liberty server which shows the following when WL.Server.sendMessage is called.
ht.integration.js.JavaScriptIntegrationLibraryImplementation E
FWLSE0227E: Failed to send notification. Reason: FPWSE0009E: Internal
server error. No devices found [project worklight]
Here is the adapter code:
function submitBroadcastNotification( notificationText) {
var notification = {};
notification.message = {};
notification.message.alert = notificationText;
//notification.target = {};
//notification.target.tagNames = ['test'];
WL.Logger.debug("broadcast: " + notification.message.alert );
var delayTimeOut = **WL.Server.sendMessage**("PushNotificationsApp", notification);
WL.Logger.debug("Return value from WL.Server.sendMessage :"+ delayTimeOut);
return {
result : "Notification sent to all users"
};
}
Here is the PushBackendEmulator code:
public static void main(String [] args){
String serverUrl =
"http://208.124.245.78:9080/worklight";
String notificationText = "Hellofrombroadcastingnotifications";
String userId = "admin";
notificationText = notificationText.replace(" ", "%20");
Logger.debug("sending broadcast notification: " + notificationText);
URL url = new URL(serverUrl
+ "/invoke?
adapter=PushAdapter&procedure=submitBroadcastNotification&parameters=['" + userId + "','" + notificationText + "']");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setReadTimeout(10000);
connection.setDoOutput(true);
Logger.debug("Connected to server");
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String response = "";
String inputLine;
while ((inputLine = in.readLine()) != null)
response+= inputLine;
Logger.debug("response is:"+ response);
in.close();
Logger.debug("Server response :: " + response);
connection.disconnect();
Looking at your application from the PMR, it seems to me like you have mixed both event source-based notifications and broadcast notifications.
If you want to use Broadcast notifications, this means you cannot try imposing sending the notification to any specific userId, etc as it is not needed nor based on userIds.
By default, all devices are auto-subscribed to a tag called "push.ALL".
You can read more about broadcast notifications API methods in the IBM Worklight Knowledge Center.
This is a modified version of your application, tested in iOS and Android: https://www.dropbox.com/s/l2yk2pbvykrzfoh/broadcastNotificationsTest.zip?dl=0
Basically, I stripped away from it anything not related to broadcast notifications:
I removed the push securitytest from application-descriptor.xml
I removed any function from the adapter XML and JS files and main.js file that is related to event source-based notifications.
The end result is that after the app is loaded, you are right inside the application (no login).
I then right-clicked the adapter folder in Studio > invoke procedure, and selected the submitBroadcastNotification option to send the notification ("aaa").
In the device, a notification was received. Tapping it (if the app is closed) launches the application, which then triggers the WL.Client.Push.onMessage API in common\js\main.js to display alerts containing the payload and props of the received notification.
This was tested in both iOS and Android.
As the application was loading, I could see in LogCat and Xcode console the token registration.
To test this in iOS, you will need to update application-descriptor.xml with your own pushSender password and add your own apns-certificatae-sandbox.p12 file.
To test in Android, make sure you are have generated a browser key in the GCM console and are using it in application-descriptor.xml
For both, make sure that all requires ports and addresses and accessible in your network

Resources