문제상황:
플레이스토어에 앱의 자동업데이트가 실행중인 상황에서도 업데이트가 자동으로 진행되지 않는 경우가 있었다. 그래서 앱 시작시에 플레이 스토어에서 버전정보를 크롤링해 현재 설치된 앱버전과 비교하는 코드를 추가했다.(gun0912님 블로그 참고)
그러나 계속 앱의 플레이 스토어 버전이 null로 반환되는 문제가 생겼다.
[안드로이드/Android]플레이스토어 버전 체크하는 방법 (업데이트 체크)
안드로이드 어플리케이션을 개발하고 계속 업데이트 하다보면 사용자가 최신버전을 사용해주길 바라는 경우가 많이 있습니다. 새로운 기능이 추가되었을경우도 그럴것이며, 해당 버전에 문제
gun0912.tistory.com
· MarketVersionChecker.class
public class MarketVersionChecker {
public static String getMarketVersion(String packageName) {
try {
Document doc = Jsoup.connect(
"https://play.google.com/store/apps/details?id="
+ packageName).get();
Elements Version = doc.select(".content");
for (Element mElement : Version) {
if (mElement.attr("itemprop").equals("softwareVersion")) {
return mElement.text().trim();
}
}
} catch (IOException ex) {
ex.printStackTrace();
}
return null;
}
public static String getMarketVersionFast(String packageName) {
String mData = "", mVer = null;
try {
URL mUrl = new URL("https://play.google.com/store/apps/details?id="
+ packageName);
HttpURLConnection mConnection = (HttpURLConnection) mUrl
.openConnection();
if (mConnection == null)
return null;
mConnection.setConnectTimeout(5000);
mConnection.setUseCaches(false);
mConnection.setDoOutput(true);
if (mConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
BufferedReader mReader = new BufferedReader(
new InputStreamReader(mConnection.getInputStream()));
while (true) {
String line = mReader.readLine();
if (line == null)
break;
mData += line;
}
mReader.close();
}
mConnection.disconnect();
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
String startToken = "softwareVersion\">";
String endToken = "<";
int index = mData.indexOf(startToken);
if (index == -1) {
mVer = null;
} else {
mVer = mData.substring(index + startToken.length(), index
+ startToken.length() + 100);
mVer = mVer.substring(0, mVer.indexOf(endToken)).trim();
}
return mVer;
}
}
· 앱 시작시 실행되는 Splashscreen.java중 버전을 체크하는 부분 (MarketVersionChecker.class가 import됨)
class VersionThread extends Thread {
@Override
public void run() {
String store_version = MarketVersionChecker.getMarketVersionFast(getPackageName());
try {
String device_version = getPackageManager().getPackageInfo(getPackageName(), 0).versionName;
System.out.println("store_version: "+store_version+"device_version: "+device_version);
try{
if (store_version.compareTo(device_version) > 0) {
// 업데이트 필요
showToast(Splashscreen.this, "store_version: "+store_version+"device_version: "+device_version);
} else {
// 업데이트 불필요
showToast(Splashscreen.this, "store_version: "+store_version+"device_version: "+device_version);
}
}catch (java.lang.NullPointerException e){
e.printStackTrace();
}
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
}
}
VersionThread VersionThread = new VersionThread();
VersionThread.start();
try {
VersionThread.join();
} catch (InterruptedException ie) {
ie.printStackTrace();
}
해결방법:
1. 정식버전을 플레이 스토어에 출시할 때까지 기다린다.....
2. firebase의 Remote config를 사용한다.(아직 공부해야함)
2/20 수정
1. firestore 데이터베이스에 버전정보를 저장하는 콜렉션을 추가하고, 앱 실행시마다 현재의 앱버전과 비교하는 코드추가.
Splashscreen.java 중 일부
String store_version = MarketVersionChecker.getMarketVersionFast(getPackageName());
DocumentReference docRef = FirebaseFirestore.getInstance().collection("AppData").document("MarketVersion");
docRef.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
@Override
public void onComplete(@NonNull Task<DocumentSnapshot> task) {
if (task.isSuccessful()) {
DocumentSnapshot document = task.getResult();
if (document.exists()) {
store_version=(String) document.getData().get("Version");
System.out.println("store_version: "+store_version);
try {
String device_version = getPackageManager().getPackageInfo(getPackageName(), 0).versionName;
System.out.println("store_version: "+store_version+"device_version: "+device_version);
try{
if (store_version.compareTo(device_version) > 0) {
// 업데이트 필요
showToast(Splashscreen.this, "현재 버전은 "+device_version+"으로, 최신버전인: "+store_version+"으로 업데이트가 필요합니다!");
System.out.println("store_version: "+store_version+"device_version: "+device_version);
} else {
// showToast(Splashscreen.this, "store_version: "+store_version+"device_version: "+device_version);
System.out.println("store_version: "+store_version+"device_version: "+device_version);
}
}catch (java.lang.NullPointerException e){
e.printStackTrace();
}
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
} else {
}
} else {
}
}
});
원인분석:
코드 자체가 웹페이지에서 정보를 가져와 앱의 정보와 비교하는 방식이기 때문에 웹에 앱 버전 정보가 없어서 반환값이 null로 뜬 것 이었다.
다른 앱들은 버전정보가 있는것에 비추어볼 때 사전테스트중인 앱은 정식 출시 전 까지는 버전 정보가 표시되지 않는 것 같다.
또한 play store웹의 html 구조가 바뀌면서 버전정보를 크롤링하는 코드가 더 이상 작동하지 않는 것 같다.
String startToken = "<div class=\"reAt0\">";//여기를
String endToken = "<";//바꿈
int index = mData.indexOf(startToken);
그래서 html class 이름을 지칭했던 start token과 end token의 이름을 바뀐 구조에 맞게 바꾸어 주었다.
2/20수정
바뀐 구조에 맞게 코드를 바꾸어 주어도 버전정보관련 html코드가 더보기 버튼을 눌러야 동적으로 생성되는 것이라 반환값이 null이 나왔다. 그래서 firestore에 버전정보를 직접 기록하는 방식을 사용하여 해결하였다.
추후에 할 것: android.os.NetworkOnMainThreadException 관련 문제도 있었는데, 쓰레드를 사용해서 해결했지만, 관련 기초지식을 공부해서 왜 해결됬는지 정확히 공부해야겠다.
참고링크:
[안드로이드/Android]플레이스토어 버전 체크하는 방법 (업데이트 체크)
안드로이드 어플리케이션을 개발하고 계속 업데이트 하다보면 사용자가 최신버전을 사용해주길 바라는 경우가 많이 있습니다. 새로운 기능이 추가되었을경우도 그럴것이며, 해당 버전에 문제
gun0912.tistory.com
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/String/indexOf
String.prototype.indexOf() - JavaScript | MDN
indexOf() 메서드는 호출한 String 객체에서 주어진 값과 일치하는 첫 번째 인덱스를 반환합니다. 일치하는 값이 없으면 -1을 반환합니다.
developer.mozilla.org