Microsoft Sync Framework Offline Storage with SQLite Database - android

I have followed the Microsoft Sync Framework tools and Tutorials.
http://code.msdn.microsoft.com/Sync-Framework-Toolkit-4dc10f0e
I am trying to use SQLite as my client database, for my server i have SQL Server 2008 R2, i provisioned my server database, and i was able to run an example with the browser cache for local storage. but i want to use SQLite database. when clicking on the "sync" button, the SQLite database in the Android devices should be synchronized with SQL Server database. Can you please guide me?
this.sendRequest = function (serviceUri, successCallback, errorCallback, dir) {
TraceObj("[" + dir + " Request]:", serviceUri, this.dataObject());
// Construct HTTP POST request
var xmlHttp = new XMLHttpRequest();
xmlHttp.open("POST", serviceUri);
xmlHttp.setRequestHeader("Accept", "application/json");
xmlHttp.setRequestHeader("Content-Type", "application/json");
// Handle success & error response from server and then callback
xmlHttp.onreadystatechange = function () {
if (xmlHttp.readyState == 4) {
if (xmlHttp.status == 200) {
var res = new SyncFormatter();
if (res.parse(xmlHttp.responseText)) {
TraceObj("[" + dir + " Response]:", serviceUri, res.dataObject());
alert("[" + dir + " Response]:", serviceUri, res.dataObject());
successCallback(res);
return;
}
}
TraceMsg("[" + dir + " Response Error]: ", xmlHttp.status + " Response: " + xmlHttp.responseText);
errorCallback(xmlHttp.responseText);
}
};
xmlHttp.send(this.toString());
};
}
In the above i'm getting xmlHttp.status is 500.

there is not out-of-the-box sync provider for SQLLite, so if you want to use that as your client database, you will have to build one by yourself.
If you have downloaded the Sync Framework Toolkit, you will find a sample sync provider for SQL CE that you can use to follow when writing your own SQLLite sync provider.

Related

How to fix this Firebase message format sent from ESP32 (Arduino, ESP-IDF - all text, no Firebase library used)

I'm trying to get this code below to work which was working perfectly a year ago the last time I tried it. After running it I receive no notification in my app. Using in Arduino IDE on ESP32 module. No changes were made at all to the sketch that was once working other than updating the token. I do not get the "firebase error" message in the serial output so assuming no error.
WiFiClient client;
String serve = "MY SERVER KEY";
String appToken = "MY APP TOKEN";
String data = "{";
data = data + "\"to\": \"" + appToken + "\",";
data = data + "\"notification\": {";
data = data + "\"body\": \"example body\",";
data = data + "\"title\" : \"my title\" ";
data = data + "} }";
Serial.println("Send data...");
if (client.connect("fcm.googleapis.com", 80)) {
Serial.println("Connected to the server..");
client.println("POST /fcm/send HTTP/1.1");
client.println("Authorization: key=" + serve + "");
client.println("Content-Type: application/json");
client.println("Host: fcm.googleapis.com");
client.print("Content-Length: ");
client.println(data.length());
client.print("\n");
client.print(data);
Serial.println("data");
Serial.println(data);
}
else {
Serial.println("firebase error");
}
Serial.println("Data sent...Reading response..");
while (client.available()) {
char c = client.read();
Serial.print(c);
}
Serial.println("Finished!");
client.flush();
client.stop();
}
I just updated Firebase in my app and migrated to AndroidX and can receive messages sent from the Firebase console and I'm currently using this library successfully to send and receive the notifications in my app. Below is the example I'm using and it's working perfectly.
#include <WiFi.h>
#include <FirebaseESP32.h>
#define WIFI_SSID "YOUR_WIFI_AP"
#define WIFI_PASSWORD "YOUR_WIFI_PASSWORD"
#define FIREBASE_HOST "YOUR_FIREBASE_PROJECT.firebaseio.com" //Do not include https:// in FIREBASE_HOST
#define FIREBASE_AUTH "YOUR_FIREBASE_DATABASE_SECRET"
#define FIREBASE_FCM_SERVER_KEY "YOUR_FIREBASE_PROJECT_CLOUD_MESSAGING_SERVER_KEY"
#define FIREBASE_FCM_DEVICE_TOKEN_1 "RECIPIENT_DEVICE_TOKEN"
#define FIREBASE_FCM_DEVICE_TOKEN_2 "ANOTHER_RECIPIENT_DEVICE_TOKEN"
FirebaseData firebaseData1;
unsigned long lastTime = 0;
int count = 0;
void sendMessage();
void setup()
{
Serial.begin(115200);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
Serial.print("Connecting to Wi-Fi");
while (WiFi.status() != WL_CONNECTED)
{
Serial.print(".");
delay(300);
}
Serial.println();
Serial.print("Connected with IP: ");
Serial.println(WiFi.localIP());
Serial.println();
Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH);
Firebase.reconnectWiFi(true);
firebaseData1.fcm.begin(FIREBASE_FCM_SERVER_KEY);
firebaseData1.fcm.addDeviceToken(FIREBASE_FCM_DEVICE_TOKEN_1);
firebaseData1.fcm.addDeviceToken(FIREBASE_FCM_DEVICE_TOKEN_2);
firebaseData1.fcm.setPriority("high");
firebaseData1.fcm.setTimeToLive(1000);
sendMessage();
}
void loop()
{
if (millis() - lastTime > 60 * 1000)
{
lastTime = millis();
sendMessage();
}
}
void sendMessage()
{
Serial.println("------------------------------------");
Serial.println("Send Firebase Cloud Messaging...");
firebaseData1.fcm.setNotifyMessage("Notification", "Hello World! " + String(count));
firebaseData1.fcm.setDataMessage("{\"myData\":" + String(count) + "}");
//if (Firebase.broadcastMessage(firebaseData1))
//if (Firebase.sendTopic(firebaseData1))
if (Firebase.sendMessage(firebaseData1, 0))//send message to recipient index 0
{
Serial.println("PASSED");
Serial.println(firebaseData1.fcm.getSendResult());
Serial.println("------------------------------------");
Serial.println();
}
else
{
Serial.println("FAILED");
Serial.println("REASON: " + firebaseData1.errorReason());
Serial.println("------------------------------------");
Serial.println();
}
count++;
}
I've tried sending the code at the top in data and notification message format with app in foreground and background and cannot receive a message. I'm wondering if something in the Firebase format or rules or such has changed within the last year. I need to use the code at the top instead of the library because I can just add a few more key value pairs in the message body and also send to iOS which I have done successfully in the past using the same code. I'm sure the key pairs could be added with the library actually which I'm working on now but would really prefer the simplicity of the top code. Would appreciate any advice.
I'm not certain but I believe the problem may be that the Arduino code is sending via HTTP and not HTTPS, which I read in the FB docs HTTPS is required. Maybe they changed that because this same code was working perfectly for me a year ago. But I was in the process of migrating my code over to ESP-IDF and this function below is working on that with no problem which has slight mods to comply with C++ I'm using in PlatformIO / VS Code IDE. This was the only thing changed:
esp_http_client_config_t config = {};
config.url = "https://fcm.googleapis.com/fcm/send";
config.event_handler = _http_event_handler;
I didn't need any type of SSL certificate, I just sent the code as shown. I didn't try messing around too much with the Arduino code for HTTPS.
static void firebasePost() {
esp_http_client_config_t config = {}; // important to initialize with "{}" when using C++ on ESP-IDF http client or it will crash easily
config.url = "https://fcm.googleapis.com/fcm/send";
config.event_handler = _http_event_handler;
esp_http_client_handle_t client = esp_http_client_init(&config);
esp_err_t err = esp_http_client_perform(client);
const char *post_data = "{\"to\": \"eCiC-20m8Zw:APA91bE4i1rkC(SHORTENED)9JZpbW3gFe5Qfz9BhOFmqua3aeZoDZEQ\",\"notification\": {\"body\": \"Sample Body\",\"title\" : \"Sample Title\"} }";
esp_http_client_set_header(client, "Authorization", "key=AAAAZrM4XXXX:APA91bFnSr_U15y6mX(SHORTENED)WqaWECxYWaCf_rVPE");
esp_http_client_set_header(client, "Content-Type", "application/json");
esp_http_client_set_method(client, HTTP_METHOD_POST);
esp_http_client_set_post_field(client, post_data, strlen(post_data));
err = esp_http_client_perform(client);
if (err == ESP_OK) {
ESP_LOGI(TAG, "HTTP POST Status = %d, content_length = %d",
esp_http_client_get_status_code(client),
esp_http_client_get_content_length(client));
} else {
ESP_LOGE(TAG, "HTTP POST request failed: %s", esp_err_to_name(err));
}
esp_http_client_cleanup(client);
}
The Arduino Firebase library connects to Firebase via SSL port 443 (HTTPS method) for both FCM and RTDB.
Your above assumption is not correct.
Your device token is invalid or not existed.
You don't have to know the code inside the Arduino library. Google only accept secure connection for their services. The problems can be the device uid or redundant of FCM payload data. You accept your answer with your own assumption. No solution for this issue. You need to open the issue at GitHub repo.

Serve mp3 stream for android with Laravel

Here's my problem: I'm writing a laravel backend which have to serve an mp3 file that had to be reproduced by using the android standard media player.
For the laravel backend I need to use JWT to handle authentication so on every request headers I have to set the "Authorization" field to "Bearer {token}" .The laravel route is "/songs/{id}" and is handled in this way:
public function getSong(Song $song) {
$file = new File(storage_path()."/songs/".$song->path.".mp3");
$headers = array();
$headers['Content-Type'] = 'audio/mpeg, audio/x-mpeg, audio/x-mpeg-3, audio/mpeg3';
$headers['Content-Length'] = $file->getSize();
$headers['Content-Transfer-Encoding'] = 'binary';
$headers['Accept-Range'] = 'bytes';
$headers['Cache-Control'] = 'must-revalidate, post-check=0, pre-check=0';
$headers['Connection'] = 'Keep-Alive';
$headers['Content-Disposition'] = 'attachment; filename="'.$song->path.'.mp3"';
$user = \Auth::user();
if($user->activated_at) {
return Response::download($file, $song->path, $headers);
}
\App::abort(400);
}
On the android side I'm using the MediaPlayer to stream the mp3 file in this way:
media_player = new MediaPlayer();
try {
media_player.setAudioStreamType(AudioManager.STREAM_MUSIC);
String token = getSharedPreferences("p_shared", MODE_PRIVATE).getString("token", null);
Map<String, String> headers = new HashMap<>();
headers.put("Authorization", "Bearer " + token);
media_player.setDataSource(
getApplicationContext(),
Uri.parse(ConnectionHelper.SERVER + "/songs/" + song.getId()),
headers
);
} catch (IOException e) {
finish();
Toast.makeText(
Round.this,
"Some error occurred. Retry in some minutes.",
Toast.LENGTH_SHORT
).show();
}
media_player.setOnCompletionListener(this);
media_player.setOnErrorListener(this);
media_player.setOnPreparedListener(this);
But every time I execute the code I get extra code -1005 on the error listener that means ERROR_CONNECTION_LOST.
The problem: Response::download(...) doesn't produce a stream, so I can't serve my .mp3 file.
The solution:
As Symfony HttpFoundation doc. says in the serving file paragraph:
"if you are serving a static file, you can use a BinaryFileResponse"
The .mp3 files I need to serve are statics in the server and stored in "/storage/songs/" so I decided to use the BinaryFileResponse, and the method for serving .mp3 became:
use Symfony\Component\HttpFoundation\BinaryFileResponse;
[...]
public function getSong(Song $song) {
$path = storage_path().DIRECTORY_SEPARATOR."songs".DIRECTORY_SEPARATOR.$song->path.".mp3");
$user = \Auth::user();
if($user->activated_at) {
$response = new BinaryFileResponse($path);
BinaryFileResponse::trustXSendfileTypeHeader();
return $response;
}
\App::abort(400);
}
The BinaryFileResponse automatically handle the requests and allow you to serve the file entirely (by making just one request with Http 200 code) or splitted for slower connection (more requests with Http 206 code and one final request with 200 code).
If you have the mod_xsendfile you can use (to make streaming faster) by adding:
BinaryFileResponse::trustXSendfileTypeHeader();
The android code doesn't need to change in order to stream the file.

Acra post script

Tried to use ACRA in my app, but I can't get the google drive or the email working (in google drive I don't know how to create the form from the template, email tells me there is no such email address even though I am sending from the same email address). I would rather get the google drive spreadsheet thing working or better yet - if there is a ready-to-use script for free web host that I can use to get the reports. Anyone knows of such a script?
EDIT: I need a php one...
Looks like ACRA uses a simple post. What language do you need it in? For asp.net:
protected void Page_Load(object sender, EventArgs e)
{
StringBuilder err = new StringBuilder();
foreach (string name in Request.Form)
{
err.AppendLine(name + ": " + Request.Form[name]);
}
TextWriter tw = null;
try
{
tw = new StreamWriter("f:\\errorLogs\\error_" + DateTime.Now.Ticks + ".txt");
tw.WriteLine(err.ToString());
}
catch (Exception) { }
finally
{
if(tw != null)
tw.Close();
}
}
Since you are using a "free web host", the location probably isn't valid for you, but this should at least get you pointed in the right direction. There is another post which is similar to yours. Most free web hosts use php.
EDIT:
Here is a basic PHP script (Not tested, but seems OK to me. My PHP is a bit rusty):
<?php
$file = 'postData.txt';
$arr= $_POST;
$fp = fopen($file, 'w') or die('Could not open file!');
foreach ($arr as $key => $value) {
$toFile = "Key: $key; Value: $value \n";
// write to file
fwrite($fp, "$toFile") or die('Could not write to file');
}
// close file
fclose($fp);
?>

Microsoft Sync Framework - ServerBlob is Empty Error

I am using Microsoft Sync Framework to sync the details from the Datadictionary on android device with SQL Server. Initially get success to sync all data from sql server. But after adding some data and when clicking on the Sync button getting the following error. Can you please tell me is anybody came across this?
[Sync Error]:Error occurs during sync. Please check logs below.
[Upload Change Response Error]: 500 Response: <ServiceError xmlns="http://schemas.datacontract.org/2004/07/Microsoft.Synchronization.Services" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><ErrorDescription>System.InvalidOperationException
 serverBlob is empty
 at Microsoft.Synchronization.Services.SqlProvider.SqlSyncProviderService.ApplyChanges(Byte[] serverBlob, List`1 entities)
 at Microsoft.Synchronization.Services.UploadChangesRequestProcessor.ProcessRequest(Request incomingRequest)
 at Microsoft.Synchronization.Services.SyncService`1.ProcessRequestForMessage(Stream messageBody)
 
 
 </ErrorDescription></ServiceError>
In the below code, i'm getting xmlHttp.status=500 when clicking on the Sync button
this.sendRequest = function (serviceUri, successCallback, errorCallback, dir) {
TraceObj("[" + dir + " Request]:", serviceUri, this.dataObject());
// Construct HTTP POST request
var xmlHttp = new XMLHttpRequest();
xmlHttp.open("POST", serviceUri);
xmlHttp.setRequestHeader("Accept", "application/json");
xmlHttp.setRequestHeader("Content-Type", "application/json");
// Handle success & error response from server and then callback
xmlHttp.onreadystatechange = function () {
if (xmlHttp.readyState == 4) {
if (xmlHttp.status == 200) {
var res = new SyncFormatter();
if (res.parse(xmlHttp.responseText)) {
TraceObj("[" + dir + " Response]:", serviceUri, res.dataObject());
alert("[" + dir + " Response]:", serviceUri, res.dataObject());
successCallback(res);
return;
}
}
TraceMsg("[" + dir + " Response Error]: ", xmlHttp.status + " Response: " + xmlHttp.responseText);
errorCallback(xmlHttp.responseText);
}
};
xmlHttp.send(this.toString());
};
}
I have found the root cause of the problem. That is when i get the values from datadictionary storage, value has the single quotes in the values so not able to load the values in webview. Now i have replaced single quotes by \'. Now working fine.

How do I enable Third-Party Cookies under Phonegap and Android 3.2?

I am using $getJSON to hit a node.js endpoint under Phonegap and Android. The code looks like this
$.getJSON(
serverURL + "/login?callback=?",
"playerId=" + playerId + "&pwd=" + pwd,
function(data){
theCallbackFunction.call(null, JSON.parse(data));
},
function(jqXHR, textStatus, errorThrown) {
alert('error ' + textStatus + " " + errorThrown);
}
);
In response to the login request, my server sends back a session cookie. This cookie is only accepted and returned in subsequent AJAX requests if 'Third-Party Cookies' are enabled in the browser. I have found that older Android devices (e.g. 2.2) allow this by default but new ones (3.2) do not.
Is it possible to force Phonegap to enable Third-Party Cookies for my Android application?
I had a similar problem when trying to authenticate with my server. I instead resorted to the use of localStorage. See the code below or here.
var store = window.localStorage,
request = {
url: {SERVER_URL},
headers : {
Cookie: store.getItem('session')
},
complete: function (jqXHR, status){
if (status != 'success') {
console.log('ajax status: failure');
} else if (store.getItem('session') != null) {
console.log('ajax status: session exists');
} else {
console.log('ajax status: saving cookie');
var header = jqXHR.getAllResponseHeaders();
var match = header.match(/(Set-Cookie|set-cookie): (.+?);/);
if (match) {
session = match[2];
store.setItem("session", session);
}
}
}
}
$.ajax(request);
In the above, I'm checking for the localStorage variable 'session' and if it exists, it will send the stored cookie. If it doesn't exist, it will take the 'set-cookie' paramater sent in the headers by the server, match the pertinent part and store it in the 'session' variable of localStorage.
Phonegap does not support cookie abstraction. Never really needed to as there are already apps/plug-ins that do. Plus it is intended to wrap up the functionality of the phone/device, not the browser. You CAN however do this with a jQuery plug-in.
https://github.com/carhartl/jquery-cookie

Categories

Resources