tag:blogger.com,1999:blog-85972683303376879632024-02-06T18:26:17.831-08:00Brendan's CompendiumMy blog follows a problem/solution format to help you get your code working ASAP. In-depth explanations are also included for those that wish to read them.Unknownnoreply@blogger.comBlogger9125tag:blogger.com,1999:blog-8597268330337687963.post-89113548339441436942019-05-30T20:04:00.000-07:002019-06-01T23:45:24.189-07:00Effective Documentation for Teams<h2>
Introduction</h2>
Documentation is hugely important. They say that a company’s most valuable asset is the knowledge inside its employees’ heads, so why not get that info out of their heads and into a place that everyone can access?<br />
<br />
I’ve been documenting things for myself and my team for over five years. I document systems, bugs, processes, troubleshooting, outages, and much more. It has saved me many, many, more hours than it has cost me. Just like any other part of your professional life, you want to do it to the best of your ability. It will make your life easier, help your team succeed, and show that you’re a star performer.<br />
<br />
This article is written with the software engineering field in mind, but the information is applicable to any industry.<br />
<br />
<h2>
The Problem</h2>
Documentation is commonly skipped or half-assed. I often hear the excuse, “I don’t have enough time to write documentation!”. The reality is that over the long term, your documentation will save you time. Overall, your job will be much better if you have documentation.<br />
<br />
There are questions that people often have that prevents them from starting their documentation journey, including:<br />
Where will I put the documentation? How can I make time to write documentation? What should I document? Can I put it in too many places? How can I make sure people understand my writing? What does documentation even mean? How do I know anyone will ever see what I write? What counts as “documentation”? Will I lose job security? How do I organize it? How can I encourage my team to contribute to documentation?<br />
<br />
<br />
<h2>
Where do I put my documentation?</h2>
Put it somewhere that is easy to access and easy to search. SharePoint is ok. A shared OneNote is better. <a href="https://www.atlassian.com/software/confluence">Confluence </a>is best, in my opinion. My teams use Jira. With Jira you also get Confluence. Most of our engineers are always logged into Jira and thus always logged into Confluence, reducing the hurdle of having to log into yet another system. This increases the amount of documentation your team produces and consumes.<br />
<br />
Make a space in Confluence or a shared OneNote and start throwing things in there. Worry about organization later. Do not let perfect be the enemy of done. Keep your documentation limited to one place if you can. Don’t have a Confluence and a Sharepoint and a OneNote and a private Stack Overflow.<br />
<br />
I also keep a personal OneNote and document a lot of things for myself. If I feel that those things would be useful to other people, I share them in Confluence.<br />
<br />
<h2>
How can I make time to write documentation?</h2>
Documentation is an effort multiplier. You may spend an hour to write documentation, and it will save you many hours over time. I cannot count the number of times that someone has asked me a question about some obscure process, and instead of meeting with them for 30 minutes I can just send them a link to a page on Confluence. This is especially helpful because it’s hard for me to get time to have a spontaneous 30 minute technical conversation without interruption, but if 80% of the knowledge they need is just one click away, I can send that link and carry on to my other tasks. Plus, they can easily share it with others.<br />
<br />
You don’t really want to type out the same “gotchas” for connecting to that third-party API over and over, do you? It’s better to just send a link with all that info. There are so many times when it has taken me hours to figure something out that could have been solved in five minutes if there was documentation for it. Those are the things you should write down.<br />
<br />
<h2>
What do I document?</h2>
Any time you’ve wondered how a process works, you could document that. If you have had questions about it, there is a very high chance that others have questions about it too. And even if they don’t, you will forget this process eventually and probably have to revisit it and relearn everything.<br />
<br />
Or, the first time you encounter an issue you could think to yourself, “This was pretty confusing, but if I knew at the start what I know now, I would have been able to solve this issue quickly.” Then you can write that information down. There are so many times where this happens, and yet people just think “yay I solved the issue :)” and move on to the next issue. If you don’t want to keep solving the same issue over and over, you should document as much as you can.<br />
<br />
You can document a specific process with a third party API. You can document columns in the database and what depends on them. You can document your git strategy, your scrum strategy, or your process for pushing code to production. Document all the web pages that new developers should bookmark. Document how to get some code to build after pulling down a repository for the first time. Document your scrum retrospective.<br />
<br />
You can, and should, also document events such as outages. Document what broke, when it started breaking, when it was resolved, and what fixed it. You should also document the root cause, and try to get as close to the real root cause as possible.<br />
<br />
There is no such thing as over documenting. Documentation will help out your team, and it will help out other teams such as your customer support team and product team, and it will help you out as well. The life you save may be your own.<br />
<br />
<h2>
How can I make sure people understand my writing?</h2>
The people who are the best candidates to write documentation are the people who like to write. However, I do not want to discourage anyone from writing documentation. If you have something you think is worth documenting but you aren’t confidence in your writing, just write down what you can. It doesn’t have to be poetry, you can just write bullet points.<br />
<br />
Even if you are documenting in a language that is not your first language, people will understand what you mean. They may fix grammar errors themselves, or you can also ask coworkers to review it. Some documentation is better than no documentation! Write away, right away!<br />
<br />
What if I write it and no one ever looks for it?<br />
Documentation can be a vicious cycle: People don’t write documentation because no one thinks to look for it, and no one thinks to look for it because no one writes it. You have to break the cycle by writing documentation. I suppose you could break it by looking for it and then complaining loudly to your team when you come up empty, and hope someone else writes it, but I haven’t tried that method yet.<br />
<br />
If you write it, they will come. If you think something is worth documenting, there is a very good chance that other people will find it worth reading. That person may very well be the future you. If you got confused about something one time, there is a good chance you’ll have questions about it again.<br />
<br />
Even in the worst case scenario, where you document something and no one ever searches for it, it is still worth it to document. Why? Because the process of writing something down will make you remember it. It will also make you realize where you have gaps in your knowledge, and then research to fill those gaps.<br />
<br />
<h2>
What does documentation even mean?</h2>
Documentation is anything that you or someone else may need to know. We often forget how much we know. There is a ton of information inside of us that would be lost forever if we left the company or got hit by a bus. These things are documented in our heads, but they could be documented somewhere that is stored in a safe place, accessible by other people.<br />
<br />
Documentation can be at the team level or the personal level. I write notes in my OneNote every day. I break it out into notes for each day and also areas where I write notes for various systems, teams, or tasks. Each day if I want to know what I worked on, I just flip to the notes of that day. If I ever leave my job or get let go, I can just share my OneNote with my team and now they have a (slightly chaotic) searchable record of everything I worked on during my employment including the “gotchas” I ran into and how I fixed them.<br />
<br />
<h2>
Will I lose job security?</h2>
No, but you will gain the ability to be promoted. No one is a golden cow. No one knows information that is absolutely impossible to be learned by someone else. Companies fire people even when they are afraid to lose them, so don’t think that hoarding information will save your butt. Documenting something is not going to be the thing that tips the scales against you. Be a team player!<br />
<br />
Think about it like this: Who is a more valuable person to the company?<br />
<br />
<ul>
<li><b>Employee A</b>: Knows a lot and keeps it to themselves. Anytime there’s an issue with something they are an expert on, you have to set up a meeting with them to get the information out of their head. You have to keep going back to them with more questions. It’s a slow process.</li>
<li><b>Employee B:</b> Knows a lot and puts it in a place where other employees can access it. When you need to know something about their system, they say: “I’m in a meeting right now but here is a link to how this process works. Let me know what questions you have and we can catch up later!”. Eventually the entire team learns that searching the documentation is easy and likely to solve their issues in a short amount of time.</li>
</ul>
<br />
<br />
<h2>
How do I organize it?</h2>
I recommend Confluence for most documentation. It is easy to add pages, easy to edit, easy to search, and easy to share with others. They have useful templates including for how-to articles, sprint retrospectives, and dozens of other things. You can break things into sections however you want; we prefer to do it per team and per product. You should also make use of the labels such as “kb-how-to-article” and “kb-troubleshooting-article” to help you find articles super fast.<br />
<br />
The most important thing is to get the information down somewhere. Once that’s done, worry about organizing it. Don’t let organization get in the way of documentation.<br />
<br />
<br />
<h2>
How can I encourage my team to contribute to documentation?</h2>
Documentation is a vicious cycle. The best way to break the cycle is to just start documenting. Eventually you will be linking people to documentation you wrote, instead of typing out how different processes work over and over and over.<br />
<br />
Usually the hardest part is starting a new document. Once the document exists, it’s easy for people to contribute pieces of information to it.<br />
<br />
Here are some ideas for encouraging it:<br />
<br />
<ul>
<li>If you do scrum, bring up in sprint retrospectives that the documentation could be improved.</li>
<li>Mention it in stand-up meetings and other team meetings. E.g. “yesterday I documented the process for how to make accounts for dogs…”</li>
<li>Add requirements to tasks that requires the employee to add information about that process to Confluence.</li>
<li>Create an OKR about creating documentation.</li>
<li>Give candy and snacks to those who document. Good ol’ classical conditioning!</li>
</ul>
<br />
<br />
<br />
<h2>
Conclusion</h2>
Creating documentation is rewarding and a great use of time. So many employees complain about a lack of documentation, yet never think to create it. Documentation is a<a href="https://en.wikipedia.org/wiki/Habit#Formation"> keystone habit</a> that is very powerful once the habit is established. It causes developers and other employees to come to a deep understand of their systems. It decreases the time required to troubleshoot bugs. It makes people think about their processes in-depth and develop process that are clear. It prevents knowledge loss from your subject matter experts. It saves you time.<br />
<br />
Start writing documentation today! Even if it’s not perfect, just get your thoughts written down and add to it little by little. Soon, you and your team members will have an impressive garden of knowledge.<br />
<div>
<br /></div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8597268330337687963.post-21021179097816157682016-09-24T18:16:00.002-07:002016-09-26T10:39:27.007-07:00Remote Debugging: "The breakpoint will not currently be hit. No symbols have been loaded for this document."<h2>
Problem:</h2>
<br />
When you are remotely debugging your breakpoints show a message that, "The breakpoint will not currently be hit. No symbols have been loaded for this document."<br />
<br />
This post is written for a .NET project where you are debugging on one computer (the local machine) and the code is running in IIS on another server (DevServer in this example).<br />
<br />
<h2>
Solution:</h2>
<h4>
Solution 1 - Ensure that PDB files are being generated for your build</h4>
<div>
On the remote server, navigate in file explorer to the bin folder for your project. This is usually located on the C: drive in inetpub\wwwroot\TheProject\bin. Ensure that there are .PDB files in this folder. If there are not, go back to Visual Studio and change your project's property's so that generated debug symbols are included.<br />
<br />
To do this in Visual Studio 2015: Right click on your project and select Properties. Click "Package/Publish Web". Ensure "Exclude Generated debug symbols" is unchecked. You will most likely want to do this for the Debug and Release Configurations.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDn4ofxx5ZZ80_02drbaCuz3MsszDaeqRIhdGi_nsTnUd_tiNhvoW_LiqNbvQ2xE4NdBf8ei6kcDDmQqfMvRT3Q0v796qmBubq828872CUROyjkfVgmv3MftAeRE8WYNtYmWk_387A2wQ/s1600/projectSettings.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="113" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDn4ofxx5ZZ80_02drbaCuz3MsszDaeqRIhdGi_nsTnUd_tiNhvoW_LiqNbvQ2xE4NdBf8ei6kcDDmQqfMvRT3Q0v796qmBubq828872CUROyjkfVgmv3MftAeRE8WYNtYmWk_387A2wQ/s400/projectSettings.png" width="400" /></a></div>
<div>
<br /></div>
<div>
If you have done Option 1 and are still getting this error, go to Option 2.<br />
<br /></div>
<h4>
Solution 2 - Ensure that you have the same version of code locally and on the remote server.</h4>
Before attaching to a process, look at the size of the DLL and PDB files if they are different sizes you may have slightly different versions. This can happen if the code was built using two different methods. For example if the code locally was built using Visual Studio but the code on the remote server was built with release management.<br />
<br />
Go
to Tools > Options > debugging > Symbols. Add a new Symbol file
location for your build server.<br />
Make it point to the bin folder of the project you want to debug. If you have multiple projects you want to debug, add each of their bin folders. It should look something like the screen shot below.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyfZoRAKc2ik2WBMP2SU76pGVI0NZ1Hn7cl1pVIY2ZB98hlcIPamknNlg7kozObx83A8fV9dV9T5ZIgU6946Eytk270FGVP1ieuLMDgtnY5f71KWJ2P2ffs4GMWkNRmkVlPTD7TDNPL2E/s1600/DebugSymbolFileLocation.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="132" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyfZoRAKc2ik2WBMP2SU76pGVI0NZ1Hn7cl1pVIY2ZB98hlcIPamknNlg7kozObx83A8fV9dV9T5ZIgU6946Eytk270FGVP1ieuLMDgtnY5f71KWJ2P2ffs4GMWkNRmkVlPTD7TDNPL2E/s400/DebugSymbolFileLocation.png" width="400" /></a></div>
<br />
Now attach your debugger to the remote server and confirm that symbols have loaded for your project.<br />
<br />
<h4>
Solution 3 - Ensure you've attached to the right process</h4>
<div>
Using your browser, navigate to the website hosted on the remote server. This ensures that the process will be running in IIS. In Visual Studio, in the "Attach to Process..." window, find the w3wp.exe process. If there are multiple, try connecting to all of them, but you should be able to tell which one is the website you want. If your symbols are loaded correctly after trying this, you had the correct DLL and PDB files locally and on the remote server, the problem was that Visual Studio was connecting to the wrong process.<br />
<br />
It should look similar to the below screen shot.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEix0ID1YtGbAVWRIqdGdzAT8OUQz1Qtq_vNkmqp_tPT0khrl_QlCqI4f6IfY5O5s3k2AcbXYcsKelx3mRHSmHolC63pi_hYukfbhqoWa4OCxcmmDqqK0Do4UUgvl43DCAf_PmINDpZfyzk/s1600/attachToProcess.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="185" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEix0ID1YtGbAVWRIqdGdzAT8OUQz1Qtq_vNkmqp_tPT0khrl_QlCqI4f6IfY5O5s3k2AcbXYcsKelx3mRHSmHolC63pi_hYukfbhqoWa4OCxcmmDqqK0Do4UUgvl43DCAf_PmINDpZfyzk/s400/attachToProcess.png" width="400" /></a></div>
<br /></div>
<h4>
Solution 4 - Ensure local and Release Management / MSBuilds are generating identical files.</h4>
The other solution would be to modify your release management build to make your local build and release management build have the exact same settings so they generate identical DLL and PDB files. This will not be covered in this post because it is outside the scope of this post. However, see the "Other things to try" section below for instructions on manually copying DLL and PDB files from your local machine to the remote server, which would ensure the local and remote versions are the same. However, that is not a proper solution and should only be used for troubleshooting.<br />
<br />
<h2>
Explanation:</h2>
The DLLs and PDBs that are generated from a local build need to match the files on the remote server where the code is running. If they do not, or if the symbol files cannot be located by Visual Studio, this error will show up on your breakpoints.<br />
<br />
Sometimes you'll build your project in Visual Studio and build that same project with release management or MSBuild, but the DLL and PDB files are different. This can be due to a difference in the build configurations for Visual Studio and release management.<br />
<h2>
Other things to try:</h2>
<h4>
Manually copy DLL and PDB files from local machine to remote server.</h4>
Build the project on your local machine, make sure symbol files (.pdb) are included. To get these symbol files try building in Debug mode. If you still don't have symbol files, right click your project file, and under Package/Publish Web uncheck "Exclude generated debug symbols".<br />
Now find you're project's bin folder in explorer. You should have a fresh set of DLL and PDB files in this folder. The "Date Modified" for any DLL and its matching PDB file should be about the same.<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzTkkGhe04SskbrTp2p_M9ML5EujJpMSxGyYUuwSziSfyGkfqsLPxV7j8rduh8HJKJzEMAc3LG_LizH9O9ZOSaxz6soWCMmBQBhIWVkpUegc4ezhKNNGYhx1nVf43Ue6KbIBs0z_H79EA/s1600/dllandpdbfiles.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzTkkGhe04SskbrTp2p_M9ML5EujJpMSxGyYUuwSziSfyGkfqsLPxV7j8rduh8HJKJzEMAc3LG_LizH9O9ZOSaxz6soWCMmBQBhIWVkpUegc4ezhKNNGYhx1nVf43Ue6KbIBs0z_H79EA/s1600/dllandpdbfiles.png" /></a></div>
<br />
Now find the bin folder for this project on the remote server. It should be the same as what you added to the symbol file locations, so in our example it's \\DevServer\c$\inetpub\wwwroot\TheProject\bin.<br />
Create a backup of this folder just for safe keeping.<br />
<br />
Now overwrite the bin folder on the server by copying the bin folder from your local computer to the remote server. The purpose of this is to ensure you have the exact same files locally and on the remote server. This is not a good permanent solution, but if your breakpoints get hit now it proves that your remote debugging is configured mostly correctly and that the problem is a difference with the DLL and PDB files between your local machine and the remote server.<br />
<br />
<h4>
Symbol Status</h4>
While debugging, in Visual Studio go to Debug > Windows > Modules. This window can provide you with lots of information for troubleshooting. Look for the DLL of your project (TheProject.dll in our examples). If the Symbol Status shows "Symbols loaded." then things are working correctly.<br />
<br />
You can right click on an entry here and click "Load Symbols" to point to a symbol file to use. If Visual Studio likes the symbol files you selected, the symbols will load and the error will go away.<br />
<br />
<h4>
Further Reading</h4>
<div>
https://blogs.msdn.microsoft.com/visualstudioalm/2015/01/05/understanding-symbol-files-and-visual-studios-symbol-settings/</div>
Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-8597268330337687963.post-60568367182801072212016-08-22T09:54:00.000-07:002016-08-22T10:06:08.111-07:00IIS 7.0 Web Site STIG V-2267 - Request Filtering<h2>
Problem</h2>
<div>
After enabling Request Filtering in IIS for your .NET website, some areas of the application no longer work as expected. This is often done to put your website in compliance with STIG Rule ID SV-32335r3_rule also known as IIS 7.0 Web Site <a href="https://www.stigviewer.com/stig/iis_7.0_web_site/2014-12-05/finding/V-2267">STIG V-2267</a>.<br />
<br /></div>
<h2>
Solution</h2>
<div>
Add .NET file extensions to the Request Filtering list. These extensions are found here: <a href="https://msdn.microsoft.com/en-us/library/2wawkw1c.aspx">ASP.NET Web Project File Types</a>.</div>
<div>
<br /></div>
<div>
Begin by adding the extensions under "File Types Managed by ASP.NET", then test the areas of your website that had previously not been functional. If these areas still do not work, try adding the file extensions under "Static File Types" and then "File Types Managed by IIS". Make sure to not add any extensions that are not allowed by the STIG.<br />
<br />
It may be regarded as bad practice to add file types to the whitelist that you do not need, so try to only add what you need.</div>
<div>
<br /></div>
<div>
If you have third-party tools that are breaking, those extensions will have to be investigated and added to the whitelist, if appropriate and allowed. Fiddler with help with this, as I explain below in "Other Things to Try."</div>
<div>
<br /></div>
<h2>
Explanation</h2>
<div>
You may think that to find all the file extensions needed for the whitelist, you should explore the files and folders of your website and add all file extensions you find to Request Filtering in IIS. This does not work because there are files that are generated by your app at runtime that have extensions that aren't found in the website's folders. For example, .axd files are a commonly forgotten file extension that will break some areas of your site if they are not included in the request filtering whitelist.</div>
<div>
<br /></div>
<div>
You also need to keep in mind that if you simply allow all file extensions from <a href="https://msdn.microsoft.com/en-us/library/2wawkw1c.aspx">ASP.NET Web Project File Types</a>, you may be in violation of the STIG. Remember, the point of STIG V-2267 is to limit script execution.</div>
<br />
<h2>
Other Things to Try</h2>
<div>
Use Fiddler. With Fiddler running, navigate to a page in your application that isn't working and look for 404 errors. These indicate requests for resources that were not found. One reason these files can't be found may be that IIS's request filtering is denying access to them. Look at any 404 errors you are getting and try adding those file types to the whitelist in IIS. For example here is what we would see if .axd files were being denied.<br />
<br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPdYt4GFrc2GC-31HvbSGqSbd63GkilzfGSUzSL97mQIrAvxx2aJ2AVssjK6ahRpDDmNRuxC0oj64rIYzLNDdf92qQJ0npElgewhDOhwvJFmeK4toysbiClGmQIBum6Pw35w8szGFf2FY/s1600/axd+404.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="85" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPdYt4GFrc2GC-31HvbSGqSbd63GkilzfGSUzSL97mQIrAvxx2aJ2AVssjK6ahRpDDmNRuxC0oj64rIYzLNDdf92qQJ0npElgewhDOhwvJFmeK4toysbiClGmQIBum6Pw35w8szGFf2FY/s400/axd+404.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Fiddler results when .axd files are not in the whitelist. Click to Enlarge</td></tr>
</tbody></table>
<div>
<br /></div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8597268330337687963.post-7026580348107228072016-08-10T12:34:00.000-07:002016-08-24T09:15:16.703-07:00Unable to start debugging on the web server. Unable to connect to the web server. Verify that the web server is running and that incoming HTTP requests are not blocked by a firewall.<h2>
Problem</h2>
<div>
When trying to debug your solution or project, hosted on IIS Express, the following error occurs:</div>
<div>
<blockquote class="tr_bq">
Unable to start debugging on the web server. Unable to connect to the<br />
web server. Verify that the web server is running and that incoming<br />
HTTP requests are not blocked by a firewall.</blockquote>
</div>
<h2>
Solution</h2>
<div>
Change the project's Web settings to "IIS Express" instead of "External Host". This is under "Web" under the "Servers" section. Visual Studio should automatically fill in the Project Url.<br />
<br />
Click the picture to enlarge.<br />
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjP_w4SrJePDq-DKHGaijc5wKM0tgxHNfsdW4der3yNu2Y44UhuKsmr8N4li4jw6q-6GR0XJ8HBxWX3Deqo84mcNsS5CADxrt7gs_abkF5_iQqpx3xpS0VQF_Qwc_9YDJJ2vXcWyLIThVc/s1600/6-1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="230" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjP_w4SrJePDq-DKHGaijc5wKM0tgxHNfsdW4der3yNu2Y44UhuKsmr8N4li4jw6q-6GR0XJ8HBxWX3Deqo84mcNsS5CADxrt7gs_abkF5_iQqpx3xpS0VQF_Qwc_9YDJJ2vXcWyLIThVc/s400/6-1.png" width="400" /></a></div>
<br />
<br />
<br />
<h2>
Explanation</h2>
When a project's Web settings are set to an external server, Visual Studio will try to connect to that server to debug the project. This would be used if you were running IIS (not IIS Express) on your local machine and wanted Visual Studio to debug the app running on IIS.<br />
<br />
<h2>
Other things to try</h2>
<ul>
<li>Restart Visual Studio, which also restarts IIS Express</li>
<li>Run Visual Studio as Administrator.</li>
</ul>
<br />
<!--
Include background info on debug vs release mode<br />
Include other things to try
info on "enable optimizations" for VS2015 withVB: https://msdn.microsoft.com/en-us/library/07bysfz2.aspx
-->Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8597268330337687963.post-82631797989034895642016-01-22T08:22:00.000-08:002016-10-04T20:46:07.050-07:00"Cannot obtain value of the local variable or argument because it is not available at this instruction pointer, possibly because it has been optimized away."<h2>
Problem</h2>
<div>
While debugging in Visual Studio 2015, many variables are not available. When you try to see a variable's value, Visual Studio tells you, "Cannot obtain value of the local variable or argument because it is not available at this instruction pointer, possibly because it has been optimized away."</div>
<div>
<br /></div>
<h2>
Solution</h2>
<div>
Change the "Solution Configurations" drop down to "Debug".<br />
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisZmvqUS83uybJ4y5BLndMNVbsXy7_3hJ6MmUSSEw6EGBmCe8y0I0dWnPf6hmAYxkfDkt-OOngjjyTKZVfzMU1VUJFm_bgPYH3uPfYuz_xm_l7nHZDA-Nwm8R1Q5YVTmFmUQdFTSQNEXo/s1600/debug.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisZmvqUS83uybJ4y5BLndMNVbsXy7_3hJ6MmUSSEw6EGBmCe8y0I0dWnPf6hmAYxkfDkt-OOngjjyTKZVfzMU1VUJFm_bgPYH3uPfYuz_xm_l7nHZDA-Nwm8R1Q5YVTmFmUQdFTSQNEXo/s1600/debug.png" /></a></div>
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<h2>
Explanation</h2>
According to Microsoft: "In Release, some locals will be optimized away and will not be available during debugging."<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_7bk0tXvsbu3cHG5gFYGgO0fTh-x1gktVfOZEZBTs624d3dSGJJSBXi6i0HC8uyZfzSDwbZd1JFfhIJgtL_HPFaZGREjv0IxPLTD6IB42GArj6ZKrmbM9L5wx2CLV-AHv4fBek-pJm6Q/s1600/debugger.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="16" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_7bk0tXvsbu3cHG5gFYGgO0fTh-x1gktVfOZEZBTs624d3dSGJJSBXi6i0HC8uyZfzSDwbZd1JFfhIJgtL_HPFaZGREjv0IxPLTD6IB42GArj6ZKrmbM9L5wx2CLV-AHv4fBek-pJm6Q/s400/debugger.png" width="400" /></a></div>
<br />
<br />
<br />
This is done for performance reasons. You can read Microsoft's <a href="https://blogs.msdn.microsoft.com/visualstudioalm/2015/08/14/debugging-optimized-code/">excellent post on the issue here.</a><br />
<br />
<h2>
Other things to try</h2>
<ul>
<li>Uncheck Project Properties > Build > Optimize Code. (For Visual Studio versions prior to 2015)</li>
<li>"In Visual Studio 2015 this option is off by default but if you must debug an application compiled Release, you can turn it back on under Debug -> Options and check “Suppress JIT optimizations on module load (Managed only)”." - <a href="https://blogs.msdn.microsoft.com/visualstudioalm/2015/08/14/debugging-optimized-code/">MSDN Blog</a></li>
</ul>
<ul>
</ul>
<br />
<!--
Include background info on debug vs release mode<br />
Include other things to try
info on "enable optimizations" for VS2015 withVB: https://msdn.microsoft.com/en-us/library/07bysfz2.aspx
-->Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-8597268330337687963.post-84672127732833144242015-08-19T22:31:00.002-07:002016-02-04T09:27:25.955-08:00"Variable is accessed within inner class. Needs to be declared final."<h2>
Problem:</h2>
"Variable is accessed within inner class. Needs to be declared final." or a similar error occurs.<br />
<br />
<h2>
Solution:</h2>
Declare the variable final, or make it an instance variable.<br />
<br />
<h2>
Explanation:</h2>
<div>
Java doesn't want developers to change local variables from within an inner class or an anonymous inner class.<br />
<br /></div>
<div>
<h4>
Inner Classes and Local Variables</h4>
</div>
<div>
Any variable defined in a method and accessed by an anonymous inner class must be final. Or, as <a href="https://docs.oracle.com/javase/tutorial/java/javaOO/anonymousclasses.html#accessing">Oracle says</a>:</div>
<blockquote class="tr_bq">
<span style="font-family: "arial" , "helvetica" , sans-serif; font-size: 12.8000001907349px; line-height: 19.2000007629395px;">"An anonymous class cannot access local variables in its enclosing scope that are not declared as </span><code style="font-family: Monaco, Courier, 'Courier New'; font-size: 12.8000001907349px; line-height: 19.2000007629395px;">final</code><span style="font-family: "arial" , "helvetica" , sans-serif; font-size: 12.8000001907349px; line-height: 19.2000007629395px;"> or effectively final"</span></blockquote>
Note: "effectively final" is something new introduced in Java SE 8. It is defined as a variable or parameter that is not declared as final, whose value is never changed after it is initialized.<div>
<span style="font-family: "arial" , "helvetica" , sans-serif; font-size: 12.8000001907349px; line-height: 19.2000007629395px;"><br /></span></div>
<div>
But why make it so inner classes can't modify variables belonging to their outer scope?</div>
<div>
The reason is that the inner class "captures" the variable. To understand why this matters, we need to understand the implications of how captured variables work. If you are familiar with closures, that is exactly what's going on here.</div>
<div>
The inner class is a closure. It copies the variable from it's enclosing scope to a new variable, and brings just that copy inside the inner class. Anything it does to that copy is independent from the variable in the enclosing scope. So if the variable changes in the inner class, and then it is used later in the enclosing scope, the changes made in the inner class did not persist in the enclosing scope.</div>
<div>
<br /></div>
<div>
Basically, what happens in the inner class stays in the inner class.<br />
Below is a proper scenario.</div>
<div>
<br /></div>
<pre class="brush:java;">
public class RadiusStuff { //This is the outer class
public void start(Stage stage) { //This method is the enclosing context
Button submit = new Button("Submit");
final string radius = "10";
submit.setOnAction(new EventHandler<ActionEvent>() {
//This is the inner class, specifically an anonymous class.
@Override
public void handle(ActionEvent e) {
submit.setText(radius);
}
});
}
}
</pre>
<br />
<h4>
</h4>
<h4>
This functionality is by design.</h4>
Java wants the developer to use the final keyword on any variables that are going to be modified in the inner class. This prevents us from thinking the things we change in the inner class will persist in the enclosing scope.<br />
In a way, adding the final keyword does not change the behavior of the code. Think about it. With or without the final keyword, any changes to the variable in the inner class won't persist, so why make any changes at all? Java forces developers to use final in this scenario just to emphasize that we shouldn't be modifying a local variable in an inner class.<br />
<div>
<br />
But what if, in the closure, we are only reading from the variable and not writing to it? Does it still need to be declared final?<br />
If you are using Java 7 or below, the answer is "yes".<br />
In Java 8, if we are only accessing but not changing the variable, the variable is "effectively final" and does not need to be declared final.<br />
<br />
The problem with this is that if we ever want to change the variable we won't be able to. In the below code I show an example of this case by assigning a new value to our "radius" variable, but it will not work.<br />
<pre class="brush:java;">
public class RadiusStuff { //This is the outer class
public void start(Stage stage) { //This method is the enclosing context
Button submit = new Button("Submit");
final string radius = "10";
submit.setOnAction(new EventHandler<ActionEvent>() {
//This is the inner class, specifically an anonymous class.
@Override
public void handle(ActionEvent e) {
submit.setText(radius);
}
});
radius = "15"; //This will throw compile-time error.
}
}
</pre>
<br />
<h4>
Instance Variables</h4>
I mentioned under the "Solution" section that we could also just make the variable an instance variable. Does this really work? Why?<br />
Referring back to Oracle's documentation we see that our inner class "<span style="font-family: "arial" , "helvetica" , sans-serif; font-size: 12.8000001907349px; line-height: 19.2000007629395px;">cannot access local variables in its enclosing scope that are not declared as </span><code style="font-family: Monaco, Courier, 'Courier New'; font-size: 12.8000001907349px; line-height: 19.2000007629395px;">final...</code><span style="font-family: "arial" , "helvetica" , sans-serif; font-size: 12.8000001907349px; line-height: 19.2000007629395px;">"</span><br />
So why would an instance variable be an exception? Note the words "local variable". This only applies to variables declared within the method that the inner class is in, also known as the "enclosing scope".<br />
So does this mean an anonymous inner class can change an instance variable, and have those changes persist outside of the inner class?<br />
Yes.<br />
<br />
<pre class="brush:java;">
public class RadiusStuff { //This is the outer class
string radius = "10"; //Instance variable, no need to be final.
public void start(Stage stage) { //This method is the enclosing context
Button submit = new Button("Submit");
submit.setOnAction(new EventHandler<ActionEvent>() {
//This is the inner class, specifically an anonymous class.
@Override
public void handle(ActionEvent e) {
submit.setText(radius);
}
});
string radius = "15"; //This is allowed now.
}
}
</pre>
<br /></div>
<div>
<h4>
Other notes:</h4>
</div>
<div>
<ul>
<li>Variables defined in interfaces are implicitly final, even if they don't have the final keyword.</li>
<li>For variables that reference objects, the properties of the object can be modified, even if the variable is final. However, you cannot change which object the variable refers to.</li>
<li>You can find excellent information on closures here: <a href="http://csharpindepth.com/Articles/Chapter5/Closures.aspx">C# in depth</a></li>
<li>The behavior mentioned in my post is similar between Java and C#, but there are some differences, so be careful. Perhaps I'll discuss those in a future post.</li>
</ul>
</div>
Unknownnoreply@blogger.com23tag:blogger.com,1999:blog-8597268330337687963.post-74635005779091536412015-07-28T22:35:00.001-07:002016-08-07T10:56:28.600-07:00"System.ComponentModel.Win32Exception: Access is denied"<h2>
Problem:</h2>
<div>
The following error is encountered after publishing a website:<br />
<blockquote class="tr_bq">
<span style="font-family: "calibri"; font-size: 11pt;">System.ComponentModel.Win32Exception:
Access is denied</span>[Win32Exception
(0x80004005): Access is denied]<br />
[ExternalException
(0x80004005): Cannot execute a program. The command being executed was
"E:\someDirectory\myWebsite.com\wwwroot\bin\roslyn\csc.exe"</blockquote>
</div>
<div style="font-family: Calibri; font-size: 11.0pt; margin: 0in;">
<br /></div>
<h2>
Solution:</h2>
<div>
Change the .NET application's framework version to 4.5.</div>
<div>
Also erase the <compiler> section from the web.config if it's throwing an error when you build.<br />
<br /></div>
<h2>
Explanation:</h2>
<div>
This happened to me when running Visual Studio 2015, and publishing my website with a .NET version of 4.5.2, on my Personal Class ASP server on <a href="http://www.arvixe.com" target="_blank">Arvixe</a>. I noticed the problem did not happen when I was using a different computer with an older version of Visual Studio 2015 CTP. I noticed that the non-working version of VS was setting the target framework to 4.5.2, but the version of VS that was working for me had it set to 4.5.<br />
<br />
The version that did not work is:<br />
<br />
Microsoft Visual Studio Enterprise 2015<br />
Version 14.0.23107.0 D14REL<br />
Microsoft .NET Framework<br />
Version 4.6.00081<br />
<div>
<br />
The version that did work is:<br />
<br />
Microsoft Visual Studio Ultimate 2015 CTP<br />
Version 14.0.22609.0 D14REL<br />
Microsoft .NET Framework<br />
Version 4.6.00030<br />
<div>
<br /></div>
<br /></div>
To fix this, open up Visual Studio. Open the Solution Explorer.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhquXySPvuKuQV8670tjCX28XG7GfstvEszuIngMbkA726KcFptnZXOg7KtgP6IVD9vmXIPvls1uD0V-1b01E2-XG-T7OKYNWAIOWwQt3130DCOHn0e6IHypF9_llTI2MFXJDqjiU7oy30/s1600/vsSolutionExplorer.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhquXySPvuKuQV8670tjCX28XG7GfstvEszuIngMbkA726KcFptnZXOg7KtgP6IVD9vmXIPvls1uD0V-1b01E2-XG-T7OKYNWAIOWwQt3130DCOHn0e6IHypF9_llTI2MFXJDqjiU7oy30/s1600/vsSolutionExplorer.png" /></a></div>
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
Right click on "WebApplication1" (or whatever you named your app) and then click on "Properties".<br />
You'll be presented with the following window.<br />
Ensure that "Target Framework" is set to 4.5. Hit Ctrl+S to save.<br />
<br />
<h3>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSc0NUc01nSbSQtyURYZD41TxJ8QaCYbGYK3SmUEdGxNhv25KGjFyOT8Il-1fTD3IVCXfw-j3leGwcAyFiWIrAA0lCDnPRF68dCKYyzyHq7fP95Rc6zAotkpct8Mjevq5S7XEixFrLGso/s1600/vsApplicationProperties.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="183" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSc0NUc01nSbSQtyURYZD41TxJ8QaCYbGYK3SmUEdGxNhv25KGjFyOT8Il-1fTD3IVCXfw-j3leGwcAyFiWIrAA0lCDnPRF68dCKYyzyHq7fP95Rc6zAotkpct8Mjevq5S7XEixFrLGso/s320/vsApplicationProperties.png" width="320" /></a>
</h3>
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
If you previously built with a target framework of 4.5.2, you may have a <compiler> section in your web.config, and this may throw an error when you build. Just remove this section to fix the issue. Removing it should not cause any problems.<br />
<br />
That solved it for me. It may not solve it for you depending on the configuration of IIS on the server you're deploying to. If it didn't work, check below for other things I tried that didn't work for me but may work for you!<br />
<br />
<h2>
Other things I tried that didn't work:</h2>
</div>
<br />
<ul>
<li>In IIS, Enabled Basic Authentication, disabled Integrated Windows Authentication.</li>
<li>In VS when publishing using Web Deploy, I selected to exclude app_data files.</li>
<li>Tried running VS as admin</li>
<li>In IIS, checked "Enable write permissions" and "enable directory browsing",</li>
<li>Deleted everything from wwwroot and published again</li>
<li>Changed platform target from "any cpu" to x86 in web application build settings.</li>
<li>Changed platform target from "any cpu" to x64 in web application build settings.</li>
</ul>
Unknownnoreply@blogger.com20tag:blogger.com,1999:blog-8597268330337687963.post-46110849133302541512015-06-03T19:06:00.000-07:002015-07-30T08:24:12.366-07:00Adding and removing GeoFences to a Google Map<h3>
Problem:</h3>
There is no native way to add, keep track of, or erase GeoFences that are added to a Google Map.<br />
<br />
<h3>
Solution:</h3>
After a GeoFence is successfully added to the GeoFencing API, use its radius, latitude, and longitude to construct a Circle object. Add this Circle to a Stack of Circles, and also add it to the Google Map object. Pop the circle off the stack and remove it from the Map when removing the GeoFence.<br />
<br />
<h3>
Explanation:</h3>
This assumes you have a GeoFencing API already set up and a Google Map set up.<br />
If you followed the Android GeoFence tutorial you should end up with something like this:<br />
<br />
<pre class="brush:java;">LocationServices.GeofencingApi.addGeofences(
mGoogleApiClient,
getGeofencingRequest(),
getGeofencePendingIntent()
).setResultCallback(this);
</pre>
<br />
In my code I call this every time a GeoFence is added. If that completes successfully, you can now add your GeoFence to the map. You'll need to know the fence's ID, latitude, longitude, and radius, so make sure to store those somewhere. Then, you're going to want to call your method that will do the work for making the circle with the map. I called mine createCircle() and I call it like this. Latlng is a LatLng type, and rad is a float.<br />
<br />
<pre class="brush:java;">createCircle(new CircleOptions()
.center(latlng)
.radius(rad)
.strokeColor(Color.BLACK));
</pre>
<br />
Here is the method that does the work:<br />
<br />
<pre class="brush:java;">private void createCircle(CircleOptions circleOptions){
if(mMap != null) {
Circle newCircle = mMap.addCircle(circleOptions);
if(newCircle != null) {
circleStack.push(newCircle);
} else {
Log.d(TAG, "newCircle is null");
}
} else {
Log.d(TAG, "mMap is null");
}
}
</pre>
<br />
mMap is an instance variable of the Google Map that was created earlier in our code. Make sure you only call this after the Map is ready. Remember that Google Maps has the onMapReady() callback method, and this should be in your code already if you implemented OnMapReadyCallback.<br />
<br />
circleStack is a stack that I instantiated like this:<br />
<br />
<pre class="brush:java;">private Stack<Circle> circleStack = new Stack<Circle>();
</pre>
<br />
Ta-da! Now we have a circle on our map exactly where the GeoFence is!<br />
And the Stack keeps track of the Circles for when we want to remove them.<br />
<br />
Removing Circles and GeoFences:<br />
<br />
The Android GeoFence tutorial only shows you how to remove all the geoFences for a pending intent. But there is another removeGeofences() method that takes a different argument and allows you to remove a list of fences based on their IDs. But how do you remove just a single GeoFence? I solved this by adding a button that would remove the most recently added GeoFence from the Geofencing Api and from the Google Map.<br />
<br />
To remove the GeoFence from the API, just get the most recently added GeoFence from your ArrayList of GeoFences, which if you followed the Android GeoFence tutorial is called mGeofenceList. The most recently added fence will be at the highest index of your mGeofenceList. So get the fence from the highest index, and then get its ID and save it in a variable. You'll also want to remove from the mGeofenceList.<br />
Then, add that ID to a List<String>. Yes, it seems a bit ridiculous to add a single entry to a List, but we need to use a List with the removeGeofences method. Now we are ready to call GeofencingApi.removeGeofences(), passing it your mGoogleApiClient (the same one from above) and your List of a single GeoFence ID to remove.<br />
<br />
Finally, remove the Circle from the map. This is where the stack comes in. Pop the circle from the stack and store it in a Circle variable, and then call remove() on that Circle. Note that pop returns the object that it popped off the top of the stack.<br />
<br />
Now your GeoFences are removed from the API, so they won't do anything if you enter, exit, or dwell within them. They are also removed from the map so no one will think a GeoFence exists where it doesn't.<br />
<br />
<pre class="brush:java;">public void removeGeofencesClick(View view) {
if(mGeofenceList.size() > 0 && mGoogleApiClient.isConnected()) {
int mGeofenceListLastIndex = mGeofenceList.size() - 1;
Geofence fenceToRemove = mGeofenceList.get(mGeofenceListLastIndex);
String geoFenceIdToRemove = fenceToRemove.getRequestId();
mGeofenceList.remove(mGeofenceListLastIndex);
//This will only ever hold 1 fence at a time, but removeGeofences()
//takes a List so that's why we make a List.
List<String> geoFenceToRemove = new ArrayList<>();
geoFenceToRemove.add(geoFenceIdToRemove);
LocationServices.GeofencingApi.removeGeofences(mGoogleApiClient,
geoFenceToRemove).setResultCallback(this);
//This removes the last added GeoFence from the Map,
// but not the GeoFence collection.
if(!circleStack.empty()){
Circle circleToRemove = (Circle)circleStack.pop();
circleToRemove.remove(); //remove it from the Map
}
}
}
</pre>
Unknownnoreply@blogger.com3tag:blogger.com,1999:blog-8597268330337687963.post-31026540650051335432015-06-02T20:52:00.001-07:002015-08-18T09:34:12.302-07:00Geofence Transition Bitwise Logic<br />
<h3>
Problem:</h3>
You want to set multiple Geofence transitions either programmatically or through user input, but you can only call setTransitionTypes() once.<br />
<br />
<h3>
Solution:</h3>
Use bitwise OR on each transition type to get an int that can represent every combination of transitions. <br />
<pre class="brush:java;">public void createGeoFence(float rad, double lat, double lng,
boolean enterChecked, boolean exitChecked, boolean dwellChecked) {
//Set transitions based on what the user selects.
int transitions = 0;
if(enterChecked){
transitions = Geofence.GEOFENCE_TRANSITION_ENTER;
}
if(exitChecked){
transitions = transitions | Geofence.GEOFENCE_TRANSITION_EXIT;
}
if(dwellChecked){
transitions = transitions | Geofence.GEOFENCE_TRANSITION_DWELL;
}
mGeofenceList.add(new Geofence.Builder()
.setRequestId(fenceId)
.setCircularRegion(lat, lng, rad)
.setExpirationDuration(86400000) //24 hours
.setTransitionTypes(transitions)
.setNotificationResponsiveness(5000) //5 seconds
.build());
}
</pre>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjc3_5DUPr7AIUx-FIk03QMswMT1sqMPefiW9Y2Mi1fWVX1zCS7nwyRNzsNtUson5fizz0a5PKeJ3C94L6ongpkRnc7yLcMiy13cai5HX2Vnt-6S8fv9hD3t3_9eWNFzRypS2SFBdFB084/s1600/geoFenceTransitions.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjc3_5DUPr7AIUx-FIk03QMswMT1sqMPefiW9Y2Mi1fWVX1zCS7nwyRNzsNtUson5fizz0a5PKeJ3C94L6ongpkRnc7yLcMiy13cai5HX2Vnt-6S8fv9hD3t3_9eWNFzRypS2SFBdFB084/s1600/geoFenceTransitions.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<span style="font-family: inherit;">The above sample method gets passed everything you need to construct a GeoFence. The booleans are the results of checking if the check boxes are checked, they will be true for each box that is checked, and false otherwise. I included a screenshot of the checkboxes for a visual aid.</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">Note that ints are primitive and can't be null, so if they are not assigned a value they are 0. Further, a transitionType of 0 will throw an error. Make sure to handle this. In another part of my code(not shown) I simply made it so that if the Dwell, Enter, and Exit controls were all unchecked the user would not be allowed to create the GeoFence and would be informed of their error.</span><br />
<br />
<h3>
Explanation:</h3>
<span style="font-family: inherit;">Google has a pretty clever way for setting the transitions for a geofence. They use bitwise logic. So we should run with that. The pipe '|' operator is a bitwise OR.</span><br />
<div>
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">Maybe you want to programmatically set your transitions on GeoFences, but you are having issues with the fact that you can only call setTransitionTypes() once for each GeoFence Builder. For me, I wanted to take user input, and add a transition type for each transition type the user selects. Instinctually you may want to examine each user input (checkboxes in this case) and then call setTransitionsTypes() for each one that the user enabled. But you can't. You can only call setTransitionTypes once, and you can only give it one argument. </span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">So you must build your transition types before calling setTranstionTypes(). One simple and readable way to do this is a bitwise OR. </span><br />
<span style="font-family: inherit;">According to the <a href="https://developers.google.com/android/reference/com/google/android/gms/location/Geofence#GEOFENCE_TRANSITION_ENTER">Android API:</a></span><br />
<span style="font-family: inherit;">GEOFENCE_TRANSITION_ENTER has a value of 1 = 001 binary</span><br />
<span style="font-family: inherit;">GEOFENCE_TRANSITION_EXIT has a value of 2 = 010 binary</span><br />
<span style="font-family: inherit;">GEOFENCE_TRANSITION_DWELL has a value of 4 = 100 binary</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">Why these values? Look at the binary logic. Adding any combination of values will produce a unique result.</span></div>
<div>
<span style="font-family: inherit;">If we do an OR on ENTER and EXIT we get </span><br />
<span style="font-family: inherit;">001 </span><br />
<span style="font-family: inherit;">010 </span><br />
<span style="font-family: inherit;">----- </span><br />
<span style="font-family: inherit;">011</span><br />
<span style="font-family: inherit;">Which equals 3. </span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">If we do EXIT and DWELL we get </span><br />
<span style="font-family: inherit;">010 </span><br />
<span style="font-family: inherit;">100 </span><br />
<span style="font-family: inherit;">---- </span><br />
<span style="font-family: inherit;">110 </span><br />
<span style="font-family: inherit;">Which equals 6.</span><br />
<br />
<span style="font-family: inherit;">So through bitwise OR you will always get a unique int between 1 and 7, inclusive. This explains why DWELL doesn't have a value of 3. Because that would mean there are multiple ways to get a value of 3. </span></div>
<div>
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">Let's pretend for a minute that DWELL = 011.</span></div>
<div>
<span style="font-family: inherit;">If you set that as the transition type, it's not clear if you want a DWELL, or if you want ENTER and EXIT transitions; these all evaluate to 3. And what if you wanted to set your transition types to DWELL and ENTER? There would be a bitwise OR between DWELL and ENTER, which would result in a value of 3 yet again, and the GeoFence wouldn't know if you wanted transitions on dwell, or dwell and enter. </span><br />
<span style="font-family: inherit;">Bitwise logic below, pretending DWELL is 011 and ENTER is 001 (which it really is).</span><br />
<span style="font-family: inherit;">001</span><br />
<span style="font-family: inherit;">011</span><br />
<span style="font-family: inherit;">---- </span><br />
<span style="font-family: inherit;">011 </span></div>
<div>
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">Now lets go back to real life where DWELL = 100 binary. How many different combinations of GeoFence transitions can you have?</span></div>
<div>
<span style="font-family: inherit;">That would be (2^3) -1 = 7. The minus 1 is because we can't send a value of 0 to setTransitionTypes without it throwing an error.</span></div>
<div>
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">So what if Google wanted to add another transition type to the GeoFence? What's the lowest positive value they could use to not interfere with their schema?</span></div>
<div>
<span style="font-family: inherit;">It would just be the next highest power of 2, which is 8, also known as 1000 binary.</span><br />
<span style="font-family: inherit;">The number of combinations this would allow is (2^4) -1 = 15.</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">You may have noticed that in the entire scenario discussed in the post you could just add the values together and you will come up with the same int. The reason I chose the bitwise OR was because I liked the readability of it, and I liked keeping with the same logic Google is using. Adding up 3 ints and passing them to setTransitionTypes may appear to be slightly simpler code, but it makes very little sense if you don't already understand how setTransitionTypes works.</span></div>
<div>
<br /></div>
<div>
<div style="margin: 0in;">
<div style="font-size: 11pt;">
<span style="font-family: inherit;"><span style="font-size: 11pt;"><br /></span></span></div>
</div>
</div>
Unknownnoreply@blogger.com0