Как исправить ошибку в андроид студио

Время на прочтение
3 мин

Количество просмотров 58K

Сегодня хотел бы поделиться своим анализом и способами лечением разных ошибок при разработке своего продукта в Android Studio. Лично я, не раз сталкивался с различными проблемами и ошибками при компиляции и/или тестировании мобильного приложения. Данный процесс, всегда однообразный и в 99% случаев и всегда нужно тратить n-колличество времени на его устранение. Даже, когда ты уже сталкивался с данной проблемой, ты все равно идешь в поисковик и вспоминаешь, как же решить ту или иную ситуацию.

Я для себя завел файлик, в котором отметил самые частые ошибки — потратив на это несколько часов и перечислил самые популярные ошибки (в дальнейшем планирую просто их запомнить), чтоб сократить свое время в дальнейшем.

Итак, начну по порядку с самой распространенной проблемы и дальше буду перечислять их по мере появления:

1) Если подчеркивает красным код, где используются ресурсы: R. — попробовать (но вероятно не поможет): Build -> Clean Project.

В принципе на Build -> Clean Project можно не терять времени, а лучше всего — слева переключиться на Project, открыть каталог .idea, затем каталог libraries и из него удалить все содержимое. Затем нажать кнопку Sync Project. А затем (если все еще красное, но скорее всего уже будет все ок ) Build -> Clean Project.

image

2) После внезапного выключения компьютера, после перезапуска может быть во всех проектах весь код красным. Перед этим может быть ошибка: Unable to create Debug Bridge: Unable to start adb server: Unable to obtain result of ‘adb version’. Есть три решения — первое помогло, второе нет (но может быть для другого случая), а третье — не пробовал:

а) File — Invalidate Caches/Restart — Invalidate and Restart

б) Закрыть студию. В корне папки проекта удалить файл(ы) .iml и папку .idea. Вновь запустить студию и импортировать проект.

в) Нажать Ctrl-Alt-O и запустить оптимизацию импорта.

Кстати, adb сервер можно проверить на версию (и работоспособность) и затем перезапустить:

adb version
adb kill-server
adb start-server

3) Если Android Studio выдает приблизительно такую ошибку: Error:Execution failed for task ‘:app:dexDebug’…

Решение:

Надо слева переключиться на опцию Project, найти и удалить папку build которая лежит в папке app, т.е. по пути app/build. Затем перестроить весь проект заново: Build -> Rebuild Project.

Такое же решение если ошибка типа: «не могу удалить (создать) папку или файл» и указан путь, который в ведет в app/build. Тоже удаляем папку build и ребилдим проект.

4) В сообщении об ошибке упоминается heap — виртуальная память. А ошибка обычно вызвана ее нехваткой, т.е. невозможностью получить запрашиваемый объем. Поэтому этот запрашиваемый объем надо уменьшить, т.е. переписать дефолтное значение (обычно 2048 MB которое можно изменить в настройках), на меньшее 1024 MB.

В файле проекта gradle.properties пишем:

org.gradle.jvmargs=-Xmx1024m

5) Android Studio пришет примерно такую ошибку: Plugin is too old, please update to a more recent version, or set ANDROID_DAILY_OVERRIDE environment variable to «83648b99316049d63656d7276cb19cc7e95d70a5»

Возможные причины (кроме необходимости регулярного обновления SDK):

а) Загруженный проект был скомпилирован с помощью уже несовместимого старого gradle плагина. В этом случае надо найти и подключить в своем build.gradle проекта этот более старый плагин. т.е. попробовать более старые версии, например: 1.1.3 (часто именно 1.1.x и подходит).

com.android.tools.build:gradle:1.1.3

Найти все версии можно здесь.

б) Если в build.gradle проекта используется beta-версия плагина — это означает, что срок ее истек. Посмотреть последние релизы (продакшн и бета) можно также здесь:

6) Иногда при подключении сторонних библиотек могут дублироваться некоторые файлы (обычно связанные с лицензированием). В сообщении будет что-то содержащее слова: duplicate files. Решение — надо посмотреть в сообщении об ошибке или в документации подключенной сторонней библиотеки — какие именно файлы стали избыточными, и перечислить их в build.gradle модуля для исключения (exclude) из билда.

Это делается в директиве packagingOptions (которая, в свою очередь, находится в директиве android).

Например, при подключении библиотеки Firebase (облачный бек-енд сервис) в случае возникновения такой ошибки в build.gradle модуля (не проекта) добавляем packagingOptions в android (уже существующие там директивы оставляем) так:

android {
    ...
    packagingOptions {
        exclude 'META-INF/LICENSE'
        exclude 'META-INF/LICENSE-FIREBASE.txt'
        exclude 'META-INF/NOTICE'
        }
}

P.S.: Думаю, данная статья была полезна. Если у вас есть еще какие-то частные проблемы при работе с проектами в Android Studio, с удовольствием выслушаю их. Как по мне, 6 проблемных причин, которые я перечислил выше — это 99% всех случаев краха проекта. Конечно, если проблема не связана с вашим личным кодом.

While developing applications in Android Studio we might encounter many errors while writing code in the editor. We know that there’s an error since the editor automatically detects in real-time and highlights it in red color like this

Well, in the above image we can see that the error occurs due to a closing bracket after orderLists in Line 58. We can say that because the editor detects that in real-time and warns us with red underlining at that line. Now we can write error-less code and our app should run, right? Well, NO. Because the editor only helps in detecting the syntax error in the code. Whereas we have many other kinds of errors that might cause our app not to work the way we want it to be. Runtime and Logical errors are the common ones and cannot be detected in the editor. 

Now the question is – We have written 100’s and 1000’s lines of error less codes or I should syntax error free code that compiles and runs without any problem. But my app still stops working or some features don’t work the way I want it to?

In this situation, the Logcat acts as our best friend. Logcat Window is the place where various messages can be printed when an application runs. Suppose, you are running your application and the program crashes, unfortunately. Then, Logcat Window is going to help you to debug the output by collecting and viewing all the messages that your emulator throws. So, this is a very useful component for the app development because this Logcat dumps a lot of system messages and these messages are actually thrown by the emulator. In Android Studio one of the most used tools is Logcat. Logcat window in Android Studio is used to display real-time system messages and messages that are added in the Log class of the app. To open Logcat Click View > Tool Windows > Logcat (Alt + 6 or from the toolbar window).

Most Common Types of Error

  • NullPointerException – When expecting from null variables, objects, or classes.
  • IOException – Exceptions produced by failed or interrupted I/O operations.
  • OutOfMemoryError – When an object cannot be allocated more memory by its garbage collector.

Solutions to fix App Crash 

1. Observe the App Crash

Suppose you have built an application with multiple activities or fragments or both then you need to observe and see which action causes the application to crash. This might sometimes help you automatically remember or recall what mistake was made and which part of the app is causing that.

2. Find the Stack Trace 

It is best to look at the logcat to find the exact point of error. You can open the logcat and in the error section start reading the log error messages. Scroll to the bottom of the screen and look for the line that says Caused by. You may find the file name and line number in the logcat messages, which will lead you directly to the cause of the error. Look for elements to resolve the error. 

  • File Name
  • Line Number
  • Exception Type
  • Exception Message

3. Investigation Techniques

There are times when you might not find the exact line of code or file name that’s causing the error. So you should following techniques to investigate by yourself – 

  • Toast – Toast messages are used to display alerts messages and in this case, you can use them to display failure messages.
  • Logging – Logging is used to print messages in the logcat.
  • Breakpoints – It can be used to investigate values at the points where breaks are applied.

4. Google for Solution

There will be times we cannot fix the bug by ourselves and that’s ok. That’s the time you should start searching for solutions on the internet. Try googling with the main query message like – java.lang.NullPointerException. Generally, try looking for links of StackOverflow with maximum matching keywords of your search in the google search results. Afterward, you can go for other portals if you do not find the solution in StackOverflow.

Last Updated :
30 Jun, 2021

Like Article

Save Article

Testing is a crucial part of Android development, allowing you to iron out all the bugs, errors and performance problems that may be lurking in your app, before you unleash it on the general public.

Every time you encounter an error, Android generates an error message, and then either displays that message as part of Android Studio’s Logcat Monitor or as a dialogue on the device you’re using to test your app.

These error messages are typically short and to the point, and at first glance may not seem all that helpful. However, these messages actually contain all the information you need to get your project back on track—you just need to know how to decipher them!

In this article, we’re going to take an in-depth look at the 13 error messages you’re most likely to encounter when developing any Android app. We’ll be scrutinising what each of these error messages really means, examining all the possible reasons why you might encounter each error and, most importantly, sharing step-by-step instructions on how you can resolve them.  

Spotting Error Messages

There’s a wide range of error messages you may encounter when testing your app, ranging from severe errors that will cause your app to crash the very first time you try to install it on a target device to more subtle errors that degrade your application’s performance over time.

Depending on the kind of error you encounter, Android will display the error message either on the device you’re using to test your app or in Android Studio.

Spotting error messages that appear on a physical device or AVD is easy—you just need to be paying attention to any dialogues that appear on your device’s screen! However, spotting errors that appear in Android Studio can be tricky, as the Logcat Monitor records a huge amount of information, making it easy to miss important error messages. 

The easiest way to make sure you don’t miss out any error messages is to open Logcat Monitor’s Verbose dropdown and set it to Error, which will filter out everything except error messages.

Open Logcat Monitors dropdown and select ErrorOpen Logcat Monitors dropdown and select ErrorOpen Logcat Monitors dropdown and select Error

1. R.layout.main Cannot Be Found / Cannot Resolve Symbol R

This error is caused when Android Studio can’t generate your R.java file correctly, and it can often crop up out of nowhere—one minute everything will be working fine, and the next minute every part of your project is failing to compile. To make matters worse, when Android Studio encounters the R.layout error, it’ll usually flag all your layout resource files as containing errors, which makes it difficult to know where to start looking for the source of the error.

Often, the most effective solution is the simplest: clean and rebuild your project. Select Build > Clean Project from the Android Studio toolbar, wait a few moments, and then build your project by selecting Build > Rebuild Project.

If a single clean/rebuild cycle doesn’t work, then try repeating this process a few times, as some developers have reported positive results after completing multiple clean/rebuild cycles in quick succession.

If you encounter this error after moving some files and directories around, then it’s possible that the R.layout error is being caused by a mismatch between Android Studio’s cache and your project’s current layout. If you suspect this may be the case, then select File > Invalidate Caches / Restart > Invalidate and Restart from Android Studio’s toolbar.

Issues with the names of your resources can also prevent the R.java file from being created correctly, so check that you don’t have multiple resources with the same name and that none of your file names contain invalid characters. Android Studio only supports lowercase a-z, 0-9, full stops and underscores, and a single invalid character can cause an R.layout error across your entire project, even if you don’t actually use this resource anywhere in your project!

If you do identify and resolve an error, but Android Studio is still displaying the R.layout error, then you may need to complete a clean/rebuild cycle before Android Studio properly registers your changes.

2. Too Many Field References….Max is 65,536

When you compile your app, the APK contains executable bytecode files in the form of Dalvik Executable (DEX) bytecode files. The DEX specification states that a single DEX file can reference a maximum of 65,536 methods, and if you encounter the Too many fields… error then it means your app has gone over this limit. Note that this is a limitation on the number of methods your project references, and not the number of methods your project defines.

If you encounter this error, then you can either:  

  • Reduce the number of references in your project. One of the most effective ways of trimming your method references is to review your application’s dependencies, as these are often one of the biggest contributors of method references.
  • Configure your app to use more than one DEX file, by enabling multidex.

The process of enabling multidex support will vary depending on the versions of Android your project supports.

If you’re targeting Android 5.0 or higher, then the first step is opening your module-level build.gradle file and setting multiDexEnabled to true:

1
android {
2
   defaultConfig {
3
       minSdkVersion 21
4
       multiDexEnabled true

However, if your minSdkVersion is 20 or lower, then you’ll need to add the multiDexEnabled true attribute and then add the multidex support library as a project dependency:

1
dependencies {
2
 compile 'com.android.support:multidex:1.0.1'
3
}

The next step depends on whether or not you’re overriding the Application class.

If your project does override the Application class, then open your Manifest and add the following to the <application> tag:

1
<application
2
           android:name="android.support.multidex.MultiDexApplication" >
3
       ...
4
       ...
5
       ...
6
   </application>

If your project doesn’t override the Application class, then you’ll need to extend MultiDexApplication instead:

1
public class MyApplication extends MultiDexApplication

Finally, if you do override the Application class but can’t change the base class, then you can enable multidex by overriding the attachBaseContext() method and calling MultiDex.install(this), for example:

1
@Override
2
 protected void attachBaseContext(Context base) {
3
    super.attachBaseContext(base);
4
    MultiDex.install(this);
5
 }

3. Please Choose a Valid JDK Directory

If you’re getting a JDK error whenever you try to build your app, then it means Android Studio is struggling to find where the JDK is installed on your development machine.

To fix this error:

  • Select File > Project structure… from the Android Studio toolbar.
  • Select SDK Location from the left-hand menu.
  • Make sure the Use embedded JDK checkbox is selected.

Navigate to File  Project structure  SDK Location and select the Use embedded JDK checkboxNavigate to File  Project structure  SDK Location and select the Use embedded JDK checkboxNavigate to File  Project structure  SDK Location and select the Use embedded JDK checkbox

If this doesn’t solve the problem, then navigate back to File > Project structure… > SDK Location, and manually enter the full file path for your JDK. If you’re not sure where the JDK is installed on your development machine, then you can find out by opening the Terminal (Mac) or Command Prompt (Windows) and entering the following command:

4. Error Installing APK

While AVDs are great for testing your app across a wide range of different hardware and software, you should always test your app on at least one physical Android smartphone or tablet. However, Android Studio’s ability to recognize a connected Android device is notoriously hit and miss.

If you’ve attached your device to your development machine but are encountering an Error installing APK message whenever you try to install your APK, or your device isn’t even appearing in the Select Deployment Target window, then try the following fixes:

Check USB debugging is enabled. 

Open your device’s Settings, then select Developer Options, and make sure USB Debugging is enabled. If you don’t see Developer Options in the Settings menu, then select About Phone and keep tapping Build Number until a You are now a developer notification appears. Return to the main Settings screen, and you should find that Developer Options has been added.

Check your smartphone or tablet’s screen. 

Sometimes your device may require some additional input before it connects to your development machine. For example, it may be asking you to choose between different modes, or to explicitly authorize the connection.

Make sure you have the correct USB driver installed. 

If you’re developing on Windows, then you’ll need to download the appropriate OEM USB driver for your device. If you’re a Nexus user, then you can download the Google USB driver through Android Studio’s SDK Manager.

Check that your device meets your project’s minimum SDK requirements. 

You’ll find your project’s minimum SDK in your module-level gradle.build file, and can check what version of Android is installed on your device by opening its Settings and swiping to the About Phone section.

Try restarting your adb (Android Debug Bridge) process. 

Open a Terminal or Command Prompt window, and then change directory (cd), so it’s pointing at your platform-tools window, for example:

1
cd /Users/Downloads/adt-bundle-mac/sdk/platform-tools

Then, terminate and restart the adb process by entering the following commands, one after the other:

Restart everything! 

If all else fails, then try disconnecting and then reconnecting your device, restarting your device, restarting Android Studio and, as an absolute last resort, restarting your development machine.

5. INSTALL_FAILED_INSUFFICIENT_STORAGE

If you encounter this error when attempting to install your project, then it means the target device doesn’t have enough memory.

If you’re trying to install your project on an AVD, then you should check how much space you’ve assigned this particular AVD:

  • Launch the AVD Manager.
  • Find the AVD in question, and click its accompanying Edit this AVD icon.
  • In the window that appears, click Show Advanced Settings.
  • Scroll to the Memory and Storage section.

This section lists the various types of memory you’ve allocated to this particular AVD. If any of these values are unusually low, then you should increase them to more closely reflect the memory that’s available to your typical Android smartphone or tablet:

  • RAM. The amount of RAM available to the emulated device.
  • VM Heap. How much heap space (i.e. memory) is allocated to the Virtual Machine (VM) of the emulated smartphone or tablet.
  • Internal Storage. The amount of non-removable memory available to the emulated device.
  • SD card. The amount of removable memory available. If you want to use a virtual SD card that’s managed by Android Studio, then select Studio-managed and enter the size of the virtual SD card you want to create (the minimum recommended value is 100 MB). Alternatively, you can manage the SD card “space” in a file, by selecting External file and then specifying the location you want to use.

If there’s nothing odd about your AVD’s memory, or you’re trying to install your app on a physical Android smartphone or tablet, then this error usually means that your compiled app is simply too large. An application that takes a significant bite out of the device’s memory at install time is never going to go down well. 

If you need to dramatically reduce the size of your APK, then try the following techniques: 

  • Use ProGuard to remove unused classes, fields, methods, and attributes. To enable ProGuard, open your module-level build.gradle file and add the following:

1
buildTypes {
2
      release {
3

4
//Enable ProGuard//
5

6
          minifyEnabled true
7

8
//Since we want to reduce our APK size as much as possible, I’m using the settings from the proguard-android-optimize.txt file//
9

10
          proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
11

12
      }
13
  }
14

15
}
  • Use the aapt tool to optimize your drawables with lossless compression, or use a program that’s designed to reduce the size of your PNG files (zopflipng, pngcrush, OptiPNG, TinyPNG, or pngquant) or the size of your JPEGs (packJPG). Alternatively,  you may want to try replacing your PNG and JPEG files with images in the WebP format.
  • Remember to remove all debug-related functionality from the release version of your app. Android doesn’t require this information to run, so it’s just taking up unnecessary space.
  • Scour your project for any duplicate resources. Even lightweight resources like duplicate strings contribute something towards your final APK size.
  • Use Lint to identify any resources that aren’t referenced anywhere in your code, and remove these resources. To run Lint, select Analyze > Inspect Code… from the Android Studio toolbar.
  • Enable resource shrinking, by adding shrinkResources true to your project’s build.gradle file.
  • If you need to use variations of the same image, then use the same base image and customize it at runtime, rather than adding multiple versions of the same image to your project. For example, you can apply different colours to an image using android:tint and tintMode, and you can rotate an image using android:fromDegrees, android:toDegrees, android:pivotX, and android:pivotY.
  • Optimize your libraries. Try to remove any unnecessary or memory-intensive libraries from your project. If you do need to use a large library, then check whether there’s any way you can optimize this library for the mobile environment, as external library code often isn’t written with mobile in mind. You should also bear in mind that many libraries contain a large amount of localized strings. If your app doesn’t officially support these libraries, then you may be able to reduce the size of the library by telling Gradle not to include these strings in your compiled APK. To specify the languages that your app officially supports, open your module-level build.gradle file and use the resConfigs attribute. For example, here we’re specifying that we want to include only English-language strings in our project:

1
android {
2
defaultConfig {
3
  resConfigs "en"
  • Consider whether your APK contains a large amount of content that the individual user may download but never use. For example, a device with an hdpi screen doesn’t have much use for xxxhdpi assets! One of the most effective ways of reducing the size of your APK is to separate it into multiple APKs, so when the user downloads your app, they’ll receive an APK that contains only the code and resources that make sense for their particular device. You’ll find more information on creating APKs that target different screen densities and specific ABIs (application binary interfaces) over at the official Android docs.

6. ActivityNotFoundException

An ActivityNotFoundException occurs when a call to startActivity(Intent) or one of its variants fails because the Activity can’t execute the given Intent.

The most common cause of an ActivityNotFoundException is forgetting to declare an activity in your manifest, so open your manifest and check that you’ve declared all your activities. You should also check that you’ve declared each activity correctly, using either a fully qualified class name or a full stop as a shorthand for the package name. For example, both of the following are valid:

1
<activity android:name=".MainActivity">
1
<activity android:name="com.jessicathornsby.myapplication.MainActivity">

If you can’t spot any problems with your manifest, then there are a few other potential causes of ActivityNotFoundExceptions. Firstly, if you encounter this error after moving an Activity class from one package to another, then it’s possible that you’ve confused Android Studio and just need to clean and rebuild your project.

An ActivityNotFoundException can also be caused if an error in the target Activity is not loading correctly. To check whether this is occurring in your project, put your intent code inside a try-catch block:

1
try {
2

3
//Your code here//

4

5
} catch ( ActivityNotFoundException e) {
6
      e.printStackTrace();
7

8
}

Run your application again, and then take a look at Android Studio’s Logcat Monitor to see whether it’s captured any exceptions that may be preventing the target activity from being created. If this is the case, then resolving these errors should solve the ActivityNotFoundException, too.

7. ClassCastException

The ClassCastException error is related to Java’s type conversion feature, which allows you to cast variables of one type to another. You encounter a ClassCastException when you try to cast an object to a class of which it’s not an instance. For example, both of the following code snippets will result in a ClassCastException:

1
Object x = new Integer(0);
2
System.out.println((String)x);
1
ImageView image = (ImageView)context.findViewById(R.id.button);

This error message contains information about the line that’s causing the ClassCastException error, so navigate to this part of your project, check what objects are being cast there, and resolve any mismatch.

If you can’t spot a problem with your casting, then consider whether you’ve recently moved some Views around in your layout resource files, as some users have reported encountering a ClassCastException after rearranging their Views. If you suspect this may be the cause of your ClassCastException, then tell Android Studio to regenerate your layout files from scratch, by performing a clean/rebuild cycle. This forces Android Studio to properly register your recent layout changes, which should resolve your ClassCastException.

8. NullPointerException

In Java, when you declare a reference variable, you’re actually creating a pointer to an object. You can declare that an object is currently pointing at an unknown piece of data by assigning a null value to that object’s reference. Null values can be useful in coding some design patterns, but if you encounter a NullPointerException (NPE) then it means that you’ve tried to use a reference that’s pointing at a null value, as though it were referencing an object. Since there’s no code to execute in the location where this reference is pointing, you wind up with an NPE.

An NPE is usually accompanied by information about where this exception was caught, so the Logcat Monitor should contain the exact line where this error occurred. Navigate to this area of your project and identify the reference that equals null. You’ll then need to find the location where the value should be set, and set it.

The findViewById method can also return null if the requested View can’t be found, so if your NPE is occurring in a line that contains a findViewById, check that you’ve initialized the layout that contains this View. Also be on the lookout for any spelling mistakes or typos that may have crept into your findViewById call, as these can also result in an NPE.  

To avoid NPEs occurring in your project, make sure all your objects are initialized before you attempt to use them, and always verify that a variable isn’t null before you request a method or field from that object.

9. Application Not Responding Error

This is an error that appears as a dialogue on the Android device or AVD you’re using to test your app. The Application Not Responding (ANR) error occurs when your app’s UI freezes and remains unresponsive to user input for more than five seconds. This usually happens because your app is trying to perform lengthy or intensive operations on Android’s main UI thread.

In Android, the main UI thread is responsible for dispatching all user input events to the appropriate UI widgets, and for updating your app’s UI. However, this thread can only process one task at a time, so if you block the main thread with any long-running or intensive operations, then your UI will be completely unresponsive until this task is complete.

If you encounter an ANR message while testing your app, then you definitely need to take a look at the work you’re performing on the main thread. However, if you don’t explicitly encounter this error but notice that your app sometimes feels sluggish or laggy, then this is an indication that you’re on the verge of an ANR error, and once again you should take a look at the state of your UI thread.

To resolve ANR errors (and near-ANR errors), you need to identify all the operations that have the potential to run slowly, or that require significant processing power, and then move them off the main thread. You do this by creating a worker thread where these operations can be performed with zero risk of blocking the main UI thread.

There are several methods of creating additional threads, but the simplest solution is to use an AsynTask, as this class already contains its own worker thread and an onPostExecute() callback that you can use to communicate with Android’s main UI thread.

However, AsyncTasks are better suited to performing short background operations, so if you need to perform a long-running operation, then you should use a Service or an IntentService instead.

Although moving long-running and intensive tasks off the main thread will have the most impact on your app’s performance, it’s best practice to perform as little work as possible on the main UI thread. Even running a small amount of unnecessary code on the main thread can have an impact on your app’s responsiveness, so once you’ve successfully relocated all of your long-running and intensive operations, you should look at whether there’s any more code that you can move off the main thread.

10. Only the Original Thread That Created a View Hierarchy Can Touch Its Views

In Android, you can update your UI from the main thread only. If you try to access UI elements from any other thread, then you’re going to encounter this error.

To resolve this issue, identify the part of your background task that’s attempting to update the UI and move it to a runOnUiThread, for example:

1
runOnUiThread(new Runnable() {
2
         @Override
3
          public void run() {
4

5
//Update your UI//

6

7
      }
8

9
});

Alternatively, you can use a handler or perform your background work in an AsyncTask, as you can communicate with the main thread using AsyncTask’s onPostExecute() callback method. Finally, if you find yourself regularly switching between threads, then you may want to look into RxAndroid, as this library allows you to create a new thread, schedule work to be performed on this thread, and then post the results to the main thread, all with just a few lines of code.

11. NetworkOnMainThreadException

This exception is thrown when your app attempts to perform networking operations on the main thread, such as sending API requests, connecting to a remote database, or downloading a file. Since network operations can be time-consuming and labour-intensive, they are highly likely to block the main thread, so Android 3.0 (Honeycomb) and higher will throw this error whenever you attempt to make a network request on the main thread.

If you do encounter a NetworkOnMainThreadException, then find the networking code that’s running on your main thread, and move it to a separate thread.

If you do need to make frequent networking requests, then you may want to take a look at Volley, an HTTP library that initiates its own background threads so that all networking requests are performed off the main thread by default.

12. Activity Has Leaked Window That Was Originally Added Here

This error occurs when trying to show a dialogue after exiting the Activity. If you do encounter this issue, then open your Activity and make sure you’re dismissing the dialogue properly, by calling dismiss() in either your Activity’s onDestroy() or onPause() method, for example:

1
@Override
2
protected void onDestroy()
3
{
4
       super.onDestroy();
5
        if(pDialogue!= null)
6
            pDialogue.dismiss();   
7
            
8
}

13. OutofMemoryError

This error occurs when your app makes a memory request that the system can’t meet. If you encounter this error message, then start by ruling out all of the most common memory management mistakes. Check that you’ve remembered to unregister all your broadcast receivers and that you’ve stopped all of your services; make sure you’re not holding onto references in any static member variables, and that you’re not attempting to load any large bitmaps.

If you’ve ruled out all the obvious causes of an OutOfMemoryError, then you’ll need to dig deeper and examine exactly how your app is allocating memory, as chances are there are a few areas where you can improve your app’s memory management.

Android Studio has a whole area dedicated to helping you analyze your app’s memory usage, so start by selecting View > Tools Window from the Android Studio toolbar. At this point you’ll see either an Android Monitor or Android Profiler option, depending on the version of Android Studio you have installed.

We’ve discussed working with the Memory Monitor on this website before, but since Android Profiler is a new addition to Android Studio, let’s take a quick look at its major features.

When you open Android Profiler, it starts recording three pieces of information automatically.

The Android Profiler tracks the apps CPU Memory and Network information automaticallyThe Android Profiler tracks the apps CPU Memory and Network information automaticallyThe Android Profiler tracks the apps CPU Memory and Network information automatically

Since we’re interested in the way our app is using memory, give the Memory section a click, which will launch the Memory Profiler.

The Memory Profiler consists of a timeline that displays the different kinds of memory currently being allocated by your app, for example Java, native, and stack. Above this graph you’ll find a row of icons that you can use to trigger different actions:

  • Force a garbage collection event.
  • Take an Hprof snapshot of the application memory. This is a snapshot of all the objects in your app’s heap, including the kind of objects your app is allocating, the number of allocated objects, and how much space these objects are taking up.
  • Record memory allocations. By recording your app’s memory allocations while performing certain actions, you can identify the specific operations that are consuming too much memory.

The Memory Profiler displays the different kinds of memory your app is allocating The Memory Profiler displays the different kinds of memory your app is allocating The Memory Profiler displays the different kinds of memory your app is allocating

To identify the parts of your application that are responsible for the OutOfMemoryError, spend some time interacting with your app, and monitor how your app’s memory allocations change in response to different actions. Once you’ve identified the section of your project that’s causing the problem, spend some time scrutinising it for any memory leaks, as well as any inefficiencies in the way it’s using memory.

Conclusion

In this article we looked at 13 of the error messages you’re most likely to encounter when developing for Android. We discussed all the different factors that can contribute towards these errors, and the steps you need to take to resolve them.

If you’re being plagued by an error message that we didn’t cover, then your first step should be copy/pasting the entire error message into Google, as this will often turn up threads and blog posts where people are discussing how to solve this particular error.

And, if you can’t find a solution anywhere on the web, then you can always reach out to the Android community for help directly, by posting your question to Stack Overflow.

While you’re here, check out some of our other posts on Android app development!

Did you find this post useful?

Jessica Thornsby

Jessica Thornsby is a technical writer based in Sheffield. She writes about Android, Eclipse, Java, and all things open source. She is the co-author of iWork: The Missing Manual, and the author of Android UI Design.

This page will compile common issues experienced with Android Studio or above as they are experienced and recorded.

Debugging

If you want to do more in-depth debugging in your code, you can setup breakpoints in your code by clicking on the left side pane and then clicking on Run->Debug. You can also click on the bug icon https://i.imgur.com/zGh8wZ0.png if you’ve enabled the Toolbar (View->Enable Toolbar):

Android Studio also provides a built-in decompiler. You can also use Navigate->Declaration within the IDE and set breakpoints even within classes for which you may not necessarily have the actual source code. Notice the warning message at the top and an example of a screenshot of setting a breakpoint of a class defined in a JAR file below:

If the debugger isn’t working, check the guide section below to get things running again.

Network Traffic Inspection

If you wish to inspect network traffic, see this guide on how to troubleshoot API calls. The networking library you use determines what approach you can use.

Database Inspection

Also, the Stetho project can be used to view your local SQLLite database. See this guide for more details.

LogCat

Android Studio contains a panel to receive logging messages from the emulator, known as LogCat. If you are not seeing any log messages, click on the Restart icon https://imgur.com/kQKr1zv.png.

https://i.imgur.com/xP3dQcG.png

Resetting adb

If you are having issues trying to connect to the emulator or see any type of “Connection refused” errors, you may need to reset the Android Debug Bridge. You can go to Tools->Android->Android Device Monitor. Click on the mobile device icon and click on the arrow facing down to find the Reset adb option.

https://i.imgur.com/srLBOMJ.gif

Virtual Device Manager

Unable to delete emulator getting “AVD is currently running in the Emulator”

Open the Tools => Android => AVD Manager and select virtual device that you want to delete. Click on the down arrow at the end and select the [Show on Disk] option which will open the emulator directory. Inside the [Your Device].avd folder, locate any *.lock files and delete them. You can now delete the emulator. See this stackoverflow post for more details.

Android Studio Issues

Android Studio is Crashing or Freezing Up

If Android Studio starts freezing up or crashing even after rebooting the IDE or your computer, your Studio has likely become corrupted. The best way to resolve this is to clear all the caches by removing all the following folders:

~/Library/Application Support/AndroidStudio
~/Library/Caches/AndroidStudio
~/Library/Logs/AndroidStudio
~/Library/Preferences/AndroidStudio

and then uninstall Android Studio and re-install the latest stable version. This should allow you to boot Android Studio again without errors.

Android Studio Design Pane isn’t loading properly

If you find yourself opening up a layout file and not seeing the design pane rendering correctly such as:

We can try the following steps to get this functioning again:

  • Try changing the API version selected in the dropdown and try a few different versions
  • Click the “refresh” icon at the top right of the design pane
  • Select File -> Invalidate Caches / Restart and restart Android Studio

You may need to install the newest version of Android and select that version within the dropdown for the pane to work as expected.

Seeing Unable to execute dex: method ID when compiling

This might also show up as Too many field references: 131000; max is 65536. or com.android.dex.DexIndexOverflowException: method ID not in [0, 0xffff]: 65536 or Error:Execution failed for task ':app:dexDebug' in the build console. This error occurs when the total number of references within a single bytecode file exceeds the 65,536 method limit. This usually means you have a substantial amount of code or are loading a large number of libraries.

If you’ve crossed this limit, this means you’ve loaded too many classes usually due to third-party libraries. Often the culprit is the Google Play Services library. Open up your app gradle file and look for this line implementation 'com.google.android.gms:play-services:X.X.X'. Remove that line and instead include the services selectively as outlined there. For example:

dependencies {
   implementation 'com.google.android.gms:play-services-maps:8.3.0'
   implementation 'com.google.android.gms:play-services-location:8.3.0'
}

This can greatly reduce the number of classes loaded. If you’ve crossed the limit even with this change, we need to adjust our project to use a multidex configuration by enabling multiDexEnabled true in your gradle configuration and updating the application to extend from android.support.multidex.MultiDexApplication.

Seeing java.lang.OutOfMemoryError : GC overhead limit when compiling

You are most likely exhausting the heap size especially during compilation. Try to add inside this setting in your app/build.gradle:

android {
   .
   .
   .
   dexOptions {
     javaMaxHeapSize "4g"
   }
}

You can also reduce the build time too by setting incremental to be true:

android {
   dexOptions { 
      incremental true
      javaMaxHeapSize "4g"
   }
}

See this Google discussion article for more context.

Still not working? Try to increase the heap size of Android Studio.

  1. Quit Android Studio.
  2. Create or edit a studio.vmoptions file.

    • On Mac, this file should be in ~/Library/Preferences/AndroidStudio/studio.vmoptions.
    • On Windows, it should be in %USERPROFILE%.AndroidStudiostudio[64].exe.vmoptions.

    Increase the maximum memory to 2 Gb and max heap size of 1 Gb.

     -Xmx2048m
     -XX:MaxPermSize=1024m`
    
  3. Start Android Studio.

Getting “No resource found that matches given name.”

If you are using multiple layout folders and decide to rename any of your ID tags in your XML files, you may get “No resource found that matches given name.” There is a current bug in how changes are detected in nested subfolders so your best option is to not use this approach until the problem is fixed. Otherwise, you will need to do a Rebuild Project so that the entire resource files can be regenerated and the build/ directories are fully removed. Note: Clean Project may not work.

Getting “tooling.GradleConnectionException” errors

If you see org.gradle.tooling.GradleConnectionException errors, you may need to install a newer version of JDK (there have been reports of 1.7.0_71 having this issue). First try to restart the adb server first.

https://i.imgur.com/1kWwmuh.png

Getting “failed to find Build Tools revision x.x.x”

If you’re opening another Android Studio project and the project fails to compile, you may see “failed to find Build Tools revision x.x.x” at the bottom of the screen. Since this package is constantly being changed, it should be no surprise that other people who have installed Android Studio may have different versions. You can either click the link below to install this specific Build Tools version, or you can modify the build.gradle file to match the version you currently have installed.

https://i.imgur.com/IsAWMrl.png

Getting “com.android.dex.DexException: Multiple dex files define”

One of the issues in the new Gradle build system is that you can often get “Multiple dex files define” issues.

If a library is included twice as a dependency you will encounter this issue. Review the libs folder for JARS and the gradle file at app/build.gradle and see if you can identify the library dependency that has been loaded into your application twice.

If one dependency library already includes an identical set of libraries, then you may have to make changes to your Gradle configurations to avoid this conflict. This problem usually happens when there are multiple third-party libraries integrated into your code base. See Must-Have-Libraries#butterknife-and-parceler for more information.

Another error if you attempt to include a library that is a subset of another library. For instance, suppose we included the Google play-services library but thought we also needed to include it with the play-services-map library.:

dependencies {
    implementation 'com.google.android.gms:play-services:6.5.+'
    implementation 'com.google.android.gms:play-services-maps:6.5.+'
}

It turns out that having both is redundant and will cause errors. It is necessary in this case to remove one or the other, depending on your need to use other Google API libraries. See this overview of the multidex issue on the Android docs.

Seeing Unsupported major.minor version 52.0 on some plugins

Some Android Studio plugins do not support Java 1.6 anymore, so it’s best to confirm what version you are using. Inside Android Studio, click on About Android Studio. You should see the JRE version listed as 1.x.x below:

If you have multiple Java versions installed, you should make sure that v1.6 is not being used. Solutions include:

  • Configuring JDK 8 as your default Java SDK within Studio. See this stackoverflow post for solutions.
  • Reset your Android Studio cache and set correct gradle version as shown in this post.

On OS X machines, you can remove the JDK from being noticed. You can move it the temporary directory in case other issues are created by this change.

sudo mv /System/Library/Java/JavaVirtualMachines/1.6.0.jdk /tmp

INSTALL_FAILED_OLDER_SDK error message

If your minSdkVersion is higher than the Android version you are using (i.e. using an emulator that supports API 19 and your target version is for API 23), then you may see an error message that appears similar to the following:

You will need to either lower the minSdkVersion or upgrade to an Android emulator or device that supports the minimum SDK version required.

Seeing java.lang.IllegalAccessError: Class ref in pre-verified class resolved to unexpected implementation

You have a third-party library reference defined twice. Check your app/build.gradle for duplicate libraries (i.e. commons-io library defined for 1.3 and another one using 2.4).

Debugger Isn’t Working: Breakpoint In Thread is Not Hit

You might notice that the debugger does not always work as expected in background threads such as AsyncTask or when using networking libraries to send network requests. The debugger breakpoints are a little bit finicky when configured to stop outside the main thread.

In order for some of these breakpoints in the callbacks to work, you have to set them after the debugger has been initialized and not before. If you have already set the breakpoints before, then you have to reset them after the debugger starts. One common strategy is to set the breakpoint on the main thread and then, once that has been hit, add the breakpoint on the background thread.

Debugger Isn’t Working: Disconnected or Client not ready yet

This is usually a signal that the emulator instance is not properly connected with ADB and Android Studio. There are a few steps to try:

  1. First, try uninstalling the app from within the emulator and then restarting the emulator completely. Try debugging again now.

  2. Next, close the emulator again and also restart Android Studio. Start Android Studio and reload the emulator. Then try debugging again.

  3. If you are using official emulator, try using Genymotion or vice-versa. Then try debugging again.

  4. Open up Tools => Android => Android SDK Manager and see if there are any updates to the platform or SDK tools. Update any suggested changes within the manager and then restart your emulator and Android Studio. Then try debugging again.

References

  • https://jaanus.com/debugging-http-on-an-android-phone-or-tablet-with-charles-proxy-for-fun-and-profit/
     


Программирование Android Eclipse, Android Studio: FAQ, устранение ошибок

Tue, May 23 2023  

| Главная | Контакты | Администрирование | Программирование | Ссылки |

UK-flag-ico.png English Version
GERMAN-flag-ico.png Die deutsche Version

Карта сайта

Поделиться

Расширенный поиск

Нашли опечатку?

Пожалуйста, сообщите об этом – просто выделите ошибочное слово или фразу и нажмите Shift Enter.

Блог одного Сумасшествия

Eclipse, Android Studio: FAQ, устранение ошибок Печать

Добавил(а) microsin

  

Здесь собраны решения проблем, которые возникают с IDE Eclipse, Android Studio, и другие вопросы программирования под Android. Все непонятные термины и сокращения ищите в статье “Словарик Android” [7].

[131228]

Q001. Что такое API Level, API number (API 3, API4, API 7, и т. д.)?

API переводится как интерфейс программирования, в данном контексте это относится к операционной системе Android, к вызову встроенных в систему подпрограмм и функций. Цифра соответствует определенной версии сборки OS Android, см. таблицу. [1].

Q002. Для чего нужен Google USB Driver?

Google USB Driver относится к набору инструментария для автоматизации тестируемых приложений (программ) на телефон/устройство с операционной системой Android. Нужен только для операционной системы Windows, см. [2, 3, 4].

Q003. Что такое Android WebDriver?

Программное обеспечение, которое позволяет запускать автоматизированные сквозные тесты. Эти тесты помогут убедиться, что ваш сайт работает корректно в браузере Android.

Q004. Что такое Activity?

Это слово в контексте программирования Android можно перевести как “видимая деятельность программы”. Это основной компонент приложения (программы) для Android, свойства и методы которого определяют работу (поведение) и внешний вид программы. Каждое отдельное окно приложения представлено отдельным компонентом Activity.

Q005. Что такое Gradle?

Специальный плагин для Android Studio, позволяющий автоматизировать сборку приложений на Java [8]. Именно с ним больше всего головной боли у разработчиков при переходе на разные версии Android Studio и JDK, особенно при импорте Android-приложений, созданных в среде разработки Eclipse.

Q006. Проблема с запуском виртуального устройства при отладке.

Я создал виртуальное устройство (AVD) для эмулятора Android Studio, на котором пытаюсь отладить свою программу. Но почему-то не могу запустить в эмуляторе мою AVD (на экране постоянно висит в центре экрана переливающаяся надпись ANDROID). Когда пытаюсь запустить свою программу, то в логе Atmel Studio вижу сообщение об ошибке “Adb Transfer Protocol Error”, “No such file or directory”. В чем проблема?

При использовании эмулятора Android Studio нужно иметь в виду, что он чрезвычайно прожорлив в плане расхода памяти и ресурсов процессора компьютера. Так что скорее всего, Вы создали AVD слишком мощное, и поэтому оно запускается в эмуляторе слишком долго. Когда в такой ситуации Вы пытаетесь запустить отладку, то скорее всего получите сообщение наподобие следующего:

Waiting for device.
"C:Program FilesAndroidandroid-studiosdktoolsemulator.exe" -avd AVD-GT-N7000 -netspeed full 
-netdelay none
Device connected: emulator-5554 Device is online: emulator-5554 Target device: AVD-GT-N7000 [emulator-5554] Uploading file local path: C:Documents and SettingsUserAndroidStudioProjectsMyApplicationProjectMyApplication
buildapkMyApplication-debug-unaligned.apk 
remote path: /data/local/tmp/com.example.myapplication
Adb Transfer Protocol Error.
No such file or directory

Это означает, что отлаживаемое приложение не может загрузиться в эмулятор, так как эмулятор еще не запустился. Чтобы решить проблему с отладкой, у Вас есть следующие варианты:

1. Перед запуском отладки нужно дождаться полной загрузки AVD в эмуляторе, и только потом запускать отладку. Наберитесь терпения, первая загрузка новой машины может занимать до 10 минут и более, в зависимости от её свойств и мощности Вашего компьютера. Чтобы ускорить загрузку эмулятора, используйте снапшоты для AVD (при создании AVD поставьте галочку Snapshot).
2. Создать другую AVD, требующую меньше ресурсов (выбрать модель смартфона с меньшим разрешением экрана и с меньшим API level).
3. Запустить отладку на виртуальной машине, см. [4].
4. Установить Google USB Driver и отлаживаться на реальном устройстве с операционной системой Android.

Q007. Случайно закрыт визуальный редактор формы…

Я редактирую разметку окна программы (форму) – файл activity_main.xml, и случайно закрыл окно просмотра внешнего вида формы (окошко, где показано окно моей программы). Как мне снова открыть просмотр формы? Как переключаться между текстовым редактированием формы (как XML-файла) и графическим редактированием (когда можно визуально редактировать форму, мышкой перетаскивать компоненты и менять их свойства)?
Для просмотра редактируемой формы выберите в меню View -> Tool Windows -> Preview. Для переключения между текстовым и визуальным вариантами редактирования формы служат нижние табы окна редактора – Design (визуальное редактирование формы) и Text (редактирование формы как XML-текста).

Q008. Почему не работает просмотр иерархии (Hierarchy View)…

… в программе Android Debug Monitor, когда я подключаюсь через USB (или Wi-Fi) к отлаживаемому устройству?

[2014-01-01 15:59:08 - hierarchyviewer]Unable to get view server version from device 0019a2fe5212ce
[2014-01-01 15:59:08 - hierarchyviewer]Unable to get view server protocol version from device 0019a2fe5212ce
[2014-01-01 15:59:08 - ViewServerDevice]Unable to debug device: samsung-gt_n7000-0019a2fe5212ce
[2014-01-01 15:59:08 - hierarchyviewer]Missing forwarded port for 0019a2fe5212ce
[2014-01-01 15:59:08 - hierarchyviewer]Unable to get the focused window from device 0019a2fe5212ce

Почти никакие телефоны и смартфоны общего производства не позволят HierarchyViewer получать доступ к ним. Обычно специальные телефоны разработчика и эмуляторы оснащены функциями, работающими с HierarchyViewer. Есть обходной способ решения проблемы, если использовать класс ViewServer в разрабатываемом приложении (см. ViewServer Local server for Android’s HierarchyViewer site:github.com).

Q009. Что такое R (R.java)?

R.java – автоматически генерируемый (средой разработки Eclipse) Java-код, который определяет специальный Java-класс ресурсов приложения R. Этот файл пересоздается, когда Вы делаете очистку или компиляцию проекта. В классе R содержатся значения идентификаторов ресурсов, которые были определены в визуальном редакторе или в соответствующем XML-файле ресурсов.

Q010. Как посмотреть последние сообщения ядра (dmesg) …

… при загрузке или установке новых устройств? Другими словами, есть ли на Android аналог dmesg?

На Андроид файл /proc/kmsg является аналогом dmesg в Linux, однако для просмотра файла /proc/kmsg (например, командой cat /proc/kmsg) нужны права root. Есть также файл /proc/last_kmesg, для его просмотра права root не нужны.

Q011. Что такое Android rooted device? Какие преимущества это дает, какие недостатки?

Пользователь root – это специальный аккаунт в UNIX системах (к которым относится также и Android), который позволяет выполнять все операции в системе без ограничений. Пользователь с правами root получает доступ ко всем системным и аппаратным ресурсам и данным, с возможностью их редактирования и удаления. Подробнее см. [5].

[140126]

Q012. Path variable name cannot contain character.

При попытке создать новую переменную окружения проекта (свойства проекта -> Resource -> Linked Resources -> Path Variables -> New…) выдается ошибка, что имя переменной не может содержать недопустимый символ. В данном случае это точка.

Eclipse-project-properties-add-PATH-variable-error

Удалите точку из имени, и переменная создастся нормально.

Q013. LINK : fatal error LNK1104: не удается открыть файл “kernel32.lib”.

Проблему можно решить так: C/C++ Build -> Settings -> Linker (link) -> Libraries -> Additional Libpath (/libpath) -> нажать на кнопочку с зеленым плюсиком -> указать папку c:Program FilesMicrosoft Visual Studio .NET 2003Vc7lib.

Или так: C/C++ General -> Paths and Symbols -> Libraries -> Add… -> File system… -> c:Program FilesMicrosoft Visual Studio .NET 2003Vc7libkernel32.lib.

Q014. LINK : fatal error LNK1104: не удается открыть файл “C:Program.obj”.

Ошибка скорее всего в том, что в конфигурации проекта добавлен путь до библиотеки, содержащий двойные кавычки, например “c:Program FilesMicrosoft Visual Studio .NET 2003Vc7libkernel32.lib”. Пути до линкуемых библиотек настраиваются в свойствах проекта C/C++ Build -> Settings -> Linker (link) -> Libraries -> Additional Libpath (/libpath), C/C++ Build -> Settings -> Linker (link) -> Libraries -> Libraries, C/C++ General -> Paths and Symbols -> Libraries -> Add… -> File system…

Уберите кавычки из пути, и ошибка LNK1104 исчезнет (поменяйте “c:Program FilesMicrosoft Visual Studio .NET 2003Vc7libkernel32.lib” на c:Program FilesMicrosoft Visual Studio .NET 2003Vc7libkernel32.lib).

Q015. “Dx trouble writing output: already prepared”.

Не запускается в эмуляторе приложение Android с ошибкой. Пример вывода в консоли сообщений об ошибке:

[2014-01-26 16:14:43 - HelloWorldAndroid] Dx trouble writing output: already prepared
[2014-01-26 16:14:44 - Dex Loader] Unable to execute dex: java.nio.BufferOverflowException.
Check the Eclipse log for stack trace. [2014-01-26 16:14:44 - HelloWorldAndroid] Conversion to Dalvik format failed: Unable to execute
dex: java.nio.BufferOverflowException. Check the Eclipse log for stack trace.

Решение проблемы: закройте Eclipse. Зайдите в каталог Android SDK (c:Program FilesAndroidandroid-studiosdktools), выполните команду android sdk. Запустится SDK Manager. Удалите Android SDK Build-tools 19, и установите Android SDK Build-tools 18.1.1. Снова запустите Eclipse, и выполните отладку в эмуляторе, проблема исчезнет.

Q016. Как запустить SDK Manager на Windows?

Вот возможные способы:

• Из Eclipse (с установленным плагином ADT) выполните команду меню Window -> Android SDK Manager.
• Перейдите в папку tools пакета Android SDK (полный путь может быть наподобие c:Program FilesAndroidandroid-studiosdktools) и выполните команду android.bat sdk.

Android-SDK-Manager

[140204]

Q017. Приложение (файл .apk) не устанавливается …

… с сообщением “Ошибка разбора данных”, “Сбой разбора пакета”. Команда ant debug install для этого приложения завершается с сообщением [INSTALL_FAILED_OLDER_SDK].

Проверьте, на какой уровень API скомпилировано приложение. Уровень API Android (API Level [1]) на сегодняшний день может меняться от 1 до 19, что соответствует версии Android от Android 1.0 до Android 4.4. Если приложение рассчитано на более современную версию (более высокий уровень API), чем установленная система на Вашем устройстве Android, то программа не установится и не запустится. Версию системы устройства можно узнать через Настройки -> Об устройстве -> Версия Android (версия обычно состоит из нескольких цифр и точек, наподобие 4.1.2). Уровень API, соответствующий версии, можно узнать из таблицы [1].

[140221]

Q018. Добавление обработчика события для визуального компонента.

Я привык, когда двойным кликом на элементе в визуальном редакторе автоматически создается обработчик события для элемента, но в Eclipse этого не происходит. Как добавить обработчик события на визуальном объекте (обработчик события клика на кнопке)? Процесс по шагам на примере кнопки:

1. Откройте визуальный редактор формы Вашего приложения, для чего сделайте двойной щелчок на XML-файле описания внешнего вида интерфейса Вашей программы (этот файл находится в Project Explorer -> Имя проекта -> res -> layout -> activity_blabla.xml). Переключитесь на графический вид просмотра формы (закладка Graphical Layout).

2. В визуальном редакторе бросьте на форму кнопку. Выберите её, и в редакторе свойств Properties дайте более подходящее Id и введите нужный текст, отображаемый на кнопке. К примеру, Id по умолчанию будет @+id/button1, Вы можете задать что-то типа @+id/MyButtonId.

3. Разрешите Вашему классу Activity прослушивать события кликов на визуальных компонентах реализацией OnClickListener. Для этого откройте файл ИмяПроектаActivity.java (Project Explorer -> Имяпроекта -> src -> имяпакета), и расширьте определение класса Activity:

public class MyAppActivity extends Activity implements OnClickListener {
   ..
}

4. В классе Activity задайте глобальную переменную, которая будет олицетворять Вашу кнопку.

public class MyAppActivity extends Activity implements OnClickListener {
   private Button myButton;
   ..
}

Примечание: если система будет ругаться на то, что не может найти определение Button, то перед объявлением класса добавьте строчку:

import android.widget.Button;

5. В коде onCreate класса Activity добавьте инициализацию переменной myButton.

        myButton = (Button) findViewById(R.id.MyButtonId);

Понятно, что в параметре должно быть передано значение, которое Вы назначили в качестве Id кнопки.

6. Сразу после инициализации переменной добавьте создание прослушивателя события клика с помощью вызова setOnClickListener:

        myButton = (Button) findViewById(R.id.MyButtonId);
        myButton.setOnClickListener(this);

По аналогии можно добавить прослушивание и для других кнопок (конечно же, для них должны быть созданы экземпляры переменных, и сделана инициализация):

        myButtonA.setOnClickListener(this);
        myButtonB.setOnClickListener(this);
         ..

7. Теперь нужно создать обработчик события клика onClick на внешнем виде формы (View). Для этого добавьте в класс Activity определение нового метода onClick:

    // Реализация обработчика события для OnClickListner.
    // Функция onClick будет вызываться всякий раз, когда
    // будет сделан клик на интерфейсе программы.
    @Override
    public void onClick(View v) {
        // Параметр v означает вид, на котором сделан клик.
        // Функция getId() возвращает идентификатор этого вида.
        if(v.getId() == R.id.myButtonId)
        {
            // тут код для действий по кнопке myButton;
            ..
        }
        else if(v.getId() == R.id.myButtonIdA)
        {
            // тут код для действий по кнопке myButtonA;
            ..
        }
        // и так далее, для всех визуальных элементов, принимающих клик.
    }

Вот полный пример листинга кода Activity:

package com.myApp;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
 
public class FirstActivity extends Activity implements OnClickListener {
   // Декларирование элементов UI.
   private TextView changingTextView;
   private Button firstButton;
   private Button secondButton;
 
   /** Вызывается, когда activity создается впервые. */
   @Override
   public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.main); // Наш единственный дизайн для этого приложения
                                     // размещен в файле main.xml.
      // Инициализация компонентов визуального интерфейса.
      changingTextView = (TextView) findViewById(R.id.changingTextView);
      firstButton = (Button) findViewById(R.id.leftButton);
      // Когда мы создаем кнопку, и нам нужно обрабатывать с нее события,
      // то нужно установить для неё прослушиватель (listener).
      // Вызов в качестве аргумента this означает, что события будут передаваться
      // родительскому экземпляру класса, в данном случае это наша Activity.
      firstButton.setOnClickListener(this);
      secondButton = (Button) findViewById(R.id.rightButton);
      secondButton.setOnClickListener(this);
   }
 
   // Реализация с OnClickListner: onClick будет вызван всякий раз, когда происходит
   // клик в каком-то месте вида программы.
   @Override
   public void onClick(View v) 
   {  // Параметр v означает вид (визуальный элемент), на котором сделан клик. 
      // Функция getId() возвращает идентификатор этого вида. По его значению
      // можно декодировать, какая кнопка нажата.
      if(v.getId() == R.id.leftButton)
      {
         // setText() устанавливает значение строки в TextView
         changingTextView.setText("Вы кликнули кнопку слева");
      }
      else if(v.getId() == R.id.rightButton)
      {
         changingTextView.setText("Вы кликнули кнопку справа");
      }
   }
}

Q019. Откуда возникают ошибки, связанные с вычислением переменных среды Eclipse …

… наподобие “Specified Java project ‘null’ does not exist.”, “Variable references empty selection: ${project_name}”?

Eclipse-javah-error1 Eclipse-javah-error2

Когда запускается конфигурация компиляции или внешний инструментарий, то значение переменных вычисляется по выбранному месту в окне Project Explorer. Обычно достаточно выбрать имя проекта (корневую папку), к которому относится запуск, и тогда ошибка исчезнет.

Q020. Как в Eclibse убрать красные маркеры ошибок из модуля C/C++? Почему при безошибочной компиляции ошибки все равно высвечиваются?

Почему проект Eclipse с native-кодом компилируется нормально, но в редакторе исходный код подсвечен с ошибками (не найдены некоторые заголовочные файлы и стандартные идентификаторы? Когда подключаете внешние файлы в native-коде (заголовки с расширением *.h), то должны делаться доступными определяемые в их теле новые символы. При этом несмотря на то, что компиляция кода проходит нормально, редактор кода все равно новые символы не видит. “Ошибочный” символ подчеркивается красным, и при наведении на него курсора высвечивается хинт, что символ “could not be resolved”.

Нераспознанные символы в редакторе кода появляются потому, что плагин CDT не может найти подходящие заголовочные файлы. Чтобы редактор кода нормально видел подключенные символы, необходимо настроить (добавить) пути поиска файлов include в плагине CDT. Откройте свойства проекта, перейдите в раздел C/C++ General -> Path and Symbols -> на закладке Includes добавьте директории, где нужно искать заголовочные файлы. Вот пример добавленных путей поиска:

${ANDROID_NDK}/platforms/android-16/arch-arm/usr/include
${ANDROID_NDK}/toolchains/arm-linux-androideabi-4.8/prebuilt/windows/lib/gcc/arm-linux-androideabi/4.8/include

При добавлении путей учитывайте API Level целевой системы, для которой будет компилироваться приложение. В этом примере учтен API Level 16 (в составе пути имеется папка android-16).

Если после добавления путей все равно появляются “нераспознанные” символы, щелкните правой кнопкой мыши на имени проекта и выберите в контекстном меню Index -> Reresolve Unresolved Includes. Пункт меню Index -> Search for Unresolved Includes поможет Вам найти заголовочные файлы, которые не может подключить редактор.

Q021. Как управлять фокусом визуальных компонентов GUI?

Я расставил на форме несколько полей ввода, и мне нужно, чтобы определенное из этих полей после запуска программы получало фокус (стало текущим). Как это сделать?

Достаточно вызвать метод requestFocus. Пример куска кода из обработчика создания Activity onCreate:

myEdit1 = (EditText) findViewById(R.id.edit1);
myEdit2 = (EditText) findViewById(R.id.edit2);
myEdit2.requestFocus();

[140221]

Q022. Почему при отладке не срабатывают точки останова?

Breakpoint-ы не действуют потому, что Вы вероятно вместо отладки просто запустили приложение на устройстве, т. е. выполнили Run -> Run (Ctrl+F11). Чтобы точки останова срабатывали и была возможна пошаговая отладка, воспользуйтесь Run -> Debug (F11).

Другие причины проблемы отладки в Eclipse и способы решения:

1. Попробуйте принудительно разрешить отладку добавлением атрибута android:debuggable=”true” в тег < application > файла AndroidManifest.xml. Вообще-то с этой задачей должен автоматически справляться плагин ADT, однако это почему-то не всегда происходит.

2. Проверьте состояние кнопки “Skip all breakpoints” (пропустить все точки останова), которая находится на панели инструментов перспективы Debug (кнопка должна быть отжата). На всякий случай понажимайте на эту кнопку, и убедитесь, что все Ваши точки останова разрешены. Если перспектива Debug не открывается или не работает, то это означает, что Ваше отлаживаемое устройство некорректно подключено. Откройте перспективу DDMS и убедитесь, что Ваше устройство и работающее приложение перечислено в окне Devices, и доступно для отладки.

3. Если Вы пользуетесь для отладки эмулятором (виртуальным устройством, не реальным Android), то проблему старта отладки может вызывать долгий запуск эмулятора (эмулятор для запуска может требовать слишком много ресурсов, что конечно зависит от настроек виртуального устройства). Можно попробовать увеличить таймаут сессии ожидания adb от 3000 до 60000 мс и более.

Q023. Что такое Package name (имя пакета)?

Имя пакета предоставляет уникальный текстовый идентификатор для приложения. Это также имя по умолчанию для процесса приложения (см. манифесте приложения атрибут process элемента < application >) и по умолчанию свойство task affinity для (см. манифесте приложения атрибут taskAffinity элемента < activity >).

Имя пакета для приложения указывается в полном соответствии стилю языка Java, имя должно быть уникальным. Имя может содержать буквы верхнего и нижнего регистра (от ‘A’ до ‘Z’), цифры и подчеркивания (‘_’). Однако индивидуальные части имени пакета должны начинаться с буквы.

Во избежание конфликтов с другими разработчиками Вы должны использовать принцип организации имен наподобие доменного, но с указанием частей имени в обратном порядке. Например, приложения, опубликованные Google, будут иметь имя пакета, начинающееся на com.google. Также не нужно использовать для публикации пространство имен com.example.

Внимание: если Вы опубликовали Ваше приложение, то нельзя менять имя пакета, поскольку оно идентифицирует приложение. Если Вы поменяете имя пакета, то это будет означать, что получится другое приложение, и пользователи предыдущей версии не смогут получить обновление до новой версии.

Q024. Как в Eclipse сделать копию проекта? Как открыть готовый проект?

[Способ 1]

Чтобы сделать копию проекта, сделайте копию его корневой папки (той папки, где находятся файлы AndroidManifest.xml и project.properties), и затем переименуйте её. Копия проекта готова, теперь необходимо импортировать её в дерево проектов Eclipse.

Чтобы открыть копию проекта или любого готового проекта (который скачали из Интернета, к примеру), используйте меню File -> Import, далее выберите General -> Existing Projects into Workspace. Затем кликните Next и выберите корневую папку (root directory) проекта. Нажмите Finish, и через несколько секунд импорт завершится. Все, проект открыт.

[Способ 2]

• В дереве Package Explorer выделите мышью проект, который хотите скопировать (щелчком левой кнопки мыши на корневой папке проекта), нажмите Ctrl+C и Ctrl+V. Появится окно, в котором нужно задать новое имя проекта.

Eclipse-copy-project-set-new-name

После подтверждения нового имени через несколько секунд в дереве проектов появится новый проект – копия имеющегося проекта под новым именем.

• Щелкните правой кнопкой на новой корневой папке проекта, и выберите в контекстном меню Android Tools -> Rename Application Package. Откроется окно, где нужно указать новое имя пакета, укажите имя и нажмите OK. Затем запустится мастер переименования имени пакета в различных исходных файлах проекта, в этом окне просто нажмите Finish.

• В дереве Package Explorer раскройте папку src проекта, щелкните правой кнопкой на имени пакета и выберите в контекстном меню Refactor -> Rename…, укажите новое имя пакета, щелкните OK.

• Выполните очистку проекта, для этого выберите в меню Project -> Clean…

• Если необходимо, то в атрибуте package поменяйте имя пакета приложения (файл AndroidManifest.xml):

< manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.newpackagename"
    android:versionCode="1"
    android:versionName="1.0" >
    
    ...
< /manifest > 

• Если необходимо, то поменяйте имя приложения в файле values/strings.xml, имя приложения задается строкой app_name:

< ?xml version="1.0" encoding="utf-8"? >
< resources >
    < string name="app_name">MyAppName< /string >
    < string name="action_settings">Settings< /string >
    < string name="hello_world">Hello world!< /string >
< /resources >

Q025. Как импортировать в Eclipse проект из Android NDK samples?

Меню File -> New -> Project… -> Android -> Android Project from Existing Code, далее в поле ввода Root Directory выберите папку проекта из каталога NDK samples (например, это может быть папка c:android-ndk-r9csamplesTeapot). Если Вы предварительно сделали копию папки проекта NDK, то ставить галочку Copy projects into workspace необязательно. Нажмите Finish, и через несколько секунд импорт завершится.

[140223]

Q026. Java Build Path: не могу добавить библиотеку .JAR к проекту.

Почему когда я пытаюсь добавить к проекту библиотеку guava-16.0.1.jar, копию файла которой я поместил в каталог libs, то не могу это сделать через стандартный диалог свойств проекта Properties? Захожу в раздел Java Build Path, перехожу на закладку Libraries, жму кнопку Add JARs…, в браузере файла перехожу в папку libs, но почему-то там не виден файл guava-16.0.1.jar (скопированный туда через Проводник).

Причина в том, что среда Eclipse не синхронизировалась с файловой системой, поэтому файл guava-16.0.1.jar не виден. Чтобы исправить это, после копирования файла guava-16.0.1.jar в папку libs поставьте курсор на имя проекта и нажмите F5 (обновить), и только потом заходите в свойства проекта, чтобы добавить guava-16.0.1.jar в Java Build Path.

Если Вы иногда редактируете файлы вне среды Eclipse, то можете установить автообновление (auto-refresh) через меню Window -> Preferences, перейдите в раздел General -> Workspace, и поставьте 2 галочки “Refresh using native hooks or polling” и “Refresh on access”.

[140301]

Q027. Android requires compiler compliance level 5.0 or 6.0. Found ‘1.7’ instead. Please use Android Tools > Fix Project Properties

Щелкните правой кнопкой на имени проекта и выберите Android Tools -> Fix Project Properties.

Q028. Type ‘int32_t’ could not be resolved

В том файле, где возникает ошибка добавьте включение заголовочного файла:

#include < jni.h >

Общее правило для поиска заголовочного файла, который нужно подключить: среди заголовочных файлов NDK выбранной платформы (к примеру для платформы API Level 16 это будет папка c:android-ndk-r9cplatformsandroid-16arch-armusr) найдите файл с расширением *.h, где определен нужный тип.

[140302]

Q029. Member declaration not found

У меня эта странная ошибка возникала, если использовался тип возврата функции в виде операции взятия адреса (несмотря на то, что метод класса GraphicsService::getHeight был одинаково объявлен и в заголовке, и в основном модуле), пример:

const int32_t& GraphicsService::getHeight()
{
    return mHeight;
}

Ошибка исчезла, когда переопределил тип возврата метода без &:

const int32_t GraphicsService::getHeight()
{
    return mHeight;
}

Q030. Предупреждение “Not targeting the latest versions of Android…”

Иногда при смене настроек android:targetSdkVersion появляется предупреждение “Not targeting the latest versions of Android; compatibility modes apply. Consider testing and updating this version. Consult the android.os.Build.VERSION_CODES javadoc for details.AndroidManifest.xml /ИмяПроекта line 6 Android Lint Problem”.

Предупреждение генерирует система Android Lint. Она сообщает о том, что режим совместимости будет применен к тем функциям, которые возможно стали недоступны в более свежих версиях, чем указано в targetSdkVersion.

Объяснение проблемы следующее: когда Ваше приложение работает на версии Android более свежей, чем задано в Вашем targetSdkVersion, различные режимы совместимости будут выключены. Такое поведение гарантирует, что Ваше приложение будет работать, однако это может выглядеть неуместным. Например, если targetSdkVersion указано меньше 14, то Ваше приложение может получить в интерфейсе пользователя кнопку настройки опций.

Чтобы исправить эту проблему, установите значение targetSdkVersion в самое высокое доступное значение. Затем протестируйте приложение, чтобы убедиться, что все возможности работают корректно. Можно проконсультироваться по теме проблем совместимости и узнать, какие произошли изменения при переходе по версиям по ссылке http://developer.android.com/reference/android/os/Build.VERSION_CODES.html. При исправлении этого предупреждения путем увеличения версии android:maxSdkVersion нужно помнить о том, что если к примеру установлено android:maxSdkVersion=”17″, и пользователь обновил свою систему Android на версию больше, чем 17, то Ваше приложение будет автоматически удалено, потому что оно будет относиться к неподдерживаемой версии.

См. также:

Android Min SDK Version vs. Target SDK Version
Difference between “Build Target SDK” in Eclipse and android:targetSdkVersion in AndroidManifest.xml?

Q031. Type ‘EGL_DEFAULT_DISPLAY’ could not be resolved

Эта ошибка возникает потому, что в Eclipse не задано макроопределение __ ANDROID__, что приводит к не заданному EGLNativeDisplayType в EGL/eglplatform.h, что в результате приводит к ошибке, что не определено EGL_DEFAULT_DISPLAY.

Чтобы исправить ошибку, зайдите в свойства проекта, перейдите в раздел C/C++ General -> Paths and Symbols, и на закладке Symbols кликните на GNU C, затем на кнопке “Add”, и введите __ANDROID__ в поле имени “Name”. Поставьте галочки “Add to all configurations” и “Add to all languages”, и нажмите OK.

Q032. Как определить версию Android SDK, которая установлена на компьютере?

Перейдите в папку, где у Вас установлен Android SDK, открыв путь %ProgramFiles%AndroidAndroid-sdkplatforms (если SDK был установлен вместе с Android Studio, то это может быть путь наподобие %ProgramFiles%Androidandroid-studiosdkplatforms). В папке platforms вы найдете подпапки от android-3 до android-19, это и есть установленные SDK для различных версий платформ Android.

Можно также узнать установленные версии SDK, запустив SDK Manager (см. вопрос Q016). Когда SDK Manager запустится, в разделе Installed packages Вы можете найти информацию об SDK. Кроме того, в среде Eclipse можно открыть окно Help -> Install New Software…, и открыть ссылку What is already installed? в правой нижней части окна. То же самое окно можно открыть через Help -> About Eclipse -> Installation Details.

В проекте Eclipse строка Build.VERSION.RELEASE даст Вам строку, удобочитаемую для пользователя, которая предоставит информацию о версии (например 1.5, 1.6, 2.0), в то время как Build.VERSION.SDK_INT даст числовое значение из Build.VERSION_CODES, которое удобнее использовать программно – например для сравнения версий.

Q033. Ошибка NDKHelper.java: PROPERTY_OUTPUT_FRAMES_PER_BUFFER cannot be resolved or is not a field

Зайдите в свойства проекта, затем в раздел Android, и в окне Project Build Target поставьте галочку на API Level уровня 17 (Android 4.2.2), нажмите OK.

В общем случае все проблемы, связанные с проверкой в условных операторах переменной SDK_INT (или android.os.Build.VERSION.SDK_INT) решаются увеличением версии API Level в свойствах проекта. Причем вовсе необязательно, что программа, скомпилированная на высоком уровне API Level, не будет работать на младших устройствах Android – все зависит от вызовов API, которая делает программа. Для этого программа должна во время выполнения проверять значение текущего API Level, и в соответствии с уровнем API предпринимать нужные действия.

Q034. Error retrieving parent for item: No resource found that matches the given name …

Это ошибка системы Android AAPT. Ошибка исчезнет, если в файле AndroidManifest.xml увеличите значение атрибута android:minSdkVersion.

[140309]

Q035. Как в приложении Eclipse писать и использовать код не на Java, а на C/C++?

NDK -> создание на C библиотеки, размещение в ней функций -> Объявление этих функций (public native …) в классе MyActivity приложения -> Загрузка созданной библиотеки по имени в классе MyActivity (System.loadLibrary(“mylib”)) -> Вызов функций из кода Java.

Подробнее хорошо написано в книге “Android NDK. Разработка приложений под Android на C/C++”, автор Сильвен Ретабоуил.

Q036. Ошибка “Cannot run program “ndk-build”: Launching failed”

Как исправить: свойства проекта -> слева выберите раздел C/C++ Build -> на закладке Builder settings введите полный путь до утилиты ndk-build:

${ANDROID_NDK}ndk-build.cmd

Q037. Различные проблемы с запуском javah.exe и методы их решения.

1. Корректно указывайте имя для Activity в командной строке. Имя должно составляться таким образом:
com.имя_проекта_в_нижнем_регистре.имя_Activity, например:

“%JAVA_HOME%binjavah.exe” -classpath binclasses;”%ANDROID_SDK%platformsandroid-16android.jar” -d jni com.myproject.MainActivity

В этом примере MainActivity можно узнать из файла MainActivity.java, который находится в корне проекта. См. в этом файле строку объявления класса Activity наподобие:

public class MainActivity extends Activity

2. В опциях javah.exe все пути с пробелами должны быть указаны в кавычках, например:

“%JAVA_HOME%binjavah.exe” -classpath binclasses;”%ANDROID_SDK%platformsandroid-16android.jar” -d jni com.myproject.MainActivity

В этом примере переменная окружения %ANDROID_SDK% содержит пробелы, поэтому для формирования пути с участием этой переменной нужно использовать двойные кавычки.

3. Ошибка “Error: no classes specified” или “Could not find class file for ‘com.myproject.MainActivity'”. Вы не указали в опции -classpath, где находятся классы Вашего приложения. Обычно это папка имя_проектаbinclasses. Вот пример содержимого опции:

“%JAVA_HOME%binjavah.exe” -classpath binclasses -d jni com.myproject.MainActivity

4. Ошибка “Error: cannot access android.app.Activity”, “class file for android.app.Activity not found”. В пути опции -classpath через точку с запятой нужно добавить путь до файла android.jar, относящегося к целевой платформе, для которой Вы компилируете приложение. Например, если Вы делаете приложение для Android 4.1.2 (API Level 16), то это будет файл %ANDROID_SDK%platformsandroid-16android.jar. Переменная окружения %ANDROID_SDK% указывает на каталог, где находится SDK (к примеру, это может быть папка c:Program FilesAndroidandroid-studiosdk). Вот пример командной строки строки javah.exe с указанием целевого android.jar:

C:Program FilesAndroidworkspaceMyProject>”%JAVA_HOME%binjavah.exe” -verbose -classpath binclasses;”%ANDROID_SDK%platformsandroid-16android.jar” -d jni com.myproject.MainActivity

Q038. Как в Eclipse настроить запуск javah.exe для генерации заголовочного файла моего модуля на C/C++?

Процесс по шагам:

a) Run -> External Tools -> External Tools Configurations…, откроется окно для настройки конфигураций запуска внешнего инструментария компиляции.

b) Слева щелкните на раздел Program, добавьте новую конфигурацию кнопкой New launch configuration. В поле Name укажите любое произвольное имя, например MyProject javah.

c) В поле Location: укажите полный путь для запуска утилиты javah.exe. Не стесняйтесь пользоваться кнопкой Variables…, которая позволяет использовать изначально настроенные переменные. В этом примере используется env_var для распаковки пути до места расположения каталога JDK через переменную окружения JAVA_HOME. Пример пути до javah.exe:
${env_var:JAVA_HOME}binjavah.exe

d) В поле Working Directory: укажите путь до рабочей директории. Обычно это папка bin, расположенная в корневом каталоге проекта. Пример указания рабочего каталога:
${workspace_loc:/MyProject/bin}

e) В поле Arguments: укажите аргументы для запуска утилиты javah.exe. Здесь должны быть указаны опция -classes (пути, где расположены классы проекта), опция -d (задает рабочий каталог), и имя для Activity приложения. Пример указания аргументов javah.exe:
-classpath “${workspace_loc}”/MyProject/bin/classes;”${env_var:ANDROID_SDK}”platformsandroid-16android.jar -d “${workspace_loc:/MyProject/jni}” com.myproject.MainActivity

f) Перейдите на закладку Refresh, поставьте галочку Refresh resources upon completion, выберите радиокнопку Specific resources и через кнопку Specify Resources… укажите на каталог jni, где будет размещаться модуль C/C++, для которого javah.exe должна генерировать заголовок.

Q039. Где меняются настройки, связанные с платформой (API Level) компилируемого приложения?

Настройки меняются во многих местах:

1. Имя проекта -> Properties -> Android -> поставьте галочку на выбранную версию Android (например Android 4.1.2, API Level 16).
2. Имя проекта -> Properties -> C/C++ General -> Paths and Symbols -> Includes -> настройте пути поиска заголовочных файлов Android NDK. Пример настроенных путей для Assembly, GNU C, GNU C++:
${ANDROID_NDK}/toolchains/arm-linux-androideabi-4.8/prebuilt/windows/lib/gcc/arm-linux-androideabi/4.8/include
${ANDROID_NDK}/sources/android/native_app_glue
${ANDROID_NDK}/platforms/android-16/arch-arm/usr/include
3. AndroidManifest.xml -> android:minSdkVersion=”16″, android:targetSdkVersion=”16″. В этом примере настроено использование SDK для API Level 16.

[140315]

Q040. Java: что такое Direct Subclass, Indirect Subclass?

Часто в документации по программированию Android встречаешь списки типа “Known Direct Subclasses”, “Known Indirect Subclasses”, однако что это на самом деле значит?

Direct Subclass – класс, который является прямым, непосредственным производным от какого-то класса.
Indirect Subclass – класс, который является наследником какого-то класса через цепочку промежуточных наследников.

Например, есть следующая иерархия наследования классов (для Java-класса TextView):

java.lang.Object -> android.view.View -> android.widget.TextView

Здесь класс TextView является прямым наследником (Direct Subclass) от класса View, и непрямым наследником (Indirect Subclass) класса Object.

Q041. Java: как получить размеры экрана устройства Android?

Пример кода (размеры экрана присваиваются переменным width и height):

public class MainActivity extends Activity{
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Display display = getWindowManager().getDefaultDisplay();
        Point size = new Point();
        display.getSize(size);
        int width = size.x;
        int height = size.y;
        ... 
    }

Q042. Java: как получить строку String из ресурса R?

Используйте getString(идентификатор_строки). Пример:

Файл XML, сохраненный в res/values/strings.xml:

< ?xml version="1.0" encoding="utf-8"? >
< resources >
    < string name="hello" >Hello!< /string >
< /resources >

Этот XML файл применяется в строке TextView (здесь приведен фрагмент файла activity_main.xml):

< TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="@string/hello" / >

Вот так приложение может получить строку:

String string = getString(R.string.hello);

Для получения строки можно использовать либо getString(int), либо getText(int). Функция getText(int) возвратит вместе с текстом стили и форматирование, которые применены к строке.

Q043. Java: как добавить к String строку?

.

Предположим, есть строка “Это строка 1”, как добавить к этой строке другую строку “Это строка 2”?

Для этой цели можно использовать класс StringBuilder. Пример:

StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("Это строка 1"); stringBuilder.append("n"); stringBuilder.append("Это строка 2"); stringBuilder.append("n");
String finalString = stringBuilder.toString();

Кроме StringBuilder можно также использовать StringBuffer. Оба этих класса используют для динамической манипуляции строками. Однако нужно помнить, что StringBuffer является thread-safe (можно безопасно использовать в многопоточной среде), а StringBuilder не thread-safe (можно безопасно использовать только в одном потоке). Поэтому в одном потоке используйте StringBuilder, поскольку он работает быстрее, чем StringBuffer.

Q044. Java: как преобразовать CharSequence в String?

Используйте метод toString, который есть у всех классов (в том числе и у класса CharSequence)

.

Q045. Java: как программно работать с визуальными компонентами интерфейса приложения? Что означает @+id?

Этот вопрос частично пересекается с вопросом Q042, где рассматривалось получение строки из ресурсов, а также с вопросом Q009, где объяснялось назначение файла класса ресурсов R.

Все ресурсы приложения Android (к ресурсам относятся все визуальные компоненты приложения, кнопки, галочки, слайдеры, метки, строки и т. п.) конфигурируются с помощью файлов XML, которые размещены в папке res (и распределены по подпапкам layout, menu). Из всех файлов XML, где описаны ресурсы, система Eclipse автоматически генерирует файл R, это файл класса ресурсов приложения, при этом каждый ресурс получает уникальный числовой идентификатор id. Получить доступ к ресурсу (запросить значение строки, создать объект класса, который соответствует контролу ресурса) можно с помощью этого id и соответствующих функций, которые принимают id в качестве параметра. Пример получения строки из ресурса уже был рассмотрен в вопросе Q042.

По такому же принципу, как было показано в вопросе Q042, работают со всеми ресурсами: создается объект, который соответствует ресурсу, и уже работают с методами этого объекта.

Теперь по поводу того, что же такое “@+id”. С цифровыми идентификаторами, которые присвоены каждому ресурсу в файле R, конечно же работать неудобно. Поэтому каждому цифровому id поставлено в соответствие символическое имя, которое редактируется в свойстве Id, и задается в виде текста “@+id/текстовое_имя_ресурса”. Плюсик означает, что должен быть создан новый ID, которому система сама назначит цифровое значение, поставленное в соответствие символическому имени ресурса “текстовое_имя_ресурса” (это соответствие автоматически генерируется и хранится в файле R).

Когда в визуальном редакторе Eclipse редактируют будущий вид приложения, то добавляют туда разные контролы (контролы это кнопки, текстовые метки, галочки и т. п.). После добавления каждого контрола в свойстве Id для удобства задают текстовый идентификатор @+id. Рассмотрим пример программной работы с интерфейсом приложения на метке TextView. Ресурсом TextView (текстовая метка) размещен визуальным редактором на экране разрабатываемого приложения, и в свойстве Id задано имя mylabel, что показано на скриншоте:

Eclipse-visual-edit-activity main-xml

Имя идентификатора, которое через слеш добавляется к @+d, потом попадает в файл activity_main.xml. Для нашего примера с меткой TextView (показан фрагмент файла activity_main.xml):

< TextView
        android:id="@+id/mylabel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" / >

Далее по имени mylabel можно программно работать с контролом TextView:

//Получим размеры экрана устройства Android.
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);int width = size.x;int height = size.y;
 
//Загрузим контрол TextView из ресурсов и установим
// его размер во весь экран. 
TextView text = (TextView)findViewById(R.id.mylabel);
text.setWidth(width);
text.setHeight(height);//Вставка своего текста в TextView
text.setText(R.string.str1);//Добавление текста к TextView
consoletxtval = text.getText().toString();
StringBuilder stringBuilder = new StringBuilder(consoletxtval);
stringBuilder.append("n");
stringBuilder.append(getString(R.string.str2));
consoletxtval = stringBuilder.toString(); 
text.setText(consoletxtval);

[140323]

Q046. Java: как выводить сообщения в LogCat?

LogCat это системный лог сообщений. Разработчик может выводить туда свои сообщения с помощью статического класса android.util.Log. Сделайте импорт android.util.Log, и далее пользуйтесь его методами без создания экземпляра класса (поскольку класс статический).

LogCat поддерживает разные уровни вывода сообщений:

V — Verbose (подробно, самый низкий приоритет)
D — Debug
I — Info
W — Warning
E — Error
F — Fatal
S — Silent (самый высокий приоритет, на котором ничто никогда не распечатывается)

Благодаря наличию уровней сообщений их можно грубо отфильтровать по уровню. Например, вот так это делается в консоли LogCat в среде Eclipse:

Eclipse-LogCat-select-message-level

Когда Вы запускаете свое приложение в режиме отладки из Eclipse, то Вы можете увидеть множество сообщений, которые появляются в окне консоли LogCat: как сообщения, отправленные Вашим приложением, так и сообщения системы и других приложений, которые работают в этот момент на Вашем устройстве.

Чтобы вывести что-то в лог, сначала определитесь, насколько критичным должно быть выводимое сообщение (должно ли оно быть в категории отладочной информации (d, Debug), или это должно быть просто информационное сообщение (i, Info), или это должно быть предупреждение (w, Warning) или это должно быть сообщение об ошибке (e, Error)? После этого используйте для вывода подходящий метод:

Log.d("myApp", "my debug message");
Log.i("myApp", "my informational message");
Log.w("myApp", "my warning message");
Log.e("myApp", "my error message");

Первый параметр myApp предоставляет текстовую метку, которая позволяет дополнительно отфильтровать сообщения в логе. Это может оказаться полезным, когда сообщений слишком много, и найти нужное сообщение будет проще, если заранее знать её метку. В консоли LogCat Eclipse такой фильтр можно создать кнопкой с зеленым плюсиком “Add new logcat filter”.

Примечание: после отладочного запуска приложения в Eclipse один такой фильтр создается автоматически по имени пакета приложения. В этот фильтр попадут сообщения, которые система Android сама сгенерирует в ответ на события, относящиеся к Вашему приложению.

Q047. C/C++: как выводить сообщения в LogCat?

Для native-кода NDK предоставляет библиотеку, аналогичную Java-классу android.util.Log. Чтобы воспользоваться её возможностями, подключите заголовочный файл log.h

#include < android/log.h >

и в файл Android.mk добавьте строку

LOCAL_LDLIBS := -landroid -llog

После этого для вывода в LogCat можете использовать функции __android_log_vprintf и __android_log_printf. Однако эти функции напрямую вызывать достаточно неудобно, поэтому есть смысл создать для них специальный класс Log:

/* Log.hpp */
#ifndef LOG_HPP_
#define LOG_HPP_
 
namespace packt
{
    class Log
    {
    public:
        static void error (const char* pMessage, ...);
        static void warn (const char* pMessage, ...);
        static void info (const char* pMessage, ...);
        static void debug (const char* pMessage, ...);
    };
}
 
#ifndef NDEBUG
  #define packt_Log_debug(...) packt::Log::debug(__VA_ARGS__)
#else
  #define packt_Log_debug(...)#endif
#endif /* LOG_HPP_ */
/* * Log.cpp */
#include "Log.hpp"
#include < stdarg.h >
#include < android/log.h >
 
namespace mypack
{
    void Log::info(const char* pMessage, ...)
    {
        va_list lVarArgs;
        va_start (lVarArgs, pMessage);
        __android_log_vprint(ANDROID_LOG_INFO, "PACKT", pMessage, lVarArgs);
        __android_log_print(ANDROID_LOG_INFO, "PACKT", "n"); va_end(lVarArgs);
    }
void Log::error(const char* pMessage, ...) { va_list lVarArgs; va_start(lVarArgs, pMessage); __android_log_vprint(ANDROID_LOG_ERROR, "PACKT", pMessage, lVarArgs); __android_log_print(ANDROID_LOG_ERROR, "PACKT", "n"); va_end(lVarArgs); }
void Log::warn(const char* pMessage, ...) { va_list lVarArgs; va_start(lVarArgs, pMessage); __android_log_vprint(ANDROID_LOG_WARN, "PACKT", pMessage, lVarArgs); __android_log_print(ANDROID_LOG_WARN, "PACKT", "n"); va_end(lVarArgs); }
void Log::debug(const char* pMessage, ...) { va_list lVarArgs; va_start(lVarArgs, pMessage); __android_log_vprint(ANDROID_LOG_DEBUG, "PACKT", pMessage, lVarArgs); __android_log_print(ANDROID_LOG_DEBUG, "PACKT", "n"); va_end(lVarArgs); } }

[140324]

Q048. Как сделать сделать полноэкранное приложение?

Для игр часто нужно создать программу, которая работает в полный экран, даже без отображения заголовка оповещений (notification bar). Есть несколько способов решения этой задачи.

[Программное отображение в полный экран]

Вот код, который позволяет загружать Activity в полный экран.

import android.app.Activity;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;
 
public class ActivityName extends Activity{
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        // remove title
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
            WindowManager.LayoutParams.FLAG_FULLSCREEN);
        setContentView(R.layout.main);
    }
}

[Отображение в полный экран, заданное в AndroidManifest.xml]

< activity android:name=".ActivityName"
    android:label="@string/app_name"
    android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
< /activity >

Имейте в виду, что вариант с манифестом может привести к загрузке приложения с отображением черного экрана, так что иногда программный вариант переключения в полный экран может быть предпочтительней.

Q049. Запуск MediaPlayer для воспроизведения звука приводит к ошибкам “prepareAsync called in state 1”, “start called in state 1”.

Причина в том, что на момент вызова метода start() экземпляр MediaPlayer еще не готов к воспроизведению. Запускать воспроизведение можно только при полной готовности MediaPlayer.

Отслеживание готовности можно в обработчике события setOnPreparedListener класса MediaPlayer:

   //Объект проигрывателя, который будет проигрывать звук на кнопке.
   MediaPlayer mp = MediaPlayer.create(this, R.raw.girlfart01);
   //Звук будет проигрываться только 1 раз:
   mp.setLooping(false);
   //Установка обработчика события на момент готовности проигрывателя:
   mp.setOnPreparedListener(new MediaPlayer.OnPreparedListener()
   {
      public void onPrepared(MediaPlayer player)
      {
         //При готовности к проигрыванию запуск вывода звука:
         player.start();
      }
   }
);

Подробнее про воспроизведение звука с помощью MediaPlayer см. статью “MediaPlayer: проигрывание звука”.

[140415]

Q050. Как рисовать на экране приложения графику и текст?

Текст и графика рисуются с помощью объектов Canvas и Paint. Пример рисования текста:

Paint paint = new Paint(); 
canvas.drawPaint(paint); 
paint.setColor(Color.BLACK); 
paint.setTextSize(16); 
canvas.drawText("Мой текст", x, y, paint);

Пример рисования линий:

canvas.drawLine(0, 0, 20, 20, paint);
canvas.drawLine(20, 0, 0, 20, paint);

[140418]

Q051. Как вывести многострочный текст с прокруткой?

Для этого можно использовать классы TextView и EditText.

[Использование TextView]

1. Добавьте на форму программы виджет TextView. Это можно сделать в графическом редакторе формы, выбрав виджет в разделе Form widgets. После добавления виджета в файле activity_main.xml добавятся строки:

        < TextView
            android:id="@+id/textView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

Здесь важно запомнить значение идентификатора виджета android:id (в нашем примере идентификатор textView1), он нам понадобится в дальнейшем для подключения к виджету в программе. Атрибут android:text можно убрать, так как начальный текст нам не нужен.

Чтобы окно с текстом занимало всю доступную область, добавьте также атрибуты:

        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"

2. Добавьте в класс Activity приложения глобальную переменную с типом TextView:

TextView txtconsole;

В обработчике onCreate Activity добавьте инициализацию переменной:

txtconsole = (TextView)findViewById(R.id.textView1);

3. Чтобы добавить текст в поле редактирования, вызовите метод append:

txtconsole.append("Это мой текстrn");

В этом примере в конец текста добавлены символы CR и LF, чтобы следующий текст отображался с новой строки. Тест будет добавляться, пока не дойдет до заполнения формы и не будет теряться снизу, чтобы этого не было, нужно добавить вертикальную полосу прокрутки.

4. Чтобы добавить справа вертикальную полосу прокрутки, в секцию TextView файла activity_main.xml добавьте атрибут android:scrollbars=”vertical”:

        < TextView
            android:id="@+id/textView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:scrollbars="vertical" />

Также добавьте в обработчике onCreate создание пустого метода для прокрутки (без этого полоса прокрутки не появится).

...
txtconsole = (TextView)findViewById(R.id.textView1);
txtconsole.setMovementMethod(new ScrollingMovementMethod());

5. Чтобы было проще добавлять текст в TextView, и сразу его прокручивать в конец при добавлении нового текста, целесообразно написать для этого отдельную процедуру:

private void appendTextAndScroll(String text){
   if(txtconsole != null)
   {
      txtconsole.append(text + "n");
      final Layout layout = txtconsole.getLayout();
      if(layout != null)
      {
         int scrollDelta = layout.getLineBottom(txtconsole.getLineCount() - 1) 
                         - txtconsole.getScrollY() - txtconsole.getHeight();
         if(scrollDelta > 0)
            txtconsole.scrollBy(0, scrollDelta);
      }
   }
}

Теперь добавлять текст нужно так:

   appendTextAndScroll("Это мой текст");

[Использование EditText]

1. Добавьте на форму программы виджет Plain Text. Это можно сделать в графическом редакторе формы, выбрав виджет в разделе Text Fields (он помечен меткой abc). После добавления виджета в файле activity_main.xml добавятся строки:

        < EditText
            android:id="@+id/editText1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:ems="10" >
        < /EditText >

Здесь важно запомнить значение идентификатора виджета android:id (в нашем примере идентификатор editText1), он нам понадобится в дальнейшем для подключения к виджету в программе.

2. Добавьте в класс Activity приложения глобальную переменную с типом EditText:

EditText txtconsole;

В обработчике onCreate Activity добавьте инициализацию переменной:

txtconsole = (EditText)findViewById(R.id.editText1);

3. Чтобы добавить текст в поле редактирования, вызовите метод append:

txtconsole.append("Это мой текстrn");

В этом примере в конец текста добавлены символы CR и LF, чтобы следующий текст отображался с новой строки.

4. Чтобы добавить справа вертикальную полосу прокрутки, в секцию EditText файла activity_main.xml добавьте атрибут android:scrollbars=”vertical”:

        < EditText
            android:id="@+id/editText1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:ems="10"
            android:scrollbars="vertical" >
        < /EditText >

5. Чтобы запретить редактирование текста, добавьте также атрибут android:editable=”false”:

        < EditText
            android:id="@+id/editText1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:ems="10"
            android:scrollbars="vertical"
            android:editable="false" >
        < /EditText >

Чтобы окно с текстом занимало всю доступную область, добавьте также атрибуты:

        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"

[140421]

Q052. Java: как преобразовать число в строку? Строку в число? Число в шестнадцатеричный формат?

[Преобразование числа в строку]

Используйте String.valueOf или Integer.toString, Float.toString и т. п. Примеры:

int intVal=5;
float floatVal=14.76;
 
//Использование String.valueOf:
myTextView.setText(String.valueOf(intVal));
myTextView.append(String.valueOf(floatVal));//Использование Integer.toString:
myTextView.setText(Integer.toString(intVal));
myTextView.append(Float.toString(floatVal));

[Преобразование числа в HEX строку]

int intval = 1234;
String txt = Integer.toHexString(intval);  // в txt получится "4D2"

[Преобразование строки в число]

Используйте метод parseInt, входящий в состав классов Integer, Float и т. п. Пример:

int intVal;
float floatVal;
String stringInt = "5";
String stringFloat = "14.76";
 
try{
    intVal = Integer.parseInt(stringInt);
    floatVal = Float.parseInt(stringFloat);
}
catch(NumberFormatException nfe){
   System.out.println("Ошибка преобразования: " + nfe);
}

Q053. Java: как правильно задать байтовый массив?

Старый метод наподобие char txtbuf[80] в Java не работает. Массивы нужно задавать с помощью оператора new:

char txtbuf[] = new char[80];
byte buffer[] = new byte[4];

Q054. Java: куда пропала директива #define?

Директива #define теперь не работает, потому что прекомпилятор как таковой отсутствует. Константы на Java нужно задавать так же, как и обычные переменные, но только с добавлением ключевого слова final (оно означает, что константе можно присвоить значение только 1 раз).

//Стандартный синтаксис #define на языке C/C++:
#define USB_TYPE_VENDOR (0x02 << 5)
#define USB_RECIP_DEVICE 0x00
#define USB_ENDPOINT_IN 0x80
#define USB_ENDPOINT_OUT 0x00
//Те же самые константы на Java нужно задавать так:
public class MainActivity extends Activity{
   private static final int USB_TYPE_VENDOR  = (0x02 << 5); 
   private static final int USB_RECIP_DEVICE = 0x00;
   private static final int USB_ENDPOINT_IN  = 0x80;
   private static final int USB_ENDPOINT_OUT = 0x00;
   ...

Q055. Eclipse: ошибка “Unable to resolve target”

Такая ошибка может возникнуть после импорта готового проекта в текущий воркспейс. После импорта проекта в Eclipse любые глюки не редкость, так что удивляться не нужно (кстати говоря, многие глюки устраняются просто перезапуском Eclipse).

Когда в свойствах старого проекта (файл project.properties) указан target на версию, которая не поддерживается текущей установкой Eclipse, то попытка очистки (Project -> Clean…) может вызвать такую ошибку. Исправить ошибку можно, если поменять версию target. Там нужно указать число API Level, например:

# Project target.
target=android-19

Q056. Можно ли выводить в TextView форматированный текст (bold, italiс и т. п.)?

В виджете TextView Android есть недокументированная возможность выводить тест в формате HTML, т. е. текст можно делать подчеркнутым, толстым, и даже вставлять в TextView ссылки. Это делается с помощью класса Html и его метода fromHtml. Пример вывода форматированного текста:

String s = "< b >Жирный< /b >, < i >наклонный< /i >, и даже < u >подчеркнутый< /u > текст!"
TextView tv = (TextView)findViewById(R.id.THE_TEXTVIEW_ID);
tv.setText(Html.fromHtml(s));

Такая возможность появилась начиная с Android 2.1, поддерживаются также теги: a href=”/…”, b, big, blockquote, br, cite, dfn, div align=”…”, em, font size=”…” color=”…” face=”…”, h1, h2, h3, h4, h5, h6, i, img src=”/…”, p, small, strike, strong, sub, sup, tt, u.

Внимание: если есть необходимость добавления форматированного текста к уже имеющемуся в TextView без потери его форматирования, то необходимо предусмотреть отдельный буфер для текста типа String, и хранить весь форматированный текст именно в этом буфере.

Q057. Java: как удалить все элементы выпадающего списка Spinner?

Удалить все записи из виджета Spinner можно с помощью метода setAdapter, если ему передать аргумент null, пример:

mySpinner.setAdapter(null);

[140428]

Q058. Как вызвать функцию getSystemService из любого класса?

Если вызвать getSystemService из класса, который не связан с GUI приложения Android (т. е. не из класса, который порожден от Activity), то компилятор Java выдаст ошибку “метод не определен”. Это происходит потому, что getSystemService связан с классом Context, от которого произведен класс Activity. В произвольном классе, который по умолчанию порожден от класса Object, нет доступа к Context и к его методу getSystemService.

Чтобы иметь возможность вызвать getSystemService из любого класса, нужно передать в него Context. Это можно сделать разными способами – через параметр конструктора, через статическую переменную класса.

[Передача Context через конструктор класса]

public class myClass
{ Context mContext; //Инициализация контекста в конструкторе. public myclass(Context mContext;) { this.mContext = mContext; } public Location getLocation() { //Есть возможность вызвать getSystemService через Context: locationManager = (LocationManager)mContext.getSystemService(context); ... }
}
 
public class MainActivity extends Activity{
   Button btnCheck;
   myClass myclass;
   
   @Override
   protected void onCreate(Bundle savedInstanceState)
   {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
btnCheck = (Button)findViewById(R.id.checkusbdev); //Передача контекста в экземпляр myClass: myclass = new myClass(this); ... } ...
}

[Передача Context через статическую переменную класса]

//В класс usbutil будет передаваться Context из класса Activity
public class usbutil{
   public static MainActivity context = null;
   public static String doReadRawDescriptors(UsbDevice device, int paramidx)
   {
      //Теперь есть возможность вызвать getSystemService через Context:
      UsbManager manager = (UsbManager)context.getSystemService(Context.USB_SERVICE);
      UsbDeviceConnection connection = manager.openDevice(device);
      
      ...
   }   
   ...
}
 
public class MainActivity extends Activity{
   Button btnCheck;
   Spinner spDeviceName;
   
   @Override
   protected void onCreate(Bundle savedInstanceState)
   {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      btnCheck = (Button)findViewById(R.id.checkusbdev);
      ...
      //Передача контекста в класс usbutil:
      usbutil.context = this;
      ...
   }
   ...
}

Q059. Eclipse: как заменить форматирование кода с табуляции на пробелы?

Вопрос не очень тривиальный, поскольку требует замены настроек во многих местах. Процесс по шагам для настроек форматирования кода Java:

1. Поменяйте свойства редактора кода Java: меню Window -> Preferences -> Java -> Code Style -> Formatter -> Edit -> Indentation выберите из списка “Spaces Only”. Для того, чтобы можно было сохранить настройки, создайте новый профиль, для этого вверху в строке ввода Profile name введите имя нового профиля.

2. Поменяйте свойства редактора по умолчанию: меню Window -> Preferences -> General -> Editors -> Text Editors -> Insert spaces for tabs поставьте галочку.

3. Для уже имеющегося файла Java, в коде которого есть Tab-ы, нужно принудительно поменять все Tab-ы на пробелы. Если этого не сделать, то даже при измененных настройках (на шагах 1, 2) добавление новых строк и операторов будет выполняться все так же с Tab-ами вместо пробелов. Чтобы быстро поменять все Tab на пробелы откройте файл, нажмите Ctrl-A (выделится весь текст) и затем нажмите Ctrl-I (применятся текущие настройки форматирования Ident). Это заменит в тексте все символы табуляции на пробелы. Дальше добавление новых строк, блоков кода будет происходить уже нормально, с пробелами.

См. также How do I change Eclipse to use spaces instead of tabs? site:stackoverflow.com.

Q060. Eclipse: как заменить “египетский” стиль блоков кода на традиционный? Чтобы фигурная скобка открывалась не в конце оператора, а на новой строке?

egyptian

//Есть "египетский", нечитаемый код:
if (myclass.enabled()) {
    myclass.doSomething();
}
else {
    myclass.doSleep();
}
 
//Нужно, чтобы был нормальный:
if (myclass.enabled())
{
    myclass.doSomething();
}
else
{
    myclass.doSleep();
}

Для того, чтобы изменить оформление блоков кода, нужно отредактировать шаблоны кода, и создать новый форматер для кода. Как то делается на примере кода Java:

1. Меню Window -> Preferences -> Java -> Editor -> Templates, выберите в таблице нужную строку с шаблоном и нажмите кнопку Edit. Отредактируйте шаблон так, чтобы фигурная скобка появилась на новой строке. Повторите то же самое для всех шаблонов, где встречается блок с фигурными скобками.

2. Создайте новый форматер и примените его. Для этого зайдите в меню Window -> Preferences -> Java -> Code Style -> Formatter. Нажмите кнопку Edit, в строке ввода Profile name введите имя нового профиля (например Normal).

3. На закладке Braces во всех выпадающих списках Brace positions выберите вариант Next line.

4. На закладках New Lines и Control Statements расставьте галочки так, чтобы оформление кода соответствовало Вашим ожиданиям.

Q061. Eclipse: как ставить закладки в коде, и как делать навигацию по закладкам?

Работа с закладками сделана не так удобно, как в Visual Studio, но работать можно.

1. Закладка добавляется через меню View -> Add Bookmark…, в коде при этом на слева от строки, где стоит закладка, прикрепляется синий флажок.
2. Удалить закладку можно через контекстное меню закладки, щелкните правой кнопкой на закладку в коде и выберите Remove Bookmark. Удалять закладки можно также через просмотр закладок (вид Bookmarks).
3. Через консоль просмотра закладок можно делать навигацию по закладкам. Чтобы открыть консоль закладок, войдите в меню Window -> Show View -> Other… -> General -> Bookmarks. В нижней части окна добавится консоль Bookmarks (среди консолей Problems, Javadoc, Declaration, Console, LogCat).
4. Для добавления закладок удобно привязать неиспользуемую горячую клавишу (через меню Windows -> Preferences -> General -> Keys). Я привязал себе для добавления закладок комбинацию Ctrl+B, предварительно отвязав её от действия по умолчанию Build all.

[140430]

Q061. Java: как закодировать дату в формате yymmdd?

Формат предоставления даты в виде YYMMDD (сначала 2 цифры года, потом 2 цифры месяца и 2 цифры дней) удобен для подставления в виде префикса к именам файлов – чтобы файлы были автоматически рассортированы по дате. Но как в Android закодировать дату в текстовое представление YYMMDD?

Оказывается, что это несложно, если использовать класс SimpleDateFormat. Вот пример функции, которая получает текущую дату и форматирует её в виде YYMMDD:

public static String YYMMDD (){
   String result = null;
        
   try
   {
      Date currDate = new Date();
      result = new SimpleDateFormat("yyMMdd").format(currDate);            
   }
   catch (Exception e)
   {
      Toast.makeText(context, 
                    "YYMMDD: " + e.toString(),
                    Toast.LENGTH_LONG).show();
   }
   return result;
}

[140502]

Q062. Java: как получить беззнаковое значение байта?

Как известно, в Java не предусмотрено использование чисел без знака. Если Вам нужно сохранить байт на диск как есть, то это не создаст проблему. Однако если нужно интерпретировать значение байта, и производить над ним математические вычисления как с беззнаковым числом, то его нужно перевести в число int с помощью операции AND с числом 0xFF. Пример:

byte bMaxPower = rawDescriptors[DEV_DESCRIPTOR_LEN+indexMaxPower];
int current_ma = 0xFF & bMaxPower;
String txtval = String.valueOf(current_ma*2) + " mA";

[Как это работает]

При преобразовании беззнакового байта в int мы сначала преобразуем в байт в int с получением числа с сохранением знака. Это преобразование происходит с учетом знака, где самый старший значащий бит (Most Significant Bit, MSB) представляет знак, и он будет задублирован в остальных битах полученного целого числа.

byte b = readAByteFromDisk();
int i = (int)b;

Вот что получится, когда преобразуется беззнаковый байт со значением 219:

                               11011011 = unsigned byte 219
                               ^          signed byte -37
                               |_________ Most Significant Bit
                               
    11111111 11111111 11111111 11011011 = signed int -37
    ^
    |____________________________________ расширение числа при создании int

Затем на число int i накладывается маска с побитным оператором AND. Это сбросит все дополнительные биты и знаковое расширение числа, которые появились при преобразовании байта в число int.

int i = 0x000000FF & i;
    11111111 11111111 11111111 11011011 = signed int -37
    00000000 00000000 00000000 11111111 = Маска 0x000000FF
    00000000 00000000 00000000 11011011 = Результат операции &

Мы использовали шестнадцатеричное число 0x000000FF (в десятичном виде 255) как маску, потому что она оставит младшие 8 числа int, это как раз та часть числа, что нас интересует. Вся функция может быть записана проще и сведена к одному короткому оператору. Значение байта, когда оно используется вместе с оператором &, будет автоматически преобразовано в число int. Шестнадцатеричное значение 0x000000FF может быть записано как 0xFF (дополнительные нули слева добавляются автоматически для дополнения до числа с размером int).

int i = 0xFF & readAByteFromDisk();

[140505]

Q063. Eclipse: новый проект не создается (Unhandled event loop exception)

Симптомы:

1. Создать новый проект “Android Application Project” невозможно, если в процессе создания в мастере установить галочку Create custom launcher icon. При этом не видны зеленые иконки разных размеров в правом окошке Preview. Мастер создания проектов не завершается, в логе выводится ошибка “Unhandled event loop exception”. Если принудительно завершить мастер, то Проект не создается полностью. При попытке clean или Build выскакивает ошибка “Errors occurred during the build. Errors running builder ‘Android Resource Manager’ on project ‘USBrelay’. java.lang.NullPointerException”.
2. Если снять галочку Create custom launcher icon, то проект создается нормально.
3. Невозможно добавить к проекту иконку запуска launcher icon.
4. Переустановки (Eclipse как отдельно, так и составе ADT Bundle) и обновления не помогают.

Условия воспроизведения ошибки: Host OS: Windows XP SP 2002 SP3 (32-bit), SDK tools version 22.6.3, Eclipse version: 4.3.1.v20130911-1000 из пакета ADT Bundle (Android Developer Tools Build: v22.6.2-1085508), ADT plug-in version: 22.6.2v201403212031-1085508.

Проблема оказалась в версии JDK (Java) 1.7.0_45. На версиях 1.6.0_13 и 1.8.0_05 проблема не наблюдается.

Q064. Eclipse: открытие activity_main.xml приводит к ошибке org.eclipse.swt.SWTException

Полный текст ошибки: An error has occurred. See error log for more details. org.eclipse.swt.SWTException: Widget is disposed.

Устранить ошибку можно перезагрузкой Eclipse, а также запуском из командной строки eclipse -clean.

Q065. Eclipse, Android: почему в onCreate методы getLeft, getTop и т. п. для виджетов возвращают 0?

Причина в том, что обработчике onCreate форма программы еще не отрисована, и координаты виджетов на форме пока неизвестны.

Устранить ошибку можно, если вычислять размеры виджетов и их позицию во время событий, которые возникают после onCreate.

[140507]

Q066. Java: как разделить строку на подстроки по пробелу или другому символу?

String text = "А роза упала на лапу Азора"
String[] separated = CurrentString.split(" ");
separated[0]; // == "А"
separated[1]; // == "роза"
separated[2]; // == "упала"
separated[3]; // == "на"
separated[4]; // == "лапу"
separated[5]; // == "Азора"

Q067. Java: как узнать количество элементов в массиве строк (String [])?

String title = "Введите номер реле";
String[] separated = title.split(" ");
separated.length;    // == 3

Q068. Java: String.format выдает ошибку java.util.UnknownFormatConversionException

Пример кода, который выдает ошибку:

int intVal = 2;
String text;
//Следующая строка даст ошибку UnknownFormatConversionException:
text = String.format("%i", intVal);

Причина тут в недопустимой опции преобразования %i, вместо неё на Java нужно использовать %d:

text = String.format("%d", intVal);  //ОК

Вот таблица поддерживаемых спецификаторов формата:

Преобразование Описание
b,B boolean
h,H hash code
s,S string
c,C character
d decimal integer
o octal integer
x,X hexadecimal integer
e,E floating point in scientific notation
f floating point in decimal notation
g,G floating point in either decimal or scientific notation
a,A hexadecimal floating point
t,T date/time
% percent
n line terminator

Q069. почему строки String не получается сравнивать оператором == ?

А на C# так сравнивать можно, почему на Java это не работает?

Причина в реализации оператора == для строк на Java. На Java оператор == сравнивает ссылки на объекты строк, а не сами строки. Чтобы сравнивать строки на Java, используйте метод equals:

String g1="Male";
String g2="Female";
 
if(gender.equals(g1))
   salutation ="Mr.";
if(gender.equals(g2))
   salutation ="Ms.";

Q070. Java: Integer.getInteger выдает ошибку

Пример кода, который выдает ошибку NullPointerException:

String txtVal = "7";
int relay = Integer.getInteger(txtVal);

Причина в том, что getInteger не делает парсинг строки и преобразование её в целое число (как Вы могли бы предположить по названию метода). Вместо этого getInteger возвращает целочисленное значение системного свойства по указанному имени. Если системное свойство не найдено, или свойство не имеет корректного числового формата, то будет возращен null.

Чтобы получить число из текстового представления, используйте метод Integer.parseInt (см. вопрос Q052).

Q071. Где находятся сохраненные скриншоты на Android?

См. следующие папки:

/storage/sdcard0/ScreenCapture
/storage/sdcard0/Pictures/Screenshots

[140509]

Q072. Как сделать, чтобы оставался запущенным всегда только один экземпляр программы?

Для этого в файле AbdroidManifest.xml для элемента activity можно использовать атрибут android:launchMode, пример:

   ...
  < activity
   android:name="com.usbrelay.MainActivity"
   android:label="@string/app_name"
   android:launchMode="singleTask" >
   ...

Если атрибут launchMode не задан, то по умолчанию используется значение standard.

Когда используется Режим запуска Несколько activity? Комментарий
Обычно используется для запуска большинства activity standard Да Значение по умолчанию. Система всегда создает новый экземпляр activity в целевой задаче (target task) и направит к нему intent.
singleTop Зависит от условий Если уже существует экземпляр activity поверх целевой задачи (target task), система перенаправит intent к этому экземпляру вызовом метода onNewIntent(), вместо того чтобы создавать новый экземпляр activity.
Специальные запуски (не рекомендуется для обычного использования) singleTask Нет Система создает activity в корне новой задачи и перенаправляет к ней intent. Однако, если экземпляр activity уже существует, то система перенаправляет intent к существующему экземпляру вызовом его метода onNewIntent(), вместо того чтобы создавать новый экземпляр.
singleInstance Нет То же самое, что и “singleTask", за исключением того, что система не будет запускать любые другие activity в задаче, которая владеет экземпляром уже работающей activity. В этом случае activity всегда одна, и только она может быть членом своей задачи.

Q073. Что такое суперкласс (superclass)? Что такое вызов метода суперкласса?

Суперкласс – это родитель, от которого произошел класс. Т. е. для дочернего класса класс-родитель является суперклассом. Дочерний класс наследует методы суперкласса, и вызов метода класса-родителя называется вызовом метода суперкласса.

Самый распространенный пример – когда при создании проекта программы создается класс активности, порожденный от класса Activity (помните? public class MainActivity extends Activity). Если нужно вызвать метод класса Activity, то в дочернем классе вызов его метода будет называться вызовом метода суперкласса, и должно сопровождаться префиксом super. Пример вызова метода суперкласса onResume в методе класса:

@Override
public void onResume(){
   super.onResume();
   Intent intent = getIntent();
   String action = intent.getAction();
   textDebug.append("[onResume]: " + action + "n");
   if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action))
   {
      usbdev = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
      if (null != usbdev)
      {
         textDebug.append("USB Attached: " + usbdev +"n");
      }
   }
}

Q074. Почему BroadcastReceiver не отслеживает события подключения устройства USB (ACTION_USB_DEVICE_ATTACHED)? События отключения ACTION_USB_DEVICE_DETACHED при этом отслеживаются нормально.

Это известный баг “Issue 25703: USB host device plugin notification failure”, который во многих Android не исправлен. Как его обойти, описано в статье “Определение событий подключения и отключения устройств USB”.

Q075. Как подключаться к adb через TCP/IP (например, через WiFi)? Это иногда полезно, когда интерфейс USB занят или отсутствует.

[Подключение вручную, если получены права root на Android]

Вы можете разрешить подключение к Android через WiFi следующими командами (в терминале на самом Android):

su
setprop service.adb.tcp.port 5555
stop adbd
start adbd

Отключить коннект через WiFi и вернуться к подключению adb через USB можно следующими командами:

setprop service.adb.tcp.port -1
stop adbd
start adbd

[Через подключение к компьютеру через USB]

Права root в этом случае необязательны, но в настройках нужно включить режим отладки, и нужно заранее знать IP-адрес подключенного по WiFi устройства Android. Выполните в cmd следующие команды:

adb tcpip 5555
adb connect 192.168.a.b:5555

Здесь 192.168.a.b адрес IP устройства Android. Вы можете определить IP адрес устройства Android двумя способами:

• Вручную, для чего зайдите в настройки WiFi на Android, выберите Advanced и там будет указан IP. Можно также запустить программу наподобие Ftp Сервер., и она покажет IP адрес устройства Android.

Android-FTP-server

• С помощью команды ADB:

adb shell ip -f inet addr show wlan0

Вернуться к подключению ADB через USB можно командой:

adb usb

[Подключение adb через сеть с помощью специальных программ]

В магазине Google Play есть несколько программ, которые позволяют автоматизировать процесс. Быстрый поиск подскажет такие программы, как adbWireless, WiFi ADB и ADB WiFi. Все эти программы требуют прав root, однако программа adbWireless требует меньше разрешений.

[170219]

Q075. Установили новую версию Java, но все еще запускается старая

Возможные причины проблемы: в папке c:Windows или c:Windowssystem32 находится старая версия. Решение проблемы: зайдите в системные папки Windows (c:Windows, c:Windowssystem32), и удалите оттуда файлы java.exe.

Еще одна причина: работает сервис быстрого запуска Java (Java Quick Starter, исполняемый файл jqs.exe). Решение проблемы: остановите и отключите сервис Java Quick Starter. Если он находится в папке Java старой версии, то удалите папку, где он находится.

Q076. Ошибка … could not open jvm.cfg

Причина ошибки в том, что Вы переключились на другую версию Java, верно настроили пути запуска в переменной окружения Path, удалили каталог со старой версией Java в папке Program Files, но все еще пытается запуститься старая версия, которая почему-то находится в папке c:Windows или c:Windowssystem32. Решение проблемы: зайдите в системные папки Windows (c:Windows, c:Windowssystem32), и удалите оттуда файлы java.exe.

[230513]

Q076. Ошибка несовместимости minCompileSdk и compileSdkVersion

В процессе сборки приложения в Android Studio часто встречается ошибка наподобие:

The minCompileSdk (33) specified in a dependency's AAR metadata (META-INF/com/android/build/gradle/aar-
 metadata.properties) is greater than this module's compileSdkVersion (android-28).
Dependency: androidx.appcompat:appcompat-resources:1.6.1.
AAR metadata file: C:Usersимя пользователя.gradlecaches transforms-3ea8525facc6d2684cea893e364228345
transformedjetified-appcompat-resources-1.6.1META-INFcomandroidbuildgradleaar-metadata.properties.

Ошибку можно исправить следующими способами, редактируя файл build.gradle:

1. Увеличить значения compileSdkVersion и targetSdkVersion (в этом примере 28 надо поменять на 33).
2. Уменьшить версию компонента, который затребовал более высокую версию. В этом примере ищите в build.gradle компонент по цифрам 1.6.1, нужно будет подобрать эти магические значения.

[Ссылки]

1. Что такое API Level?
2. Google USB Driver site:developer.android.com.
3. OEM USB Drivers site:developer.android.com – где найти и как установить драйвер отладки USB именно для Вашего устройства Android.
4. Отладка разрабатываемого приложения Android.
5. Что такое Android rooted device?
6. Android Debug Bridge – что это такое?
7. Словарик Android.
8. Что такое Gradle?

Добавить комментарий

Добавить комментарий