[안드로이드] androidBridge they will not be visible in API 17 오류 해결 방법




none of the methods in the added interface(androidBridge) have been annotated with @android.webkit   they will not be visible in API 17 


이 오류의 해결 방법 입니다.



1. 원인


안드로이드 버전 API 17 이상부터 androidBridge 사용시 메소드에 어노테이션을 사용해야 정상 구동 하도록

바뀌어서 생기는 오류


2. 해결 방법


간단하게 androidBridge에서 사용하는 메소드위에 어노테이션을 추가 하면 됩니다.



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
48
49
50
51
package com.xxx.xxxx;
 
import android.os.Handler;
import android.util.Log;
import android.webkit.JavascriptInterface;
import android.webkit.WebView;
import java.text.SimpleDateFormat;
import java.util.Date;
 
/**
 * Created by Administrator on 2017-08-03.
 */
 
public class AndroidBridge {
    private final Handler handler = new Handler();
    private WebView mWebView;
    private DBHelper dbHelper;
    private  boolean newtwork;
 
    // 생성자
    public AndroidBridge(WebView mWebView, DBHelper dbHelper, boolean newtwork) {
        this.mWebView = mWebView;
        this.dbHelper = dbHelper;
        this.newtwork = newtwork;
    }
 
    // 네트워크 상태 확인
    @JavascriptInterface
    public void requestNetwork() { // must be final
        handler.post(new Runnable() {
            public void run() {
                Log.d("HybridApp""네트워크 상태 요청");
                mWebView.loadUrl("javascript:getNetwork("+newtwork+")");
            }
        });
    }
 
 
 
    @JavascriptInterface
    public void setMessage(final String arg) { // must be final
        handler.post(new Runnable() {
            public void run() {
                Log.d("HybridApp""setMessage("+arg+")");
                mWebView.loadUrl("javascript:getAndroidMessage('ANDROID -> JAVASCRIPT CALL!!')");
            }
        });
    }
 
 
}
cs


간단하게 다른거 볼 필요 없이


28번라인에 추가한 어노테이션을 29번같은 메소드 위에 선언하기만 하면 해당 오류가 해결 된다.




[화정 브레인기타학원] 초보 4비트, 8비트 스트로크 연습 방법!




최고의 화정 기타학원! 브레인기타학원의 야심작!

쪼심자 기타레슨!


 

'쪼심자 기타레슨' 은 기타를 '쉽게 연습하는 방법' 을 알려드리는 영상입니다!

마구마구 많이 치는 것도 중요하지만 '얼마나 어떻게 치는가' 라는 부분에 초점을 맞춘 영상입니다!

궁금한 부분에 해답이 되시길 바라며

쪼심이와 함께 시작!



먼저 영상을 봐주세요! 길지 않은 영상이니

지루하지 않으 실 겁니다!

 


 

<레슨생 귀엽네요 ㅎㅎㅎㅎ>





선생님한테 배운대로 혹은 책에 나온대로 열심히 치고 있는데

누군가가 옆에서 핀잔을 주는 경우가 있죠

 

아마 그런 경우가

'정확하지 않은' 

리듬으로 곡을 연주하는 경우라고 생각해요


그래서 쪼심이는 이번에 

정확하게 연습할 수 있는 방법을 여러분께 소개해드리고 있습니다

사실 많이들 하고 계시지 않아서 그렇지

방법 자체는 너무나 기본적이고 쉽습니다



방법은 바로!



네!

 

역시 입으로 숫자 세는 것 만큼 제대로 된 연습방법이 없습니다!

아주우-

약간의-

박치끼를 가지신 분들도 

입으로 숫자를 세면서 연습하면 

틀릴 확률이 아주아주아주아주아주 x1000 적어진다구요!

 



4비트 리듬일때는 


하나! 둘! 셋! 넷!


에 맞춰서 다운스트로크 해주세요!



8비트 리듬일때는

하! 나! 두! 울! 세! 엣! 네! 엣!

의 구령에 맞춰 다운과 업을 반복적으로 스트로크 해주세요!



귀찮고 걸리적거리는 숫자세기 연습!

아주 조금만 반복하다보면


숙련된 연주를 모두에게 보여주실 수 있답니다!

 




https://m.blog.naver.com/aofg/221051461400

[안드로이드] FCM 화면 깨우기 화면 켜지게 하는 방법

2017/07/10 - [Yame Programmer/Android] - [안드로이드] FCM 푸시메세지 웹서버(JAVA)에서 보내기

2017/07/10 - [Yame Programmer/Android] - [안드로이드] FCM 토큰 저장방법 개별 보내는 방법 SharedPreferences 사용

2017/07/12 - [Yame Programmer/Android] - [안드로이드] FCM 백그라운드에서 진동 오도록 하는 방법




후.. FCM메세지를 노티피케이션이 아니라 data로 날리도록 하니


지금까지 삽질해도 안되던 화면 깨우기가 되었다..


진짜 아무것도 모르는 상태로 근본없이 맨땅에 헤딩하니 좀 지친다



화면 깨우기는 간단하다


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public void onMessageReceived(RemoteMessage remoteMessage) {
        //추가한것
       // sendNotification(remoteMessage.getData().get("message"));
 
        // 이거 추가 하면 
        PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE );
        PowerManager.WakeLock wakeLock = pm.newWakeLock( PowerManager.SCREEN_DIM_WAKE_LOCK
                | PowerManager.ACQUIRE_CAUSES_WAKEUP, "TAG" );
        wakeLock.acquire(3000);
 
 
        String title = remoteMessage.getData().get("title");
        String body = remoteMessage.getData().get("body");
        sendNotification(title, body);
    }
cs



이렇게 6,7,8,9,10 번 라인을 추가해주면 된다


그런데 저기에 있는 SCREEN_DIM_WAKE_LOCK는 deprecated 되었다



아 몰랑 그냥 쓸거야!


화면 켜지게 하면 된다구!


지금 안드로이드 버전에서 권장하는 방법은 FLAG_KEEP_SCREEN_ON


이거 쓰라고 하는데


사실 당장 뭐 어떻게 쓰는지도 잘 모르기도 하고


문서들을 찾아보니 뭐 밝게했다가 어둡게도 했다가도 하고 그런 여러가지 기능들이 있는것 같긴 한데


아직 다 써보진 못했다 PARTIAL_WAKE_LOCK 이런거라든가 FLAG_KEEP_SCRREN_ON


이런거 쓰라고 하는데


FLAG_KEEP_SCRREN_ON 얘는 어찌 써야할지 레이아웃에 걸어줘야 하는 애 같아서 못썻고


PARTIAL_WAKE_LOCK 이건 화면이 안켜진다. 그래서 저 위의 코드를 사용하기로 함.


물론 소스는 더 많이 있고 써보기도 했는데 백그라운드에서 안돌아갔던 문제 때문에


되는건지 모르겠고 다시 그 소스들 찾아가면서 해보긴 귀찮다.


그건 다음에 또 이런 어플 만들때 되면 해보도록 하자


아니면 해본 사람들이 댓글을 남겨준다면 더 고마울 것이다.






[안드로이드] FCM 백그라운드에서 진동 오도록 하는 방법






얼마전 포스팅에서 웹서버를 통해  FCM 메세지를 날리는 방법에 대해서 알아보았다


2017/07/10 - [Yame Programmer/Android] - [안드로이드] FCM 토큰 저장방법 개별 보내는 방법 SharedPreferences 사용

2017/07/10 - [Yame Programmer/Android] - [안드로이드] FCM 푸시메세지 웹서버(JAVA)에서 보내기



그런데 문제가 있었다.


어플을 켜놓은 상태에선 진동이 오는데


어플을 끄거나 화면을 끈 상태에선 진동알람도 안오고 화면이 켜지는 것도 안되서


알람이 온줄 모르는 상태가 되버린 것



이것때문에 얼마나 삽질을 했던가..



화면켜지는건 고사하고 아얘 어플 끈 상태에선


상단에 알람바만 조용히 생기고 애초에 onMessageReceived 여기서 지정해 놓은 것들이


아얘 안돌아 가는 것 같았다


삽질을 하다가


결국 스택오버 형님들의 글에서 답을 찾았다


저번 포스팅을 보면  웹서버에서 FCM요청을 할떄



1
2
3
4
5
6
7
8
JSONObject root = new JSONObject();
                JSONObject notification = new JSONObject();
                notification.put("body""공조기 장애 현재상태 : OFF");
                notification.put("title""알림 입니다.");
                notification.put("icon""ic_message");
                root.put("notification", notification);
                root.put("to", token);
                root.put("click_action""OPEN_ACTIVITY");
cs




이런식으로 보냈었는데 6번라인의저 노티피케이션이 문제였다.


노티피케이션으로 날려주면 onMessageReceived가 실행이 안된단다


그래서 저 노티피케이션을 data로 바꾸어 주었다



1
2
3
4
5
6
7
8
                JSONObject root = new JSONObject();
                JSONObject notification = new JSONObject();
                notification.put("body""공조기 장애 현재상태 : OFF");
                notification.put("title""알림 입니다.");
                notification.put("icon""ic_message");
                root.put("data", notification);
                root.put("to", token);
                root.put("click_action""OPEN_ACTIVITY"); // click_action 추가!
cs



이렇게 바꾸고 나니 백그라운드 상태에서도 설정해놓은 vibrate대로 진동도 잘온다!!


화면켜지는것까진 바라지도 않는다 


일단 사용자한테 알람이 왔다고 알리기만 하면 되니까



그렇다면 안드로이드 에서도


받는 부분의 메세지를 다르게 받을 필요가 있었다



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
public void onMessageReceived(RemoteMessage remoteMessage) {
        //추가한것
       // sendNotification(remoteMessage.getData().get("message"));
        
        // 이렇게 데이터에 있는걸 키값으로 뽑아 쓰면 된다.
        String title = remoteMessage.getData().get("title");
        String body = remoteMessage.getData().get("body");
        sendNotification(title, body);
    }
 
    private void sendNotification(String title, String body) {
        Intent intent = new Intent(this, MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
 
        PendingIntent pendingIntent = PendingIntent.getActivity(this0 /* Request code */, intent,
                PendingIntent.FLAG_ONE_SHOT);
 
        Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentTitle(title)
                .setContentText(body)
                .setAutoCancel(true)
                .setSound(defaultSoundUri)
                .setVibrate(new long[]{10001000})
                .setLights(Color.BLUE,1,1)
                .setContentIntent(pendingIntent);
        NotificationManager notificationManager =
                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
 
    }
cs



이렇게 코드를 바꿔주면 된다


기존 코드에서 6,7번 라인과 11번읜 매개변수만 바꿔주면 끝!



후.. 이제 다시 화면도 켜지게 하는 방법을 찾아 떠나보도록 하자....

-------------------------------------------------------------------------------

방법 찾았음 ㅋ


2017/07/12 - [Yame Programmer/Android] - [안드로이드] FCM 화면 깨우기 화면 켜지게 하는 방법




 

[안드로이드] FCM 웹(JAVA)서버에서 푸시메세지 보내기


안드로이드의 기존 GCM에서 FCM으로 바뀌었다


구글 클라우드 메세지에서 파이어베이스 클라우드 메세지로 바뀐건진 정확히 모르겠지만..



일단 뜬금없이 웹개발하다가 갑자기 회사에서 안드로이드 개발할 일이 생겼지만


웹뷰로 때워버리자! 라고 외친 후 만들어 놓고 보니 안드로이드 알림 메세지가 가야 한단다...



하....


그래서 뭐 삽질좀 하고 여기저기 뒤적뒤적이면서 구현을 했다




일단 가장 먼저


https://console.firebase.google.com/u/0/


당연히 구글 아이디는 있을것이지 콘솔 파이어베이스로 들어가


알람메세지 구현알 어플을 등록해준다.


이곳의 도움을 많이 받았다. 기초 설정은 여기 보고 따라하자


사실 저 블로그만 봐도


어지간하면 구현 가능하다.



진짜 생각보다 좀 간단하다.



1. Android JAVA 



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
48
49
50
51
52
53
54
55
56
57
58
59
import android.content.SharedPreferences;
import android.util.Log;
 
import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.iid.FirebaseInstanceIdService;
 
import java.io.IOException;
 
import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
 
 
public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService {
 
    private static final String TAG = "MyFirebaseIIDService";
 
    /**
     * Called if InstanceID token is updated. This may occur if the security of
     * the previous token had been compromised. Note that this is called when the InstanceID token
     * is initially generated so this is where you would retrieve the token.
     */
    // [START refresh_token]
    @Override
    public void onTokenRefresh() {
        // 설치할때 여기서 토큰을 자동으로 만들어 준다
        String refreshedToken = FirebaseInstanceId.getInstance().getToken();
        Log.d(TAG, "Refreshed token: " + refreshedToken);
 
        // 생성한 토큰을 서버로 날려서 저장하기 위해서 만든거
        sendRegistrationToServer(refreshedToken);
    }
    
    private void sendRegistrationToServer(String token) {
        // Add custom implementation, as needed.
 
        // OKHTTP를 이용해 웹서버로 토큰값을 날려준다. 
        OkHttpClient client = new OkHttpClient();
        RequestBody body = new FormBody.Builder()
                .add("Token", token)
                .build();
 
        //request
        Request request = new Request.Builder()
                .url("토큰 저장할라고 보낼 URL")
                .post(body)
                .build();
 
        try {
            client.newCall(request).execute();
        } catch (IOException e) {
            e.printStackTrace();
        }
 
    }
}
cs




여기서 우리가 잘 봐야 할 건


30번 라인과 


37번라인의 sendRegistrationToServer 메소드다


30번라인에서 토큰을 생성하는데 여기선 어플을 설치할때 한번 생성한다.


그럼 만들어지자마자 


37번라인 메소드로 날려서 HTTP로 전송한다.


그럼 웹서버에서 저 토큰을 받고 저장을 하게 되고


그 해당 토큰으로 메세지를 날려주면 되는 것이다.




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
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.media.RingtoneManager;
import android.net.Uri;
import android.support.v4.app.NotificationCompat;
 
import com.google.firebase.messaging.RemoteMessage;
 
 
public class MyFirebaseMessagingService extends com.google.firebase.messaging.FirebaseMessagingService {
    private static final String TAG = "FirebaseMsgService";
 
    // [START receive_message]
    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
 
        //추가한것
        sendNotification(remoteMessage.getData().get("message"));
    }
 
    private void sendNotification(String messageBody) {
        Intent intent = new Intent(this, MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(this0 /* Request code */, intent,
                PendingIntent.FLAG_ONE_SHOT);
 
        Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentTitle("FCM Push Test"// 이부분은 어플 켜놓은 상태에서 알림 메세지 받으면 저 텍스트로 띄워준다.
                .setContentText(messageBody)
                .setAutoCancel(true)
                .setSound(defaultSoundUri)
                .setContentIntent(pendingIntent);
 
        NotificationManager notificationManager =
                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
 
        notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
    }
 
}
 
cs

MyFirebaseMessagingService.java 얘는 알림메세지를 받았을때 처리하는건데

사실 딱히 건들일거 없이 그대로 사용 하면 된다.








일단 저 블로그에서


MyFirebaseInstanceIDService.java 와

MyFirebaseMessagingService.java



이 두개를 구현했다면 




여기로 들어와서 앱단위로 앱선택하고 보내면


모든 앱 설치자들에게 메세지가 날아간다.



하지만 우린 웹서버에서 푸시메세지를 날려주고 싶을 것이다.


알람이라면 뭐 값이 변한다거나 새로운 정보가 등록 되었을때 날려줘야 하니까


그때마다 저기 접속해서 날려주기엔 너무 귀찮으니까 분명히


웹서버에서 인터벌을 돌리든 트리거를 걸든 해서 웹서버에서 날려주고 싶을 것이다


그런데 웹서버에서 날려주는건


잘 안나와있고 복사 붙여넣기 해도 안되는 경우도 있고 하니까


내가 해서 성공한 코드를 보자










2. JAVA Web Server 



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
48
49
50
51
@RequestMapping(value="mobile/sendFCM")
    public String index(Model model, HttpServletRequest request, HttpSession session, MobileTokenVO vo)throws Exception{
            
            List<MobileTokenVO> tokenList = fcmService.loadFCMInfoList(vo); 
            
                String token = tokenList.get(count).getDEVICE_ID();
                
                final String apiKey = "파이어 베이스의 서버 API키를 여기에 넣는다";
                URL url = new URL("https://fcm.googleapis.com/fcm/send");
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.setDoOutput(true);
                conn.setRequestMethod("POST");
                conn.setRequestProperty("Content-Type""application/json");
                conn.setRequestProperty("Authorization""key=" + apiKey);
 
                conn.setDoOutput(true);
                
                String userId =(String) request.getSession().getAttribute("ssUserId");
 
                // 이렇게 보내면 주제를 ALL로 지정해놓은 모든 사람들한테 알림을 날려준다.
                String input = "{\"notification\" : {\"title\" : \"여기다 제목 넣기 \", \"body\" : \"여기다 내용 넣기\"}, \"to\":\"/topics/ALL\"}";
                
                // 이걸로 보내면 특정 토큰을 가지고있는 어플에만 알림을 날려준다  위에 둘중에 한개 골라서 날려주자
                String input = "{\"notification\" : {\"title\" : \" 여기다 제목넣기 \", \"body\" : \"여기다 내용 넣기\"}, \"to\":\" 여기가 받을 사람 토큰  \"}";
 
                OutputStream os = conn.getOutputStream();
                
                // 서버에서 날려서 한글 깨지는 사람은 아래처럼  UTF-8로 인코딩해서 날려주자
                os.write(input.getBytes("UTF-8"));
                os.flush();
                os.close();
 
                int responseCode = conn.getResponseCode();
                System.out.println("\nSending 'POST' request to URL : " + url);
                System.out.println("Post parameters : " + input);
                System.out.println("Response Code : " + responseCode);
                
                BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                String inputLine;
                StringBuffer response = new StringBuffer();
 
                while ((inputLine = in.readLine()) != null) {
                    response.append(inputLine);
                }
                in.close();
                // print result
                System.out.println(response.toString());
                
 
        return "jsonView";
    }
cs



위의 코드처럼 쓰면 된다.



8번 라인의 API키는 






저 파이어베이스 콘솔에서 빨간동그라미 누르고 프로젝트 설정의 클라우드 메세징으로 가면


서버키가 나와있다 그 서버키를 넣으면 된다. 




그런데 20번 21번 라인의  주제가 ALL인걸 어떻게 지정 하냐고?


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
 
        // 웹뷰 셋팅팅
       mWebView = (WebView)findViewById(webView);
        mWebView.getSettings().setJavaScriptEnabled(true);
 
        mWebView.loadUrl(myUrl+"/mobile/login");
        mWebView.setWebChromeClient(new WebChromeClient());
        mWebView.setWebViewClient(new WebViewClientClass());
 
        mWebView.addJavascriptInterface(new AndroidBridge(), "android");
 
 
        //이렇게 ALL 추가 하면 이 디바이스는 ALL을 구독한다는 얘기가 된다.
        FirebaseMessaging.getInstance().subscribeToTopic("ALL");
 
    }
cs



안드로이드의 MainActivity.java 의 oncreate에다가 저 18번 라인을 추가 해주자


그런데 주제 등록은 즉시 안되고 몇시간 기다리거나 몇일 기다려야 등록 되는 경우도


있다고 하니까 급하게 하진 말자.




그리고 24번 라인에 들어가는 토큰은 MyFirebaseInstanceIDService.java 의 36번 메소드에 날려준 값이다


여기까지가 기초적인 FCM을 이용한 메세지 보내는 방법이다!


다음강좌는


저 토큰아이디를 어떻게 사용자 ID랑 묶어서 저장하고 원하는 사용자에게


보낼 수 있는지 알아보자



2017/07/10 - [Yame Programmer/Android] - [안드로이드] FCM 토큰 저장방법 개별 보내는 방법 SharedPreferences 사용




[레슨] 기타 초보 기초 레슨 1 [코드 체인지]




최고의 화정 기타학원! 브레인기타학원의 야심작!

쪼심자 기타레슨!


'쪼심자 기타레슨' 은 기타를 '쉽게 연습하는 방법' 을 알려드리는 영상입니다!

마구마구 많이 치는 것도 중요하지만 '얼마나 어떻게 치는가' 라는 부분에 초점을 맞춘 영상입니다!

궁금한 부분에 해답이 되시길 바라며

쪼심이와 함께 시작!



먼저 영상을 봐주세요! 길지 않은 영상이니

지루하지 않으 실 겁니다!



1. 기초 동영상 강좌

 




2. 코드 체인지, 코드 쉽게 바꾸는 방법





초보분들이 기타를 연습하며 가장 어렵다고 느끼는 부분이 

코드 바꾸기 

일거라고 생각해요


특히나 생각보다 왜 초반에 나오는지 모르겠는 

B7코드



역시나 왜 인지는 모르겠지만

은근히 어려운 

D코드




이 코드를 가지고 어려운 코드 바꾸는 연습을

어떻게 효율 적으로 할 수 있는지 살펴보겠습니다.


그나저나 쪼심이는 손톱을 꼭 잘라야 하겠군요





사실 조금도 어렵지 않아요.


첫번째는 당연히 코드를 외우는 것이겠죠?




두번째로 외운 코드의 손가락을 어떤 순서로 잡을지 정해볼거에요




이런방법입니다!









순서는 임의적으로  정하면 되겠으나

가능하면 코드의 가장 높은줄에서부터

ex) G코드라면 6번줄에서 부터

순서를 정해주시면 

조금 더 음손실을 막으실 수 있을거에요!



조금 더 자세히는 영상을 봐주세요!





마지막으로 리듬에 구령을 붙여 

 우리가 미리 정해놓은 손가락 순서대로

연주 연습을 합니다!!







물론 목표는 완벽하게 한번에 잡는 것이겠지만


이렇게 천천히 하나씩 연습하다 보면

금방 금방 목표에 다가가실 수 있을 거에요.



모두에게 도움이 되셨길 바라며! 

오늘은 여기까지이!








학원 연락처 : 031-970-2322 010-2070-5765

[리니지M] 리니지M 게임 꿀팁




1. 기본무기는 상점에서 사지 말자

 

비싸긴 비싼데 어차피 퀘스트 하다보면 나옵니다. 


상점에 5만아덴짜리 사서 다시 팔땐 1천아덴 밖에 안나옴


 

 

2. [필수] 캐릭터는 2개 생성 합니다.

 

생성된 캐릭끼리는 창고 공유가 가능 합니다.


변식목록에 나오는 몬스터는 얻으면 바로 배워지는게 아니라 카드형태로 


획득이 되는데 두캐릭을 같이 키우면 중복되는 카드는 창고에 맡겨서 다른 캐릭이


배우게 하면 훨씬 이득이 되지요. 아니면 몰아주기를 통해 합성을 해서 상위 몬스터


변신으로 가는 것도 엄청 이득 입니다.


상위 몬스터는 공속이 빠르기 때문에 사냥에 유리 합니다. 


레벨업이 빠른건 엘프 입니다.

 

 

3. 아데나는 최대한 아껴두세요


현황판이나 드랍되는거 보면 아데나가 귀합니다.

 

퀘스트 진행시 1~2만씩 보상으로 주는데 

 

초반에 퀘스트 보상받은 아데나로  막 뽑고 사고 하게되는데

 

캐릭터 삭제는 50랩 이후에 가능하기 때문에 캐릭 다시 만들기가 힘듭니다.

 

막키우고 막썼다가는 난처해지는 상황이 올 수 있습니다.

 

고급 뽑기는 9만아데나 인데

 

하루 이틀정도는 뽑아볼만도 함 


(고급에서 나온 경비병(창) 변신시 공속98%, 이속2% 시전속도15%)

 

 

4. 상점에 잡템 파는 방법

 

아덴상인 매입한다는 뚱땡이 npc 있음

 

목록에는 몇가지만 산다고 되어있는데

 

걍 템 더블클릭? 하면 팔수있는건 어지간하면 다 팔아짐

 

근데 미래를 보면 용해제로 녹이는게 나을듯

 

- 용해제 상점에서 1000씩에 판매

 

녹일아이템 클릭후 상세보기 선택하면 [용해]있음

 

축복의가루 줌 (제작재료)

 

 

5. 시련의 던전 등에서 메테오로 몹잡는다거나 턴언데드로 몹잡아야되는데

 

자동사냥 눌러두고  스킬 퀵슬롯과 아이템 퀵슬롯 사이에  이벤트용 스킬 아이콘있는거 연타하시면 됩니다.



 

 6. 쪼렙 퀘스트 빨리 깨기


몇마리 잡아와라 이런거 사람 많아서 기사 군주는 힘들다고 하는데


첨에 배워지는 에너지볼트로 일단 멀리서 한대라도 쳐두면 머릿수 올라가서


빨리 깰 수 있습니다.



[리니지M] 사전 캐릭터 확인 방법



미리 선점한 캐릭터 확인 방법


- 미리 내 계정과 사전 선점한 캐릭터, 서버 확인하기!

사전 캐릭터 생성에 참여한 계정이 기억나지 않으신다면?
서버 번호가 가물가물 하다면?

아래 방법을 통해 캐릭터 이름과 서버를 확인하실 수 있습니다.

1. https://lineagem.plaync.com/preorder/character/index 으로 이동!
2. 사전 캐릭터 생성에 참여했던 계정으로 로그인!
3. 사전 생성한 캐릭터명과 서버 확인!



내 계정으로 로그인 하는 방법


- 소중한 내 캐릭터를 지키기 위해 반드시 지켜야 할 방법, <내 계정>으로 로그인하기!

많은 용사님들께서 사전 캐릭터 생성에 참여해주셨는데,
사전 캐릭터 생성에 참여했던 계정으로 로그인 해야 한다는 사실! 다들 알고 계신가요?

용사님들의 소중한 캐릭터를 지키기 위해서는 반드시 <내 계정>으로 접속해야 하는데요,
그 이유는!! 게스트 계정으로 플레이 할 경우 자칫 게임 정보가 영영 소실될 우려가 있기 때문입니다!

용사님들! 내 캐릭터를 지킬 준비 되셨나요? ^^ 이것만 기억해주세요!
리니지M 실행 후 가장 먼저 <내 계정>으로 로그인 하기!





[리니지M] 마법인형과 변신 방법


리니지 M 홈페이지에 올라와 있는 글이다.


리니지M에서 중요한 변신과 마법인형의 경우, 원작의 요소를 리니지M 환경에 맞춰서 계승한 컨텐츠 입니다.
이에 대해 리니지M에서 마법인형과 변신에 대해 정보를 안내 드리고자 합니다. .

● 변신 카드
- 기존 PC에서는 변신의 기준이 직업별 레벨이었으나, 리니지M에서는 변신카드 획득을 통해 해당 변신 카드의 보유 여부가 기준이 됩니다.
- 변신카드는 총 5개의 등급으로 구분됩니다.


- 변신카드는 1번이라도 획득하면, 고객님의 계정 어떤 캐릭터라도 변신이 가능합니다.
예시] 52레벨 기사 캐릭터로 군터 변신카드 획득 후 신규 캐릭터를 생성하면,  1레벨 캐릭터가 군터 변신 선택 가능

- 변신카드의 대상으로 변신을 위해서는 꼭! 변신 주문서를 상점에서 구입하여, 사용 하셔야 합니다.
- 변신카드 목록 중 획득한 변신 카드의 조합에 따라 변신 컬렉션이 발동됩니다.
변신 컬렉션은 계정 단위로 적용되며, 더 많은 변신 카드를 수집할수록 더 많은 효과가 계정에 적용 됩니다.
- 변신 카드의 경우, 계정 최초 1회 획득 이후에는 변신 카드가 자동으로 쌓이며, 동일 등급의 변신 카드 4장이 있을 경우
상위 단계 카드를 획득 할 수 있는 [변신 카드 합성]이 가능합니다.  



예시1]
희귀 등급 아크 위자드 카드를 5장 획득 -> 계정 최초 변신목록 획득 1장을 제외한 4장의 카드가 보관

예시2]
합성 가능 사례 : 일반 등급 오크 변신 카드 5장 -> 합성 기회 1회
합성 불가 사례 : 일반 등급 오크 변신 카드 2장, 희귀 등급 데스나이트 변신 카드 2장 -> 합성 불가

- 변신 카드 중 일부 카드의 경우에는 오직 [변신 카드 합성] 으로만 획득 가능한 카드가 존재 합니다.
- 합성에 성공할 경우, 상위 등급의 변신 카드 중 1개를 랜덤하게 획득합니다. 실패할 경우에는 재료로 쓰인 4장의 카드 중
1장만 돌려 받게 됩니다.


● 마법인형 카드
- 마법인형 카드는 1번이라도 획득하면, 고객님의 계정 어떤 캐릭터라도 소환이 가능합니다.
예시] 52레벨 기사 캐릭터로 나이트발드 마법인형 카드 획득 후 신규 캐릭터를 생성하면, 1레벨 캐릭터가 나이트발드 마법인형 소환가능
- 마법인형은 총 5개의 등급으로 구분됩니다.


- 마법인형을 소환하기 위해서는 꼭! 마법인형 소환 주문서를 상점에서 구입하여, 사용 하셔야 합니다.
- 마법인형 카드 목록 중 획득한 마법인형의 조합에 따라, 마법인형 컬렉션이 발동됩니다.
마법인형 컬렉션은 계정 단위로 적용되며, 더 많은 마법인형 카드를 수집할수록 더 많은 효과가 계정에 적용 됩니다.
- 마법인형 카드의 경우, 계정 최초 1회 획득 이후에는 마법인형 카드가 자동으로 쌓이며, 동일 등급의 마법인형 카드 4장이
있을 경우, 상위 단계 카드를 확률적으로 획득 할 수 있는 [마법인형 카드 합성]이 가능합니다.  
예시1]
일반 등급 늑대인간 마법인형 카드를 5장 획득 -> 계정 최초 마법인형 목록 획득 1장을 제외한 4장의 카드가 보관
예시2]
합성 가능 사례 : 일반 등급 늑대인간 마법인형 카드 5장 -> 합성 기회 1회
합성 불가 사례 : 일반 등급 늑대인간 마법인형 카드 2장, 고급 등급 장로 마법인형 카드 2장 -> 합성 불가
- 마법인형 카드 중 일부 카드의 경우에는 오직 [마법인형 카드 합성] 으로만 획득 가능한 카드가 존재 합니다.
- 합성에 성공할 경우, 상위 등급의 마법인형 카드 중 1개를 랜덤하게 획득합니다. 실패할 경우에는 재료로 쓰인 4장의 카드 중 1장만 돌려 받게 됩니다.


[Spring] MyBatis Batch + Transaction 을 이용한 대용량 SQL작업


마을에서 오크잡는 퀘스트 하고 있는데 갑자기


중간보스를 잡아오라는 퀘스트가 떨어졌다...



일정시간마다 라즈베리파이에서 받아온 원시데이터를 재가공하여


DB에 insert 해주어야 하는 작업


로우수가 적다면 그냥 만들겠지만 대용량 작업일 경우 답이 안나온다.


약 1만건~10만건 정도의 데이터를 날려줘야 하는데 ㅂㄷㅂㄷㅂㄷ


그래서 찾아본 방법은 Batch와 Transaction 을 이용한 대용량 sql 작업



나도 정확히 내가 뭘 한건지도 모르고 그냥 스택오버 플로우, 오키, 전자정부 뒤적거리면서 이것 저것 다 때려 박느라

필요 없는 설정이 있을 수도 있으니 아는 사람은 댓글좀 달아주시길 바랍니다.



1.  XML 설정


1) mapper 설정

context-mapper.xml 파일이나 context-sqlMap.xml 파일에


마이바티스 연동을 위해 만들어놨던 설정을 아래와 같이 바꿔준다.


9번 라인의 batch설정으로 batch 사용이 가능 하도록 하는 듯 하다.


1
2
3
4
5
6
7
8
9
10
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="configLocation" value="classpath:/egovframework/sqlmap/example/sql-mapper-config.xml" />
        <property name="mapperLocations" value="classpath:/egovframework/sqlmap/example/mappers/mssql/*.xml" />
    </bean>
 
    <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate" destroy-method="clearCache">
        <constructor-arg index="0" ref="sqlSession" />      
        <constructor-arg index="1" value="BATCH" />
    </bean>
cs



2) datasource 설정

DB접속 정보 작성하는 곳에 트렌젝션메니저 설정을 하는데 이걸 해야 하는 건진 잘 모르겠다.


1
2
3
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
</bean>
cs



3) dispatcher-servlet 설정


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" 
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:p="http://www.springframework.org/schema/p"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        xmlns:task="http://www.springframework.org/schema/task" 
        xmlns:tx="http://www.springframework.org/schema/tx"
        xsi:schemaLocation="http://www.springframework.org/schema/beans 
                   http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
                http://www.springframework.org/schema/context 
                http://www.springframework.org/schema/context/spring-context-4.0.xsd
                http://www.springframework.org/schema/task
                http://www.springframework.org/schema/task/spring-task.xsd
                http://www.springframework.org/schema/mvc 
                http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
                http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
 
 
<tx:annotation-driven proxy-target-class="true"/>
cs


7번 라인과 17번 라인을 추가해주고 20번라인의 내용을 넣어 주도록 한다.



4) pom.xml


1
2
3
4
5
6
7
8
<!-- 트랜젝션 처리를 위함 -->
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>2.2</version>
            <type>jar</type>
            <scope>compile</scope>
        </dependency>
cs



디펜던시에 추가를 해줘야 트랜젝션 처리가 가능한건진 모르겠음. 전자정부 자체에 관련된게 이미 추가 되어 있을 수도 있고

정확히 모르겠음 저건



2. DAO or impl 작성


나는 DAO를 사용하지 않고 공통DAO하나 만들어 놓고 impl에서 바로 쿼리를 날려주는 방식을

좋아 한다.


어차피 DAO에서 특별히 해줄것도 없고.. 해줘야 하는것이 있어도 impl에서 해주면 되니까



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Override
    public void updateSchedulerHistoryRow(List<MinHistoryVO> historyList) {
        // TODO Auto-generated method stub
        
       // 트렌젝션 시작
        SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
        long startTime = System.currentTimeMillis();
            try {
                
                for (MinHistoryVO list : historyList) {                     
                    sqlSession.update("scheduler.updateSchedulerHistoryRow", list);
                }
 
            } finally {
                sqlSession.flushStatements();
                sqlSession.close();
            }
 
        long endTime = System.currentTimeMillis();
        long resutTime = endTime - startTime;
        System.out.println("트랜젝션 배치" + " 소요시간  : " + resutTime/1000 + "(ms)");
    }
cs



난 이런식으로 작성 했다.


가끔 6번 라인에 ExecutorType.BATCH 이 매개변수를 안넣고 시작 할 수 있는데

그러면 트렌젝션 안돌고 커넥션 다 찍으면서 돌게 된다.


저렇게 해도 수만건이 돌게 되면 세션에저장될 데이터들이 넘쳐흘러서 그런지 버벅거릴때가 있는데


그럴땐 컨트롤러에서 조금씩 끊어서 날려 주도록 하자



3. controller


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 
        //컨트롤러에서 일정 개수 단위로 끊어서 날려 준다.
        int insertCount = 0;
        List<MinHistoryVO> divHisList  = new ArrayList<MinHistoryVO>();
        for(int hisCount = 0, hisSize = historyList.size(); hisCount < hisSize; hisCount++){
            MinHistoryVO _tempData = new MinHistoryVO();
            _tempData = historyList.get(hisCount);
            divHisList.add(_tempData);
            if(insertCount == 1000 || hisSize-1 == hisCount){
                schedulerService.updateSchedulerHistoryRow(divHisList); // 트렌젝션
                divHisList =  new ArrayList<MinHistoryVO>();
                insertCount = 0;
            }
            else{                    
                insertCount++;
            }
        }
cs



while문 사용하는게 익숙하지 않아서 나는 for문을 주로 사용 한다.

리스트에 잔뜩 있는 데이터들을 새로운 작은 바구니에 담아서 끊어서 날려준다.








이렇게 하면 MsSql Server 2005버전 기준 1만건 insert하는데 5초정도 걸린다.


저기에  마이바티스 foreach까지 써서 벌크인서트 하면 시간은 더 단축 된다.


원시데이터를 쪼개서 60개컬럼에 따로 박아야 하기 때문에


넘겨주는 파라미터 개수 2100개 제한이 있어서 제대로 사용 못했는데


여러개로 쪼갠다음에  Mybatis foreach 돌려서 한번에 날려주면 시간은


훨씬 더더더더더 단축 된다.





+ Recent posts