블로그 이미지
Every unexpected event is a path to learning for you. blueasa

카테고리

분류 전체보기 (2795)
Unity3D (852)
Programming (478)
Server (33)
Unreal (4)
Gamebryo (56)
Tip & Tech (185)
협업 (61)
3DS Max (3)
Game (12)
Utility (68)
Etc (98)
Link (32)
Portfolio (19)
Subject (90)
iOS,OSX (55)
Android (14)
Linux (5)
잉여 프로젝트 (2)
게임이야기 (3)
Memories (20)
Interest (38)
Thinking (38)
한글 (30)
PaperCraft (5)
Animation (408)
Wallpaper (2)
재테크 (18)
Exercise (3)
나만의 맛집 (3)
냥이 (10)
육아 (16)
Total
Today
Yesterday

Using coroutines in Unity is often a great way to solve certain problems, however it comes with certain drawbacks as well:

  1. Coroutines can’t return values. This encourages programmers to create huge monolithic coroutine methods instead of composing them out of many smaller methods. Some workarounds exist, such as passing a callback parameter of type Action<> to the coroutine, or casting the final untyped value that is yielded from the coroutine after it completes, but these approaches are awkward to use and error prone.
  2. Coroutines make error handling difficult. You cannot put a yield inside a try-catch, so it is not possible to handle exceptions. Also, when exceptions do occur the stack trace only tells you the coroutine where the exception was thrown, so you have to guess which other coroutines it might have been called from.

With the release of Unity 2017, it is now possible to use a new C# feature called async-await for our asynchronous methods instead. This comes with a lot of nice features compared to coroutines.

To enable this feature, all you need to do is open your player settings (Edit -> Project Settings -> Player) and change “Scripting Runtime Version” to “Experimental (.NET 4.6 Equivalent).

Let’s look at a simple example. Given the following coroutine:

1
2
3
4
5
6
7
8
9
public class AsyncExample : MonoBehaviour
{
    IEnumerator Start()
    {
        Debug.Log("Waiting 1 second...");
        yield return new WaitForSeconds(1.0f);
        Debug.Log("Done!");
    }
}

The equivalent way to do this using async-await would be the following:

1
2
3
4
5
6
7
8
9
public class AsyncExample : MonoBehaviour
{
    async void Start()
    {
        Debug.Log("Waiting 1 second...");
        await Task.Delay(TimeSpan.FromSeconds(1));
        Debug.Log("Done!");
    }
}

It’s helpful to be somewhat aware of what’s happening under-the-hood in both these cases.

In short, Unity coroutines are implemented using C#’s built-in support for iterator blocks. The IEnumerator iterator object that you provide to the StartCoroutine method is saved by Unity and each frame this iterator object is advanced forward to get new values that are yielded by your coroutine. The different values that you ‘yield return’ are then read by Unity to trigger special case behaviour, like executing a nested coroutine (when returning another IEnumerator), delaying by some number of seconds (when returning an instance of type WaitForSeconds), or just waiting until the next frame (when returning null).

Unfortunately, due to the fact that async-await is quite new within Unity, this built-in support for coroutines as explained above does not exist in a similar fashion for async-await. Which means that we have to add a lot of this support ourselves.

Unity does provide one important piece for us however. As you can see in the above example, our async methods will be run on the main unity thread by default. In non-unity C# applications, async methods are often automatically run on separate threads, which would be a big problem in Unity since we would not always be able to interact with the Unity API in these cases. Without this support from the Unity engine, our calls to Unity methods/objects inside our async methods would sometimes fail because they would be executed on a separate thread. Under the hood it works this way because Unity has provided a default SynchronizationContext called UnitySynchronizationContext which automatically collects any async code that is queued each frame and continues running them on the main unity thread.

As it turns out, however, this is enough to get us started with using async-await! We just need a bit of helper code to allow us to do some more interesting things than just simple time delays.

Custom Awaiters

Currently, there’s not a lot of interesting async code we can write. We can call other async methods, and we can use Task.Delay, like in the example above, but not much else.

As a simple example, let’s add the ability to directly ‘await’ on a TimeSpan instead of always having to call Task.Delay every time like the example above. Like this:

1
2
3
4
5
6
7
public class AsyncExample : MonoBehaviour
{
    async void Start()
    {
        await TimeSpan.FromSeconds(1);
    }
}

All we need to do to support this is to simply add a custom GetAwaiter extension method to the TimeSpan class:

1
2
3
4
5
6
7
    public static class AwaitExtensions
{
    public static TaskAwaiter GetAwaiter(this TimeSpan timeSpan)
    {
        return Task.Delay(timeSpan).GetAwaiter();
    }
}

This works because in order to support ‘awaiting’ a given object in newer versions of C#, all that’s needed is that the object has a method named GetAwaiter that returns an Awaiter object. This is great because it allows us to await anything we want, by using an extension method like above, without needing to change the actual TimeSpan class.

We can use this same approach to support awaiting other types of objects too, including all of the classes that Unity uses for coroutine instructions! We can make WaitForSeconds, WaitForFixedUpdate, WWW, etc all awaitable in the same way that they are yieldable within coroutines. We can also add a GetAwaiter method to IEnumerator to support awaiting coroutines to allow interchanging async code with old IEnumerator code.

The code to make all this happen can be downloaded from either asset store or the releases section of the github repo. This allows you to do things like the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
public class AsyncExample : MonoBehaviour
{
    public async void Start()
    {
        // Wait one second
        await new WaitForSeconds(1.0f);
 
        // Wait for IEnumerator to complete
        await CustomCoroutineAsync();
 
        await LoadModelAsync();
 
        // You can also get the final yielded value from the coroutine
        var value = (string)(await CustomCoroutineWithReturnValue());
        // value is equal to "asdf" here
 
        // Open notepad and wait for the user to exit
        var returnCode = await Process.Start("notepad.exe");
 
        // Load another scene and wait for it to finish loading
        await SceneManager.LoadSceneAsync("scene2");
    }
 
    async Task LoadModelAsync()
    {
        var assetBundle = await GetAssetBundle("www.my-server.com/myfile");
        var prefab = await assetBundle.LoadAssetAsync<GameObject>("myasset");
        GameObject.Instantiate(prefab);
        assetBundle.Unload(false);
    }
 
    async Task<AssetBundle> GetAssetBundle(string url)
    {
        return (await new WWW(url)).assetBundle
    }
 
    IEnumerator CustomCoroutineAsync()
    {
        yield return new WaitForSeconds(1.0f);
    }
 
    IEnumerator CustomCoroutineWithReturnValue()
    {
        yield return new WaitForSeconds(1.0f);
        yield return "asdf";
    }
}

As you can see, using async await like this can be very powerful, especially when you start composing multiple async methods together like in the LoadModelAsync method above.

Note that for async methods that return values, we use the generic version of Task and pass our return type as the generic argument like with the GetAssetBundle above.

Note also that using WaitForSeconds above is actually preferable to our TimeSpan extension method in most cases because WaitForSeconds will use the Unity game time whereas our TimeSpan extension method will always use real time (so it would not be affected by changes to Time.timeScale)

Triggering Async Code and Exception Handling

One thing you might have noticed with our code above is that some methods are defined ‘async void’ and some are defined ‘async Task’. So when should you use one over the other?

The main difference here is that methods that are defined ‘async void’ cannot be waited on by other async methods. This would suggest that we should always prefer to define our async methods with return type Task so that we can ‘await’ on them.

The only exception to this rule is when you want to call an async method from non-async code. Take the following example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class AsyncExample : MonoBehaviour
{
    public void OnGUI()
    {
        if (GUI.Button(new Rect(100, 100, 100, 100), "Start Task"))
        {
            RunTaskAsync();
        }
    }
 
    async Task RunTaskAsync()
    {
        Debug.Log("Started task...");
        await new WaitForSeconds(1.0f);
        throw new Exception();
    }
}

In this example, when the user clicks the button, we want to start our async method. This code will compile and run, however there is a major issue with it. If any exceptions occur within the RunTaskAsync method, they will happen silently. The exception will not be logged to the unity console.

This is because when exceptions occur in async methods returning Task, they are captured by the returned Task object instead of being thrown and handled by Unity. This behaviour exists for a good reason: To allow async code to work properly with try-catch blocks. Take the following code for example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
async Task DoSomethingAsync()
{
    var task = DoSomethingElseAsync();
 
    try
    {
        await task;
    }
    catch (Exception e)
    {
        // do something
    }
}
 
async Task DoSomethingElseAsync()
{
    throw new Exception();
}

Here, the exception is captured by the Task returned by the DoSomethingElseAsync method and is only re-thrown when it is ‘awaited’. As you can see, invoking async methods is distinct from awaiting on them, which is why it’s necessary to have the Task object capture the exceptions.

So in our OnGUI example above, when the exception is thrown inside the RunTaskAsync method, it is captured by the returned Task object, and since nothing awaits on this Task, the exception does not get bubbled up to Unity and therefore is never logged to the console.

But that leaves us with the question of what to do in these cases where we want to call async methods from non-async code. In our example above, we want to start the RunTaskAsync async method from inside the OnGUI method and we don’t care about waiting for it to complete, so we don’t want to have to add an await just so that exceptions can be logged.

The rule of thumb to remember here is:

Never call `async Task` methods without also awaiting on the returned Task. If you don’t want to wait for the async behaviour to complete, you should call an `async void` method instead.

So our example becomes:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class AsyncExample : MonoBehaviour
{
    public void OnGUI()
    {
        if (GUI.Button(new Rect(100, 100, 100, 100), "Start Task"))
        {
            RunTask();
        }
    }
 
    async void RunTask()
    {
        await RunTaskAsync();
    }
 
    async Task RunTaskAsync()
    {
        Debug.Log("Started task...");
        await new WaitForSeconds(1.0f);
        throw new Exception();
    }
}

If you run this code again, you should now see that the exception is logged. This is because when the exception gets thrown during the await in the RunTask method, it bubbles up to Unity and gets logged to the console, because in that case there is no Task object to capture it instead.

Methods that are marked as `async void` represent the root level ‘entry point’ for some async behaviour. A good way to think about them is that they are ‘fire and forget’ tasks that go off and execute some number of things in the background while any calling code immediately continues on.

By the way, this is also a good reason to follow the convention of always using the suffix ‘Async’ on async methods that return Task. This is standard practice in most code bases that use async-await. It is helpful in conveying the fact that the method should always be preceded by an ‘await’, but also allows you to create an `async void` counterpart for the method that does not include the suffix.

Also worth mentioning is that if you are compiling your code in visual studio, then you should receive warnings when you attempt to call an `async Task` method without an associated await, which is a great way to avoid this mistake.

As an alternative to creating your own ‘async void’ method, you can also use a helper method (included with the source code associated with this article) that will perform the await for you. In this case our example would become:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class AsyncExample : MonoBehaviour
{
    public void OnGUI()
    {
        if (GUI.Button(new Rect(100, 100, 100, 100), "Start Task"))
        {
            RunTaskAsync().WrapErrors();
        }
    }
 
    async Task RunTaskAsync()
    {
        Debug.Log("Started task...");
        await new WaitForSeconds(1.0f);
        throw new Exception();
    }
}

The WrapErrors() method is simply a generic way to ensure that the Task gets awaited on, so that Unity will always receive any exceptions that are thrown. It simply does an await and that’s it:

1
2
3
4
public static async void WrapErrors(this Task task)
{
    await task;
}

Calling async from coroutines

For some code bases, migrating away from coroutines to use async-await might seem like a daunting task. We can make this process simpler by allowing async-await to be adopted incrementally. In order to do this however, we not only need the ability to call IEnumerator code from async code but we also need to be able to call async code from IEnumerator code. Thankfully, we can add this very easily with yet another extension method:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static class TaskExtensions
{
    public static IEnumerator AsIEnumerator(this Task task)
    {
        while (!task.IsCompleted)
        {
            yield return null;
        }
 
        if (task.IsFaulted)
        {
            throw task.Exception;
        }
    }
}

Now we can call async methods from coroutines like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class AsyncExample : MonoBehaviour
{
    public void Start()
    {
        StartCoroutine(RunTask());
    }
 
    IEnumerator RunTask()
    {
        yield return RunTaskAsync().AsIEnumerator();
    }
 
    async Task RunTaskAsync()
    {
        // run async code
    }
}

Multiple Threads

We can also use async-await to execute multiple threads. You can do this in two ways. The first way is to use the ConfigureAwait method like this:

1
2
3
4
5
6
7
8
9
10
11
12
public class AsyncExample : MonoBehaviour
{
    async void Start()
    {
        // Here we are on the unity thread
 
        await Task.Delay(TimeSpan.FromSeconds(1.0f)).ConfigureAwait(false);
 
        // Here we may or may not be on the unity thread depending on how the task that we
        // execute before the ConfigureAwait is implemented
    }
}

As mentioned above, Unity provides something called a default SynchronizationContext, which will execute asynchronous code on the main Unity thread by default. The ConfigureAwait method allows us to override this behaviour, and so the result will be that the code below the await will no longer be guaranteed to run on the main Unity thread and will instead inherit the context from the task that we are executing, which in some cases might be what we want.

If you want to explicitly execute code on a background thread, you can also do this:

1
2
3
4
5
6
7
8
9
10
11
12
public class AsyncExample : MonoBehaviour
{
    async void Start()
    {
        // We are on the unity thread here
 
        await new WaitForBackgroundThread();
 
        // We are now on a background thread
        // NOTE: Do not call any unity objects here or anything in the unity api!
    }
}

WaitForBackgroundThread is a class included in the source code for this post, and will do the work of starting a new thread and also ensuring that Unity’s default SynchronizationContext behaviour is overridden.

What about returning to the Unity thread?

You can do this simply by awaiting any of the Unity specific objects that we created above. For example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class AsyncExample : MonoBehaviour
{
    async void Start()
    {
        // Unity thread
 
        await new WaitForBackgroundThread();
 
        // Background thread
 
        await new WaitForSeconds(1.0f);
 
        // Unity thread again
    }
}

The included source code also provides a class WaitForUpdate() that you can use if you just want to return to the unity thread without any delay:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class AsyncExample : MonoBehaviour
{
    async void Start()
    {
        // Unity thread
 
        await new WaitForBackgroundThread();
 
        // Background thread
 
        await new WaitForUpdate();
 
        // Unity thread again
    }
}

Of course, if you do use background threads, you need to be very careful to avoid concurrency issues. However it can be worth it in a lot of cases to improve performance.

Gotchas and Best Practices

  • Avoid async void in favour of async Task, except in ‘fire and forget’ cases where you want to start async code from non-async code
  • Attach the suffix ‘Async’ to all async methods which return Task. This is helpful in conveying the fact that it should always be preceded by an ‘await’ and allows an async void counterpart to be added easily without conflict
  • Debugging async methods using breakpoints in visual studio doesn’t work yet. However the “VS tools for Unity” team says that they are working on it, as indicated here

UniRx

Yet another way to do asynchronous logic is to use reactive programming with a library like UniRx. Personally I am a huge fan of this type of coding and use it extensively in many projects that I’m involved with. And thankfully, it is very easy to use alongside async-await with just another custom awaiter. For example:

1
2
3
4
5
6
7
8
9
10
public class AsyncExample : MonoBehaviour
{
    public Button TestButton;
 
    async void Start()
    {
        await TestButton.OnClickAsObservable();
        Debug.Log("Clicked Button!");
    }
}

I find that UniRx observables serve a different purpose from long-running async methods/coroutines, so they naturally fit alongside a workflow using async-await like in the examples above. I won’t go into detail here, because UniRx and reactive programming is a separate topic in itself, but I will say that once you get comfortable thinking about data flow in your application in terms of UniRx “streams”, there is no going back.

Source Code

You can download the source code that includes async-await support from either asset store or the releases section of the github repo.

Further Reading




[출처] http://www.stevevermeulen.com/index.php/2017/09/using-async-await-in-unity3d-2017/

반응형
Posted by blueasa
, |

 안드로이드 앱을 개발하다 보면 부득이하게 액티비티 화면을 가로, 혹은 세로로 고정해야 할 때가 있습니다. 예를 들자면 게임의 경우는 대부분 가로모드로 고정이 되어 실행되죠. 물론 액티비티 화면을 세로 모드로 고정해야 할 때도 있습니다. 화면의 레이아웃이 가로, 혹은 세로 모드에 최적화되어 있는 경우에는 부득이하게 화면의 회전을 강제로 막아야만 합니다.

 가로 모드는 Landscape, 세로 모드는 Portrait가 정식 명칭입니다. 안드로이드 액티비티의 화면을 Landscape 혹은 Portrait로 고정하고 싶은 경우, 두 가지 방법이 있습니다. 첫번째는 Manifest 파일에서 Activity에 screenOrientation 속성을 주는 방법이고, 두번째는 안드로이드 액티비티의 onCreate() 메소드 내에서 코드로 화면 오리엔테이션을 지정해주는 방법입니다.



 먼저 첫 번째로, Android Manifest 파일에 속성을 지정하는 방법입니다. 먼저 원하는 안드로이드 프로젝트의 AndroidManifest.xml 파일을 엽니다. 그리고 화면을 고정하기 원하는 액티비티의 이름을 찾아 아래 코드의 3번째(혹은 4번째) 열에 해당하는 코드를 추가합니다.


<activity android:name="com.example.appname.ActivityName"
            android:theme="@style/AppTheme"
            android:screenOrientation="portrait" //화면을 portrait(세로) 화면으로 고정하고 싶은 경우
            android:screenOrientation="landscape"> //화면을 landscape(가로) 화면으로 고정하고 싶은 경우
        </activity>



 두 번째로, 액티비티 실행 시에 onCreate() 메소드 내부에서 지정해주는 방법입니다. 원하는 안드로이드 프로젝트의 해당 액티비티를 열어서 아래 코드의 6열(8열)에 해당하는 코드를 추가해 줍니다.

@Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
         
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        // 화면을 portrait(세로) 화면으로 고정하고 싶은 경우
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        // 화면을 landscape(가로) 화면으로 고정하고 싶은 경우
         
        setContentView(R.layout.main);
        // setContentView()가 호출되기 전에 setRequestedOrientation()이 호출되어야 함
    }



이제 해당 프로젝트를 실행하면 지정한 액티비티의 화면이 회전하지 않는 것을 볼 수 있습니다.

출처: https://proletariat.tistory.com/86 [프롤레타리아, IT에 범접하다.]

반응형
Posted by blueasa
, |


[링크] https://xtasy.tistory.com/665

반응형
Posted by blueasa
, |


[링크] https://eunplay.tistory.com/54

반응형
Posted by blueasa
, |

이클립스/Eclipse JAR 파일 만들기



Java 프로젝트를 진행하다 보면, 보안상이나 라이브러리 구축을 이유로 JAR 파일을 만들게 되는 데요. 이클립스에서 JAR 파일을 만드는 방법에 대해 알아 보겠습니다.


(1) JAR 파일을 만들 해당 프로젝트에서 마우스 오른쪽 버튼을 클릭 합니다.


(2) 마우스 오른쪽 버튼을 클릭하면 나오는 메뉴중에 [Export] 라는 메뉴를 클릭해 줍니다. 그러면 아래의 Export 메뉴가 나오게 되는데 검색바에서 JAR 라고 입력해 주면, JAR 파일 Export 메뉴가 나오게 됩니다.




(3) [JAR file] 메뉴를 선택해 주시고, JAR 파일을 만들 프로젝트를 선택해 줍니다. 프로젝트를 클릭하면, JAR 파일을 만들 때 디테일한 부분 까지 선택하여 만들 수 있습니다. [Export generated class files and resources] 를 선택해 주시고 [Finish] 버튼을 클릭하시면 Class 형식으로 JAR 파일을 만들 수 있습니다. API 처럼 참조 할 수 있게 말이죠.




(4) 다음은 완성된 Jar 파일의 모습 입니다.




출처: https://arabiannight.tistory.com/entry/이클립스Eclipse-JAR-파일-만들기 [아라비안나이트]

반응형
Posted by blueasa
, |


안드로이드(Android) library projects cannot be launched 에러발생시 처치

 

개발환경 : window 7 64bit, Eclipse Mars, Android 4.2.2

 

이클립스를 또 하나 띄워서 다른workspce 

실행했는데 Android library projects cannot be launched

에러가 나면서 debung 가 되지 않았습니다.

 

안드로이드(Android) library projects cannot be launched 에러발생시 처치

 

이것은 현재 프로젝트가 라이브러리로 인식이 되어서

그렇습니다. Main 이 있는 실행 프로그램이 아니고

참조만 되는 라이브러리가 실행이 될리가 없겠죠.

이것은 나도 모르게 어떤 옵션을 체크해서 그런것인데

프로젝트를 선택하고 properties 옵션으로 갑니다.

화면 왼쪽에서 Android 를 선택하고 오른쪽으로 가서

Library 란에 Is Library 체크를 풉니다.

안드로이드(Android) library projects cannot be launched 에러발생시 처치



출처: https://mainia.tistory.com/1163 [녹두장군 - 상상을 현실로]

반응형
Posted by blueasa
, |


 < 개발 환경 >  
   작성일 : 2013.01.13
   OS 설치 버전 : Windows7 32bit
   SDK 설치 버전 : 안드로이드 SDK 4.2 (젤리빈) / API LEVEL : 17  
   ADT 설치 버전 : 21   
   Java 설치 버전 : JDK 1.6.0_20 / JRE6 
   이클립스 설치 버젼 : Indigo
   테스트단말 : 삼성 갤럭시 S2 4.0.4 (아이스크램 샌드위치)

 < 프로젝트 적용 > 
   API LEVEL : 8  
   minSdkVersion : 8 
   targetSdkVersion : 16  
   Java Compiler Level : 1.6  
   Text file encoding : UTF-8





이클립스/Eclipse 프로젝트 Import시 콘솔에 Unable to resolve target 'android-16' 메시지가 뜰 때 ~!




안드로이드 프로젝트를 Import 할 때 콘솔에 


 Unable to resolve target 'android-16'



위와 같은 메시지가 뜨면서 프로젝트에 "X" 표시가 생기게 되는데, 원인은 해당 프로젝트 AndroidManifest.xml 파일에 타겟으로 지정한(android:targetSdkVersion) SDK 버전을 사용 할 수 없을 경우에 나타나는 에러 메시지 입니다.


위의 경우에는 해당 프로젝트에 targetSdkVersion으로 지정한 'android-16' SDK 버전을 사용 할 수 없는 경우 입니다.


해결책으로는 

1-1) Target SDK 버전을 설치 한다.

1-2) [이클립스 상단 메뉴] -> [Project] -> [Clean]


2-1) Target SDK 버전을 변경 한다. (AndroidManifest.xml에 android:targetSdkVersion를 변경해 준다. 되도록 상위 버전으로 변경하는게 좋음.)

2-2) 변경한 Target SDK 버전을 프로젝트에도 적용해 준다.

[이클립스 해당 프로젝트 폴더] -> [Alt + Enter] -> [Properties 창] -> [Android] -> [Project Build Target 변경] 해준다. (AndroidManifest.xml 에 변경해준 Target SDK와 동일하게 설정해 준다.)



출처: https://arabiannight.tistory.com/entry/287 [아라비안나이트]

반응형
Posted by blueasa
, |


[링크] https://github.com/shmhlove/iOSPlugin

반응형
Posted by blueasa
, |

참조 : https://stackoverflow.com/questions/42724450/failed-to-get-the-required-adt-version-number-from-the



이클립스에 SDK를 연동하는 과정에서 이런 현상이 계속해서 발생한다.


위와 같은 팝업이 발생하고,


이렇게 SDK Manager가 실행되는듯 하다가 아무 창도 열리지가 않았다.

검색해보니 여러가지 방법이 있었는데 결국 내가 해결한 방법은 두 가지였다.

1) 아래의 경로에서 SDK 구버전으로 다운받기


2) 이클립스에서 사용하는 SDK 경로는 안드로이드 스튜디오에 설정된 SDK 와 다른 경로로 지정하기

Window - Preferences - Android 에서 SDK 경로를 안드로이드 스튜디오와 다르게 지정할것.


[출처] http://thegoodmen.egloos.com/6133033

반응형
Posted by blueasa
, |

이클립스(Eclipse) 안드로이드 개발도구 ADT 설치하기

 

환경: Eclipse Mars

 

안드로이드 개발도구 ADT 는 Android Development Tool 의 약자 입니다. 안드로이드개발 전용 Studio 툴을 다운 받으면 별도의 추가 설치 절차가 필요 없지만 이클립스를 이용해서 개발하기 위해서는 작업이 필요합니다. 먼저 ADT 툴 설치가 끝나면 안드로이드 사이트로 SDK 를 다운받아야 합니다. 그리고 두 개를 연결해야 개발환경이 갖춰 지는 것입니다. 오늘은 ADT 와 SDK 를 다운받아 안드로이드 개발환경을 갖추는 방법에 대해 알아 보겠습니다.

 

이클립스를 다운로드 해서 실행하는 방법은 아래 링크를 참고하세요.

 

이클립스(Eclipse) 설치하는 방법과 실행 오류 해결 하기

 

 먼저 이클립스 홈페이지로 가서 최신 버전을 다운 받습니다. 아래 링크를 클릭해서 다운로드 페이지로 접속한 뒤 자신의 컴퓨터 비트수에 맞는 버전을 설치해 줍니다. 실행을 위한 환경설정은 위에 링크한 포스팅 주소를 참고하세요.

http://www.eclipse.org/downloads

이클립스(Eclipse) 안드로이드 개발도구 ADT 설치하기

 

 안드로이드 개발툴인 ADT 를 설치하려면 플러그인 설치 팝업창으로 가야 합니다. [Help] > [Install New Software] 메뉴를 선택합니다. 다운 받을 주소를 알지 못한다면 Eclipse Marketplace 로 가서 ADT 를 검색해도 됩니다. 

이클립스(Eclipse) 안드로이드 개발도구 ADT 설치하기

 

 ADT 다운로드 주소는 아래와 같습니다. 플러그인을 설치 페이지에서 Add 버튼을 눌러 주소 입력창을 띄웁니다. Name 은 사용자가 임의로 지정해도 됩니다. 아래 Location 에는 아래 주소를 복사해서 넣고 OK 를 눌러 창을 닫습니다.

https://dl-ssl.google.com/android/eclipse

이클립스(Eclipse) 안드로이드 개발도구 ADT 설치하기

 

 Repository 주소를 추가하게 되면 업데이트 목록을 체크하게 됩니다. 현재 이클립스에 설치된 것이 없기 때문에 아래 그림처럼 목록에 나타나는 것입니다. Developer Tools 를 체크하고 하단으로 내려가 Next 버튼을 눌러 설치를 진행합니다. 라이센스에 동의하고 설치를 종료하면 이클립스를 재시작해야 합니다. 재시작할지 묻기 때문에 메시지 창이 뜰 때 “예” 라고 하면 됩니다. 

이클립스(Eclipse) 안드로이드 개발도구 ADT 설치하기

 

◎ android SDK 다운 받아 설정하기

 

 ADT 설치 후 이클립스를 재 실행하게 되면 아래와 같은 메시지가 뜹니다. ADT 의 실행과 안드로이드 개발을 위한 라이브러리가 있어야 하기 때문입니다. Android SDK 를 다운 받아 링크를 걸어야 합니다. 

이클립스(Eclipse) 안드로이드 개발도구 ADT 설치하기

 

 안드로이드 SDK 를 다운 받을 수 있는 링크가 사라져서 다른 방법을 찾았습니다. 귀찮기는 하지만 굳이 이클립스로 앱을 개발하고자 한다면 이 방법 밖에는 없을 것 같네요. 우선 Android Studio 를 다운받아야 합니다.

https://developer.android.com/studio/index.html

이클립스(Eclipse) 안드로이드 개발도구 ADT 설치하기

 

 설치가 끝나면 안드로이드 SDK 를 최신으로 업데이트 해야 합니다. [File] > [Settings] 메뉴를 클릭합니다. 

이클립스(Eclipse) 안드로이드 개발도구 ADT 설치하기

 

 먼저 업데이트 채널이 제대로 설정이 되어 있는지 확인합니다. System Settings > Updates 에서 Automatically check updates for 와 Automatically check updates for Android SDK 가 체크되어 있는지 확인합니다. 그리고 모두 Stable Channel 로 선택합니다. 

이클립스(Eclipse) 안드로이드 개발도구 ADT 설치하기

 

 다음은 Android SDK 로 가서 Android SDK Location 을 확인합니다. 해당 폴더에 다운받은 SDK 는 이클립스와 연결할 것입니다. 

이클립스(Eclipse) 안드로이드 개발도구 ADT 설치하기

 

 SDK 를 최신으로 업데이트 하기 위해 Lanunch Standalone SDK Manager 링크를 클릭합니다. SDK Manager 팝업창에서 다운 받을 tools 과 API 를 체크하고 설치를 진행합니다. 

이클립스(Eclipse) 안드로이드 개발도구 ADT 설치하기

 

 설치가 끝나면 안드로이드 스튜디오에서 다운 받은 폴더를 이클립스와 연결해야 합니다. 이클립스의 Preferences > Android 로 가서 SDK Location 을 수정합니다. 

이클립스(Eclipse) 안드로이드 개발도구 ADT 설치하기

 

◎ 이클립스와 SDK 연결하기

 

 Android SDK를 업그레이드까지 받았다면 환경설정에서 연결을 해 줘야 합니다. [Window] > [Preferences] 메뉴를 선택해서 환경설정 팝업창을 띄웁니다. 

이클립스(Eclipse) 안드로이드 개발도구 ADT 설치하기

 

 왼쪽 메뉴 목록에서 Android 를 선택합니다. 그럼 SDK 의 위치를 세팅할 수 있는 화면이 나타납니다. SDK Location 에 위치를 지정해 줍니다. 

이클립스(Eclipse) 안드로이드 개발도구 ADT 설치하기

 

 위치 지정이 끝나면 아래 그림과 같이 목록에 안드로이드 버전과 Google APIs 버전 목록이 나타나야 합니다. 이상으로 이클립스에서 안드로이드 개발을 위한 ADT 툴을 설치하는 방법에 대해 알아 보았습니다. 

이클립스(Eclipse) 안드로이드 개발도구 ADT 설치하기



출처: https://mainia.tistory.com/4425 [녹두장군 - 상상을 현실로]

반응형
Posted by blueasa
, |