├── .gitignore
├── LICENSE
├── MiniVK
├── .gitignore
├── .idea
│ ├── .gitignore
│ ├── .name
│ ├── compiler.xml
│ ├── gradle.xml
│ └── misc.xml
├── app
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ ├── release
│ │ ├── app-release.apk1
│ │ └── output-metadata.json
│ └── src
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ └── com
│ │ │ └── monobogdan
│ │ │ └── minivk
│ │ │ ├── BitmapCache.java
│ │ │ ├── PersistStorage.java
│ │ │ ├── Preferences.java
│ │ │ ├── api
│ │ │ ├── VK.java
│ │ │ └── VKDataSet.java
│ │ │ ├── service
│ │ │ ├── AudioDownloader.java
│ │ │ └── PollService.java
│ │ │ └── ui
│ │ │ ├── AuthActivity.java
│ │ │ ├── ChatActivity.java
│ │ │ ├── DialogsActivity.java
│ │ │ ├── MainMenu.java
│ │ │ ├── MusicActivity.java
│ │ │ ├── UIUtils.java
│ │ │ ├── UserPopupWindow.java
│ │ │ └── VKActivity.java
│ │ └── res
│ │ ├── drawable
│ │ ├── chat.png
│ │ ├── divider.xml
│ │ ├── download.png
│ │ ├── headphone.png
│ │ ├── menu_item.png
│ │ ├── music.png
│ │ ├── search.png
│ │ └── vk.png
│ │ ├── layout
│ │ ├── activity_audio.xml
│ │ ├── activity_auth.xml
│ │ ├── activity_chat.xml
│ │ ├── activity_main.xml
│ │ ├── dialog_search.xml
│ │ ├── frag_audio.xml
│ │ ├── frag_dialog.xml
│ │ ├── frag_menu.xml
│ │ ├── frag_message.xml
│ │ ├── overlay_menu.xml
│ │ ├── popup_profile.xml
│ │ └── test.xml
│ │ └── values
│ │ ├── strings.xml
│ │ └── theme.xml
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
├── MiniVKv2
├── .gitignore
├── .idea
│ ├── .gitignore
│ ├── .name
│ ├── compiler.xml
│ ├── gradle.xml
│ ├── misc.xml
│ └── render.experimental.xml
├── app
│ ├── .gitignore
│ ├── build.gradle
│ ├── jackson-annotations-2.11.1.jar
│ ├── jackson-core-2.11.1.jar
│ ├── jackson-databind-2.11.1.jar
│ └── proguard-rules.pro
├── build.gradle
├── gradle.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
├── README.md
├── TinyYT
├── .gitignore
├── .idea
│ ├── .gitignore
│ ├── .name
│ ├── compiler.xml
│ ├── gradle.xml
│ └── misc.xml
├── app
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ ├── release
│ │ ├── app-release.apk1
│ │ └── output-metadata.json
│ └── src
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ └── com
│ │ │ └── monobogdan
│ │ │ └── miniyt
│ │ │ ├── backend
│ │ │ ├── History.java
│ │ │ ├── VideoDownloader.java
│ │ │ └── YTAPI.java
│ │ │ ├── ui
│ │ │ └── MainActivity.java
│ │ │ └── utils
│ │ │ └── SSLFucker.java
│ │ └── res
│ │ ├── drawable
│ │ ├── history.png
│ │ ├── search.png
│ │ ├── star.png
│ │ ├── trending.png
│ │ └── youtube.png
│ │ ├── layout
│ │ ├── activity_main.xml
│ │ ├── activity_video.xml
│ │ ├── frag_tab.xml
│ │ └── frag_video.xml
│ │ ├── values
│ │ └── strings.xml
│ │ └── xml
│ │ └── network_security_config.xml
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
├── release
└── output-metadata.json
└── vkrelay
├── apirelay.php
└── audiorelay.php
/.gitignore:
--------------------------------------------------------------------------------
1 | # Built application files
2 | *.apk
3 | *.aar
4 | *.ap_
5 | *.aab
6 |
7 | # Files for the ART/Dalvik VM
8 | *.dex
9 |
10 | # Java class files
11 | *.class
12 |
13 | # Generated files
14 | bin/
15 | gen/
16 | out/
17 | # Uncomment the following line in case you need and you don't have the release build type files in your app
18 | # release/
19 |
20 | # Gradle files
21 | .gradle/
22 | build/
23 |
24 | # Local configuration file (sdk path, etc)
25 | local.properties
26 |
27 | # Proguard folder generated by Eclipse
28 | proguard/
29 |
30 | # Log Files
31 | *.log
32 |
33 | # Android Studio Navigation editor temp files
34 | .navigation/
35 |
36 | # Android Studio captures folder
37 | captures/
38 |
39 | # IntelliJ
40 | *.iml
41 | .idea/workspace.xml
42 | .idea/tasks.xml
43 | .idea/gradle.xml
44 | .idea/assetWizardSettings.xml
45 | .idea/dictionaries
46 | .idea/libraries
47 | # Android Studio 3 in .gitignore file.
48 | .idea/caches
49 | .idea/modules.xml
50 | # Comment next line if keeping position of elements in Navigation Editor is relevant for you
51 | .idea/navEditor.xml
52 |
53 | # Keystore files
54 | # Uncomment the following lines if you do not want to check your keystore files in.
55 | #*.jks
56 | #*.keystore
57 |
58 | # External native build folder generated in Android Studio 2.2 and later
59 | .externalNativeBuild
60 | .cxx/
61 |
62 | # Google Services (e.g. APIs or Firebase)
63 | # google-services.json
64 |
65 | # Freeline
66 | freeline.py
67 | freeline/
68 | freeline_project_description.json
69 |
70 | # fastlane
71 | fastlane/report.xml
72 | fastlane/Preview.html
73 | fastlane/screenshots
74 | fastlane/test_output
75 | fastlane/readme.md
76 |
77 | # Version control
78 | vcs.xml
79 |
80 | # lint
81 | lint/intermediates/
82 | lint/generated/
83 | lint/outputs/
84 | lint/tmp/
85 | # lint/reports/
86 |
--------------------------------------------------------------------------------
/MiniVK/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/caches
5 | /.idea/libraries
6 | /.idea/modules.xml
7 | /.idea/workspace.xml
8 | /.idea/navEditor.xml
9 | /.idea/assetWizardSettings.xml
10 | .DS_Store
11 | /build
12 | /captures
13 | .externalNativeBuild
14 | .cxx
15 | local.properties
16 |
--------------------------------------------------------------------------------
/MiniVK/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 |
--------------------------------------------------------------------------------
/MiniVK/.idea/.name:
--------------------------------------------------------------------------------
1 | MiniVK
--------------------------------------------------------------------------------
/MiniVK/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/MiniVK/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
18 |
19 |
--------------------------------------------------------------------------------
/MiniVK/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/MiniVK/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/MiniVK/app/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.android.application'
3 | }
4 |
5 | android {
6 | namespace 'com.monobogdan.minivk'
7 | compileSdk 8
8 | buildToolsVersion '17.0.0'
9 |
10 | defaultConfig {
11 | applicationId "com.monobogdan.minivk"
12 | minSdk 3
13 | //noinspection ExpiredTargetSdkVersion
14 | targetSdk 3
15 | versionCode 11
16 | versionName "1.01"
17 | }
18 |
19 | buildTypes {
20 | debug {
21 | zipAlignEnabled false
22 | }
23 | release {
24 | minifyEnabled false
25 |
26 | }
27 | }
28 | compileOptions {
29 | sourceCompatibility JavaVersion.VERSION_1_8
30 | targetCompatibility JavaVersion.VERSION_1_8
31 | }
32 | }
33 |
34 | dependencies {
35 |
36 | }
--------------------------------------------------------------------------------
/MiniVK/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
--------------------------------------------------------------------------------
/MiniVK/app/release/app-release.apk1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/monobogdan/selfeco/9d4cd71ae0f524f9bc41394197a167cb4bdd5d08/MiniVK/app/release/app-release.apk1
--------------------------------------------------------------------------------
/MiniVK/app/release/output-metadata.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": 3,
3 | "artifactType": {
4 | "type": "APK",
5 | "kind": "Directory"
6 | },
7 | "applicationId": "com.monobogdan.minivk",
8 | "variantName": "release",
9 | "elements": [
10 | {
11 | "type": "SINGLE",
12 | "filters": [],
13 | "attributes": [],
14 | "versionCode": 1,
15 | "versionName": "1.0",
16 | "outputFile": "app-release.apk"
17 | }
18 | ],
19 | "elementType": "File"
20 | }
--------------------------------------------------------------------------------
/MiniVK/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
13 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/MiniVK/app/src/main/java/com/monobogdan/minivk/BitmapCache.java:
--------------------------------------------------------------------------------
1 | package com.monobogdan.minivk;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.graphics.Bitmap;
6 | import android.graphics.BitmapFactory;
7 | import android.net.Uri;
8 | import android.util.Log;
9 |
10 | import java.io.BufferedInputStream;
11 | import java.io.BufferedReader;
12 | import java.io.File;
13 | import java.io.FileOutputStream;
14 | import java.io.InputStream;
15 | import java.io.InputStreamReader;
16 | import java.net.URL;
17 | import java.util.HashMap;
18 | import java.util.WeakHashMap;
19 | import java.util.concurrent.Executor;
20 | import java.util.concurrent.ExecutorService;
21 | import java.util.concurrent.Executors;
22 |
23 | import javax.net.ssl.HttpsURLConnection;
24 |
25 | public class BitmapCache {
26 |
27 | class LifetimedBitmap
28 | {
29 | Bitmap bitmap;
30 | int lifeTime;
31 | }
32 |
33 | private static ExecutorService threadPool;
34 | private static HashMap cache;
35 |
36 | public static interface CacheCallback
37 | {
38 | void success(Bitmap bitmap);
39 | }
40 |
41 | static
42 | {
43 | cache = new HashMap<>();
44 | threadPool = Executors.newSingleThreadExecutor();
45 | }
46 |
47 | public static byte[] downloadBinary(Uri uri)
48 | {
49 | try
50 | {
51 | HttpsURLConnection conn = (HttpsURLConnection) new URL(uri.toString()).openConnection();
52 | conn.setDoInput(true);
53 | conn.setRequestMethod("GET");
54 | conn.connect();
55 |
56 | BufferedInputStream stream = new BufferedInputStream(conn.getInputStream());
57 | byte[] ret = new byte[conn.getContentLength()];
58 |
59 | int ptr = 0;
60 | while(ptr < ret.length)
61 | ptr += stream.read(ret, ptr, ret.length - ptr);
62 |
63 | return ret;
64 | }
65 | catch (Exception e)
66 | {
67 | e.printStackTrace();
68 |
69 | return null;
70 | }
71 | }
72 |
73 | public static void getBitmapFromCache(Context ctx, Uri uri, CacheCallback cb)
74 | {
75 | File cacheDir = ctx.getCacheDir();
76 | File absPath = new File(cacheDir.getAbsolutePath() + "/" + new File(uri.toString()).getName());
77 |
78 | if(absPath.exists()) {
79 | threadPool.submit(new Runnable() {
80 | @Override
81 | public void run() {
82 | Bitmap bmp = null;
83 |
84 | if(cache.containsKey(absPath.getName())) {
85 | bmp = cache.get(absPath.getName());
86 | }
87 | else
88 | {
89 | bmp = BitmapFactory.decodeFile(absPath.getAbsolutePath());
90 | cache.put(absPath.getName(), bmp);
91 | }
92 |
93 | cb.success(bmp);
94 | }
95 | });
96 | }
97 | else
98 | {
99 | threadPool.submit(new Runnable() {
100 | @Override
101 | public void run() {
102 | byte[] data = downloadBinary(uri);
103 |
104 | if(data != null)
105 | {
106 | try {
107 | FileOutputStream strm = new FileOutputStream(absPath.getAbsolutePath());
108 | strm.write(data);
109 | strm.close();
110 |
111 | cb.success(BitmapFactory.decodeByteArray(data, 0, data.length));
112 | }
113 | catch(Exception e)
114 | {
115 | e.printStackTrace();
116 | }
117 | }
118 | }
119 | });
120 | }
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/MiniVK/app/src/main/java/com/monobogdan/minivk/PersistStorage.java:
--------------------------------------------------------------------------------
1 | package com.monobogdan.minivk;
2 |
3 | import android.content.Context;
4 | import android.util.Log;
5 |
6 | import org.json.JSONObject;
7 |
8 | import java.io.BufferedReader;
9 | import java.io.File;
10 | import java.io.FileInputStream;
11 | import java.io.FileOutputStream;
12 | import java.io.InputStreamReader;
13 | import java.io.OutputStreamWriter;
14 |
15 | public class PersistStorage {
16 | private static PersistStorage appInstance;
17 |
18 | private final int PERSIST_VERSION = 100;
19 | private final String TAG = "PersistStorage";
20 | private final String FILENAME = "/minivk.obj";
21 |
22 | public String apiToken;
23 | public String secret;
24 | public String uid;
25 | public String audioToken;
26 |
27 | public static PersistStorage getAppInstance() {
28 | if(appInstance == null)
29 | appInstance = new PersistStorage();
30 |
31 | return appInstance;
32 | }
33 |
34 | private PersistStorage()
35 | {
36 |
37 | }
38 |
39 | public boolean isAuthorized()
40 | {
41 | return apiToken != null && apiToken.length() > 0;
42 | }
43 |
44 | public void load(Context context)
45 | {
46 | File file = new File(context.getFilesDir().getAbsolutePath() + FILENAME);
47 |
48 | try {
49 | BufferedReader strm = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
50 | String json = "";
51 |
52 | while(strm.ready())
53 | json += strm.readLine();
54 | strm.close();
55 |
56 | JSONObject obj = new JSONObject(json);
57 | apiToken = obj.getString("apiToken");
58 | uid = obj.getString("uid");
59 | secret = obj.getString("secret");
60 | audioToken = obj.getString("audioToken");
61 | }
62 | catch(Exception e)
63 | {
64 | Log.i(TAG, "save: Failed to load PersistStorage");
65 | }
66 | }
67 |
68 | public void save(Context context)
69 | {
70 | File file = new File(context.getFilesDir().getAbsolutePath() + FILENAME);
71 |
72 | try {
73 | OutputStreamWriter strm = new OutputStreamWriter(new FileOutputStream(file));
74 |
75 | JSONObject obj = new JSONObject();
76 | obj.put("version", PERSIST_VERSION);
77 | obj.put("apiToken", apiToken);
78 | obj.put("uid", uid);
79 | obj.put("secret", secret);
80 | obj.put("audioToken", audioToken);
81 |
82 | strm.write(obj.toString());
83 | strm.close();
84 | }
85 | catch(Exception e)
86 | {
87 | Log.i(TAG, "save: Failed to save PersistStorage");
88 | }
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/MiniVK/app/src/main/java/com/monobogdan/minivk/Preferences.java:
--------------------------------------------------------------------------------
1 | package com.monobogdan.minivk;
2 |
3 | import android.os.Bundle;
4 | import android.preference.PreferenceActivity;
5 |
6 | public class Preferences extends PreferenceActivity {
7 | @Override
8 | protected void onCreate(Bundle savedInstanceState) {
9 | super.onCreate(savedInstanceState);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/MiniVK/app/src/main/java/com/monobogdan/minivk/api/VK.java:
--------------------------------------------------------------------------------
1 | package com.monobogdan.minivk.api;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.net.ConnectivityManager;
6 | import android.util.Log;
7 | import android.view.inputmethod.InputMethodManager;
8 |
9 | import com.monobogdan.minivk.PersistStorage;
10 |
11 | import org.apache.http.util.EncodingUtils;
12 | import org.json.JSONException;
13 | import org.json.JSONObject;
14 |
15 | import java.io.BufferedReader;
16 | import java.io.InputStreamReader;
17 | import java.io.OutputStreamWriter;
18 | import java.net.HttpURLConnection;
19 | import java.net.URL;
20 | import java.net.URLEncoder;
21 | import java.security.MessageDigest;
22 | import java.util.Random;
23 | import java.util.concurrent.ExecutorService;
24 | import java.util.concurrent.Executors;
25 | import java.util.concurrent.atomic.AtomicBoolean;
26 |
27 | import javax.net.ssl.HostnameVerifier;
28 | import javax.net.ssl.HttpsURLConnection;
29 | import javax.net.ssl.SSLSession;
30 |
31 | public class VK {
32 |
33 | private final String apiUrl = "http://90.156.209.92/apirelay.php";
34 | private final String audioUrl = "http://90.156.209.92/audiorelay.php";
35 | private final String version = "5.131";
36 |
37 | private final String APP_ID = "2274003";
38 | private final String APP_SECRET = "hHbZxrka2uZ6jB1inYsH";
39 |
40 | private Context context;
41 | private ExecutorService threadPool;
42 | private AtomicBoolean jobInProgress;
43 |
44 | final int THREAD_COUNT = 3;
45 |
46 | public interface VKResult
47 | {
48 | void success(JSONObject json);
49 | void failed(String reason);
50 | }
51 |
52 | public interface AuthResult
53 | {
54 | void success();
55 | void error(String desc);
56 | }
57 |
58 | private ConnectivityManager conMan;
59 |
60 | public VK(Context context)
61 | {
62 | this.context = context;
63 | threadPool = Executors.newSingleThreadExecutor();
64 |
65 | jobInProgress = new AtomicBoolean();
66 |
67 | HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
68 | @Override
69 | public boolean verify(String s, SSLSession sslSession) {
70 | return true;
71 | }
72 | });
73 | }
74 |
75 | public boolean isJobInProgress() {
76 | return jobInProgress.get();
77 | }
78 |
79 | public void beginDirectAuthFlow(String login, String password, AuthResult auth, Activity thiz)
80 | {
81 | String fmt = String.format("https://oauth.vk.com/token?grant_type=password&validate_token=true&client_id=%s&client_secret=%s&username=%s&password=%s",
82 | APP_ID, APP_SECRET, URLEncoder.encode(login), URLEncoder.encode(password));
83 |
84 | directRequest(fmt, new VKResult() {
85 | @Override
86 | public void success(JSONObject json) {
87 | try {
88 | if (json.has("access_token")) {
89 | // Grant us access as official app
90 | PersistStorage.getAppInstance().apiToken = json.getString("access_token");
91 |
92 | auth.success();
93 | }
94 | else
95 | auth.error(json.getString("error_description"));
96 | }
97 | catch (JSONException e)
98 | {
99 | auth.error(e.getLocalizedMessage());
100 | }
101 | }
102 |
103 | @Override
104 | public void failed(String reason) {
105 | auth.error(reason);
106 | }
107 | }, thiz);
108 | }
109 |
110 | private String genericRequest(String request)
111 | {
112 | try {
113 | HttpURLConnection conn = (HttpURLConnection) new URL(request).openConnection();
114 | conn.setDoInput(true);
115 | conn.setDoOutput(true);
116 | conn.setRequestProperty("Content-Type", "text/plain");
117 | //conn.setRequestMethod("POST");
118 |
119 | BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
120 | String response = "";
121 | while (reader.ready())
122 | response += reader.readLine();
123 |
124 | return response;
125 | }
126 | catch (Exception e)
127 | {
128 | e.printStackTrace();
129 |
130 | return "";
131 | }
132 | }
133 |
134 | private void directRequest(String url, VKResult handler, Activity thiz)
135 | {
136 | jobInProgress.set(true);
137 | threadPool.submit(new Runnable() {
138 | @Override
139 | public void run() {
140 | try {
141 | HttpURLConnection conn = (HttpURLConnection) new URL(apiUrl).openConnection();
142 | conn.setDoInput(true);
143 | conn.setDoOutput(true);
144 | conn.setRequestMethod("POST");
145 | conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 4.01; Windows NT)");
146 | conn.connect();
147 |
148 | OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream());
149 | writer.write(url);
150 | writer.close();
151 |
152 | BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
153 | String response = "";
154 | String line = "";
155 | while ((line = reader.readLine()) != null)
156 | response += line;
157 |
158 | String finalResponse = response;
159 | Log.i("", "run: " + finalResponse);
160 | JSONObject obj = new JSONObject(finalResponse);
161 |
162 | if(thiz != null)
163 | thiz.runOnUiThread(new Runnable() {
164 | @Override
165 | public void run() {
166 | handler.success(obj);
167 | }
168 | });
169 | else
170 | handler.success(obj);
171 | }
172 | catch (Exception e)
173 | {
174 | e.printStackTrace();
175 | handler.failed(e.getLocalizedMessage());
176 | }
177 |
178 | jobInProgress.set(false);
179 | }
180 | });
181 | }
182 |
183 | public void audioRequest(String request, VKResult handler, Activity thiz)
184 | {
185 | threadPool.submit(new Runnable() {
186 | @Override
187 | public void run() {
188 | String result = genericRequest(audioUrl + "?" + request);
189 |
190 | try
191 | {
192 | handler.success(new JSONObject(result));
193 | }
194 | catch (JSONException e)
195 | {
196 | e.printStackTrace();
197 | handler.failed("Failed to parse JSON");
198 | }
199 | }
200 | });
201 | }
202 |
203 | public void request(String request, VKResult handler, Activity thiz)
204 | {
205 | request = "/method/" + request + "access_token=" + PersistStorage.getAppInstance().apiToken + "&v=" + version;
206 |
207 | try {
208 | /*MessageDigest md5 = MessageDigest.getInstance("md5");
209 | byte[] digest = md5.digest(EncodingUtils.getAsciiBytes( request + PersistStorage.getAppInstance().secret));
210 | String sig = "";
211 |
212 | for(byte b : digest)
213 | {
214 | if(b == 0)
215 | break;
216 |
217 | sig += String.format("%x", b);
218 | }*/
219 |
220 | //Log.i("TAG", "md5: " + sig);
221 | //Log.i("TAG", "request: " + request + PersistStorage.getAppInstance().secret);
222 | directRequest("https://api.vk.com" + request, handler, thiz);
223 | }
224 | catch (Exception e)
225 | {
226 | e.printStackTrace();
227 | }
228 | }
229 |
230 | }
231 |
--------------------------------------------------------------------------------
/MiniVK/app/src/main/java/com/monobogdan/minivk/api/VKDataSet.java:
--------------------------------------------------------------------------------
1 | package com.monobogdan.minivk.api;
2 |
3 | import android.text.format.DateUtils;
4 |
5 | import org.json.JSONArray;
6 | import org.json.JSONException;
7 | import org.json.JSONObject;
8 |
9 | import java.io.File;
10 | import java.text.DateFormat;
11 | import java.util.ArrayList;
12 | import java.util.Collections;
13 | import java.util.Comparator;
14 | import java.util.Date;
15 | import java.util.HashMap;
16 | import java.util.Map;
17 |
18 | public class VKDataSet {
19 |
20 | public static final class Dialog
21 | {
22 | public int id;
23 | public String avatar;
24 | public String name;
25 | public String lastMessage;
26 | public String date;
27 | public int inRead;
28 |
29 | public int lastMessageDate;
30 | }
31 |
32 | public static final class Message
33 | {
34 | public int sender;
35 | public String avatarName;
36 | public String senderReadable;
37 | public String text;
38 | public long date;
39 | public String dateFormatted;
40 | public boolean isRead;
41 |
42 | public boolean hasVoiceAttachment;
43 | public String voiceUrl;
44 |
45 | public boolean hasAttachments;
46 | public ArrayList attachments; // Pictures are meant to be here
47 | }
48 |
49 | public static final class User
50 | {
51 | public String name;
52 | public int id;
53 | public String avatarUrl;
54 | public boolean isOnline;
55 | }
56 |
57 | public static final class Audio
58 | {
59 | public String contentId; // Used also for caching
60 | public String artist;
61 | public String title;
62 | public String duration;
63 | }
64 |
65 | private static Map getUsersFromResponse(JSONArray resp) throws JSONException
66 | {
67 | Map ret = new HashMap<>();
68 |
69 | for(int i = 0; i < resp.length(); i++)
70 | {
71 | JSONObject profile = resp.getJSONObject(i);
72 | User user = new User();
73 |
74 | user.id = profile.getInt("id");
75 | user.avatarUrl = profile.getString("photo_100");
76 | user.isOnline = profile.getInt("online") == 1;
77 | user.name = profile.getString("first_name") + " " + profile.get("last_name");
78 |
79 | ret.put(user.id, user);
80 | }
81 |
82 | return ret;
83 | }
84 |
85 | private static String formatDate(long date)
86 | {
87 | if(DateUtils.isToday(date)) {
88 | return DateFormat.getTimeInstance(DateFormat.SHORT).format(new Date(date * 1000));
89 | }
90 | else
91 | {
92 | return DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT).format(new Date(date * 1000));
93 | }
94 | }
95 |
96 | public static ArrayList fetchMessages(JSONObject obj)
97 | {
98 | try
99 | {
100 | obj = obj.getJSONObject("response");
101 | JSONArray dialogs = obj.getJSONArray("items");
102 |
103 | ArrayList ret = new ArrayList<>();
104 | Map users = getUsersFromResponse(obj.getJSONArray("profiles"));
105 |
106 | for(int i = 0; i < dialogs.length(); i++)
107 | {
108 | JSONObject jmsg = dialogs.getJSONObject(i);
109 | Message message = new Message();
110 |
111 | message.date = jmsg.getLong("date");
112 | message.dateFormatted = formatDate(message.date);
113 | message.text = jmsg.getString("text");
114 | message.sender = jmsg.getInt("from_id");
115 | message.senderReadable = users.get(message.sender).name;
116 | message.avatarName = new File(users.get(message.sender).avatarUrl).getName();
117 |
118 | JSONArray attachments = jmsg.getJSONArray("attachments");
119 |
120 | if(attachments.length() == 1 && attachments.getJSONObject(0).getString("type").equals("audio_message"))
121 | {
122 | message.hasVoiceAttachment = true;
123 | message.voiceUrl = attachments.getJSONObject(0).getJSONObject("audio_message").getString("link_mp3");
124 | }
125 | else
126 | {
127 | message.hasAttachments = attachments.length() > 0;
128 | message.attachments = new ArrayList<>();
129 |
130 | for(int j = 0; j < attachments.length(); j++)
131 | {
132 | JSONObject at = attachments.getJSONObject(j);
133 |
134 | if(at.getString("type").equals("photo")) {
135 | JSONArray sizes = at.getJSONObject("photo").getJSONArray("sizes");
136 | message.attachments.add(sizes.getJSONObject(sizes.length() - 1).getString("url"));
137 | }
138 | }
139 | }
140 |
141 | ret.add(message);
142 | }
143 |
144 | return ret;
145 | }
146 | catch (JSONException e)
147 | {
148 | e.printStackTrace();
149 |
150 | return new ArrayList<>();
151 | }
152 | }
153 |
154 | public static ArrayList