Loading api/current.xml +13 −0 Original line number Diff line number Diff line Loading @@ -86967,6 +86967,19 @@ <parameter name="listener" type="android.media.MediaRecorder.OnInfoListener"> </parameter> </method> <method name="setOrientationHint" return="void" abstract="false" native="false" synchronized="false" static="false" final="false" deprecated="not deprecated" visibility="public" > <parameter name="degrees" type="int"> </parameter> </method> <method name="setOutputFile" return="void" abstract="false" core/res/res/values/attrs_manifest.xml +3 −4 Original line number Diff line number Diff line Loading @@ -90,10 +90,9 @@ <attr name="manageSpaceActivity" format="string" /> <!-- Option to let applications specify that user data can/cannot be cleared. Some applications might not want to clear user data. Such applications can explicitly set this value to false. This flag is turned on by default unless explicitly set to false by applications. --> cleared. This flag is turned on by default. <em>This attribute is usable only by applications included in the system image. Third-party apps cannot use it.</em> --> <attr name="allowClearUserData" format="boolean" /> <!-- Option to let applications specify that user data should Loading core/tests/coretests/src/android/bluetooth/BluetoothStressTest.java +15 −0 Original line number Diff line number Diff line Loading @@ -94,6 +94,21 @@ public class BluetoothStressTest extends InstrumentationTestCase { mTestUtils.disable(adapter); } public void testAcceptPair() { int iterations = BluetoothTestRunner.sPairIterations; BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); BluetoothDevice device = adapter.getRemoteDevice(BluetoothTestRunner.sPairAddress); mTestUtils.enable(adapter); for (int i = 0; i < iterations; i++) { mTestUtils.writeOutput("acceptPair iteration " + (i + 1) + " of " + iterations); mTestUtils.acceptPair(adapter, device, BluetoothTestRunner.sPairPasskey, BluetoothTestRunner.sPairPin); mTestUtils.unpair(adapter, device); } mTestUtils.disable(adapter); } public void testConnectA2dp() { int iterations = BluetoothTestRunner.sConnectA2dpIterations; BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); Loading core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java +21 −8 Original line number Diff line number Diff line Loading @@ -635,6 +635,17 @@ public class BluetoothTestUtils extends Assert { } public void pair(BluetoothAdapter adapter, BluetoothDevice device, int passkey, byte[] pin) { pairOrAcceptPair(adapter, device, passkey, pin, true); } public void acceptPair(BluetoothAdapter adapter, BluetoothDevice device, int passkey, byte[] pin) { pairOrAcceptPair(adapter, device, passkey, pin, false); } private void pairOrAcceptPair(BluetoothAdapter adapter, BluetoothDevice device, int passkey, byte[] pin, boolean pair) { String methodName = pair ? "pair()" : "acceptPair()"; int mask = PairReceiver.PAIR_FLAG; int pairMask = PairReceiver.PAIR_STATE_BONDING | PairReceiver.PAIR_STATE_BONDED; Loading @@ -642,7 +653,7 @@ public class BluetoothTestUtils extends Assert { mReceivers.add(pairReceiver); if (!adapter.isEnabled()) { fail("pair() bluetooth not enabled"); fail(methodName + " bluetooth not enabled"); } int state = device.getBondState(); Loading @@ -656,10 +667,12 @@ public class BluetoothTestUtils extends Assert { break; case BluetoothDevice.BOND_NONE: assertFalse(adapter.getBondedDevices().contains(device)); if (pair) { assertTrue(device.createBond()); } break; default: fail("pair() invalide state: state=" + state); fail(methodName + " invalide state: state=" + state); } long s = System.currentTimeMillis(); Loading @@ -669,8 +682,8 @@ public class BluetoothTestUtils extends Assert { assertTrue(adapter.getBondedDevices().contains(device)); if ((pairReceiver.getFiredFlags() & mask) == mask && (pairReceiver.getPairFiredFlags() & pairMask) == pairMask) { writeOutput(String.format("pair() completed in %d ms: device=%s", (System.currentTimeMillis() - s), device)); writeOutput(String.format("%s completed in %d ms: device=%s", methodName, (System.currentTimeMillis() - s), device)); mReceivers.remove(pairReceiver); mContext.unregisterReceiver(pairReceiver); return; Loading @@ -682,9 +695,9 @@ public class BluetoothTestUtils extends Assert { int firedFlags = pairReceiver.getFiredFlags(); int pairFiredFlags = pairReceiver.getPairFiredFlags(); pairReceiver.resetFiredFlags(); fail(String.format("pair() timeout: state=%d (expected %d), flags=0x%x (expected 0x%x), " + "pairFlags=0x%x (expected 0x%x)", state, BluetoothDevice.BOND_BONDED, firedFlags, mask, pairFiredFlags, pairMask)); fail(String.format("%s timeout: state=%d (expected %d), flags=0x%x (expected 0x%x), " + "pairFlags=0x%x (expected 0x%x)", methodName, state, BluetoothDevice.BOND_BONDED, firedFlags, mask, pairFiredFlags, pairMask)); } public void unpair(BluetoothAdapter adapter, BluetoothDevice device) { Loading docs/html/guide/developing/tools/proguard.jd 0 → 100644 +187 −0 Original line number Diff line number Diff line page.title=ProGuard @jd:body <div id="qv-wrapper"> <div id="qv"> <h2>In this document</h2> <ol> <li><a href="#enabling">Enabling ProGuard</a></li> <li><a href="#configuring">Configuring ProGuard</a></li> <li> <a href="#decoding">Decoding Obfuscated Stack Traces</a> <ol> <li><a href="#considerations">Debugging considerations for published applications</a></li> </ol> </li> </ol> <h2>See also</h2> <ol> <li><a href="http://proguard.sourceforge.net/manual/introduction.html">ProGuard Manual</a></li> <li><a href="http://proguard.sourceforge.net/manual/retrace/introduction.html">ProGuard ReTrace Manual</a></li> </ol> </div> </div> <p>The ProGuard tool shrinks, optimizes, and obfuscates your code by removing unused code and renaming classes, fields, and methods with semantically obscure names. The result is a smaller sized <code>.apk</code> file that is more difficult to reverse engineer. Because ProGuard makes your application harder to reverse engineer, it is important that you use it when your application utilizes features that are sensitive to security like when you are <a href="{@docRoot}guide/publishing/licensing.html">Licensing Your Applications</a>.</p> <p>ProGuard is integrated into the Android build system, so you do not have to invoke it manually. ProGuard runs only when you build your application in release mode, so you do not have to deal with obfuscated code when you build your application in debug mode. Having ProGuard run is completely optional, but highly recommended.</p> <p>This document describes how to enable and configure ProGuard as well as use the <code>retrace</code> tool to decode obfuscated stack traces.</p> <h2 id="enabling">Enabling ProGuard</h2> <p>When you create an Android project, a <code>proguard.cfg</code> file is automatically generated in the root directory of the project. This file defines how ProGuard optimizes and obfuscates your code, so it is very important that you understand how to customize it for your needs. The default configuration file only covers general cases, so you most likely have to edit it for your own needs. See the following section about <a href="#configuring">Configuring ProGuard</a> for information on customizing the ProGuard configuration file.</p> <p>To enable ProGuard so that it runs as part of an Ant or Eclipse build, set the <code>proguard.config</code> property in the <code><project_root>/default.properties</code> file. The path can be an absolute path or a path relative to the project's root.</p> <p>If you left the <code>proguard.cfg</code> file in its default location (the project's root directory), you can specify its location like this:</p> <pre class="no-pretty-print"> proguard.config=proguard.cfg </pre> <p> You can also move the the file to anywhere you want, and specify the absolute path to it: </p> <pre class="no-pretty-print"> proguard.config=/path/to/proguard.cfg </pre> <p>When you build your application in release mode, either by running <code>ant release</code> or by using the <em>Export Wizard</em> in Eclipse, the build system automatically checks to see if the <code>proguard.config</code> property is set. If it is, ProGuard automatically processes the application's bytecode before packaging everything into an <code>.apk</code> file. Building in debug mode does not invoke ProGuard, because it makes debugging more cumbersome.</p> <p>ProGuard outputs the following files after it runs:</p> <dl> <dt><code>dump.txt</code></dt> <dd>Describes the internal structure of all the class files in the <code>.apk</code> file</dd> <dt><code>mapping.txt</code></dt> <dd>Lists the mapping between the original and obfuscated class, method, and field names. This file is important when you receive a bug report from a release build, because it translates the obfuscated stack trace back to the original class, method, and member names. See <a href="#decoding">Decoding Obfuscated Stack Traces</a> for more information.</dd> <dt><code>seeds.txt</code></dt> <dd>Lists the classes and members that are not obfuscated</dd> <dt><code>usage.txt</code></dt> <dd>Lists the code that was stripped from the <code>.apk</code></dd> </ul> <p>These files are located in the following directories:</p> <ul> <li><code><project_root>/bin/proguard</code> if you are using Ant.</li> <li><code><project_root>/proguard</code> if you are using Eclipse.</li> </ul> <p class="caution"><strong>Caution:</strong> Every time you run a build in release mode, these files are overwritten with the latest files generated by ProGuard. Save a copy of them each time you release your application in order to de-obfuscate bug reports from your release builds. For more information on why saving these files is important, see <a href="#considerations">Debugging considerations for published applications</a>. </p> <h2 id="configuring">Configuring ProGuard</h2> <p>For some situations, the default configurations in the <code>proguard.cfg</code> file will suffice. However, many situations are hard for ProGuard to analyze correctly and it might remove code that it thinks is not used, but your application actually needs. Some examples include:</p> <ul> <li>a class that is referenced only in the <code>AndroidManifest.xml</code> file</li> <li>a method called from JNI</li> <li>dynamically referenced fields and methods</li> </ul> <p>The default <code>proguard.cfg</code> file tries to cover general cases, but you might encounter exceptions such as <code>ClassNotFoundException</code>, which happens when ProGuard strips away an entire class that your application calls.</p> <p>You can fix errors when ProGuard strips away your code by adding a <code>-keep</code> line in the <code>proguard.cfg</code> file. For example:</p> <pre> -keep public class <MyClass> </pre> <p>There are many options and considerations when using the <code>-keep</code> option, so it is highly recommended that you read the <a href="http://proguard.sourceforge.net/manual/introduction.html">ProGuard Manual</a> for more information about customizing your configuration file. The <a href= "http://proguard.sourceforge.net/manual/usage.html#keepoverview">Overview of Keep options</a> and <a href="http://proguard.sourceforge.net/index.html#/manual/examples.html">Examples section</a> are particularly helpful. The <a href= "http://proguard.sourceforge.net/manual/troubleshooting.html">Troubleshooting</a> section of the ProGuard Manual outlines other common problems you might encounter when your code gets stripped away.</p> <h2 id="decoding">Decoding Obfuscated Stack Traces</h2> <p>When your obfuscated code outputs a stack trace, the method names are obfuscated, which makes debugging hard, if not impossible. Fortunately, whenever ProGuard runs, it outputs a <code><project_root>/bin/proguard/mapping.txt</code> file, which shows you the original class, method, and field names mapped to their obfuscated names.</p> <p>The <code>retrace.bat</code> script on Windows or the <code>retrace.sh</code> script on Linux or Mac OS X can convert an obfuscated stack trace to a readable one. It is located in the <code><sdk_root>/tools/proguard/</code> directory. The syntax for executing the <code>retrace</code> tool is:</p> <pre>retrace.bat|retrace.sh [-verbose] mapping.txt [<stacktrace_file>]</pre> <p>For example:</p> <pre>retrace.bat -verbose mapping.txt obfuscated_trace.txt</pre> <p>If you do not specify a value for <em><stacktrace_file></em>, the <code>retrace</code> tool reads from standard input.</p> <h3 id="considerations">Debugging considerations for published applications</h3> <p>Save the <code>mapping.txt</code> file for every release that you publish to your users. By retaining a copy of the <code>mapping.txt</code> file for each release build, you ensure that you can debug a problem if a user encounters a bug and submits an obfuscated stack trace. A project's <code>mapping.txt</code> file is overwritten every time you do a release build, so you must be careful about saving the versions that you need.</p> <p>For example, say you publish an application and continue developing new features of the application for a new version. You then do a release build using ProGuard soon after. The build overwrites the previous <code>mapping.txt</code> file. A user submits a bug report containing a stack trace from the application that is currently published. You no longer have a way of debugging the user's stack trace, because the <code>mapping.txt</code> file associated with the version on the user's device is gone. There are other situations where your <code>mapping.txt</code> file can be overwritten, so ensure that you save a copy for every release that you anticipate you have to debug.</p> <p>How you save the <code>mapping.txt</code> file is your decision. For example, you can rename them to include a version or build number, or you can version control them along with your source code.</p> No newline at end of file Loading
api/current.xml +13 −0 Original line number Diff line number Diff line Loading @@ -86967,6 +86967,19 @@ <parameter name="listener" type="android.media.MediaRecorder.OnInfoListener"> </parameter> </method> <method name="setOrientationHint" return="void" abstract="false" native="false" synchronized="false" static="false" final="false" deprecated="not deprecated" visibility="public" > <parameter name="degrees" type="int"> </parameter> </method> <method name="setOutputFile" return="void" abstract="false"
core/res/res/values/attrs_manifest.xml +3 −4 Original line number Diff line number Diff line Loading @@ -90,10 +90,9 @@ <attr name="manageSpaceActivity" format="string" /> <!-- Option to let applications specify that user data can/cannot be cleared. Some applications might not want to clear user data. Such applications can explicitly set this value to false. This flag is turned on by default unless explicitly set to false by applications. --> cleared. This flag is turned on by default. <em>This attribute is usable only by applications included in the system image. Third-party apps cannot use it.</em> --> <attr name="allowClearUserData" format="boolean" /> <!-- Option to let applications specify that user data should Loading
core/tests/coretests/src/android/bluetooth/BluetoothStressTest.java +15 −0 Original line number Diff line number Diff line Loading @@ -94,6 +94,21 @@ public class BluetoothStressTest extends InstrumentationTestCase { mTestUtils.disable(adapter); } public void testAcceptPair() { int iterations = BluetoothTestRunner.sPairIterations; BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); BluetoothDevice device = adapter.getRemoteDevice(BluetoothTestRunner.sPairAddress); mTestUtils.enable(adapter); for (int i = 0; i < iterations; i++) { mTestUtils.writeOutput("acceptPair iteration " + (i + 1) + " of " + iterations); mTestUtils.acceptPair(adapter, device, BluetoothTestRunner.sPairPasskey, BluetoothTestRunner.sPairPin); mTestUtils.unpair(adapter, device); } mTestUtils.disable(adapter); } public void testConnectA2dp() { int iterations = BluetoothTestRunner.sConnectA2dpIterations; BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); Loading
core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java +21 −8 Original line number Diff line number Diff line Loading @@ -635,6 +635,17 @@ public class BluetoothTestUtils extends Assert { } public void pair(BluetoothAdapter adapter, BluetoothDevice device, int passkey, byte[] pin) { pairOrAcceptPair(adapter, device, passkey, pin, true); } public void acceptPair(BluetoothAdapter adapter, BluetoothDevice device, int passkey, byte[] pin) { pairOrAcceptPair(adapter, device, passkey, pin, false); } private void pairOrAcceptPair(BluetoothAdapter adapter, BluetoothDevice device, int passkey, byte[] pin, boolean pair) { String methodName = pair ? "pair()" : "acceptPair()"; int mask = PairReceiver.PAIR_FLAG; int pairMask = PairReceiver.PAIR_STATE_BONDING | PairReceiver.PAIR_STATE_BONDED; Loading @@ -642,7 +653,7 @@ public class BluetoothTestUtils extends Assert { mReceivers.add(pairReceiver); if (!adapter.isEnabled()) { fail("pair() bluetooth not enabled"); fail(methodName + " bluetooth not enabled"); } int state = device.getBondState(); Loading @@ -656,10 +667,12 @@ public class BluetoothTestUtils extends Assert { break; case BluetoothDevice.BOND_NONE: assertFalse(adapter.getBondedDevices().contains(device)); if (pair) { assertTrue(device.createBond()); } break; default: fail("pair() invalide state: state=" + state); fail(methodName + " invalide state: state=" + state); } long s = System.currentTimeMillis(); Loading @@ -669,8 +682,8 @@ public class BluetoothTestUtils extends Assert { assertTrue(adapter.getBondedDevices().contains(device)); if ((pairReceiver.getFiredFlags() & mask) == mask && (pairReceiver.getPairFiredFlags() & pairMask) == pairMask) { writeOutput(String.format("pair() completed in %d ms: device=%s", (System.currentTimeMillis() - s), device)); writeOutput(String.format("%s completed in %d ms: device=%s", methodName, (System.currentTimeMillis() - s), device)); mReceivers.remove(pairReceiver); mContext.unregisterReceiver(pairReceiver); return; Loading @@ -682,9 +695,9 @@ public class BluetoothTestUtils extends Assert { int firedFlags = pairReceiver.getFiredFlags(); int pairFiredFlags = pairReceiver.getPairFiredFlags(); pairReceiver.resetFiredFlags(); fail(String.format("pair() timeout: state=%d (expected %d), flags=0x%x (expected 0x%x), " + "pairFlags=0x%x (expected 0x%x)", state, BluetoothDevice.BOND_BONDED, firedFlags, mask, pairFiredFlags, pairMask)); fail(String.format("%s timeout: state=%d (expected %d), flags=0x%x (expected 0x%x), " + "pairFlags=0x%x (expected 0x%x)", methodName, state, BluetoothDevice.BOND_BONDED, firedFlags, mask, pairFiredFlags, pairMask)); } public void unpair(BluetoothAdapter adapter, BluetoothDevice device) { Loading
docs/html/guide/developing/tools/proguard.jd 0 → 100644 +187 −0 Original line number Diff line number Diff line page.title=ProGuard @jd:body <div id="qv-wrapper"> <div id="qv"> <h2>In this document</h2> <ol> <li><a href="#enabling">Enabling ProGuard</a></li> <li><a href="#configuring">Configuring ProGuard</a></li> <li> <a href="#decoding">Decoding Obfuscated Stack Traces</a> <ol> <li><a href="#considerations">Debugging considerations for published applications</a></li> </ol> </li> </ol> <h2>See also</h2> <ol> <li><a href="http://proguard.sourceforge.net/manual/introduction.html">ProGuard Manual</a></li> <li><a href="http://proguard.sourceforge.net/manual/retrace/introduction.html">ProGuard ReTrace Manual</a></li> </ol> </div> </div> <p>The ProGuard tool shrinks, optimizes, and obfuscates your code by removing unused code and renaming classes, fields, and methods with semantically obscure names. The result is a smaller sized <code>.apk</code> file that is more difficult to reverse engineer. Because ProGuard makes your application harder to reverse engineer, it is important that you use it when your application utilizes features that are sensitive to security like when you are <a href="{@docRoot}guide/publishing/licensing.html">Licensing Your Applications</a>.</p> <p>ProGuard is integrated into the Android build system, so you do not have to invoke it manually. ProGuard runs only when you build your application in release mode, so you do not have to deal with obfuscated code when you build your application in debug mode. Having ProGuard run is completely optional, but highly recommended.</p> <p>This document describes how to enable and configure ProGuard as well as use the <code>retrace</code> tool to decode obfuscated stack traces.</p> <h2 id="enabling">Enabling ProGuard</h2> <p>When you create an Android project, a <code>proguard.cfg</code> file is automatically generated in the root directory of the project. This file defines how ProGuard optimizes and obfuscates your code, so it is very important that you understand how to customize it for your needs. The default configuration file only covers general cases, so you most likely have to edit it for your own needs. See the following section about <a href="#configuring">Configuring ProGuard</a> for information on customizing the ProGuard configuration file.</p> <p>To enable ProGuard so that it runs as part of an Ant or Eclipse build, set the <code>proguard.config</code> property in the <code><project_root>/default.properties</code> file. The path can be an absolute path or a path relative to the project's root.</p> <p>If you left the <code>proguard.cfg</code> file in its default location (the project's root directory), you can specify its location like this:</p> <pre class="no-pretty-print"> proguard.config=proguard.cfg </pre> <p> You can also move the the file to anywhere you want, and specify the absolute path to it: </p> <pre class="no-pretty-print"> proguard.config=/path/to/proguard.cfg </pre> <p>When you build your application in release mode, either by running <code>ant release</code> or by using the <em>Export Wizard</em> in Eclipse, the build system automatically checks to see if the <code>proguard.config</code> property is set. If it is, ProGuard automatically processes the application's bytecode before packaging everything into an <code>.apk</code> file. Building in debug mode does not invoke ProGuard, because it makes debugging more cumbersome.</p> <p>ProGuard outputs the following files after it runs:</p> <dl> <dt><code>dump.txt</code></dt> <dd>Describes the internal structure of all the class files in the <code>.apk</code> file</dd> <dt><code>mapping.txt</code></dt> <dd>Lists the mapping between the original and obfuscated class, method, and field names. This file is important when you receive a bug report from a release build, because it translates the obfuscated stack trace back to the original class, method, and member names. See <a href="#decoding">Decoding Obfuscated Stack Traces</a> for more information.</dd> <dt><code>seeds.txt</code></dt> <dd>Lists the classes and members that are not obfuscated</dd> <dt><code>usage.txt</code></dt> <dd>Lists the code that was stripped from the <code>.apk</code></dd> </ul> <p>These files are located in the following directories:</p> <ul> <li><code><project_root>/bin/proguard</code> if you are using Ant.</li> <li><code><project_root>/proguard</code> if you are using Eclipse.</li> </ul> <p class="caution"><strong>Caution:</strong> Every time you run a build in release mode, these files are overwritten with the latest files generated by ProGuard. Save a copy of them each time you release your application in order to de-obfuscate bug reports from your release builds. For more information on why saving these files is important, see <a href="#considerations">Debugging considerations for published applications</a>. </p> <h2 id="configuring">Configuring ProGuard</h2> <p>For some situations, the default configurations in the <code>proguard.cfg</code> file will suffice. However, many situations are hard for ProGuard to analyze correctly and it might remove code that it thinks is not used, but your application actually needs. Some examples include:</p> <ul> <li>a class that is referenced only in the <code>AndroidManifest.xml</code> file</li> <li>a method called from JNI</li> <li>dynamically referenced fields and methods</li> </ul> <p>The default <code>proguard.cfg</code> file tries to cover general cases, but you might encounter exceptions such as <code>ClassNotFoundException</code>, which happens when ProGuard strips away an entire class that your application calls.</p> <p>You can fix errors when ProGuard strips away your code by adding a <code>-keep</code> line in the <code>proguard.cfg</code> file. For example:</p> <pre> -keep public class <MyClass> </pre> <p>There are many options and considerations when using the <code>-keep</code> option, so it is highly recommended that you read the <a href="http://proguard.sourceforge.net/manual/introduction.html">ProGuard Manual</a> for more information about customizing your configuration file. The <a href= "http://proguard.sourceforge.net/manual/usage.html#keepoverview">Overview of Keep options</a> and <a href="http://proguard.sourceforge.net/index.html#/manual/examples.html">Examples section</a> are particularly helpful. The <a href= "http://proguard.sourceforge.net/manual/troubleshooting.html">Troubleshooting</a> section of the ProGuard Manual outlines other common problems you might encounter when your code gets stripped away.</p> <h2 id="decoding">Decoding Obfuscated Stack Traces</h2> <p>When your obfuscated code outputs a stack trace, the method names are obfuscated, which makes debugging hard, if not impossible. Fortunately, whenever ProGuard runs, it outputs a <code><project_root>/bin/proguard/mapping.txt</code> file, which shows you the original class, method, and field names mapped to their obfuscated names.</p> <p>The <code>retrace.bat</code> script on Windows or the <code>retrace.sh</code> script on Linux or Mac OS X can convert an obfuscated stack trace to a readable one. It is located in the <code><sdk_root>/tools/proguard/</code> directory. The syntax for executing the <code>retrace</code> tool is:</p> <pre>retrace.bat|retrace.sh [-verbose] mapping.txt [<stacktrace_file>]</pre> <p>For example:</p> <pre>retrace.bat -verbose mapping.txt obfuscated_trace.txt</pre> <p>If you do not specify a value for <em><stacktrace_file></em>, the <code>retrace</code> tool reads from standard input.</p> <h3 id="considerations">Debugging considerations for published applications</h3> <p>Save the <code>mapping.txt</code> file for every release that you publish to your users. By retaining a copy of the <code>mapping.txt</code> file for each release build, you ensure that you can debug a problem if a user encounters a bug and submits an obfuscated stack trace. A project's <code>mapping.txt</code> file is overwritten every time you do a release build, so you must be careful about saving the versions that you need.</p> <p>For example, say you publish an application and continue developing new features of the application for a new version. You then do a release build using ProGuard soon after. The build overwrites the previous <code>mapping.txt</code> file. A user submits a bug report containing a stack trace from the application that is currently published. You no longer have a way of debugging the user's stack trace, because the <code>mapping.txt</code> file associated with the version on the user's device is gone. There are other situations where your <code>mapping.txt</code> file can be overwritten, so ensure that you save a copy for every release that you anticipate you have to debug.</p> <p>How you save the <code>mapping.txt</code> file is your decision. For example, you can rename them to include a version or build number, or you can version control them along with your source code.</p> No newline at end of file