Unable to read or right data to/ from Firestore SwiftUI - arrays

I've setup Firestore DB and wanted to test it. However I was unable neither read or wright data to it. Here is what console shows on connection status to Firebase.
Debug Console:
2020-11-19 17:58:49.802849+0300 Demo [813:165300] 6.34.0 - [Firebase/Analytics][I-ACS023007] Analytics v.60900000 started
2020-11-19 17:58:49.803819+0300 Demo [813:165300] 6.34.0 - [GoogleUtilities/AppDelegateSwizzler][I-SWZ001014] App Delegate does not conform to UIApplicationDelegate protocol.
2020-11-19 17:58:49.804498+0300 Demo [813:165300] 6.34.0 - [Firebase/Analytics][I-ACS023008] To enable debug logging set the following application argument: -FIRAnalyticsDebugEnabled (see https://help.apple.com/xcode/mac/8.0/#/dev3ec8a1cb4)
2020-11-19 17:58:50.586054+0300 Demo [813:165306] 6.34.0 - [Firebase/Analytics][I-ACS800023] No pending snapshot to activate. SDK name: app_measurement
2020-11-19 17:58:51.138985+0300 Demo [813:165306] 6.34.0 - [Firebase/Analytics][I-ACS023012] Analytics collection enabled
2020-11-19 17:58:51.139362+0300 Demo [813:165306] 6.34.0 - [Firebase/Analytics][I-ACS023220] Analytics screen reporting is enabled. Call +[FIRAnalytics logEventWithName:FIREventScreenView parameters:] to log a screen view event. To disable automatic screen reporting, set the flag FirebaseAutomaticScreenReportingEnabled to NO (boolean) in the Info.plist
2020-11-19 17:58:51.850205+0300 Demo [813:165012] [AXRuntimeCommon] This class 'SwiftUI.AccessibilityNode' is not a known serializable element and returning it as an accessibility element may lead to crashes
Also Firebase it self shows that I had some reads in stats.
I stuck and don't understand what important part I didn't do in order to start implementing Firebase use. Will appreciate any help or suggestion.!
I used several methods to initiate Firebase in SwiftUI.
This one:
import SwiftUI
import Firebase
#main
struct DemoApp: App {
init() {
FirebaseApp.configure()
}
var body: some Scene {
WindowGroup {
ContentView()
.onOpenURL(perform: { url in
Auth.auth().canHandle(url)
})
}
}
Also tried with DelegateAdaptor:
#main
struct DemoApp: App {
#UIApplicationDelegateAdaptor(AppDelegate.self) var delegate
appDelegate
init() {
FirebaseApp.configure()
}
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication,didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
print("Application is starting up. ApplicationDelegate didFinishLaunchingWithOptions.")
return true
}
}
To test writing to:
func letE() {
let db = Firestore.firestore()
db.collection("wine").addDocument(data: ["Cool" : 2017])
}
And to fetch an array
private var db = Firestore.firestore()
func fetchData() {
db.collection("collection").document("document")
.addSnapshotListener { documentSnapshot, error in
guard let document = documentSnapshot else {
print("Error fetching document: \(error!)")
return
}
guard let data = document.data()!["array name"] else {
print("Document data was empty.")
return
}
print(data)
}
And like this:
func getData(){
db.collection("skills").getDocuments() { (querySnapshot, err) in
if let err = err {
print("Error getting documents: \(err)")
} else {
for document in querySnapshot!.documents {
print("\(document.documentID) => \(document.data())")
}
}
Hello, Peter! I was trying to come to solving this problem from different angels but still no luck.
Basically I am trying to perform wright operation
It goes like this
#main
struct DemoApp: App {
init() {
FirebaseApp.configure()
}
var body: some Scene {
WindowGroup {
ContentView()
.onOpenURL(perform: { url in
Auth.auth().canHandle(url)
})
}
}
}
func addData() {
//
let db = Firestore.firestore()
//
db.collection("wine").addDocument(data: ["Test":100])
}
Then i press Build.
From my understanding that already should create collection "Wine" with autogenerated Document with contains field "Test" with value "100"
But once again nothing happens on the firebase side.
The Debug console
2021-01-26 16:22:21.907902+0300 Demo [27616:342494] 6.34.0 - [Firebase/Analytics][I-ACS023007] Analytics v.60900000 started
2021-01-26 16:22:21.908067+0300 Demo [27616:342494] 6.34.0 - [Firebase/Analytics][I-ACS023008] To enable debug logging set the following application argument: -FIRAnalyticsDebugEnabled (see https://help.apple.com/xcode/mac/8.0/#/dev3ec8a1cb4)
2021-01-26 16:22:21.934626+0300 Demo [27616:342498] 6.34.0 - [GoogleUtilities/AppDelegateSwizzler][I-SWZ001014] App Delegate does not conform to UIApplicationDelegate protocol.
2021-01-26 16:22:21.979114+0300 Demo [27616:342490] [] nw_protocol_get_quic_image_block_invoke dlopen libquic failed
2021-01-26 16:22:21.994921+0300 Demo [27616:342490] 6.34.0 - [Firebase/Analytics][I-ACS800023] No pending snapshot to activate. SDK name: app_measurement
2021-01-26 16:22:22.000217+0300 Demo [27616:342490] 6.34.0 - [Firebase/Analytics][I-ACS023012] Analytics collection enabled
2021-01-26 16:22:22.000724+0300 Demo [27616:342490] 6.34.0 - [Firebase/Analytics][I-ACS023220] Analytics screen reporting is enabled. Call +[FIRAnalytics logEventWithName:FIREventScreenView parameters:] to log a screen view event. To disable automatic screen reporting, set the flag FirebaseAutomaticScreenReportingEnabled to NO (boolean) in the Info.plist
2021-01-26 16:22:22.032550+0300 Demo [27616:342197] [LayoutConstraints] Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0x60000341ce60 'BIB_Trailing_CB_Leading' H:[_UIModernBarButton:0x7fb0e7d16480]-(6)-[_UIModernBarButton:0x7fb0e7d0a710'Skills'] (active)>",
"<NSLayoutConstraint:0x60000341ceb0 'CB_Trailing_Trailing' _UIModernBarButton:0x7fb0e7d0a710'Skills'.trailing <= _UIButtonBarButton:0x7fb0e7d10cb0.trailing (active)>",
"<NSLayoutConstraint:0x60000341dc20 'UINav_static_button_horiz_position' _UIModernBarButton:0x7fb0e7d16480.leading == UILayoutGuide:0x600002e54ee0'UIViewLayoutMarginsGuide'.leading (active)>",
"<NSLayoutConstraint:0x60000341dc70 'UINavItemContentGuide-leading' H:[_UIButtonBarButton:0x7fb0e7d10cb0]-(0)-[UILayoutGuide:0x600002e54e00'UINavigationBarItemContentLayoutGuide'] (active)>",
"<NSLayoutConstraint:0x60000347eda0 'UINavItemContentGuide-trailing' UILayoutGuide:0x600002e54e00'UINavigationBarItemContentLayoutGuide'.trailing == _UINavigationBarContentView:0x7fb0e7e0f7e0.trailing (active)>",
"<NSLayoutConstraint:0x60000341e3f0 'UIView-Encapsulated-Layout-Width' _UINavigationBarContentView:0x7fb0e7e0f7e0.width == 0 (active)>",
"<NSLayoutConstraint:0x60000347e9e0 'UIView-leftMargin-guide-constraint' H:|-(0)-[UILayoutGuide:0x600002e54ee0'UIViewLayoutMarginsGuide'](LTR) (active, names: '|':_UINavigationBarContentView:0x7fb0e7e0f7e0 )>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x60000341ce60 'BIB_Trailing_CB_Leading' H:[_UIModernBarButton:0x7fb0e7d16480]-(6)-[_UIModernBarButton:0x7fb0e7d0a710'Skills'] (active)>
Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.
The changed Debug Console outcome presented is because I've setup authorised access and it does work. I can create user and then perform login with crated login and password. All users do show up on the Firebase console.

Related

Firestore create collection in console or add doc not working

I'm trying to create a collection on firestore within the console, but it doesn't let me move forward. It's asking to add the first document, but the save button is still disabled even tho I added an ID with Auth-ID as you can see in the picture below
I've red a lot of conversations on the web, and they all say we need to set an ID but nothing seems to work for me.
On another hand, I've tried to add a new document straight from my ReactJS app following the documentation example, but same thing here, there are no errors but nothing happens.
import { collection, addDoc } from "firebase/firestore";
try {
const docRef = await addDoc(collection(db, "users"), {
first: "Ada",
last: "Lovelace",
born: 1815
});
console.log("Document written with ID: ", docRef.id);
} catch (e) {
console.error("Error adding document: ", e);
}
In the code above, docRef.id is undefined and nothing is added to the collection. The console prints the following:
Document written with ID: undefined
My rules are set to "production" as follow:
`rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if false;
}
}
}`
The documentation states that Cloud Firestore creates collections and documents implicitly the first time you add data to the document. So it should be there
thanks for the help

Submitting Data to Google Analytics from WPF

I am trying to send data to Google Analytics from a WPF application. I can't find any resource online which clearly defines how to do that. I know that there are numerous NuGet packages available, but I'm not sure which to use, nor how to implement them. I also know that there are some third-party "helper" libraries available (see Using Google Analytics from a .NET desktop application), which I'm not interested in. It also looks like most instructions online are showing how to "pull" data from GA, not how to push. Not looking for "maybe"'s or workarounds but what the normal straightforward way to do this is. This shouldn't be complicated. Just need a "Hello World".
Can you please point me in the right direction? Thanks,
This worked for me:
var request = (HttpWebRequest)WebRequest.Create("http://www.google-analytics.com/collect");
request.Method = "POST";
// the request body we want to send
var postData = new Dictionary<string, string>
{
{ "v", "1" }, //analytics protocol version
{ "tid", "UA-XXXXXXXX-X" }, //analytics tracking property id
{ "cid", "XXXX"}, //unique user identifier
{ "t", "event" }, //event type
{ "ec", category },
{ "ea", action },
};
var postDataString = postData
.Aggregate("", (data, next) => string.Format("{0}&{1}={2}", data, next.Key,
Uri.EscapeDataString(next.Value)))
.TrimEnd('&');
// set the Content-Length header to the correct value
request.ContentLength = Encoding.UTF8.GetByteCount(postDataString);
// write the request body to the request
using (var writer = new StreamWriter(request.GetRequestStream()))
{
writer.Write(postDataString);
}
var webResponse = (HttpWebResponse)request.GetResponse();
if (webResponse.StatusCode != HttpStatusCode.OK)
{
throw new Exception($"Google Analytics tracking did not return OK 200. Returned: {webResponse.StatusCode}");
}

Swift EKCalendar not persisting

I can create a new calendar and save it with the following function:
func createCalendarForUser() {
let sourcesInEventStore = self.eventStore.sources
//works but doesn't persist
let subscribedSourceIndex = sourcesInEventStore.index {$0.title == "Subscribed Calendars"}
if let subscribedSourceIndex = subscribedSourceIndex {
let userCalendar = EKCalendar(for: .event, eventStore: self.eventStore)
userCalendar.title = "newCalendar"
userCalendar.source = sourcesInEventStore[subscribedSourceIndex]
do {
try self.eventStore.saveCalendar(userCalendar, commit: true)
print("calendar creation successful")
} catch {
print("cal \(userCalendar.source.title) failed : \(error)")
}
}
}
This functions great while the app is open and running. I can save events to them, i can see them in my local calendar, and life is good. However, once the app is terminated and goes into the background the calendars disappear, along with any events created in them. I've tried saving the calendar to different sources other then the Subscribed Calendars source but when i do that the calendars wont even save in the first place. Heres one of the attempts at using the local source:
func createCalendarForUser() {
let sourcesInEventStore = self.eventStore.sources
//never saves calendar
let localSourceIndex = sourcesInEventStore.index {$0.sourceType == .local}
if let localSourceIndex = localSourceIndex {
let userCalendar = EKCalendar(for: .event, eventStore: self.eventStore)
userCalendar.title = "newCalendar"
userCalendar.source = sourcesInEventStore[localSourceIndex]
do {
try self.eventStore.saveCalendar(userCalendar, commit: true)
print("creating new calendar successful")
} catch {
print("creating new calendar failed : \(error)")
}
}
}
I also tried this method :
func createCalendarForUser() {
let sourcesInEventStore = self.eventStore.sources
//doesnt work
let userCalendar = EKCalendar(for: .event, eventStore: self.eventStore)
userCalendar.title = "newCalendar"
userCalendar.source = sourcesInEventStore.filter{
(source: EKSource) -> Bool in
source.sourceType.rawValue == EKSourceType.local.rawValue
}.first!
do {
try self.eventStore.saveCalendar(userCalendar, commit: true)
print("creating new calendar succesful")
} catch {
print("creating new calendar failed : \(error)")
}
}
As metioned here as mentioned here https://www.andrewcbancroft.com/2015/06/17/creating-calendars-with-event-kit-and-swift/
Has anyone else come across this problem?
The blog post you link do does two things when it saves the calendar, it uses the saveCalendar(, commit) method to save the calendar to the event store, and then also saves the identifier for the calendar to user defaults so that it can be retrieved at a later time:
NSUserDefaults.standardUserDefaults().setObject(newCalendar.calendarIdentifier, forKey: "EventTrackerPrimaryCalendar")
You're doing the first, but not the second step, so your calendars will be persisting in the store, but you're not keeping the information needed to retrieve them in the future.

Error 404 when calling Google Cloud Endpoint API from Google Apps Script

I am trying to call a Google Cloud Endpoint API (developed on App Engine) via Google Apps Script. The endpoint is up and running, honestly I don't know which URL I should use but through Google Chrome Web Tools it looks like the URL is something like:
https://myapp.appspot.com/_ah/api/myendpointapi/v1/myEndPointMethod/
Along with API parameters directly included in the URL, separeted by slashes:
https://myapp.appspot.com/_ah/api/myendpointapi/v1/myEndPointMethod/param1value/param2value/...
Now, in order to call that API from Google App Script I am using the following code snippet:
function myFunction() {
var params =
{
"param1" : "param1value",
"param2" : "param2value",
};
var result = UrlFetchApp.fetch('https://myapp.appspot.com/_ah/api/myendpointapi/v1/myEndPointMethod/', params);
DocumentApp.getUi().alert(result);
}
However I always get a 404 error. If I have to be honest I don't even know if UrlFetchApp is the correct way of calling the API. I noticed this thread on StackOverflow but no one answered. What's the correct URL to use? Many thanks.
EDIT: Now I am trying with an API method which does not require any parameter. I found a way to call a specific URL (using method='get' as suggested by the answer below) but now I get a 401 error because it says I am not logged in. I believe I need to use some kind of OAuth parameter now. Any idea? I tryed using OAuthConfig but no luck with that as well :( From App Engine logs I can see the following error:
com.google.api.server.spi.auth.GoogleIdTokenUtils verifyToken: verifyToken: null
com.google.api.server.spi.auth.AppEngineAuthUtils getIdTokenEmail:
getCurrentUser: idToken=null
function myFunction() {
var result = UrlFetchApp.fetch('myurl', googleOAuth_());
result = result.getContentText();
}
function googleOAuth_() {
var SCOPE = 'https://www.googleapis.com/auth/drive';
var NAME = 'myAPIName';
var oAuthConfig = UrlFetchApp.addOAuthService(NAME);
oAuthConfig.setRequestTokenUrl('https://www.google.com/accounts/OAuthGetRequestToken?scope='+SCOPE);
oAuthConfig.setAuthorizationUrl('https://www.google.com/accounts/OAuthAuthorizeToken');
oAuthConfig.setAccessTokenUrl('https://www.google.com/accounts/OAuthGetAccessToken');
oAuthConfig.setConsumerKey('anonymous');
oAuthConfig.setConsumerSecret('anonymous');
return {oAuthServiceName:NAME, oAuthUseToken:'always'};
}
UrlFetchApp is the only way to call a Google Cloud Endpoints API at the moment. The second parameter to UrlFetchApp.fetch is a special key-value map of advanced options. To pass POST parameters, you need to do the following:
UrlFetchApp.fetch(url, {
method: 'post',
payload: {
"param1" : "param1value",
"param2" : "param2value",
}
});
I was fighting a similar (not the same) problem, when testing feasibility of a GCM backed by EndPoints server. Basically testing if it is possible to get the Google Spreadsheet Appscript to send notification to an Android device. Please bear with me, the following explanation may be a bit convoluted;
Starting with a standard 'Cloud Messaging for Android', backed by the 'App Engine Backend with Google Cloud Messaging', I managed to build a test system that would send messages between Android devices (Github here).
Here is a VERY sparse EndPoints server code that handles register / un-register Android devices, as well as reporting registered devices and sending a message to a list of registered devices.
WARNING: This is not a production quality code, it is stripped of any logging, error handling in order to keep it short.
#Api( name = "gcmEP", version = "v1",
namespace = #ApiNamespace(ownerDomain = "epgcm.example.com", ownerName = "epgcm.example.com", packagePath = "" )
)
public class GcmEP {
#ApiMethod(name = "registToken")
public void registToken(#Named("token") String token) {
if (ofy().load().type(TokenRec.class).filter("token", token).first().now() == null) {
ofy().save().entity(new TokenRec(token)).now();
}
}
#ApiMethod(name = "unregToken")
public void unregToken(#Named("token") String token) {
TokenRec record = ofy().load().type(TokenRec.class).filter("token", token).first().now();
if (record != null) {
ofy().delete().entity(record).now();
}
}
#ApiMethod(name = "listTokens")
public CollectionResponse<TokenRec> listTokens() {
return CollectionResponse.<TokenRec>builder().setItems(ofy().load().type(TokenRec.class).list()).build();
}
#ApiMethod(name = "sendMsg")
public void sendMsg(#Named("message") String message) throws IOException {
if (message != null && message.length() > 0) {
Sender sender = new Sender(System.getProperty("gcm.api.key"));
Message msg = new Message.Builder().addData("message", message).build();
for (TokenRec record : ofy().load().type(TokenRec.class).list()) {
Result result = sender.send(msg, record.getToken(), 4);
if (result.getMessageId() != null) {
// handle CanonicalRegistrationId
} else {
// handle errors, delete record
}
}
}
}
}
Android code for registration and message sending is shown here, even if it is not relevant.
GcmEP mRegSvc;
String mToken;
// register device on EndPoints backend server
private void registerMe() {
new Thread(new RegisterMe(this)).start();
}
private class RegisterMe implements Runnable {
Activity mAct;
public RegisterMe(Activity act) { mAct = act; }
public void run() {
String senderId = null;
if (mAct != null) try {
if (mRegSvc == null) {
mRegSvc = new GcmEP
.Builder(AndroidHttp.newCompatibleTransport(), new AndroidJsonFactory(), null).setRootUrl(UT.ROOT_URL).build();
}
senderId = getString(R.string.gcm_defaultSenderId);
mToken = InstanceID.getInstance(mAct).getToken(senderId, GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
mRegSvc.registToken(mToken).execute();
GcmPubSub.getInstance(mAct).subscribe(mToken, "/topics/global", null); // subscribing to all 'topics' from 'mToken'
} catch (IOException e) { e.printStackTrace(); }
}
}
// send message to EndPoints backend server
new Thread(new Runnable() {
#Override
public void run() {
if (mRegSvc != null) try {
mRegSvc.sendMsg("hello").execute();
} catch (IOException e) { e.printStackTrace(); }
}
}).start();
// receive GCM message
public class GcmListenSvc extends GcmListenerService {
#Override
public void onMessageReceived(String senderId, Bundle data) {
Log.i("_X_", data.getString("message"));
}
}
What is relevant, thought, there is also an APIs Explorer created for the project, that can be used to send messages to your Android device from any browser.
If you use this Explorer, you can see the GET, POST requests for your EndPoints backend server, i.e.
list all registered devices:
GET https://epgcm.appspot.com/_ah/api/gcmEP/v1/tokenrec?fields=items
send a message to all registered devices:
POST https://epgcm.appspot.com/_ah/api/gcmEP/v1/sendMsg/Hello%20World!
Now, you can use this knowledge to send messages to your Android device from an AppScript code as shown:
Version 1: Get list of registered devices and send a GCM message to all of them (or a filtered set).
function sendMsg() {
var msg = 'test from CODE.GS';
var url = 'https://epgcm.appspot.com/_ah/api/gcmEP/v1/tokenrec?fields=items';
var params = { method : 'get'};
var response = UrlFetchApp.fetch(url, params);
var data = JSON.parse(response.getContentText());
var regIds = [];
for (i in data.items)
regIds.push(data.items[i].token);
var payload = JSON.stringify({
'registration_ids' : regIds,
'data' : { 'message' : msg }
});
var params = {
'contentType' : 'application/json',
'headers' : {'Authorization' : 'key=AIza............................'},
'method' : 'post',
'payload' : payload
};
url = 'https://android.googleapis.com/gcm/send';
UrlFetchApp.fetch(url, params);
}
This version relies on code from an old YouTube video, and I don't know if the call to 'android.googleapis.com' is still supported (but it works).
Version 2: Use the EndPoints's 'sendMsg' directly.
function sendMsg() {
var msg = 'test from CODE.GS';
var params = { method : 'post'};
var url = 'https://demoepgcm.appspot.com/_ah/api/gcmEP/v1/sendMsg/' + encodeURIComponent(msg.trim());
UrlFetchApp.fetch(url, params);
}
I have to admit I've never written a line of JavaScript code before, so it may not be up-to-par, but I made it work as a 'proof of concept'.
I would like to get feedback about this problem from people-who-know, since there is so little published info on this specific issue.

Error 404 when creating a calendar with Google Calendar Api v3 using c# .net

I am trying to create a calendar using Google Calendar API v3 if it does not already exist. My implementation successfully retrieves all my calendars and events and can change calendars, but I am struggling with adding a new calendar. This is what I do in order to try to add a new calendar for the user:
...
var calendarService = new CalendarService(_authenticator);
var calendarId = "com.somedomain.somename.1234"; // Some random ID
try {
calendarManager.GetCalendar(calendarId); // No calandar found
} catch(GoogleCalandarServiceProxyException e){
// Ok, so far so good, calendar not found (that is correct) and I am here
var someCalendar = new Google.Apis.Calendar.v3.Data.CalendarListEntry {
Summary = "Some summary!",
Description = "A calendar descr.",
AccessRole = "writer",
BackgroundColor = "#E7323C",
Id = calendarId
};
calendarService.CalendarList.Insert(someCalendar).Fetch(); // Fetch to execute
}
Request generated:
insert # https://www.googleapis.com/calendar/v3/users/me/calendarList?alt=json&prettyPrint=true
RequestError:
Google.Apis.Request.RequestErrorNotFound[404]Errors [Message[Not Found]Location[-] Reason[notFound] Domain[global]]]
Weird thing is that doing a GET at https://www.googleapis.com/calendar/v3/users/me/calendarList?alt=json&prettyPrint=true does not return something, so it should be there.
I hope that there is some awesome guy/girl out there which knows what to do! I'm completely stuck.
Update
Seems like I am receiving the same 404 error on CalendarList Google Api Explorer also:
Url:
https://developers.google.com/google-apps/calendar/v3/reference/calendarList/insert
Request:
POST https://www.googleapis.com/calendar/v3/users/me/calendarList?key={YOUR_API_KEY}
Content-Type: application/json
Authorization: Bearer ya29.AHES6ZQTj-D6uIMOWr_AoFYVvfefsEGcVvLvvMf4aKhgrdvQE25aVw
X-JavaScript-User-Agent: Google APIs Explorer
{
"id": "hastalavista"
}
Response:
404 Not Found
- Show headers - { "error": { "errors": [ {
"domain": "global",
"reason": "notFound",
"message": "Not Found" } ], "code": 404, "message": "Not Found" } }
Does anyone know whether Google have changed the URL for this resource? And if yes, how I change the Google Calendar Api v3 to use the updated url ...?
Okey, my bad:
You can't create a calendar with your own identifier, the purpose of CalendarListEntry.Insert() is to insert a created Calendar into the list of calendars
So to create a new calendar one has to:
Insert a new Calendar: https://developers.google.com/google-apps/calendar/v3/reference/calendars/insert
(DO NOT add id as paramater, this will be automatically created)
Insert the ID of the calendar created in step 1 and insert it into the calendarList: https://developers.google.com/google-apps/calendar/v3/reference/calendarList/insert
I'm still totally confused as to Google's distinction between a Calendar and a CalendarList since the data seems to overlap. Why is a calendar considered a "secondary" calendar.
The next code dit the trick for me, The mentioned reference is Java not .Net and, as usual ther e are some anoying differences...
private bool createCalendar()
{
// use Google.Apis.Calendar
Calendar calendar = new Calendar();
calendar.Summary = "MyNewCalendar";
calendar.Description = "Your new Calendar";
calendar.Location = "Aadorp";
calendar.TimeZone = "Europe/Amsterdam";
try
{
// Not inserting in CalendarList but in Calendar!
calendarService.Calendars.Insert(calendar).Execute();
}
catch (Exception exception)
{
MessageBox.Show(exception.Message);
return false;
}
return true;
}

Resources