<?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>Forem: Josh</title>
    <description>The latest articles on Forem by Josh (@josholadele).</description>
    <link>https://forem.com/josholadele</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%2F819163%2Fab0aab73-f9f3-4010-a20c-00dfa6d19f13.jpeg</url>
      <title>Forem: Josh</title>
      <link>https://forem.com/josholadele</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/josholadele"/>
    <language>en</language>
    <item>
      <title>Implementing a Countdown Element in a Quick App</title>
      <dc:creator>Josh</dc:creator>
      <pubDate>Sun, 10 Apr 2022 22:14:36 +0000</pubDate>
      <link>https://forem.com/josholadele/implementing-a-countdown-element-in-a-quick-app-m75</link>
      <guid>https://forem.com/josholadele/implementing-a-countdown-element-in-a-quick-app-m75</guid>
      <description>&lt;h2&gt;
  
  
  What Is a Countdown Element
&lt;/h2&gt;

&lt;p&gt;The countdown element is used to display the remaining time for a promotion activity and will send a notification when such time ends. This element supports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Time setting by day, hour, minute, and second&lt;/li&gt;
&lt;li&gt;Configuration of text, border, and delimiter styles&lt;/li&gt;
&lt;li&gt;Time delay&lt;/li&gt;
&lt;li&gt;Callback event for countdown ending&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As shown in the following figure, the layout of the element consists of numbers and delimiters. Generally, the numbers indicate the remaining time by day, hour, minute, and second. The delimiters are used to separate numbers. Common delimiters can be words (day, hour, minute, and second) and colon (:).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4nt1IUVA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dvivhltr5vnfp04tauzc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4nt1IUVA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dvivhltr5vnfp04tauzc.png" alt="Image descriptio" width="743" height="216"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;import name="countdown" src="../Countdown/countdown"&amp;gt;&amp;lt;/import&amp;gt;
&amp;lt;template&amp;gt;
  &amp;lt;div class="container"&amp;gt;
    &amp;lt;text&amp;gt;General usage&amp;lt;/text&amp;gt;
    &amp;lt;div class="example-body"&amp;gt;
      &amp;lt;countdown class="countdown" day="{{this.day}}" hour="{{this.hour}}" minute="{{this.minute}}" second="{{this.second}}" splitor-color="#007AFF" border-width="{{3}}" border-style="dotted" border-color="#007AFF"&amp;gt;&amp;lt;/countdown&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Implementation Steps
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Customizing Subelements
&lt;/h3&gt;

&lt;p&gt;The countdown UI can be used universally, while the layout of its content may vary and therefore cannot be hardcoded. Otherwise, once any part of the content UI is changed, the subelements will also need to be modified, which violates the principle of open-source programming.&lt;/p&gt;

&lt;p&gt;Therefore, multiple style attributes are supported in countdown.ux for you to customize the style of subelements.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6Bq7BiYA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/20pdyj8d6nt6zxqcvttn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6Bq7BiYA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/20pdyj8d6nt6zxqcvttn.png" alt="Image descption" width="880" height="241"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Designing the Attributes and Supported Event of Subelements
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--S_KaPb15--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fwp1t0fud6qgbuozr0zz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--S_KaPb15--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fwp1t0fud6qgbuozr0zz.png" alt="Image descriptin" width="880" height="1003"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Designing the Overall Layout
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The text element is used to design the layout of the delimiters and numbers, as displayed in Figure 1 below.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Define the related attributes in props of the subelements and pass the values when the parent element references the subelements. Call this.$watch(‘day’, ‘changeFlag’) to listen to the changes of the values and then update and process the values in the subelements, as displayed in Figure 2 below.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement the countdown algorithm. You need to convert days, hours, and minutes to seconds, set the timer to decrease by 1 every second, and reconvert the seconds back into days, hours, minutes, and seconds accordingly, as shown in Figure 3 and 4 below.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1Th98XXT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mbywovduh8xfcwgmhuqa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1Th98XXT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mbywovduh8xfcwgmhuqa.png" alt="Imagedescription" width="340" height="498"&gt;&lt;/a&gt;&lt;br&gt;
Figure 1&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cIrWac5x--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mpc5ww9hany8limqve7b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cIrWac5x--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mpc5ww9hany8limqve7b.png" alt="Image descripti" width="256" height="512"&gt;&lt;/a&gt;&lt;br&gt;
Figure 2a&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--90bDJYe4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1n36t9pmjegh0vf5tp7f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--90bDJYe4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1n36t9pmjegh0vf5tp7f.png" alt="Imae description" width="512" height="174"&gt;&lt;/a&gt;&lt;br&gt;
Figure 2b&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--v7-CSHzM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o7puyd2qztyn9fkn3ul4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--v7-CSHzM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o7puyd2qztyn9fkn3ul4.png" alt="Image descaription" width="512" height="108"&gt;&lt;/a&gt;&lt;br&gt;
Figure 3&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qVS0meZg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yv94fe9v39pdlbn1i7py.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qVS0meZg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yv94fe9v39pdlbn1i7py.png" alt="Figure 4" width="512" height="307"&gt;&lt;/a&gt;&lt;br&gt;
Figure 4&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Define the timeup callback event in the parent element, and implement and bind the event, as displayed in Figure 5.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Trigger the timeup event of the parent element in the subelements, as displayed in Figure 6.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GWh-Zbv5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vfsg3jot19izbekdt7eo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GWh-Zbv5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vfsg3jot19izbekdt7eo.png" alt="Image descriptioan" width="512" height="53"&gt;&lt;/a&gt;&lt;br&gt;
Figure 5a&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Han8HZXr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7by0zxi83islh10mszwk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Han8HZXr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7by0zxi83islh10mszwk.png" alt="Image_ description" width="252" height="102"&gt;&lt;/a&gt;&lt;br&gt;
Figure 5b&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cKn3mYLI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j89riuhzxfz70cb2cg8o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cKn3mYLI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j89riuhzxfz70cb2cg8o.png" alt="Image dscription" width="436" height="121"&gt;&lt;/a&gt;&lt;br&gt;
Figure 6&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;In this tutorial, you have learned how to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Design subelements, including their attributes and supported events.&lt;/li&gt;
&lt;li&gt;Implement data communication between the parent element and subelements.&lt;/li&gt;
&lt;li&gt;Convert days, hours, minutes, and seconds, and set a timer.&lt;/li&gt;
&lt;li&gt;Configure the style of the element.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Reference
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://developer.huawei.com/consumer/en/doc/development/quickApp-References/quickapp-animation-styles-0000001123530340"&gt;Quick app official document&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>huawei</category>
    </item>
    <item>
      <title>Customizing a Drawer Element in a Quick App</title>
      <dc:creator>Josh</dc:creator>
      <pubDate>Fri, 01 Apr 2022 20:47:30 +0000</pubDate>
      <link>https://forem.com/josholadele/customizing-a-drawer-element-in-a-quick-app-93a</link>
      <guid>https://forem.com/josholadele/customizing-a-drawer-element-in-a-quick-app-93a</guid>
      <description>&lt;h2&gt;
  
  
  About the Drawer Element
&lt;/h2&gt;

&lt;p&gt;The drawer element is a special pop-up panel that can create the effect of opening and closing a drawer in an app. This element has the following features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It can be displayed on either side of the screen.&lt;/li&gt;
&lt;li&gt;Its width can be customized.&lt;/li&gt;
&lt;li&gt;It has a mask layer that a user can tap to close the drawer.&lt;/li&gt;
&lt;li&gt;It can be opened by swiping on the screen.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;strong&gt;drawer&lt;/strong&gt; element consists of two parts: controls and content. In most cases, &lt;strong&gt;controls&lt;/strong&gt; is a clickable element, such as button or icon that can be seen as real handles, whereas &lt;strong&gt;content&lt;/strong&gt; refers to what is inside the drawer. You can expand or collapse content by tapping &lt;strong&gt;controls&lt;/strong&gt;. Therefore, when the &lt;strong&gt;drawer&lt;/strong&gt; element is used, the page layout can be designed as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div class=“page"&amp;gt;
    &amp;lt;div class=“controls"&amp;gt;
      &amp;lt;image&amp;gt;&amp;lt;/image&amp;gt;
     &amp;lt;/div&amp;gt;
    &amp;lt;stack class=“drawer_container”&amp;gt;
        &amp;lt;div class=“page_content”&amp;gt;
           …
        &amp;lt;/div&amp;gt;
         &amp;lt;drawer class="drawer"&amp;gt;
            &amp;lt;div class=“content”&amp;gt;
             …
             &amp;lt;/div&amp;gt;
          &amp;lt;/drawer &amp;gt;
    &amp;lt;/stack&amp;gt;
 &amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Development Procedure
&lt;/h2&gt;

&lt;p&gt;The drawer element is an extended capability that you cannot implement using the existing elements of quick apps. It requires custom elements.&lt;/p&gt;

&lt;h2&gt;
  
  
  Customizing the Subelements
&lt;/h2&gt;

&lt;p&gt;Unlike the drawer’s appearance, which can be universally used, the layout of the drawer’s content may vary and therefore cannot be hardcoded. Otherwise, once any part of the content UI is changed, the subelements need to be modified, which violates the open-closed principle of programming.&lt;br&gt;
Therefore, in the drawer.ux file, the slot element is used to bear the content defined in the parent element, and the drawer element is used to define the content’s layout. The code is as follows:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0mgEzS8L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n3yuk6tzxaqoqu1mrg2x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0mgEzS8L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n3yuk6tzxaqoqu1mrg2x.png" alt="Image descriptio" width="880" height="121"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Customizing the Attributes and Supported Events of           Subelements
&lt;/h2&gt;

&lt;p&gt;Supported attributes&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uqQGLbrg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hd7isqbayvdu5l52rgf0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uqQGLbrg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hd7isqbayvdu5l52rgf0.png" alt="Image descriptin" width="880" height="268"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Supported event&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4shi0hgA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gy9ntk92rcfewhy5scgg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4shi0hgA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gy9ntk92rcfewhy5scgg.png" alt="Image descriptin" width="880" height="117"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Designing the Opening and Closing Animation of the Drawer
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Set &lt;strong&gt;display&lt;/strong&gt; to &lt;strong&gt;none&lt;/strong&gt; to hide the drawer by default.&lt;/li&gt;
&lt;li&gt;Control the opening and closing animation of the drawer by changing the X coordinate. When opened, the drawer moves to the visible area, and when closed, it moves off the screen. The animation effect is smooth regardless of whether the drawer is opened or closed.&lt;/li&gt;
&lt;li&gt;Control the displayed position of the drawer through &lt;strong&gt;flex-direction&lt;/strong&gt; of the &lt;strong&gt;div&lt;/strong&gt; element. To display the drawer on the left or right, set the value to &lt;strong&gt;row&lt;/strong&gt; or &lt;strong&gt;row-reverse&lt;/strong&gt; accordingly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cAFjh2Lz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fjf8m7kiceptkakchm7t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cAFjh2Lz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fjf8m7kiceptkakchm7t.png" alt="Image descripion" width="527" height="522"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 1: Style for opening and closing the drawer on the left&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eT_G75ea--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/20nqsv7yygy2mpn803ki.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eT_G75ea--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/20nqsv7yygy2mpn803ki.png" alt="Image descripton" width="537" height="522"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 2: Style for opening and closing the drawer on the right&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NnUTYkJ_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xakl2lu0ou19vahqp9x3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NnUTYkJ_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xakl2lu0ou19vahqp9x3.png" alt="Image descripton" width="589" height="597"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 3: Code for opening and closing the drawer on the left&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oSN6Y-O0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/56e9f0vzan0rkx2tny9b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oSN6Y-O0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/56e9f0vzan0rkx2tny9b.png" alt="Image descriptin" width="510" height="515"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 4: Code for opening and closing the drawer on the right&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Designing the Mask Layer
&lt;/h2&gt;

&lt;p&gt;The mask layer is hidden by default, which means the value of display is none. The mask layer is displayed when the drawer is opened and hidden when the drawer is closed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7xDB0xer--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sqowljt7zy14ubwu1kbd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7xDB0xer--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sqowljt7zy14ubwu1kbd.png" alt="Image descrption" width="490" height="438"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing Data Communication Between the Parent Element and Subelements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The parent element transfers events of opening and closing the drawer to subelements through &lt;strong&gt;parentVm.$broadcast()&lt;/strong&gt;. The subelements listen to events and parameters through &lt;strong&gt;$on()&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The subelements listen to how &lt;strong&gt;mode&lt;/strong&gt; changes through &lt;strong&gt;$watch()&lt;/strong&gt; to modify the CSS style, displaying the drawer in the correct position.&lt;/li&gt;
&lt;li&gt;The subelements notify the parent element through the &lt;strong&gt;drawerchange&lt;/strong&gt; event and returned parameters.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Opening the Drawer by Swiping
&lt;/h2&gt;

&lt;p&gt;By listening to the &lt;strong&gt;touchstart&lt;/strong&gt; and &lt;strong&gt;touchend&lt;/strong&gt; events, you can swipe on the edge of the screen to open the drawer. &lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;In this article, you will learn how to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Customize subelements, including their attributes and supported events.&lt;/li&gt;
&lt;li&gt;Implement data communication between the parent element and subelements.&lt;/li&gt;
&lt;li&gt;Design the opening and closing animation.&lt;/li&gt;
&lt;li&gt;Design the mask layer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can check &lt;a href="https://developer.huawei.com/consumer/en/doc/development/quickApp-References/quickapp-animation-styles-0000001123530340"&gt;related documents&lt;/a&gt; to learn even more.&lt;/p&gt;

&lt;p&gt;Sample code — &lt;a href="https://filebin.net/xlzp8cxmd2s22kah"&gt;drawer.ux&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>huawei</category>
    </item>
    <item>
      <title>Generating and Uploading an iOS Symbol File Using Crash</title>
      <dc:creator>Josh</dc:creator>
      <pubDate>Sat, 12 Mar 2022 21:53:05 +0000</pubDate>
      <link>https://forem.com/josholadele/generating-and-uploading-an-ios-symbol-file-using-crash-jk5</link>
      <guid>https://forem.com/josholadele/generating-and-uploading-an-ios-symbol-file-using-crash-jk5</guid>
      <description>&lt;p&gt;With the Crash service, you can symbolicate a crash report based on the iOS symbol file to obtain a readable report, when classes, fields, and methods in code are overridden with unreadable code during compilation. This article describes how to generate and upload an iOS symbol file.&lt;/p&gt;

&lt;h4&gt;
  
  
  Automatically Uploading the iOS Symbol File
&lt;/h4&gt;

&lt;p&gt;1) Download the &lt;a href="https://appfile1.hicloud.com/FileServer/getFile/app/011/111/111/0000000000011111111.20210209092523.34910175183564543772200303094023:20471231000000:0001:B23FB30E45653EFE85008C313B14476B0A7A557FA6553FC17E8CBB6FB0752C90.zip?needInitFileName=true"&gt;script&lt;/a&gt; used for automatically uploading the iOS symbol file.&lt;/p&gt;

&lt;p&gt;2) Build the script in Xcode.&lt;/p&gt;

&lt;p&gt;a) Double-click the Xcode project and click &lt;strong&gt;New Run Script Phase&lt;/strong&gt; under &lt;strong&gt;Build Phases&lt;/strong&gt; for the target.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7ns9CeYS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t59a7tka83vxubr53qw9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7ns9CeYS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t59a7tka83vxubr53qw9.png" alt="Image descriptio" width="739" height="244"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;b) Open &lt;strong&gt;dsymUploader.sh&lt;/strong&gt; in the script package, copy all content, and paste it to &lt;strong&gt;Run Script Phase&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4SCI02Cy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0xrjyo4yjf8838rprw4x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4SCI02Cy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0xrjyo4yjf8838rprw4x.png" alt="Image descriptio" width="880" height="419"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;c) Enter your project information in the run script.&lt;br&gt;
Find the following parameters and their values in the configuration file: &lt;strong&gt;&amp;lt;your_app_id&amp;gt;&lt;/strong&gt;: app ID; &lt;strong&gt;&amp;lt;your_client_id&amp;gt;&lt;/strong&gt;: client ID of your project; &lt;strong&gt;&amp;lt;your_agcgw_url&amp;gt;&lt;/strong&gt;: URL of AppGallery Connect; &lt;strong&gt;&amp;lt;your_collector_url&amp;gt;&lt;/strong&gt;: URL of HUAWEI Analytics; &lt;strong&gt;&amp;lt;your_client_secret&amp;gt;&lt;/strong&gt;: client secret of your project, which can be obtained under &lt;strong&gt;Project settings &amp;gt; General information&lt;/strong&gt; in AppGallery Connect.&lt;br&gt;
d) By default, the symbol file is not uploaded in debug mode or when compiled using a simulator. To modify this, set the values of the following parameters to 1:&lt;br&gt;
UPLOAD_DEBUG_SYMBOLS=1&lt;br&gt;
UPLOAD_SIMULATOR_SYMBOLS=1&lt;/p&gt;

&lt;p&gt;3) The symbol file is then automatically uploaded to AppGallery Connect each time the Xcode project is compiled. The log information is as follows:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--on6WXx1z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k90fg5sxcojnvxjn6brs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--on6WXx1z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k90fg5sxcojnvxjn6brs.png" alt="Image descriptio" width="650" height="516"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Manually Uploading the iOS Symbol File
&lt;/h4&gt;

&lt;p&gt;1) First, locate the &lt;strong&gt;dSYM&lt;/strong&gt; file. Go to &lt;strong&gt;Products&lt;/strong&gt; in Xcode, right-click &lt;strong&gt;xxx.app&lt;/strong&gt;, choose &lt;strong&gt;Show in Finder&lt;/strong&gt;, and locate the generated &lt;strong&gt;xxx.app.dSYM&lt;/strong&gt; file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7SEg5Jvz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ljoxyaqff5xwt5njuam7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7SEg5Jvz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ljoxyaqff5xwt5njuam7.png" alt="Image descriptio" width="525" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;2) Right-click the &lt;strong&gt;xxx.app.dSYM&lt;/strong&gt; file and choose &lt;strong&gt;Show Package Contents&lt;/strong&gt;. In the &lt;strong&gt;Contents/Resources/DWARF/&lt;/strong&gt; directory, find the file with the same name as your app, and compress the file into a ZIP package. Then sign in to AppGallery Connect, click &lt;strong&gt;My projects&lt;/strong&gt;, click your project card, and select your app. Go to &lt;strong&gt;Quality &amp;gt; Crash &amp;gt; Mapping file &amp;gt; iOS symbol files&lt;/strong&gt;, and click &lt;strong&gt;Upload file&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--meU9SL3v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hafrf45dui33i5fzy9ka.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--meU9SL3v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hafrf45dui33i5fzy9ka.png" alt="Image descriptio" width="880" height="289"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;3) You can click &lt;strong&gt;View upload records&lt;/strong&gt; to view upload records or delete a specific file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YWWPoNQG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t68xo0nu1wovb3g8zxhd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YWWPoNQG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t68xo0nu1wovb3g8zxhd.png" alt="Image descriptio" width="880" height="365"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>huawei</category>
      <category>ios</category>
      <category>crash</category>
      <category>appgallery</category>
    </item>
    <item>
      <title>APM for iOS Apps</title>
      <dc:creator>Josh</dc:creator>
      <pubDate>Thu, 10 Mar 2022 10:16:05 +0000</pubDate>
      <link>https://forem.com/josholadele/apm-for-ios-apps-45ln</link>
      <guid>https://forem.com/josholadele/apm-for-ios-apps-45ln</guid>
      <description>&lt;p&gt;&lt;strong&gt;Introduction&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Overview&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;App Performance Management (APM) provides minute-level app performance monitoring capabilities. You can view and analyze app performance data that APM collects, to gain a clear understanding of real-time online app performance, helping you quickly and accurately rectify app performance problems and enhance user experience.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What You Will Create&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this codelab, you will build an app that integrates APM, manually trigger a network request to test the APM service, and learn how to view and analyze app performance problems with APM.&lt;br&gt;
During app development and debugging, you may need to disable APM performance monitoring, which can be done (or re-enabled) by Remote Configuration. Moreover, the APM SDK provides a performance collection API allowing users to determine whether they can enable the APM performance monitoring function in the app.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What You Will Learn&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this codelab, you will learn how to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Integrate APM into your app.&lt;/li&gt;
&lt;li&gt;View and analyze app performance data on the APM page in AppGallery Connect.&lt;/li&gt;
&lt;li&gt;Enable and disable APM performance monitoring.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What You Will Need&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Development Environment Requirements&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mac with Xcode 10.1 or later installed&lt;/li&gt;
&lt;li&gt;CocoaPods 1.4.0 or later installed&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.huawei.com/consumer/en/doc/start/registration-and-verification-0000001053628148"&gt;A HUAWEI ID&lt;/a&gt;, whose identity has been verified&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Device Requirements&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An iPhone or a simulator for testing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Integration Preparations&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Before integrating APM, you must complete the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a project in AppGallery Connect.&lt;/li&gt;
&lt;li&gt;Add an app to your project.&lt;/li&gt;
&lt;li&gt;Create an Xcode project.&lt;/li&gt;
&lt;li&gt;Integrate the SDK into your Xcode project.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: You need to register as a developer to complete the operations above.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Configuring the Development Environment&lt;/strong&gt;&lt;/p&gt;
&lt;h5&gt;
  
  
  Enabling HUAWEI Analytics
&lt;/h5&gt;

&lt;p&gt;The APM service uses &lt;a href="https://developer.huawei.com/consumer/en/doc/development/HMS-Guides/79044452"&gt;HUAWEI Analytics&lt;/a&gt; to report performance management events. Therefore, you must enable HUAWEI Analytics before integrating the APM SDK.&lt;/p&gt;
&lt;h5&gt;
  
  
  Integrating the Service SDK
&lt;/h5&gt;

&lt;p&gt;If you are using Xcode, you need to integrate the APM SDK into your Xcode project with CocoaPods.&lt;/p&gt;

&lt;p&gt;1) Add the configuration file in AppGallery Connect to your Xcode project.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sign in to AppGallery Connect and click My projects.&lt;/li&gt;
&lt;li&gt;Click your project card and select an app to be integrated from the app drop-down list on the top.&lt;/li&gt;
&lt;li&gt;Go to Project settings &amp;gt; General information and download agconnect-services.plist under App information.&lt;/li&gt;
&lt;li&gt;Copy the agconnect-services.plist file to your app's root directory.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ow7DPPr0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8revpcez9939zk8wmctb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ow7DPPr0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8revpcez9939zk8wmctb.png" alt="Image descriptio" width="880" height="343"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;2) Create a Podfile.&lt;/p&gt;

&lt;p&gt;Open the CLI and navigate to the location of the Xcode project. Then, create a Podfile. Skip this step if a Podfile already exists.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd project-directory
pod init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3) Edit the Podfile.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Integrate the Analytics SDK, APM SDK, and Remote Configuration SDK.
Edit the Podfile to add pod dependencies of the Analytics SDK, AppGallery Connect SDK, APM SDK, and Remote Configuration SDK.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;target 'apmIOSDemo' do
   pod 'AGConnectCore'
    pod 'AGConnectRemoteConfig'
    pod 'HiAnalytics', '~&amp;gt; 5.0.4.23'
    pod 'AGConnectAPM'
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Install the pod and open the .xcworkspace file to view the project.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pod install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Designing the UI&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can create a page in your Xcode project and design the UI according to the following figure. Only three buttons are needed: one for initiating a network request, one for disabling APM, and the last one for enabling APM.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--X1TAyjKv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c5isc9uy7318ookixacn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--X1TAyjKv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c5isc9uy7318ookixacn.png" alt="Image descriptio" width="674" height="1196"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reporting Network Events&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can manually add a time-consuming cyclic log recording operation to trigger a network request, and check whether the launch duration and network performance indicators on the APM page are normal. App launch and screen events are automatically reported when the app is launched. The procedure is as follows: &lt;/p&gt;

&lt;p&gt;1) Initialize the AppGallery Connect SDK, import the header file to the AppDelegate.m file of the project, and add the initialization code. Add a time-consuming cyclic log recording operation, and change the number of cycles while monitoring changes to the launch duration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#import "AppDelegate.h"
#import &amp;lt;AGConnectCore/AGConnectCore.h&amp;gt;
@implementation AppDelegate
- (BOOL)Application:(UIApplication *)Application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override the code for customization after the app launch.
[AGCInstance startup];// Initialization.
long sum = 0;
for (int i = 0; i &amp;lt; 9999; i++) {
sum = sum + i;
NSLog(@"sum=%ld",sum);
}
return YES;
}
…
@end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2) Create a &lt;strong&gt;Send Network Request&lt;/strong&gt; test button in &lt;strong&gt;ViewController&lt;/strong&gt; in your app. You can tap the button to call &lt;strong&gt;sendNetworkRequest&lt;/strong&gt; to trigger a network request event.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#import "ViewController.h"
#import "AGConnectAPM/AGConnectAPM.H"
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIButton* sendNetworkRequestBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
sendNetworkRequestBtn.frame = CGRectMake(80, 100, 200, 40);
[sendNetworkRequestBtn setTitle:@"Send Network Request" forState:UIControlStateNormal];
[sendNetworkRequestBtn addTarget:self action:@selector(sendNetworkRequest) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:sendNetworkRequestBtn];
}
- (void)sendNetworkRequest {
NSURL *url = [NSURL URLWithString:@"https://developer.huawei.com/consumer/cn/"];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *task = [session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
NSString* str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"result: %@", str);
}];
[task resume];
}
…
@end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Enabling/Disabling Performance Data Collection&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;1) Create an APM Collection Off test button in ViewController in your app. You can tap the button to call the enableCollection method to disable APM.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#import "ViewController.h"
#import "AGConnectAPM/AGConnectAPM.H"
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIButton* disableBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
disableBtn.frame = CGRectMake(80, 150, 200, 40);
[disableBtn setTitle:@"APM Collection Off" forState:UIControlStateNormal];
[disableBtn addTarget:self action:@selector(disableCollection) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:disableBtn];
}
- (void)disableCollection {
[[AGCAPM sharedInstance] enableCollection:NO];// Disable APM.
}
…
@end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2) Create an &lt;strong&gt;APM Collection On&lt;/strong&gt; test button in &lt;strong&gt;ViewController&lt;/strong&gt; in your app. You can tap the button to call the &lt;strong&gt;enableCollection&lt;/strong&gt; method to enable APM.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- (void)enableCollection {
[[AGCAPM sharedInstance] enableCollection:YES];// Enable APM.
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Viewing and Analyzing App Performance Data&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;1) Sign in to &lt;a href="https://developer.huawei.com/consumer/en/service/josp/agc/index.html#/"&gt;AppGallery Connect&lt;/a&gt; and click &lt;strong&gt;My projects&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;2) Click your project card and select your app from the app drop-down list at the top.&lt;/p&gt;

&lt;p&gt;3) Go to &lt;strong&gt;Quality &amp;gt; APM&lt;/strong&gt;. Click &lt;strong&gt;Overview&lt;/strong&gt;. The overview presents indicators including the launch duration (by version), slow frame rate (top 5 view controllers), frozen frame rate (top 5 view controllers), network request duration (top 5 countries/regions), and network request success rate (trend over time).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---jhaK_95--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dysdbbzh5dxqa2sw4srr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---jhaK_95--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dysdbbzh5dxqa2sw4srr.png" alt="Image descriptio" width="880" height="551"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;4) Go to &lt;strong&gt;App analysis &amp;gt; App launch duration&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yvq7zWcz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0p12pxhpnnuxj2nkeky2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yvq7zWcz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0p12pxhpnnuxj2nkeky2.png" alt="Image descriptio" width="880" height="588"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;5) Click &lt;strong&gt;View details&lt;/strong&gt; to bring up the app launch duration details page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vDob8npS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v86ti3xg381jt7lmtnbc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vDob8npS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v86ti3xg381jt7lmtnbc.png" alt="Image descriptio" width="880" height="331"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;6) (Optional) Select Modify threshold, set the threshold, and then click Ok.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ii5812Eo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wc1btqb836594ta3f7xe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ii5812Eo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wc1btqb836594ta3f7xe.png" alt="Image descriptio" width="669" height="295"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;7) Go to App analysis &amp;gt; Native page rendering to view details about the page freezing information (corresponding to ViewController), and then make optimizations accordingly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZnjGXtzu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0fdt5q1obcu5nscv037q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZnjGXtzu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0fdt5q1obcu5nscv037q.png" alt="Image descriptio" width="880" height="331"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Disabling APM&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;1) Method 1: You can disable APM for a released app on the cloud. On the App performance management page, click the Configuration tab and find Overall switch. Then, disable the switch.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--udtjpXV9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l6gv6pbf3psecqjuexf8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--udtjpXV9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l6gv6pbf3psecqjuexf8.png" alt="Image descriptio" width="880" height="343"&gt;&lt;/a&gt;&lt;br&gt;
2) Method 2: You can disable the performance data reporting function for some versions. On the App performance management page, click the Configuration tab and find Version blocklist settings. Click Add to add the disabled version number to the list.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Zz9Anfs1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3xoobqkw15na3h7z8n7w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Zz9Anfs1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3xoobqkw15na3h7z8n7w.png" alt="Image descriptio" width="880" height="156"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;3) Method 3: If your app allows users to enable or disable performance monitoring, use the method provided by the APM SDK. Call &lt;strong&gt;getInstance&lt;/strong&gt; for initialization and call &lt;strong&gt;enableCollection&lt;/strong&gt; to enable or disable performance monitoring. Performance monitoring in apps will be disabled where applicable. If users disable performance monitoring in apps, APM will not collect performance data even if the performance monitoring function is enabled through Remote Configuration in AppGallery Connect.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Congratulations&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Well done. You have successfully created an app with APM integrated, and learned how to view and analyze app performance data. You can also disable or enable APM as needed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;References&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;API reference&lt;br&gt;
Sample code&lt;/p&gt;

</description>
      <category>ios</category>
      <category>huawei</category>
      <category>apm</category>
    </item>
    <item>
      <title>Creating a Remote Configuration Experiment Using A/B Testing</title>
      <dc:creator>Josh</dc:creator>
      <pubDate>Fri, 04 Mar 2022 09:56:40 +0000</pubDate>
      <link>https://forem.com/josholadele/creating-a-remote-configuration-experiment-using-ab-testing-2k5o</link>
      <guid>https://forem.com/josholadele/creating-a-remote-configuration-experiment-using-ab-testing-2k5o</guid>
      <description>&lt;p&gt;A/B Testing allows you to run notifications experiments or Remote Configuration experiments, create A/B tests that engage with different audiences to compare your variants, and measure the aspects of your business that matter most to you, so that you can make informed decisions at all time.&lt;/p&gt;

&lt;p&gt;Let’s take a look at how this process works in practice.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Integrating the Remote Configuration SDK and Setting the Default Parameter Value&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;a) Configure the Maven repository address in the project-level &lt;strong&gt;build.gradle&lt;/strong&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;buildscript {
    repositories {
        maven { url 'https://developer.huawei.com/repo/'}
    }
    dependencies {
        classpath 'com.huawei.agconnect:agcp:1.5.2.300'
    }
}
allprojects {
    repositories {
        maven { url 'https://developer.huawei.com/repo/'}
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;b) Add the AppGallery Connect plugin and the JSON configuration file.&lt;br&gt;
Add the AppGallery Connect plugin to the app-level build.gradle file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apply plugin: 'com.huawei.agconnect'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sign in to AppGallery Connect, click &lt;strong&gt;My projects&lt;/strong&gt;, click your project card, and go to &lt;strong&gt;Project settings &amp;gt; General information&lt;/strong&gt;. Download the JSON configuration file and add it to the &lt;strong&gt;app&lt;/strong&gt; directory of your project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--w2Oql31f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ywi5vrgsx0dxpvdu4oif.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--w2Oql31f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ywi5vrgsx0dxpvdu4oif.png" alt="Image 7" width="384" height="289"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;C) Add the SDK dependency to the app-level &lt;strong&gt;build.gradle&lt;/strong&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dependencies {
implementation 'com.huawei.agconnect:agconnect-remoteconfig:1.5.2.300'
implementation 'com.huawei.hms:hianalytics:5.3.1.300'
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;d) Set the default parameter value.&lt;br&gt;
You can create a button for obtaining the updated parameter value from Remote Configuration.&lt;/p&gt;

&lt;p&gt;Configure the default parameter value in the button, and apply the &lt;strong&gt;fetch&lt;/strong&gt; method to obtain the updated parameter value from Remote Configuration. Set the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Override
protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);

 HiAnalyticsTools.enableLog();
 HiAnalyticsInstance instance = HiAnalytics.getInstance(this);
 getAAID();
 findViewById(R.id.button).setOnClickListener(view -&amp;gt; {
  getRemoteCongfig();
 });

}
public void getRemoteCongfig() {
 // Obtain the Remote Configuration instance.
 config = AGConnectConfig.getInstance();
 Map&amp;lt;String, Object&amp;gt; defaultValue = new HashMap&amp;lt;&amp;gt;();
 // Add a key-value pair.
 defaultValue.put("welcome_string", "this is a default welcome_slogan");
 config.applyDefault(defaultValue);

 config.fetch(10).addOnSuccessListener(configValues -&amp;gt; {
  config.apply(configValues);
  String newSlogan = config.getValueAsString("welcome_string");
  Log.i(TAG, "RemoteConfig Success: " + newSlogan);
 }).addOnFailureListener(e1 -&amp;gt;
   Log.e(TAG, "getRemoteConfig failed: " + e1.getMessage())
 );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Integrating Analytics Kit&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To generate reports for A/B tests, HUAWEI Analytics will need to be enabled, since it automatically captures A/B Testing events.&lt;/p&gt;

&lt;p&gt;a) Add the SDK dependency to the app-level &lt;strong&gt;build.gradle&lt;/strong&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dependencies {
implementation 'com.huawei.hms:hianalytics:5.3.1.300'
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;b) Initialize HUAWEI Analytics in &lt;strong&gt;onCreate&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HiAnalyticsTools.enableLog();
HiAnalyticsInstance instance = HiAnalytics.getInstance(this);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Setting the Parameter Value in Remote Configuration&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Sign in to &lt;a href="https://developer.huawei.com/consumer/en/service/josp/agc/index.html#/"&gt;AppGallery Connect&lt;/a&gt;, click &lt;strong&gt;My projects&lt;/strong&gt;, click the project card, and select your app. Go to &lt;strong&gt;Grow &amp;gt; Remote Configuration&lt;/strong&gt;, and click &lt;strong&gt;New parameter&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--O8dCAkZ---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1l86h473e81rwrwq13qg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--O8dCAkZ---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1l86h473e81rwrwq13qg.png" alt="Image 8" width="880" height="273"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note: Make sure that the parameter name is the same as that of the default parameter.&lt;/p&gt;

&lt;p&gt;Save the parameter settings and click &lt;strong&gt;Release&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Creating a Remote Configuration Experiment&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In &lt;a href="https://developer.huawei.com/consumer/en/service/josp/agc/index.html#/"&gt;AppGallery Connect&lt;/a&gt;, click &lt;strong&gt;My projects&lt;/strong&gt;, click the project card, and select your app. Go to &lt;strong&gt;Grow &amp;gt; A/B Testing&lt;/strong&gt;. On the &lt;strong&gt;A/B Testing&lt;/strong&gt; page, select &lt;strong&gt;Remote configuration&lt;/strong&gt; from the &lt;strong&gt;New experiment&lt;/strong&gt; drop-down list.&lt;/p&gt;

&lt;p&gt;Configure a higher user percentage for &lt;strong&gt;Target users&lt;/strong&gt;, and skip &lt;strong&gt;Activation event&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Set &lt;strong&gt;Conditions&lt;/strong&gt; to &lt;strong&gt;Language&lt;/strong&gt;, and select the languages as needed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Boi0rE_1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/arv0erlya1h6cymev9bv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Boi0rE_1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/arv0erlya1h6cymev9bv.png" alt="Image 1" width="880" height="327"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Configure &lt;strong&gt;Parameter&lt;/strong&gt; for &lt;strong&gt;Treatment &amp;amp; control groups&lt;/strong&gt; as follows.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--d9tlD3Gr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wygxbs13pwfvsin0xy7v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--d9tlD3Gr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wygxbs13pwfvsin0xy7v.png" alt="Image 2" width="880" height="369"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Set &lt;strong&gt;Indicators to track&lt;/strong&gt;, for example, to &lt;strong&gt;Click-through rate&lt;/strong&gt;. Click &lt;strong&gt;Save&lt;/strong&gt; to save all configurations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Starting Your Experiment and Fetching the Parameter Value from Remote Configuration&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;a) Click &lt;strong&gt;Start&lt;/strong&gt; under the &lt;strong&gt;Operation&lt;/strong&gt; column of the record to run the experiment in AppGallery Connect.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Fnkc_vys--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iskqvp0ugenrsbe8cveo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Fnkc_vys--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iskqvp0ugenrsbe8cveo.png" alt="Image 3" width="880" height="345"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;b) Run your app, and click the button to fetch the parameter value from Remote Configuration.&lt;br&gt;
The log is as follows:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OsDfX7jo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hpkbjwctm0a0aadjov87.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OsDfX7jo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hpkbjwctm0a0aadjov87.png" alt="Image 4" width="819" height="159"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pay attention to the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can click Test under the Operation column of the experiment record. The anonymous application identifier (AAID) of the test device can be obtained as follows:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public void getAAID() {
 Task&amp;lt;AAIDResult&amp;gt; idResult = HmsInstanceId.getInstance(this).getAAID();
 idResult.addOnSuccessListener(new OnSuccessListener&amp;lt;AAIDResult&amp;gt;() {
  @Override
  public void onSuccess(AAIDResult aaidResult) {
   // Obtained the AAID successfully.
   String aaid = aaidResult.getId();
   Log.d(TAG, "getAAID successfully, aaid is " + aaid );
  }
 }).addOnFailureListener(new OnFailureListener() {
  @Override
  public void onFailure(Exception myException) {
   // Failed to obtain the AAID.
   Log.d(TAG, "getAAID failed, catch exceptio : " + myException);
  }
 });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zbwkjUVq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3ro1cnciguoic56osfaa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zbwkjUVq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3ro1cnciguoic56osfaa.png" alt="Image 5" width="880" height="268"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Viewing the Experiment Report&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Click &lt;strong&gt;View report&lt;/strong&gt; under the &lt;strong&gt;Operation&lt;/strong&gt; column of a record to view the details for the experiment.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7MFkPkGI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a5y1c4yg9vqsewhqrjwz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7MFkPkGI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a5y1c4yg9vqsewhqrjwz.png" alt="Image 6" width="880" height="401"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;References&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://developer.huawei.com/consumer/en/doc/development/AppGallery-connect-Guides/agc-abtest-introduction-0000001058210679"&gt;Service introduction of A/B Testing&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://developer.huawei.com/consumer/en/doc/development/AppGallery-connect-Guides/agc-remoteconfig-android-getstarted-0000001056347165"&gt;Get started tutorials for Remote Configuration&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://developer.huawei.com/consumer/en/doc/development/HMSCore-Guides/android-dev-process-0000001050163813"&gt;Get started tutorials of HUAWEI Analytics&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>android</category>
      <category>abtesting</category>
      <category>huawei</category>
    </item>
  </channel>
</rss>
