How to call revit API from external thread? - exception

I'am in the revit's test project,
When i create transaction , since evenement 'ComponentManager_UIElementActivated' from button of ComponentManager.Ribbon,
i have exception 'Starting a transaction from an external application running outside of API context is not allowed'.
Have you a solution ?
void ComponentManager_UIElementActivated(
object sender,<br>
adWin.UIElementActivatedEventArgs e)
{
Transaction trans = new Transaction(uidoc.Document); //Work good.<br>
trans.Start("ReTraceWall"); //It don't work, because i have exception "Starting a transaction from an external application running outside of API context is not allowed."<br>
CommandRetraceWall.retracewall(uidoc); //function not called because there is exception before<br>
trans.Commit();<br>
}
*
Thank you for help .
Have you sample which solve this problem ?
Sample using ComponentManager.Ribbon

I don't know what Revit version you are using but there is a similar question to yours described in this post. You have basically 2 options:
polling for jobs inside the Idling event
using an ExternalEvent
I won't elaborate it again here.
By the way, before asking a questions make a quick search in the forums as yours may already have an answer :)
Jeremy Tammik is a Revit API guru, he has an entire blog that you may find useful as well.

Related

Chainlink Request Event Emit - Unsure whether events are being emitted, requests seem to be sucessful

I am trying to learn how to use the ChainlinkClient and I am using their example as well as one for the API that I am trying to uses.
You can see them here on this Gist.
The two contracts in the Gist are deployed on Rinkenby here:
APIConsumner.sol
APIConsumner2.sol
When I call the requestData() method on both contracts they seems to work, the transactions goes through and Link gets taken from the contracts, I am however unable to determine whether the actual data I am requesting from the external APIs gets returned, either by looking in the transaction event or trying to access the value that I am setting.
I am a bit bamboozled at this point, any guidance or suggestions would be greatly appreciated.
Thanks for the flag. The node that was hosting this is deprecated, the article has been updated, and the docs have the latest example.
Please use:
oracle = 0xc57B33452b4F7BB189bB5AfaE9cc4aBa1f7a4FD8;
jobId = "d5270d1c311941d0b08bead21fea7747";

Google Data Studio - When is resetAuth() being called?

I am having troubles with the resetAuth() function. I implemented it roughly like this example, but I have no idea when it is being called. Adding a console output and observing the Stackdriver Log tells me that this function is never being called during what I would call a normal workflow.
The documentation is weirdly brief and is missing this part about why I need to implement it and when it is being called. Do I need to call resetAuth() manually on some point? Is there a button somewhere that calls this function?
I'm using the AuthType USER_PASS by the way and everything else seems to work just fine after some investigation and debugging.
I found this document called Community Connectors Developer Launch where, among other things, the following it listed (as of 2018-07-30):
What's next: Upcoming changes and improvements
Some of the features and improvements we'll be working on in the
coming months include:
Configuration and Authentication
Capability to execute the resetAuth function of community connectors from within Data Studio.
Does this mean that calling resetAuth() is currently not yet implemented?
resetAuth is called when the user revokes access to the connector via the https://datastudio.google.com/datasources/create endpoint.
There was a bug that caused this function to not be called for certain auth types, but it has been resolved.

hyperledger composer & access security

I am currently building a network with a lot of different company with each one running a node.
The model is basically one big asset. A company might access couple of property and be restricted from other.
I saw that asset property permission is not possible.
The only solution I can see would be to create sub asset of that main asset and apply different permission and deny the possibility to host a node ?
Thanks a lot for your ideas & suggestions.
Jonathan.
Yes your solution work perfectly in case of a participant that does not host a node. However if the participant host a node It is now possible with a new feature implemented in Fabric 1.2: http://hyperledger-fabric.readthedocs.io/en/latest/private-data/private-data.html
Hyperledger Composer:
I suggest you to split your asset in smaller ones and implement the right access control for each one.
However you can implement specific logics in the transaction processor based on the identity / participant which is invoking the chaincode.
For example:
// Get the current participant.
var currentParticipant = getCurrentParticipant();
if (currentParticipant.getFullyQualifiedType() == 'org.example.ParticipantOfCompanyA') {
//do something
} else if (currentParticipant.getFullyQualifiedType() == 'org.example.ParticipantOfCompanyB') {
//do something else
}
Here the link to the official documentation:
https://hyperledger.github.io/composer/unstable/api/runtime-api#getcurrentparticipant
Hyperledger Fabric:
From Fabric v1.2 is possible to create private data between organizations on the same channel.
Here the link to the official documentation:
http://hyperledger-fabric.readthedocs.io/en/latest/private-data/private-data.html

Autodesk Forge register job conflict

When POSTing to https://developer.api.autodesk.com/viewingservice/v1/register I sometiems receive the following error:
{
Diagnostic: The request is rejected as it conflicts with a previous request that is in-progress.,
registerKeys: {},
Result: Conflict
}
How can I find out which job is already in progress so that I can track its progress and get its result?
First, this is the old API, you need to consider using the ModelDerivtive API instead (ie https://developer.autodesk.com/en/docs/model-derivative/v2)
Like Xiaodond said there is no API to collect all jobs currently processing on your account. You need to request each URN manifest to determine how many jobs runs on this model as know you can translate to SVF, but also export to other formats such as obj, stl, ... when it is possible. Manifest end point and documentation here - https://developer.autodesk.com/en/docs/model-derivative/v2/reference/http/urn-manifest-GET/
Last, we are working on a webhook solution which will be a better solution as a Webhook will call you back when a job is starting and completes. Webhooks aren't yet available at the time of this post, but you should be notified via the developer newsletter when it will be on production.
Hope that helps,

App Widget getting hijacked by Google Sound Search?

So I'm seeing some bizarre behavior in an appwidget that I wrote.
The widget itself is quite simple - it reads a few values from persistent storage and then displays them as text. Nothing fancy in the layout - just a FrameLayout root element with some Linear Layout and TextView children.
The widget has a simple configuration activity associated with it.
The bizarre behavior is that the widget will initially show "Problem Loading Widget" after the user closes the configuration activity, and then after a few seconds it shows a "Google Sound Search" button (and clicking on the button actually does launch Google Sound Search). Then, after a few more seconds, it finally shows the expected display.
I am away from my code right now, so I'll have to wait until tonight to post code snippets. However, in the meantime, can anyone provide some insight into how such a thing could happen? Has anyone else ever experienced this? How could another widget "hijack" mine?
Thanks,
-Ron
Here are some screenshots:
There are a couple of issues with your widget and there are answers to all of them (although you didn't post any code so some of my statements are based on assumptions):
"Problem loading widget": this is the default view Android uses before the widget is initialized and the layout updated. Simply add the following line to your widget xml configuration (to show a loading message instead of the problem message):
android:initialLayout="#layout/my_cool_widget_loading_message"
If the widget shows the wrong layout then you probably have an issue in the widget's onReceive method. onReceive is called for all the widgets no matter whether the broadcast is for that specific widget. Android's AppWidgetProvider filters the broadcasts by appwidget Id and dispatches to the other methods (like onUpdate).
See also: https://developer.android.com/reference/android/appwidget/AppWidgetProvider.html#onReceive(android.content.Context, android.content.Intent).
If you override onReceive (which I assume you do), you need to call through to super.onReceive(Context, Intent) to make sure your other methods don't get calls meant for other widgets.
Now for the configuration of the widget. If you follow the Google documentation then it will all work nicely. The only improvement I'd do is what my other answer that you reference suggests (https://stackoverflow.com/a/14991479/534471). This will NOT send out two broadcasts. The setResult()/finish() part does only terminate the config Activity and let Android know whether to actually add the widget or not (depending on whether the result is RESULT_CANCELED or RESULT_OK.
From your own answer I can see why your code wouldn't work. The code is:
Intent intent = new Intent();
intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[] {mAppWidgetId});
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
setResult(RESULT_OK, intent);
sendBroadcast(intent);
finish();
First of all there's no need to add the appWidgetId twice, use the AppWidgetManager.EXTRA_APPWIDGET_IDS version and you're good. Second you're using the same Intent to return as a result for the Activity. AFAIK it's not documented what happens when you do set an action on that Intent but my experience with Android widgets is that you need to stick exactly to the documentation or you'll end up having strange issues (like the ones you encounter). So please use two different Intents.
Activity result:
Intent resultValue = new Intent();
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
setResult(RESULT_OK, resultValue);
finish();
Broadcast:
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE, null, this, MyWidget.class);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[] {mAppWidgetId});
sendBroadcast(intent);
ok, so I figured it out. Posting here in case anyone else runs into this. I think that the Android Developer docs are a little misleading here.
The problem was that in my configuration Activity, I had this code at the end:
Intent intent = new Intent();
intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[] {mAppWidgetId});
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
setResult(RESULT_OK, intent);
sendBroadcast(intent);
finish();
Providing an intent with the extra EXTRA_APPWIDGET_ID is recommended by the documentation provided by google.
However, that same document says that you have to update the widget's view by creating a RemoteView and calling AppWidgetManager.updateAppWidget() like so:
RemoteViews views = new RemoteViews(context.getPackageName(),
R.layout.example_appwidget);
appWidgetManager.updateAppWidget(mAppWidgetId, views);
I didn't like the idea of placing the presentation logic in both the configuration activity and the widget class, so I instead decided to broadcast an intent at the end of the configuration activity to tell the widget to redraw itself. That's why I have setResult() AND sendBroadcast() at the end of the activity. The documentation further states that the onUpdate() callback will not be called when using a configuration activity. So this seemed neccessary. I added the ACTION_APPWIDGET_UPDATE and the EXTRA_APPWIDGET_IDS to the intent so that it would trigger the onUpdate() method. This practice was recommended by this SO answer (albeit without being included in the activity result intent - but I tried separating the two and it had no effect).
Now I'm not certain exactly how the "Google Sound Search" widget got in there, nor do I fully understand the mechanics of how the intents interacted to produce the observed results. However, as soon as I replaced my code above with the code stated in the docs, the widget was updated properly.
Intent resultIntent = new Intent();
resultIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
setResult(RESULT_OK, resultIntent);
finish();
This seems to contradict the documentation's statement that the configuration activity must update the widget's view. Simply providing the configuration activity result as below triggers the onUpdate() method in the widget, thus allowing the widget to redraw itself. I confirmed the behavior on an emulator running API 23 and also on a Samsung device running Samsung's android flavor.