2026/02/28
오늘의 이야기
#스하리1000명프로젝트
스치니들!
내가 만든 이 앱은, 내 폰에 오는 알림 중에서 중요한 키워드가 있는 경우
등록해둔 친구에게 자동으로 전달해주는 앱이야 📲
예를 들어, 카드 결제 알림을 와이프나 자녀에게 보내주거나
이번 달 지출을 달력처럼 확인할 수도 있어!
앱을 함께 쓰려면 친구도 설치 & 로그인해줘야 해.
그래야 친구 목록에서 서로 선택할 수 있으니까~
서로 써보고 불편한 점 있으면 알려줘 🙏
👉 https://play.google.com/store/apps/details?id=com.nari.notify2kakao
오늘의 이야기
오늘은 인앱 업데이트에 도전해 보자.
https://developer.android.com/guide/playcore/in-app-updates?hl=ko
인앱 업데이트 | Android 개발자 | Android Developers
인앱 업데이트 사용자는 기기에서 앱을 최신 상태로 유지하여 새로운 기능을 사용해 보고 성능 향상과 버그 수정을 통한 이점도 얻을 수 있습니다. 사용자 중에는 기기가 무제한 데이터에 연결
developer.android.com
앱을 만들어 게시를 하다보면 업데이트를 하게 되는 데, 내가 만든 앱의 사용자들이 업데이트를 잘 하고 있는 가에 대한 고민을 하게 된다. 그러나 사용자들은 그다지 업데이트에 관심이 없다. 자동으로 해 주면 좋은 거고, 아니면 말고, 혹시 android 설정에서 충전중 자동 업데이트를 설정해 두었다면 모르겠으나...
개발자 가이드의 설명은 AppUpdateManager 을 활용하는 방법에 대한 설명을 하고 있다. 이걸 보면서 그냥 따라하기를 해 보았다.
...
import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentSender;
import android.util.Log;
import androidx.appcompat.app.AlertDialog;
import com.google.android.play.core.appupdate.AppUpdateInfo;
import com.google.android.play.core.appupdate.AppUpdateManager;
import com.google.android.play.core.appupdate.AppUpdateManagerFactory;
import com.google.android.play.core.install.model.AppUpdateType;
import com.google.android.play.core.install.model.UpdateAvailability;
import com.google.android.play.core.tasks.Task;
import com.kakao.sdk.common.KakaoSdk;
import com.nari.notify2kakao.InitActivity;
import com.nari.notify2kakao.R;
public class GlobalApplication extends Application {
private static volatile GlobalApplication obj = null;
private static volatile Activity currentActivity = null;
private static String TAG = "GlobalApplication";
static AppUpdateManager appUpdateManager ;
static int MY_REQUEST_CODE = 1000;
@Override
public void onCreate() {
super.onCreate();
obj = this ;
KakaoSdk.init(this, getString(R.string.kakao_app_key));
}
public static void doUpdateStart(AppUpdateInfo appUpdateInfo) {
AlertDialog.Builder builder = new AlertDialog.Builder(getCurrentActivity(), R.style.DialogTheme);
builder.setTitle(getCurrentActivity().getString(R.string.beginInAppUpdate))
.setMessage(getCurrentActivity().getString(R.string.msgRunUpdateStart))
.setPositiveButton(getCurrentActivity().getString(R.string.OK), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
Log.e(TAG, "startUpdateFlowForResult");
try {
appUpdateManager.startUpdateFlowForResult(
// Pass the intent that is returned by 'getAppUpdateInfo()'.
appUpdateInfo,
// Or 'AppUpdateType.FLEXIBLE' for flexible updates.
AppUpdateType.IMMEDIATE,
// The current activity making the update request.
getCurrentActivity(),
// Include a request code to later monitor this update request.
MY_REQUEST_CODE);
} catch (IntentSender.SendIntentException e) {
e.printStackTrace();
}
}
});
AlertDialog dialog = builder.create();
dialog.show();
}
public static GlobalApplication getGlobalApplicationContext() {
return obj;
}
public static Activity getCurrentActivity() {
return currentActivity;
}
// Activity가 올라올때마다 Activity의 onCreate에서 호출해줘야한다.
public static void setCurrentActivity(Activity currentActivity) {
GlobalApplication.currentActivity = currentActivity;
appUpdateManager = AppUpdateManagerFactory.create(getCurrentActivity());
Log.e(TAG, "checkUpdate start...");
// 업데이트를 확인하는 데 사용하는 인텐트 개체를 반환합니다.
Task<AppUpdateInfo> appUpdateInfoTask = appUpdateManager.getAppUpdateInfo();
// 플랫폼이 지정된 유형의 업데이트를 허용하는지 확인합니다.
appUpdateInfoTask.addOnSuccessListener(appUpdateInfo -> {
Log.e(TAG, "updateAvailability=" + appUpdateInfo.updateAvailability());
Log.e(TAG, "IMMEDIATE=" + appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE));
if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE
// 이 예는 즉시 업데이트를 적용합니다. 유연한 업데이트를 적용하려면
// 대신 AppUpdateType.FLEXIBLE을 전달합니다.
&& appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE)) {
// 업데이트를 요청합니다.
doUpdateStart(appUpdateInfo);
}
});
}
}소스 예시는 알림을 카카오톡으로 보내는 앱에 사용된 GlobalApplication 안에 들어가 있는 내용이다. 다만, 아직 이렇게 구현된 소스가 정상적으로 구동 되고 있는 지는 알 수 없다. 아직 구동이 되어 보지 않아서...
난 오늘도 뭔 삽질을 하고 있는 건지 알 수 없다. 나중에 또 이글을 업데이트 할 날이 오기를 기다리며...
오늘의 이야기
예전 부터 만들어 관리하던 앱이 있는데... 알림을 카카오톡을 보내주는 ... 카카오에서 api 을 upgrade 하고 있어서 나도 해 보기로 했다.
먼저 gradle 파일의 변화
변경전
implementation group: project.KAKAO_SDK_GROUP, name: 'usermgmt', version: project.KAKAO_SDK_VERSION
implementation group: project.KAKAO_SDK_GROUP, name: 'kakaotalk', version: project.KAKAO_SDK_VERSION
implementation group: project.KAKAO_SDK_GROUP, name: 'friends', version: project.KAKAO_SDK_VERSION변경후
implementation "com.kakao.sdk:v2-user:2.9.0" // 카카오 로그인
implementation "com.kakao.sdk:v2-talk:2.9.0" // 친구, 메시지(카카오톡)
implementation "com.kakao.sdk:v2-story:2.9.0" // 카카오스토리
implementation "com.kakao.sdk:v2-link:2.9.0" // 메시지(카카오링크)
implementation "com.kakao.sdk:v2-navi:2.9.0" // 카카오내비
이제 로그인 시도해 보는 방법의 차이
변경전에는 제공된 login activity 을 이용해서 login 을 시도 하면 계정으로 로그인하는 것만을 지원했다면...
변경후에는
if (UserApiClient.getInstance().isKakaoTalkLoginAvailable(InitActivity.this)) {
UserApiClient.getInstance().loginWithKakaoTalk(InitActivity.this, new Function2<OAuthToken, Throwable, Unit>() {
@Override
public Unit invoke(OAuthToken oAuthToken, Throwable throwable) {
if (throwable != null) {
Log.e(TAG, throwable.getMessage());
return null;
} else {
Intent intent = new Intent(InitActivity.this, MonthlyMain.class);
startActivity(intent);
finish();
}
return null;
}
});
} else {
Log.e(TAG, "keyHash=" + Utility.INSTANCE.getKeyHash(InitActivity.this));
UserApiClient.getInstance().loginWithKakaoAccount(InitActivity.this, prompts, new Function2<OAuthToken, Throwable, Unit>() {
@Override
public Unit invoke(OAuthToken oAuthToken, Throwable throwable) {
Log.e(TAG, oAuthToken.getAccessToken());
if (throwable != null) {
Log.e(TAG, throwable.getMessage());
return null;
} else {
Intent intent = new Intent(InitActivity.this, MonthlyMain.class);
startActivity(intent);
finish();
}
return null;
}
});
};** 2022.03.24 수정 : 위 소스에서 getApplicationContext() 에서 InitActivity.this 로 수정함.
** getApplicationContext() 에 파라미터를 전달하게 되면 정상적으로 실행이 되지 않는 현상이 발견됨.
내폰에서 카카오톡으로 로그인이 가능한 상태 인지를 확인해 보고 가능 하다면 단순 로그인이 지원이 되고 그렇지 않을 떄면 예전 처럼 계정으로 로그인을 시도 하도록 구성할 수 있다는 차이가 생겼다.
친구 목록을 받아오는 방법은
변경전
AppFriendContext friendContext = new AppFriendContext( AppFriendOrder.NICKNAME, 0, 100, "asc");
KakaoTalkService.getInstance().requestAppFriends(friendContext,
new TalkResponseCallback<AppFriendsResponse>() {
@Override
public void onNotKakaoTalkUser() {
// 발신자가 카카오톡 유저가 아님
Log.e(TAG, "onNotKakaoTalkUser") ;
}
@Override
public void onFailure(ErrorResult errorResult) {
// 그 외 에러
Log.e(TAG, "getErrorMessage =" + errorResult.getErrorMessage());
Log.e(TAG, "getErrorCode =" + errorResult.getErrorCode());
Log.e(TAG, "getHttpStatus =" + errorResult.getHttpStatus());
Log.e(TAG, "errorResult =" + errorResult.toString());
kakaoToast.makeToast(StrValueAdd.this, errorResult.getErrorMessage(), Toast.LENGTH_LONG).show();
}
@Override
public void onSessionClosed(ErrorResult errorResult) {
// 액세스토큰 및 리프레시토큰이 만료됨. 재로그인 필요.
Log.e(TAG, "onSessionClosed" ) ;
redirectLoginActivity() ;
}
@Override
public void onSuccess(AppFriendsResponse result) {
// context의 beforeUrl과 afterUrl이 업데이트 된 상태.
appFriendInfos = result.getFriends();
adapter = new kakaoFriendinfoAdapter(appFriendInfos);
listAppFriendInfo.setAdapter(adapter);
appFriendCount = result.getTotalCount();
Log.e(TAG, "onSuccess " + result.getTotalCount()) ;
if (!"".equals(strUUID)) {
for(int i=0; i < appFriendCount ; i++) {
if (strUUID.equals(appFriendInfos.get(i).getUUID())) {
Log.e(TAG, strUUID + "/" + appFriendInfos.get(i).getUUID()) ;
appFiendIndex = i;
break ;
}
}
if (appFriendInfos != null) {
try {
kakaoUserId.setText(appFriendInfos.get(appFiendIndex).getProfileNickname());
} catch (Exception e) {
kakaoUserId.setText("");
}
} else {
kakaoUserId.setText("");
}
}
}
});
변경후
TalkApiClient.getInstance().friends(new Function2<Friends<Friend>, Throwable, Unit>() {
@Override
public Unit invoke(Friends<Friend> friendFriends, Throwable throwable) {
if (friendFriends != null) {
appFriends = friendFriends;
adapter = new kakaoFriendinfoAdapter(appFriends);
listAppFriendInfo.setAdapter(adapter);
appFriendCount = appFriends.getTotalCount();
Log.e(TAG, "onSuccess " + appFriends.getTotalCount()) ;
if (!"".equals(strUUID)) {
for(int i=0; i < appFriendCount ; i++) {
if (strUUID.equals(appFriends.getElements().get(i).getUuid())) {
Log.e(TAG, strUUID + "/" + appFriends.getElements().get(i).getUuid()) ;
appFiendIndex = i;
break ;
}
}
try {
kakaoUserId.setText(appFriends.getElements().get(appFiendIndex).getProfileNickname());
} catch (Exception e) {
kakaoUserId.setText("");
}
} else {
kakaoUserId.setText("");
}
}
return null;
}
});훨씬 소스의 길이가 간결해진다.
다음은 문자공유하는 sendMessage 의 차이
변경전
LinkObject link = LinkObject.newBuilder().setWebUrl("https://developers.kakao.com")
.setMobileWebUrl("https://developers.kakao.com")
.build();
TextTemplate params = TextTemplate.newBuilder(strBody, link)
.setButtonTitle("OK").build();
if (!"".equals(rs.getString(5))) {
List<String> uuids = Collections.singletonList(rs.getString(5));
KakaoTalkService.getInstance().sendMessageToFriends(uuids, params, new TalkResponseCallback<MessageSendResponse>() {
@Override
public void onNotKakaoTalkUser() {
Log.e(TAG, " 발신자가 카카오톡 유저가 아님 ");
}
@Override
public void onFailure(ErrorResult errorResult) {
Log.e(TAG, " 그 외 에러 ");
}
@Override
public void onSessionClosed(ErrorResult errorResult) {
Log.e(TAG, " 액세스토큰 및 리프레시토큰이 만료됨. 재로그인 필요. ");
}
@Override
public void onSuccess(MessageSendResponse result) {
Log.e(TAG, "API 호출 성공. 일부 사용자에게는 전송이 실패했을 수 있음. ");
kakaoToast.makeToast(context, strBody, Toast.LENGTH_LONG).show();
}
});
} else {
KakaoTalkService.getInstance().requestSendMemo(new TalkResponseCallback<Boolean>() {
@Override
public void onNotKakaoTalkUser() {
Log.e(TAG, " 발신자가 카카오톡 유저가 아님 ");
}
@Override
public void onSessionClosed(ErrorResult errorResult) {
Log.e(TAG, " 그 외 에러 ");
}
@Override
public void onSuccess(Boolean result) {
Log.e(TAG, "API 호출 성공. 일부 사용자에게는 전송이 실패했을 수 있음. ");
kakaoToast.makeToast(context, "To Me : " + strBody, Toast.LENGTH_LONG).show();
}
}, params);
}변경후
Link link = new Link("http://billcorea.tistory.com","http://billcorea.tistory.com", null, null);
TextTemplate textTemplate = new TextTemplate(strBody, link, null, "알림을 카톡으로");
if (!"".equals(rs.getString(5))) {
List<String> uuids = Collections.singletonList(rs.getString(5));
TalkApiClient.getInstance().sendDefaultMessage(uuids, textTemplate, new Function2<MessageSendResult, Throwable, Unit>() {
@Override
public Unit invoke(MessageSendResult messageSendResult, Throwable throwable) {
Log.e("context", messageSendResult.toString());
return null;
}
});
} else {
TalkApiClient.getInstance().sendDefaultMemo(textTemplate, new Function1<Throwable, Unit>() {
@Override
public Unit invoke(Throwable throwable) {
Log.e("context", "메모 등록");
return null;
}
});
}수정하면서 url 등은 변경을 했지만... 훨씬 간결하게 코드를 구현할 수 있게 된 것 같다.
이제 안드로이드 패치가 되어도 더는 고민할 이유가 없어졌다.
로그인 실행된 샘플 이미지는 다음과 같이...

오늘의 이야기
#스하리1000명프로젝트,
Kadang-kadang susah nak bercakap dengan pekerja asing kan?
Saya membuat aplikasi mudah yang membantu! Anda menulis dalam bahasa anda, dan orang lain melihatnya dalam bahasa mereka.
Ia auto-terjemah berdasarkan tetapan.
Sangat berguna untuk sembang mudah. Lihatlah apabila anda mendapat peluang!
https://play.google.com/store/apps/details?id=com.billcoreatech.multichat416
오늘의 이야기
https://github.com/PierfrancescoSoffritti/android-youtube-player
GitHub - PierfrancescoSoffritti/android-youtube-player: YouTube Player library for Android and Chromecast, stable and customizab
YouTube Player library for Android and Chromecast, stable and customizable. - GitHub - PierfrancescoSoffritti/android-youtube-player: YouTube Player library for Android and Chromecast, stable and c...
github.com
youtube 에 올라가 있는 동영상을 내 앱에서도 볼 수 있을까 하는 생각이 든다. 위 링크의 라이브러리를 이용하면
가능해 보인다.
도전 !

구현할 것은 별 거 없어 보인다. 먼저 gradle 파일에 종속성을 추가한다.
implementation 'com.pierfrancescosoffritti.androidyoutubeplayer:core:11.0.1'이것은 위에 기술한 링크에 있는 라이브러리를 연결하기만 하면 되고 layout 은 그냥 player 만 올리면 된다.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.pierfrancescosoffritti.androidyoutubeplayer.core.player.views.YouTubePlayerView
android:id="@+id/youtube_player_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:ignore="MissingClass,MissingConstraints" />
</androidx.constraintlayout.widget.ConstraintLayout>아무것도 없이 그냥 플레이어만 있는 layout 을 만들고 activity 을 만들면 끝이다.
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import com.billcoreatech.myyoutube.databinding.ActivityMainBinding;
import com.pierfrancescosoffritti.androidyoutubeplayer.core.player.YouTubePlayer;
import com.pierfrancescosoffritti.androidyoutubeplayer.core.player.listeners.AbstractYouTubePlayerListener;
public class MainActivity extends AppCompatActivity {
ActivityMainBinding binding ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
getLifecycle().addObserver(binding.youtubePlayerView);
binding.youtubePlayerView.addYouTubePlayerListener(new AbstractYouTubePlayerListener() {
@Override
public void onReady(@NonNull YouTubePlayer youTubePlayer) {
super.onReady(youTubePlayer);
String videoId = "cd_X7Os3OVE";
youTubePlayer.loadVideo(videoId, 0);
}
});
}
}저기 나오는 viodeId 는 youtube 에 올라간 영상의 링크 값이다. 다만, youtube 에 올라간 영상의 경우에는 youtube 설정에서 다른 player 에서 플레이가 되도록 설정하는 게 필요해 보인다.
이것으로 youtube 의 영상 플레이어 구현은 끝.
오늘의 이야기
이전에 posting 했던 pdf 공유 하기이 다음 이야기 정도가 될 것 같다. 요 몇일은 앱 수리를 하느라.. 좀
아무튼 이번에 작업하면서 찾아낸 것에 대해서 기억을 정리해 두어야 겠다.
이번에 하게 된 일은 pdf 을 만들어서 공유를 하는 것인데, 방법이 2가지 정도는 되는 것 같다.
첫번째는 이전 posting 에서 처럼 공유할 파일만 지정해서 ACTION_SEND 액션을 실행하는 방법이고, 이번에는 그것을 특정앱으로 한정해 보는 것이다.
public void sharePdf(String sPackageName) {
File pdfFile = new File(getCacheDir(), "/" + fileName + ".pdf");
Uri contentUri = FileProvider.getUriForFile(getApplicationContext(), getApplicationContext().getPackageName()+".fileProvider", pdfFile);
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("application/pdf");
shareIntent.putExtra(Intent.EXTRA_STREAM, contentUri);
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
shareIntent.setPackage(sPackageName);
if (getPackageList(sPackageName)) {
shareIntent.setPackage(sPackageName);
shareIntent.putExtra(Intent.EXTRA_SUBJECT, "전달할 제목");
shareIntent.putExtra(Intent.EXTRA_TEXT, "전달할 메시지 내용.");
startActivity(Intent.createChooser(shareIntent, "알림TITLE"));
} else {
String url = "market://details?id=" + sPackageName;
Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(i);
}
}
public boolean getPackageList(String packageName) {
boolean isExist = false;
PackageManager pkgMgr = getPackageManager();
List<ResolveInfo> mApps;
Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
mApps = pkgMgr.queryIntentActivities(mainIntent, 0);
try {
for (int i = 0; i < mApps.size(); i++) {
Log.e("PackageName=", "" + mApps.get(i).activityInfo.packageName);
if(mApps.get(i).activityInfo.packageName.startsWith(packageName)){
isExist = true;
break;
}
}
}
catch (Exception e) {
isExist = false;
}
return isExist;
}이렇게 함수를 만들어 놓으면 구현 가능한 부분이 쉬워진다. 보내고 싶은 앱의 패키지 이름만 알아낸다면 그 앱으로 내가 만든 파일 (예시에서는 pdf 가 있다고 가정했다.) 을 바로 전달을 하게 되는 것이다.
// com.dho.mobilefax : skt 모바일 팩스
// com.google.android.gm : gmail
// com.google.android.apps.docs : google drive 문서저장
// com.samsung.android.messaging : 삼성 문자 메시지
// com.google.android.apps.messaging : 구글 기본 메시지
// net.daum.android.mail : 다음메일
// com.kakao.talk : 카카오톡
// com.sec.print.mobileprint : 삼성모바일 프린트
// epson.print : epson print예을 들면 이런 package name 을 찾아서 위에서 기술한 함수에 호출을 넣어 주면 된다. 그리고 위 예시 소스에서 getPackageList 함수를 이용해서 해당 앱이 사용중인 폰에 설치 되어 있는 지 확인하고 없으면 앱을 설치하도록 유도 페이지로 이동시키면 되는 것이다.

이렇게 코드를 구현해 보았다.
오늘의 이야기
#billcorea #운동동아리관리앱
🏸 Schneedle, aplikasi mesti ada untuk kelab badminton!
👉 Main Perlawanan – Rekod Markah & Cari Lawan 🎉
Sesuai untuk mana-mana sahaja, bersendirian, bersama rakan-rakan atau dalam kelab! 🤝
Jika anda suka badminton, pasti mencubanya
Pergi ke aplikasi 👉 https://play.google.com/store/apps/details?id=com.billcorea.matchplay
오늘의 이야기

이런 이미지는 어떤 생각에서 만들어 내는 것일까 ?
식물인지 동물인지 야간은 애매한 이미지 이다. 늘 새로운 생각이 드는 건 맞는 데... 이걸 보면서 오늘은 또 어떤 생각이 들어야 하는 건지...
또 다른 시간이 오길 기다리며...
오늘의 이야기
앱을 만들다 보니 이런 일도 생긴다. 주 내용은 다름이 아니라 앱의 접근성에 관한 부분이다.
구글은 사용자가 편리하게 앱을 사용하게 될 수 있도록 하기 위해서 이기는 하겠지만 , 개발자 입장에서는 아무래도 번거로운 일이 아닐까 싶다.
앱을 만들어 console 에 올리고 내부 테스트 버전을 적용하였더니, 한 두시간후에 메일와 와서 열어 보았더니, 아래 와 같은 출시 사전 보고서를 볼 수 있었다.

접근성과 관련 해서는 앱의 버튼 메뉴등을 만들어 달았는데, 그것들이 시각장애를 가지고 있는 친구들이 사용하기에 불편함이 없도록 하려면 그것들을 청각적인 요소로 들려 주어야 하는데, 그것을 알려 주어야 하는 것이다.
방법은 각 layout object 에 contentDesciption 을 설정해 주는 것이다. 앱의 구동되고 있는 동안에도 동적으로 그 설정을 지정할 수 있는 데,
그런때에는 setContentDescription 을 이용해서 설정을 해 주는 것이다.
그럼... 오늘은 여기 까지...
오늘의 이야기
#스하리1000명프로젝트,
Bị lạc ở Hàn Quốc? Ngay cả khi bạn không nói được tiếng Hàn, ứng dụng này vẫn giúp bạn đi lại dễ dàng.
Chỉ cần nói ngôn ngữ của bạn—nó sẽ dịch, tìm kiếm và hiển thị kết quả bằng ngôn ngữ của bạn.
Tuyệt vời cho du khách! Hỗ trợ hơn 10 ngôn ngữ bao gồm tiếng Anh, tiếng Nhật, tiếng Trung, tiếng Việt, v.v.
Hãy thử nó ngay bây giờ!
https://play.google.com/store/apps/details?id=com.billcoreatech.opdgang1127
2026/02/27
오늘의 이야기
추천 [16,27,30,31,38,39]
추천 [02,04,18,29,33,40]
추천 [03,11,17,25,32,45]
추천 [07,15,24,28,34,42]
추천 [09,19,26,35,41,43]
### 다음 라운드 번호 추천 분석
#### 1. 번호 출현 빈도 분석
전체 회차(20회) 번호별 출현 빈도:
01: 5회, 02: 2회, 03: 4회, 04: 2회, 05: 3회, 06: 3회, 07: 4회, 08: 3회, 09: 3회, 10: 2회, 11: 1회, 12: 2회, 13: 1회, 15: 3회, 16: 5회, 17: 4회, 18: 1회, 19: 1회, 20: 2회, 21: 1회, 22: 1회, 23: 3회, 24: 4회, 25: 2회, 26: 3회, 27: 6회, 28: 3회, 29: 2회, 30: 4회, 31: 4회, 32: 2회, 33: 4회, 34: 2회, 35: 4회, 36: 4회, 37: 4회, 38: 5회, 39: 4회, 40: 3회, 41: 3회, 42: 2회, 43: 1회, 44: 2회, 45: 2회
가장 많이 출현한 번호 6개: [16,27,30,31,38,39]
#### 2. 홀/짝 비율 분석
회차별 홀/짝 조합 빈도:
짝 3개/홀 3개: 9회, 짝 2개/홀 4개: 5회, 짝 4개/홀 2개: 5회, 짝 1개/홀 5개: 1회
가장 빈번한 홀/짝 조합은 짝 3개, 홀 3개입니다. 마지막 라운드는 짝 3개, 홀 3개였습니다.
#### 3. 총합 및 평균 분석
역대 총합 범위: 104 - 187 (평균: 147.25)
역대 평균값 범위: 17.33 - 31.17 (평균: 24.54)
마지막 라운드(1212) 총합: 154, 평균: 25.67
#### 4. 간격 패턴 분석
번호 간격별 출현 빈도:
1: 16회, 2: 13회, 3: 16회, 4: 5회, 5: 6회, 6: 7회, 7: 6회, 8: 7회, 9: 2회, 10: 4회, 11: 2회, 12: 2회, 13: 1회, 14: 1회, 15: 3회, 16: 1회, 17: 3회, 18: 1회, 21: 1회, 22: 1회, 24: 1회, 25: 1회, 26: 1회, 30: 1회
마지막 라운드(1212) 간격: [3, 17, 6, 10, 3]
작은 간격(1-5)과 중간 간격(6-15)의 혼합이 자주 관찰됩니다.
#### 5. 패턴 일치도 및 주기 분석
과거 데이터를 통해 총합, 평균, 홀/짝 비율, 간격 패턴 등 4가지 속성을 기준으로 패턴 일치도를 분석했습니다. 일부 속성에서 동일 패턴 반복 주기가 관찰되었으나, 20회차 데이터만으로는 강력한 주기성을 단정하기 어렵습니다. 다만, 특정 패턴(예: 3짝 3홀 조합, 중간 범위의 총합)이 자주 나타나는 경향이 있습니다.
### 추천 조합 생성 근거
**추천1 [16,27,30,31,38,39]**: 전체 20회차 데이터에서 가장 높은 출현 빈도를 보인 6개의 번호를 조합했습니다.
**추천2 [02,04,18,29,33,40]**: 과거 당첨 번호의 통계적 균형(예: 짝수 3개, 홀수 3개, 중간 범위의 총합)을 고려하여 선정했습니다.
**추천3 [03,11,17,25,32,45]**: 최근 라운드의 번호 간격 패턴(작은 간격, 중간 간격, 큰 간격의 조화)을 반영하여 번호의 분포를 예측했습니다.
**추천4 [07,15,24,28,34,42]**: 출현 빈도가 높은 '핫'한 번호와 상대적으로 출현이 적은 '콜드'한 번호를 균형 있게 조합하여 선정했습니다.
**추천5 [09,19,26,35,41,43]**: 과거 특정 당첨 라운드(예: 1201회차)의 주요 특징(홀/짝 비율, 총합, 평균 등)을 모방하여 유사한 통계적 특성을 가지는 번호 조합을 생성했습니다.
### 마지막 라운드(1212회차)와 추천 조합 비교 분석
**1212회차 당첨 번호**: [05,08,25,31,41,44]
- 총합: 154, 평균: 25.67
- 홀/짝: 짝수 3개, 홀수 3개
- 간격: [3, 17, 6, 10, 3]
**추천1 조합 ([16,27,30,31,38,39]) 분석**:
- 총합: 181, 평균: 30.17 (1212회차 총합 154, 평균 25.67)
- 홀/짝: 짝수 3개, 홀수 3개 (1212회차 짝수 3개, 홀수 3개)
- 간격: [11, 3, 1, 7, 1] (1212회차 간격 [3, 17, 6, 10, 3])
- **1212회차 대비 특징**: 총합이 다소 차이 남, 홀/짝 비율이 동일함. 이 조합은 1212회차와 번호 구성이 다르며, 최근 10회차 당첨 번호와도 중복되지 않습니다.
**추천2 조합 ([02,04,18,29,33,40]) 분석**:
- 총합: 126, 평균: 21.00 (1212회차 총합 154, 평균 25.67)
- 홀/짝: 짝수 3개, 홀수 3개 (1212회차 짝수 3개, 홀수 3개)
- 간격: [2, 14, 11, 4, 7] (1212회차 간격 [3, 17, 6, 10, 3])
- **1212회차 대비 특징**: 총합이 다소 차이 남, 홀/짝 비율이 동일함. 이 조합은 1212회차와 번호 구성이 다르며, 최근 10회차 당첨 번호와도 중복되지 않습니다.
**추천3 조합 ([03,11,17,25,32,45]) 분석**:
- 총합: 133, 평균: 22.17 (1212회차 총합 154, 평균 25.67)
- 홀/짝: 짝수 2개, 홀수 4개 (1212회차 짝수 3개, 홀수 3개)
- 간격: [8, 6, 8, 7, 13] (1212회차 간격 [3, 17, 6, 10, 3])
- **1212회차 대비 특징**: 총합이 다소 차이 남, 홀/짝 비율이 다름, 일부 간격 패턴이 1212회차와 겹침. 이 조합은 1212회차와 번호 구성이 다르며, 최근 10회차 당첨 번호와도 중복되지 않습니다.
**추천4 조합 ([07,15,24,28,34,42]) 분석**:
- 총합: 150, 평균: 25.00 (1212회차 총합 154, 평균 25.67)
- 홀/짝: 짝수 3개, 홀수 3개 (1212회차 짝수 3개, 홀수 3개)
- 간격: [8, 9, 4, 6, 8] (1212회차 간격 [3, 17, 6, 10, 3])
- **1212회차 대비 특징**: 총합이 유사함, 홀/짝 비율이 동일함, 일부 간격 패턴이 1212회차와 겹침. 이 조합은 1212회차와 번호 구성이 다르며, 최근 10회차 당첨 번호와도 중복되지 않습니다.
**추천5 조합 ([09,19,26,35,41,43]) 분석**:
- 총합: 173, 평균: 28.83 (1212회차 총합 154, 평균 25.67)
- 홀/짝: 짝수 1개, 홀수 5개 (1212회차 짝수 3개, 홀수 3개)
- 간격: [10, 7, 9, 6, 2] (1212회차 간격 [3, 17, 6, 10, 3])
- **1212회차 대비 특징**: 총합이 다소 차이 남, 홀/짝 비율이 다름. 이 조합은 1212회차와 번호 구성이 다르며, 최근 10회차 당첨 번호와도 중복되지 않습니다.

사용하는 예시 영상 보기
이 앱이 궁금 하다면, 아래 링크에서 설치할 수 있습니다.
로또 645
오늘의 이야기
<알림수집기앱 : 이하 사용자앱으로 표시 >:는) 「개인정보 보호법」 제30조에 따라 정보주체의 개인정보를 보호하고 이와 관련한 고충을 신속하고 원활하게 처리할 수 있도록 하기 위하여 다음과 같이 개인정보 처리방침을 수립·공개합니다. ○ ...