commit 46be3ddfa89920737a121ce95ec38c165290b88e
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Fri Jan 28 15:11:41 2022 +0100

    progress with the Updates: download the jsons.

diff --git a/src/main/java/org/distorted/dialogs/RubikDialogScoresPagerAdapter.java b/src/main/java/org/distorted/dialogs/RubikDialogScoresPagerAdapter.java
index 3e131a38..9a971ed7 100644
--- a/src/main/java/org/distorted/dialogs/RubikDialogScoresPagerAdapter.java
+++ b/src/main/java/org/distorted/dialogs/RubikDialogScoresPagerAdapter.java
@@ -38,7 +38,7 @@ import org.distorted.screens.RubikScreenPlay;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-class RubikDialogScoresPagerAdapter extends PagerAdapter implements RubikNetwork.Receiver
+class RubikDialogScoresPagerAdapter extends PagerAdapter implements RubikNetwork.ScoresReceiver
   {
   private final FragmentActivity mAct;
   private final RubikDialogScores mDialog;
@@ -157,7 +157,7 @@ class RubikDialogScoresPagerAdapter extends PagerAdapter implements RubikNetwork
 
     switch(errorNumber)
       {
-      case '1': message("Network error");
+      case '1': message(mAct.getString(R.string.networkError));
                 break;
       case '2': RubikScores scores = RubikScores.getInstance();
                 Bundle bundle = new Bundle();
diff --git a/src/main/java/org/distorted/dialogs/RubikDialogUpdateView.java b/src/main/java/org/distorted/dialogs/RubikDialogUpdateView.java
index f0951f75..2294f014 100644
--- a/src/main/java/org/distorted/dialogs/RubikDialogUpdateView.java
+++ b/src/main/java/org/distorted/dialogs/RubikDialogUpdateView.java
@@ -21,6 +21,7 @@ package org.distorted.dialogs;
 
 import android.app.Activity;
 import android.graphics.Bitmap;
+import android.graphics.Color;
 import android.util.TypedValue;
 import android.view.View;
 import android.widget.Button;
@@ -30,26 +31,36 @@ import android.widget.ProgressBar;
 import android.widget.TextView;
 
 import org.distorted.main.R;
+import org.distorted.network.RubikNetwork;
 import org.distorted.network.RubikUpdates;
 
+import java.io.InputStream;
+
 import static android.view.View.GONE;
+import static android.view.View.VISIBLE;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-public class RubikDialogUpdateView
+public class RubikDialogUpdateView implements RubikNetwork.Downloadee
   {
   private ImageView mIcon;
+  private RubikUpdates.UpdateInfo mInfo;
+  private ProgressBar mBar;
+  private Button mButton;
+  private TextView mDescription;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public View createView(Activity act, RubikUpdates.UpdateInfo info, int fontSize, int padding,
                          LinearLayout.LayoutParams pView, LinearLayout.LayoutParams pText, LinearLayout.LayoutParams pButt )
     {
+    mInfo = info;
+    final RubikNetwork.Downloadee downloadee = this;
     View view = act.getLayoutInflater().inflate(R.layout.dialog_updates_pane, null);
     TextView title = view.findViewById(R.id.updates_pane_title);
     title.setText(info.mObjectLongName);
-    TextView description = view.findViewById(R.id.updates_pane_description);
-    description.setText(info.mDescription);
+    mDescription = view.findViewById(R.id.updates_pane_description);
+    mDescription.setText(info.mDescription);
 
     mIcon = view.findViewById(R.id.updates_pane_image);
     mIcon.setImageResource(R.drawable.unknown_icon);
@@ -57,36 +68,39 @@ public class RubikDialogUpdateView
     view.setLayoutParams(pView);
 
     title.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize);
-    description.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize);
+    mDescription.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize);
 
     title.setLayoutParams(pText);
-    description.setLayoutParams(pText);
+    mDescription.setLayoutParams(pText);
 
     view.setPadding(padding,padding,padding,padding);
 
-    ProgressBar bar = view.findViewById(R.id.updates_pane_bar);
-    Button button   = view.findViewById(R.id.updates_pane_button);
+    mBar    = view.findViewById(R.id.updates_pane_bar);
+    mButton = view.findViewById(R.id.updates_pane_button);
 
     if( info.mPercent>=100 )
       {
-      bar.setVisibility(GONE);
-      button.setOnClickListener( new View.OnClickListener()
+      mBar.setVisibility(GONE);
+      mButton.setOnClickListener( new View.OnClickListener()
         {
         @Override
         public void onClick(View v)
           {
-          android.util.Log.e("D", "INSTALL pressed");
+          startDownload();
+          RubikNetwork network = RubikNetwork.getInstance();
+          network.downloadJSON(info,downloadee);
           }
         });
 
-      button.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize);
-      button.setLayoutParams(pButt);
+      mButton.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize);
+      mButton.setLayoutParams(pButt);
+      mBar.setLayoutParams(pButt);
       }
     else
       {
-      button.setVisibility(GONE);
-      bar.setLayoutParams(pButt);
-      bar.setProgress(info.mPercent);
+      mButton.setVisibility(GONE);
+      mBar.setLayoutParams(pButt);
+      mBar.setProgress(info.mPercent);
       }
 
     return view;
@@ -98,4 +112,30 @@ public class RubikDialogUpdateView
     {
     mIcon.setImageBitmap(icon);
     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void startDownload()
+    {
+    mDescription.setText(R.string.downloading);
+    mBar.setProgress(20);
+    mButton.setVisibility(GONE);
+    mBar.setVisibility(VISIBLE);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void jsonDownloaded()
+    {
+    if( mInfo.mUpdateObject && mInfo.mObjectStream==null )
+      {
+      mDescription.setTextColor(Color.parseColor("#ff0000"));
+      mDescription.setText(R.string.networkError);
+      }
+    else
+      {
+      mBar.setProgress(50);
+      mDescription.setText(R.string.installing);
+      }
+    }
   }
diff --git a/src/main/java/org/distorted/dialogs/RubikDialogUpdates.java b/src/main/java/org/distorted/dialogs/RubikDialogUpdates.java
index 874b8622..9d62feda 100644
--- a/src/main/java/org/distorted/dialogs/RubikDialogUpdates.java
+++ b/src/main/java/org/distorted/dialogs/RubikDialogUpdates.java
@@ -46,7 +46,7 @@ import org.distorted.network.RubikUpdates;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-public class RubikDialogUpdates extends AppCompatDialogFragment implements RubikNetwork.Updatee
+public class RubikDialogUpdates extends AppCompatDialogFragment implements RubikNetwork.IconReceiver, RubikNetwork.Updatee
   {
   private TextView mText;
   private LinearLayout mLayout;
@@ -218,7 +218,8 @@ public class RubikDialogUpdates extends AppCompatDialogFragment implements Rubik
 
   public void errorUpdate()
     {
-    mText.setText("Network error");
+    FragmentActivity act = getActivity();
+    if( act!=null ) mText.setText(act.getString(R.string.networkError));
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/network/RubikNetwork.java b/src/main/java/org/distorted/network/RubikNetwork.java
index 0213e920..b4f96e59 100644
--- a/src/main/java/org/distorted/network/RubikNetwork.java
+++ b/src/main/java/org/distorted/network/RubikNetwork.java
@@ -46,20 +46,29 @@ import static org.distorted.objects.RubikObjectList.MAX_LEVEL;
 
 public class RubikNetwork
   {
-  public interface Receiver
+  public interface ScoresReceiver
     {
     void receive(String[][][] country, String[][][] name, float[][][] time);
     void message(String mess);
     void error(String error);
     }
 
-  public interface Updatee
+  public interface IconReceiver
     {
     void iconDownloaded(int ordinal, Bitmap bitmap);
+    }
+
+  public interface Updatee
+    {
     void receiveUpdate(RubikUpdates update);
     void errorUpdate();
     }
 
+  public interface Downloadee
+    {
+    void jsonDownloaded();
+    }
+
   public static final int MAX_PLACES = 10;
 
   private static final int REND_ADRENO= 0;
@@ -114,10 +123,8 @@ public class RubikNetwork
   private static RubikNetwork mThis;
   private static String mScores = "";
   private static boolean mRunning = false;
-  private static Receiver mReceiver;
   private static Updatee mUpdatee;
   private static String mVersion;
-  private static String mSuspicious;
   private static int mNumObjects;
   private static RubikUpdates mUpdates;
   private static int mDebugState;
@@ -168,19 +175,19 @@ public class RubikNetwork
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  private boolean fillValuesNormal()
+  private boolean fillValuesNormal(ScoresReceiver receiver)
     {
     int begin=-1 ,end, len = mScores.length();
     String row;
 
     if( len==0 )
       {
-      if( mReceiver!=null ) mReceiver.error("1");
+      receiver.error("1");
       return false;
       }
     else if( len<=2 )
       {
-      if( mReceiver!=null ) mReceiver.error(mScores);
+      receiver.error(mScores);
       return false;
       }
 
@@ -376,7 +383,7 @@ public class RubikNetwork
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  private boolean network(String url)
+  private boolean network(String url, ScoresReceiver receiver)
     {
     try
       {
@@ -400,26 +407,27 @@ public class RubikNetwork
         }
 
       mScores = total.toString();
+      conn.disconnect();
       }
     catch( final UnknownHostException e )
       {
-      if( mReceiver!=null ) mReceiver.message("No access to Internet");
+      receiver.message("No access to Internet");
       return false;
       }
     catch( final SecurityException e )
       {
-      if( mReceiver!=null ) mReceiver.message("Application not authorized to connect to the Internet");
+      receiver.message("Application not authorized to connect to the Internet");
       return false;
       }
     catch( final Exception e )
       {
-      if( mReceiver!=null ) mReceiver.message(e.getMessage());
+      receiver.message(e.getMessage());
       return false;
       }
 
     if( mScores.length()==0 )
       {
-      if( mReceiver!=null ) mReceiver.message("Failed to download scores");
+      receiver.message("Failed to download scores");
       return false;
       }
 
@@ -428,11 +436,11 @@ public class RubikNetwork
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  private String constructSuspiciousURL()
+  private String constructSuspiciousURL(String suspURL)
     {
     RubikScores scores = RubikScores.getInstance();
     int deviceID= scores.getDeviceID();
-    String suspicious = URLencode(mSuspicious);
+    String suspicious = URLencode(suspURL);
 
     String url="https://distorted.org/magic/cgi-bin/suspicious.cgi";
     url += "?i="+deviceID+"&d="+suspicious;
@@ -534,33 +542,33 @@ public class RubikNetwork
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  private void downloadThread()
+  private void downloadThread(ScoresReceiver receiver)
     {
     try
       {
       if( gottaDownload() )
         {
         mRunning = true;
-        boolean receiveValues = network(constructDownloadURL());
+        boolean receiveValues = network(constructDownloadURL(),receiver);
 
         if( mRunning )
           {
-          receiveValues = fillValuesNormal();
+          receiveValues = fillValuesNormal(receiver);
           mRunning = false;
           }
 
-        if( receiveValues && mReceiver!=null ) mReceiver.receive(mCountry, mName, mTime);
+        if( receiveValues ) receiver.receive(mCountry, mName, mTime);
         }
       }
     catch( Exception e )
       {
-      if( mReceiver!=null ) mReceiver.message("Exception downloading records: "+e.getMessage() );
+      receiver.message("Exception downloading records: "+e.getMessage() );
       }
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  private void submitThread()
+  private void submitThread(ScoresReceiver receiver)
     {
     try
       {
@@ -569,24 +577,24 @@ public class RubikNetwork
 
       if( scores.thereAreUnsubmittedRecords() )
         {
-        boolean receiveValues = network(constructSubmitURL());
+        boolean receiveValues = network(constructSubmitURL(),receiver);
 
         if( mRunning )
           {
-          receiveValues = fillValuesNormal();
+          receiveValues = fillValuesNormal(receiver);
           mRunning = false;
           }
 
         if( receiveValues )
           {
           RubikScores.getInstance().successfulSubmit();
-          if( mReceiver!=null ) mReceiver.receive(mCountry, mName, mTime);
+          receiver.receive(mCountry, mName, mTime);
           }
         }
       }
     catch( Exception e )
       {
-      if( mReceiver!=null ) mReceiver.message("Exception submitting records: "+e.getMessage() );
+      receiver.message("Exception submitting records: "+e.getMessage() );
       }
     }
 
@@ -621,6 +629,7 @@ public class RubikNetwork
         }
 
       String updates = answer.toString();
+      conn.disconnect();
       mUpdates.parse(updates);
 
       if( mUpdatee!=null ) mUpdatee.receiveUpdate(mUpdates);
@@ -635,9 +644,9 @@ public class RubikNetwork
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  private void suspiciousThread()
+  private void suspiciousThread(String suspURL)
     {
-    String url = constructSuspiciousURL();
+    String url = constructSuspiciousURL(suspURL);
 
     try
       {
@@ -651,6 +660,7 @@ public class RubikNetwork
       conn.connect();
       conn.getOutputStream().flush();
       conn.getInputStream();
+      conn.disconnect();
       }
     catch( final Exception e )
       {
@@ -664,14 +674,14 @@ public class RubikNetwork
     {
     try
       {
-      android.util.Log.e("D", "downloading "+url);
-
       java.net.URL connectURL = new URL(url);
       HttpURLConnection conn = (HttpURLConnection) connectURL.openConnection();
       conn.setDoInput(true);
       conn.connect();
       InputStream input = conn.getInputStream();
-      return BitmapFactory.decodeStream(input);
+      Bitmap icon = BitmapFactory.decodeStream(input);
+      conn.disconnect();
+      return icon;
       }
     catch (IOException e)
       {
@@ -683,7 +693,7 @@ public class RubikNetwork
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  private void iconThread()
+  private void iconThread(IconReceiver receiver)
     {
     int numC = mUpdates.getCompletedNumber();
     int numS = mUpdates.getStartedNumber();
@@ -704,7 +714,7 @@ public class RubikNetwork
         if( icon!=null )
           {
           mUpdates.setCompletedIcon(c,icon);
-          mUpdatee.iconDownloaded(c,icon);
+          receiver.iconDownloaded(c,icon);
           }
         }
       }
@@ -725,12 +735,46 @@ public class RubikNetwork
         if( icon!=null )
           {
           mUpdates.setStartedIcon(s,icon);
-          mUpdatee.iconDownloaded(numC+s,icon);
+          receiver.iconDownloaded(numC+s,icon);
           }
         }
       }
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private InputStream downloadJSON(String name)
+    {
+    String url = mUpdates.getURL() + name;
+
+    try
+      {
+      java.net.URL connectURL = new URL(url);
+      HttpURLConnection conn = (HttpURLConnection) connectURL.openConnection();
+      conn.setDoInput(true);
+      conn.connect();
+      InputStream stream = conn.getInputStream();
+      conn.disconnect();
+      return stream;
+      }
+    catch (IOException e)
+      {
+      android.util.Log.e("D", "Failed to download "+url);
+      android.util.Log.e("D", e.getMessage() );
+      return null;
+      }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void jsonThread(final RubikUpdates.UpdateInfo info, Downloadee downloadee)
+    {
+    if(info.mUpdateObject) info.mObjectStream = downloadJSON(info.mObjectShortName+"_object.json");
+    if(info.mUpdateExtras) info.mExtrasStream = downloadJSON(info.mObjectShortName+"_extras.json");
+
+    downloadee.jsonDownloaded();
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   private RubikNetwork()
@@ -761,17 +805,16 @@ public class RubikNetwork
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public void download(Receiver receiver, FragmentActivity act)
+  public void download(final ScoresReceiver receiver, final FragmentActivity act)
     {
     initializeStatics();
-    mReceiver = receiver;
     figureOutVersion(act);
 
     Thread thread = new Thread()
       {
       public void run()
         {
-        downloadThread();
+        downloadThread(receiver);
         }
       };
 
@@ -780,17 +823,16 @@ public class RubikNetwork
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public void submit(Receiver receiver, FragmentActivity act)
+  public void submit(ScoresReceiver receiver, final FragmentActivity act)
     {
     initializeStatics();
-    mReceiver = receiver;
     figureOutVersion(act);
 
     Thread thread = new Thread()
       {
       public void run()
         {
-        submitThread();
+        submitThread(receiver);
         }
       };
 
@@ -817,16 +859,15 @@ public class RubikNetwork
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public void suspicious(String suspicious)
+  public void suspicious(final String suspicious)
     {
     initializeStatics();
-    mSuspicious = suspicious;
 
     Thread thread = new Thread()
       {
       public void run()
         {
-        suspiciousThread();
+        suspiciousThread(suspicious);
         }
       };
 
@@ -852,16 +893,32 @@ public class RubikNetwork
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public void downloadIcons(Updatee updatee)
+  public void downloadIcons(final IconReceiver receiver)
+    {
+    initializeStatics();
+
+    Thread thread = new Thread()
+      {
+      public void run()
+        {
+        iconThread(receiver);
+        }
+      };
+
+    thread.start();
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void downloadJSON(final RubikUpdates.UpdateInfo info, final Downloadee downloadee)
     {
     initializeStatics();
-    mUpdatee = updatee;
 
     Thread thread = new Thread()
       {
       public void run()
         {
-        iconThread();
+        jsonThread(info,downloadee);
         }
       };
 
diff --git a/src/main/java/org/distorted/network/RubikUpdates.java b/src/main/java/org/distorted/network/RubikUpdates.java
index c86689d7..070e6294 100644
--- a/src/main/java/org/distorted/network/RubikUpdates.java
+++ b/src/main/java/org/distorted/network/RubikUpdates.java
@@ -19,6 +19,7 @@
 
 package org.distorted.network;
 
+import java.io.InputStream;
 import java.util.ArrayList;
 import android.graphics.Bitmap;
 import org.distorted.objects.RubikObjectList;
@@ -39,6 +40,8 @@ public class RubikUpdates
     public final boolean mUpdateObject;
     public final boolean mUpdateExtras;
     public Bitmap mIcon;
+    public InputStream mObjectStream;
+    public InputStream mExtrasStream;
 
     public UpdateInfo(String shortName, String longName, String description, int objectMinor,
                       int extrasMinor, int percent, int iconPresent, boolean updateO, boolean updateE)
@@ -237,6 +240,13 @@ public class RubikUpdates
     return info!=null ? mUrl + info.mObjectShortName + ".png" : null;
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public String getURL()
+    {
+    return mUrl;
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public void setCompletedIcon(int ordinal, Bitmap icon)
diff --git a/src/main/java/org/distorted/screens/RubikScreenPlay.java b/src/main/java/org/distorted/screens/RubikScreenPlay.java
index 1b6ae9ec..5708ff4f 100644
--- a/src/main/java/org/distorted/screens/RubikScreenPlay.java
+++ b/src/main/java/org/distorted/screens/RubikScreenPlay.java
@@ -25,7 +25,6 @@ import android.app.Activity;
 import android.content.Context;
 import android.content.SharedPreferences;
 import android.content.res.Resources;
-import android.graphics.Bitmap;
 import android.graphics.drawable.BitmapDrawable;
 import android.os.Build;
 import android.os.Bundle;
@@ -745,11 +744,4 @@ public class RubikScreenPlay extends RubikScreenBase implements RubikNetwork.Upd
     {
     android.util.Log.e("D", "Screen: Error receiving update");
     }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public void iconDownloaded(int ordinal, Bitmap bitmap)
-    {
-    // empty
-    }
   }
diff --git a/src/main/res/values-de/strings.xml b/src/main/res/values-de/strings.xml
index 3fbd569f..a15c40ef 100755
--- a/src/main/res/values-de/strings.xml
+++ b/src/main/res/values-de/strings.xml
@@ -30,6 +30,8 @@
     <string name="new_name_try_again">Der von Ihnen ausgewählte Name %s ist bereits vergeben. Versuchen Sie es noch einmal:</string>
     <string name="downloading">Wird heruntergeladen…</string>
     <string name="submitting">Einreichen…</string>
+    <string name="installing">Installieren…</string>
+    <string name="networkError">Netzwerkfehler</string>
     <string name="view">Sehen</string>
     <string name="level_full">Volles Scramble</string>
 
diff --git a/src/main/res/values-es/strings.xml b/src/main/res/values-es/strings.xml
index 2715ad11..2a3a27ba 100755
--- a/src/main/res/values-es/strings.xml
+++ b/src/main/res/values-es/strings.xml
@@ -30,6 +30,8 @@
     <string name="new_name_try_again">El nombre que has elegido, %s, ya está en uso. Inténtalo de nuevo:</string>
     <string name="downloading">Descargando…</string>
     <string name="submitting">Enviando…</string>
+    <string name="installing">Instalando…</string>
+    <string name="networkError">Error de red</string>
     <string name="view">Ver</string>
     <string name="level_full">Revuelto Completo</string>
 
diff --git a/src/main/res/values-fr/strings.xml b/src/main/res/values-fr/strings.xml
index c6370c1d..582591c5 100755
--- a/src/main/res/values-fr/strings.xml
+++ b/src/main/res/values-fr/strings.xml
@@ -30,6 +30,8 @@
     <string name="new_name_try_again">Le nom que vous avez choisi, %s, est déjà pris. Réessayez :</string>
     <string name="downloading">Téléchargement…</string>
     <string name="submitting">Soumission…</string>
+    <string name="installing">Installation…</string>
+    <string name="networkError">Erreur réseau</string>
     <string name="view">Regarder</string>
     <string name="level_full">Brouillage Complet</string>
 
diff --git a/src/main/res/values-ja/strings.xml b/src/main/res/values-ja/strings.xml
index fa35c6c8..d79f4f40 100755
--- a/src/main/res/values-ja/strings.xml
+++ b/src/main/res/values-ja/strings.xml
@@ -30,6 +30,8 @@
     <string name="new_name_try_again">選択した名前%sは既に使用されています。もう一度トライする：</string>
     <string name="downloading">ダウンロードしています…</string>
     <string name="submitting">送信しています…</string>
+    <string name="installing">インストール…</string>
+    <string name="networkError">ネットワークエラー</string>
     <string name="view">見る</string>
     <string name="level_full">フルスクランブル</string>
 
diff --git a/src/main/res/values-ko/strings.xml b/src/main/res/values-ko/strings.xml
index a6dede10..b6664635 100755
--- a/src/main/res/values-ko/strings.xml
+++ b/src/main/res/values-ko/strings.xml
@@ -30,6 +30,8 @@
     <string name="new_name_try_again">선택한 이름 %s이(가) 이미 사용되었습니다. 다시 시도하십시오:</string>
     <string name="downloading">다운로드 중…</string>
     <string name="submitting">제출 중…</string>
+    <string name="installing">설치 중…</string>
+    <string name="networkError">네트워크 오류</string>
     <string name="view">보다</string>
     <string name="level_full">풀 스크램블</string>
 
diff --git a/src/main/res/values-pl/strings.xml b/src/main/res/values-pl/strings.xml
index d3b29287..d62ddd8c 100644
--- a/src/main/res/values-pl/strings.xml
+++ b/src/main/res/values-pl/strings.xml
@@ -30,6 +30,8 @@
     <string name="new_name_try_again">Imię które wybrałeś, %s, jest zajęte. Spróbuj jeszcze raz:</string>
     <string name="downloading">Ściąganie…</string>
     <string name="submitting">Przesyłanie…</string>
+    <string name="installing">Instalowanie…</string>
+    <string name="networkError">Błąd sieci</string>
     <string name="view">Zobacz</string>
     <string name="level_full">Pełne Pomieszanie</string>
 
diff --git a/src/main/res/values-ru/strings.xml b/src/main/res/values-ru/strings.xml
index 8fdf89cb..7c3c62d8 100755
--- a/src/main/res/values-ru/strings.xml
+++ b/src/main/res/values-ru/strings.xml
@@ -30,6 +30,8 @@
     <string name="new_name_try_again">Выбранное вами имя %s уже занято. Попробуй еще раз:</string>
     <string name="downloading">Загрузка…</string>
     <string name="submitting">Добавляю…</string>
+    <string name="installing">Установка…</string>
+    <string name="networkError">Ошибка сети</string>
     <string name="view">Смотри</string>
     <string name="level_full">Полная Схватка</string>
 
diff --git a/src/main/res/values-zh-rCN/strings.xml b/src/main/res/values-zh-rCN/strings.xml
index c2cf02ee..6de73b20 100644
--- a/src/main/res/values-zh-rCN/strings.xml
+++ b/src/main/res/values-zh-rCN/strings.xml
@@ -30,6 +30,8 @@
     <string name="new_name_try_again">您选择的名称,%s,已被使用。请重试：</string>
     <string name="downloading">正在下载……</string>
     <string name="submitting">正在提交……</string>
+    <string name="installing">安装…</string>
+    <string name="networkError">網絡錯誤</string>
     <string name="view">看</string>
     <string name="level_full">级满</string>
 
diff --git a/src/main/res/values-zh-rTW/strings.xml b/src/main/res/values-zh-rTW/strings.xml
index 08987256..675c8aad 100644
--- a/src/main/res/values-zh-rTW/strings.xml
+++ b/src/main/res/values-zh-rTW/strings.xml
@@ -30,6 +30,8 @@
     <string name="new_name_try_again">您選擇的名稱,%s,已被使用。請重試：</string>
     <string name="downloading">正在下載……</string>
     <string name="submitting">正在傳送……</string>
+    <string name="installing">安裝…</string>
+    <string name="networkError">網絡錯誤</string>
     <string name="view">看</string>
     <string name="level_full">級滿</string>
 
diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml
index 3b1c8b16..36f884b7 100644
--- a/src/main/res/values/strings.xml
+++ b/src/main/res/values/strings.xml
@@ -31,6 +31,8 @@
     <string name="new_name_try_again">The name you have chosen, %s, is already taken. Try again:</string>
     <string name="downloading">Downloading…</string>
     <string name="submitting">Submitting…</string>
+    <string name="installing">Installing…</string>
+    <string name="networkError">Network Error</string>
     <string name="view">View</string>
     <string name="level_full">Full Scramble</string>
 
