<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jake Bloom</title>
    <description>The latest articles on DEV Community by Jake Bloom (@jakebloom).</description>
    <link>https://dev.to/jakebloom</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F110704%2Fde53daf9-a155-4883-a238-b9ca3114745b.jpeg</url>
      <title>DEV Community: Jake Bloom</title>
      <link>https://dev.to/jakebloom</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jakebloom"/>
    <language>en</language>
    <item>
      <title>Using Share Sheets on iOS and Android</title>
      <dc:creator>Jake Bloom</dc:creator>
      <pubDate>Fri, 12 Jun 2020 15:27:09 +0000</pubDate>
      <link>https://dev.to/jakebloom/using-share-sheets-on-ios-and-android-4obi</link>
      <guid>https://dev.to/jakebloom/using-share-sheets-on-ios-and-android-4obi</guid>
      <description>&lt;p&gt;A Share Sheet is a really powerful feature that's available on pretty much any phone today. If you are an application developer and you want your users to be talking about your product, a compelling experience with a well set up Share Sheet can help unlock network-effect growth.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is a Share Sheet and why should I use it?
&lt;/h3&gt;

&lt;p&gt;Share Sheets are interfaces in both iOS and Android that allows you to share content from your app to another app. For example, in your Photos app, you can select an image and then share it to other apps like Instagram, your mail app, your messaging app and plenty more. &lt;/p&gt;

&lt;p&gt;The actual logic behind the Share Sheets is handled by the operating system, all you need to do as an app developer is tell it to open. Share sheets are set up this way so you don't have to update your app code to handle new apps that can share the same content. You send the operating system your content to be shared, and it will tell the user where it can be shared to.&lt;/p&gt;

&lt;p&gt;On iOS, the Share Sheet looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.imore.com%2Fsites%2Fimore.com%2Ffiles%2Fstyles%2Flarge%2Fpublic%2Ffield%2Fimage%2F2019%2F10%2Fshare-sheet-screen.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.imore.com%2Fsites%2Fimore.com%2Ffiles%2Fstyles%2Flarge%2Fpublic%2Ffield%2Fimage%2F2019%2F10%2Fshare-sheet-screen.jpg" alt="Share Sheet"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And on Android, it looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcbxamuhrcbtop64btk6j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcbxamuhrcbtop64btk6j.png" alt="Android share sheet"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How do I do it?
&lt;/h3&gt;

&lt;p&gt;Lets get into some code!&lt;/p&gt;

&lt;h4&gt;
  
  
  iOS
&lt;/h4&gt;

&lt;p&gt;On iOS, the Share Sheet comes in the form of a view controller that you need to programmatically create and present to the user. It is called &lt;code&gt;UIActivityViewController&lt;/code&gt;, and for simple use cases, it is pretty easy:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;textToSend&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"This is some text that will be exported to another app!"&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;activityViewController&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;UIActivityViewController&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;activityItems&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;textToSend&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nv"&gt;applicationActivities&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;currentViewController&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;present&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;activityViewController&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;animated&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;completion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;With that code in place, this is what we see:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fsrn5s6gp99idesebu8yp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fsrn5s6gp99idesebu8yp.png" alt="Simple share sheet"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And that works great for text, but what if we wanted to share an image?&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UIImage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getImage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;activityViewController&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;UIActivityViewController&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;activityItems&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nv"&gt;applicationActivities&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;currentViewController&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;present&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;activityViewController&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;animated&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;completion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fsrn5s6gp99idesebu8yp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fsrn5s6gp99idesebu8yp.png" alt="Broken thumbnail"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It works great, but looks a little plain. It is possible to customise the Share Sheet with a title, description and thumbnail though, by passing the controller an instance of &lt;code&gt;UIActivityItemProvider&lt;/code&gt; instead of just raw data:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;ShareImage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UIActivityItemProvider&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UIImage&lt;/span&gt;

  &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;item&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Any&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;get&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;placeholderItem&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;guard&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;placeholderItem&lt;/span&gt; &lt;span class="k"&gt;as?&lt;/span&gt; &lt;span class="kt"&gt;UIImage&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;fatalError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Couldn't create image from provided item"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;placeholderItem&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;placeholderItem&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;@available&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iOS&lt;/span&gt; &lt;span class="mf"&gt;13.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;activityViewControllerLinkMetadata&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;activityViewController&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UIActivityViewController&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;LPLinkMetadata&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;metadata&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;LPLinkMetadata&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"1 Image"&lt;/span&gt;

    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;thumbnail&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;NSSecureCoding&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;NSNull&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;imageData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pngData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;thumbnail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;NSData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;imageData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;imageProvider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;NSItemProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;item&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;thumbnail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;typeIdentifier&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"public.png"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;...&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UIImage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getImage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;ShareImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;placeholderItem&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;activityViewController&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;UIActivityViewController&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;activityItems&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nv"&gt;applicationActivities&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;currentViewController&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;present&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;activityViewController&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;animated&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;completion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F0eihxyyzjtp1pfhzbcg3.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F0eihxyyzjtp1pfhzbcg3.PNG" alt="Finished product"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And there you have it! It is also possible to send multiple data objects to the Share Sheet, or specify which apps can access the data using the &lt;code&gt;applicationActivities&lt;/code&gt; parameter.&lt;/p&gt;

&lt;h4&gt;
  
  
  Android
&lt;/h4&gt;

&lt;p&gt;I've found that doing this on Android is more complex than on iOS, mainly due to how Android deals with file permissions. Basically, you have to set the permissions of the file you want to share manually, whereas in iOS it was handled automatically.&lt;/p&gt;

&lt;p&gt;In android, you need to designate the class you are going to be calling from as a &lt;code&gt;FileProvider&lt;/code&gt;, and specifying which files it is allowed to access. You do this by specifying the class in the &lt;code&gt;AndroidManifest.xml&lt;/code&gt; file:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;

&lt;span class="nt"&gt;&amp;lt;activity&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;".MainActivity"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;provider&lt;/span&gt;
    &lt;span class="na"&gt;android:authorities=&lt;/span&gt;&lt;span class="s"&gt;"com.package.ClassName"&lt;/span&gt;
    &lt;span class="na"&gt;android:exported=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt;
    &lt;span class="na"&gt;android:grantUriPermissions=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;
    &lt;span class="na"&gt;android:name=&lt;/span&gt;&lt;span class="s"&gt;"androidx.core.content.FileProvider"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta-data&lt;/span&gt;
        &lt;span class="na"&gt;android:name=&lt;/span&gt;&lt;span class="s"&gt;"android.support.FILE_PROVIDER_PATHS"&lt;/span&gt;
        &lt;span class="na"&gt;android:resource=&lt;/span&gt;&lt;span class="s"&gt;"@xml/file_paths"&lt;/span&gt;  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/provider&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;And then creating a new directory called &lt;code&gt;xml&lt;/code&gt; and a file in it called &lt;code&gt;file_paths&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;

&lt;span class="nt"&gt;&amp;lt;paths&lt;/span&gt; &lt;span class="na"&gt;xmlns:android=&lt;/span&gt;&lt;span class="s"&gt;"http://schemas.android.com/apk/res/android"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;files-path&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"my_images"&lt;/span&gt; &lt;span class="na"&gt;path=&lt;/span&gt;&lt;span class="s"&gt;"images/"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/paths&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Note that you might need to use a different tag than &lt;code&gt;files-path&lt;/code&gt; depending on where your files are stored. If you are using temp files, you might need to use &lt;code&gt;cache-path&lt;/code&gt;. For a full list of what you might need, see the &lt;a href="https://developer.android.com/reference/androidx/core/content/FileProvider#SpecifyFiles" rel="noopener noreferrer"&gt;android docs here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, inside the class that we specified in the provider above:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;

&lt;span class="nc"&gt;File&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getFile&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="nc"&gt;Uri&lt;/span&gt; &lt;span class="n"&gt;uri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FileProvider&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getUriForFile&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;getContext&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getClass&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getName&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="nc"&gt;Intent&lt;/span&gt; &lt;span class="n"&gt;intent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Intent&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;intent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setAction&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Intent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ACTION_SEND&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;intent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;putExtra&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Intent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;EXTRA_STREAM&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;intent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setType&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"MIME_TYPE_OF_FILE"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="nc"&gt;Intent&lt;/span&gt; &lt;span class="n"&gt;shareIntent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Intent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;createChooser&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;intent&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Share File"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;shareIntent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addFlags&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Intent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;FLAG_ACTIVITY_NEW_TASK&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Intent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;FLAG_GRANT_READ_URI_PERMISSION&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;startActivity&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;shareIntent&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcbxamuhrcbtop64btk6j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcbxamuhrcbtop64btk6j.png" alt="Android share sheet"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Executing that will open up the Share Sheet and send your file on it's merry way. I haven't found a consistent way to customise the Share Sheet on Android like we did earlier on iOS, but if I do, I'll update this post.&lt;/p&gt;

</description>
      <category>ios</category>
      <category>android</category>
      <category>swift</category>
      <category>java</category>
    </item>
    <item>
      <title>Creating Static and Dynamic Libraries for your C Programs</title>
      <dc:creator>Jake Bloom</dc:creator>
      <pubDate>Sat, 03 Nov 2018 20:27:32 +0000</pubDate>
      <link>https://dev.to/jakebloom/creating-static-and-dynamic-libraries-for-your-c-programs-3037</link>
      <guid>https://dev.to/jakebloom/creating-static-and-dynamic-libraries-for-your-c-programs-3037</guid>
      <description>

&lt;p&gt;G'day world! This is my first post here on dev.to. I'm stoked to be here, and today, I'm going to talk about code reuse in the C/C++ world.&lt;/p&gt;

&lt;p&gt;Bill Gates never actually said "Hire the laziest person for the job, because they will find the easiest way to do it", but the sentiment certainly rings true. &lt;/p&gt;

&lt;p&gt;If you're a Civil Engineer, you can't reuse a pylon from a previous bridge in a new building, but a Software Engineer can reuse code from a previous project. This is a huge productivity win, and we should be leveraging it as hard as we can.&lt;/p&gt;

&lt;p&gt;When dealing with C or C++, there are two general ways of reusing code between projects - static libraries and dynamic libraries.&lt;/p&gt;

&lt;h2&gt;Static Libraries&lt;/h2&gt;

&lt;p&gt;A Static Library is just a series of object files (.o files) that have been archived together. On Windows, you'll see them with .lib extensions, whereas on linux systems they have .a extensions.&lt;/p&gt;

&lt;p&gt;For example, let's say we have a project called "Wave" that makes web requests in C. We have two .c files, &lt;code&gt;waveRequest.c&lt;/code&gt; and &lt;code&gt;waveResponse.c&lt;/code&gt;. In order to create and use a static library, we do the following:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; # Create the object files
&amp;gt; gcc -c -o waveRequest.o waveRequest.c
&amp;gt; gcc -c -o waveResponse.o waveResponse.c
&amp;gt; # Create the Static Libaray
&amp;gt; ar rcs libWave.a waveRequest.o waveResponse.o
&amp;gt; # compile your code with the library
&amp;gt; gcc -o main main.c -lWave # The compiler adds the "lib" and ".a" itself
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now, whenever you want to use your Wave library, you can copy the &lt;code&gt;libWave.a&lt;/code&gt; and compile it into your project. This has a few advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We are reusing code&lt;/li&gt;
&lt;li&gt;We can write unit tests for our Wave Library and be confident that it will work everywhere&lt;/li&gt;
&lt;li&gt;If the library gets updates and is not backwards-compatible, the older version is still compiled into your code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, there are some disadvantages to using static libraries:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Copying the .a file around to different projects is kinda clunky and doesn't feel like a nice workflow&lt;/li&gt;
&lt;li&gt;If the library is updated and you want to move to the new version, you need to recompile your project&lt;/li&gt;
&lt;li&gt;You might not be using all the functionality of the library, so compiling all of it in with your code could be a waste of space&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So what do we do if we don't want to compile in the static library to our own code?&lt;/p&gt;

&lt;h2&gt;Dynamic Libraries&lt;/h2&gt;

&lt;p&gt;While you have to compile in your static library, the dynamic library is stored in one place and loaded into multiple programs at runtime (think of common C libraries, like stdlib, stdio and assert). They typically have .so file extensions (or .dll in Windows) and don't require any extra compile flags for use. &lt;/p&gt;

&lt;p&gt;Using our Wave example, and assuming we have a Wave.h file, you can create a dynamic library as follows:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; # Compile the object files
&amp;gt; gcc -fPIC -c -o waveRequest.o waveRequest.c
&amp;gt; gcc -fPIC -c -o waveResponse.o waveResponse.c
&amp;gt; # Create the dynamic library
&amp;gt; gcc -shared -o libWave.so waveRequest.o waveResponse.o
&amp;gt; # Copy the library to where it can be included
&amp;gt; cp libWave.so /usr/local/lib/libWave.so
&amp;gt; cp Wave.h /usr/local/include/libWave.h
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now, there's a bit going on here, so let's unpack it. Firstly, we are compiling our object files with the &lt;code&gt;-fPIC&lt;/code&gt; flag, which means "Position Independent Code" - this will remove all absolute address references from the code and use relative addresses instead, allowing us to reuse the code across multiple projects without having to recompile it.&lt;/p&gt;

&lt;p&gt;We are also copying our library and header files to a place where the compiler knows to look for library and header files. This might be different on your machine, for info on osx, &lt;a href="https://developer.apple.com/library/archive/documentation/DeveloperTools/Conceptual/DynamicLibraries/100-Articles/UsingDynamicLibraries.html"&gt;look here&lt;/a&gt; and for linux you can use &lt;code&gt;ldconf&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We can use our wave library in code as follows:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#include &amp;lt;Wave.h&amp;gt;

int main(int argc, char* argv) {
    wave_make_request("https://dev.to");
    return 0;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now that we are using the dynamic library, we get the following benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Whenever our library is upgraded, we automatically get the new version&lt;/li&gt;
&lt;li&gt;We don't have to copy files between projects&lt;/li&gt;
&lt;li&gt;We don't have to remember to compile in the library, just include it!
But there are some drawbacks too:&lt;/li&gt;
&lt;li&gt;If updates are made to the library that aren't backwards compatible, you will probably end up with a runtime error&lt;/li&gt;
&lt;li&gt;On lower memory machines, paging between the dynamic library and your application code might cause a hit to your app's performance.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So there's my summary of static and dynamic libraries! Hopefully you found this useful, and we can all continue to be lazy.&lt;/p&gt;

&lt;p&gt;Cheers&lt;/p&gt;


</description>
      <category>c</category>
    </item>
  </channel>
</rss>
