mirror of
https://github.com/ArcaneChat/android.git
synced 2026-07-03 14:05:24 +02:00
Compare commits
483 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6c625d078f | |||
| a69afe11f4 | |||
| 4ff15e433b | |||
| 6c81d03c50 | |||
| 9f0b322249 | |||
| e8831b0dfc | |||
| d6e9ba2ea9 | |||
| 2c8c5a7558 | |||
| d2e76a5e61 | |||
| 2263c24019 | |||
| 19e414e65c | |||
| f5a52c1aa2 | |||
| 1cf5039c81 | |||
| 90a5e39872 | |||
| 30868b107e | |||
| 546d4a3bda | |||
| 33eaf71e5b | |||
| a61e73b91b | |||
| f03a3a9b50 | |||
| e2225be331 | |||
| f1f23a5099 | |||
| db3bcb017c | |||
| ab0ce1393e | |||
| b941b9e21a | |||
| b838e0d69e | |||
| 8459f5552d | |||
| 293d249024 | |||
| 38a39aec17 | |||
| f4fb855cb6 | |||
| 8fa34e8659 | |||
| eb2f2de29c | |||
| 1b2c5a028a | |||
| 4057c08df9 | |||
| 074d2054ec | |||
| cf2ea4cc56 | |||
| cff6b6bba7 | |||
| 595111fb56 | |||
| cfc0485579 | |||
| 7e7d4176f2 | |||
| 8abaa7bc02 | |||
| 714e079b17 | |||
| 6983491586 | |||
| 2cea64ccff | |||
| 0ef81716c5 | |||
| c780ddf081 | |||
| 30b778c4f6 | |||
| 5e0c7553e2 | |||
| b5fe0acd89 | |||
| 01551fe71a | |||
| edd4176890 | |||
| f4f27ac0ae | |||
| aeb297548c | |||
| eb3aa46ff7 | |||
| 05fbf5bdce | |||
| 8a5f05fe2e | |||
| 590841d139 | |||
| 44caf01cae | |||
| db36341251 | |||
| 0a63816ece | |||
| ceb0155f5f | |||
| 723e677b2b | |||
| fab24ee956 | |||
| 94f4c8b302 | |||
| 008a2410a7 | |||
| b43f337af9 | |||
| 21895cf00f | |||
| 721d016d86 | |||
| 89aaa9c072 | |||
| bcb00a9d23 | |||
| 34cd40fdd9 | |||
| c8001cedce | |||
| 880353888b | |||
| 2c67d20233 | |||
| 42c08a4d5b | |||
| 01bf0f3af5 | |||
| e765968c2c | |||
| 3837463e41 | |||
| 545a2ddc24 | |||
| 4f6f0b4685 | |||
| 1d1bad8b3b | |||
| af5769f231 | |||
| 42c6337c4d | |||
| 37a49c9d39 | |||
| 3b2f778114 | |||
| b55cc03f6d | |||
| 2e6eead045 | |||
| e77c3303a1 | |||
| e83c4f315c | |||
| 833c75d874 | |||
| 9688003648 | |||
| a2609d5bbe | |||
| 227f129455 | |||
| 4e683e5b37 | |||
| c5a0a00dd8 | |||
| de0bce163f | |||
| 9dcb58c1ea | |||
| 4729642f87 | |||
| 751cbfa635 | |||
| e40cae149b | |||
| 758dfbaa67 | |||
| 29ec49b806 | |||
| 8afb5595d0 | |||
| 8430e9ddc6 | |||
| 7439fafe2b | |||
| e1655a40bd | |||
| 92fc521d5b | |||
| 023d34f2b6 | |||
| 8fc064a5a4 | |||
| b9a329f416 | |||
| 4997fa7301 | |||
| e267d67d6e | |||
| 83b04a97ef | |||
| 7852c9e9f9 | |||
| 009adc09bc | |||
| 4d3929576d | |||
| 7712def225 | |||
| 9509919431 | |||
| 15cc62f559 | |||
| ae46cbbf5e | |||
| 1664fcdc84 | |||
| 2c45f4af37 | |||
| b3d1747c0b | |||
| 693952d0eb | |||
| 0ad5bd6e48 | |||
| 89c34f89c9 | |||
| 70971a73ad | |||
| 2c5b377712 | |||
| ae4b5a711b | |||
| 252bc52d47 | |||
| 655783db1e | |||
| 10b2af3656 | |||
| 54c3a963a4 | |||
| a7836eaded | |||
| 10fcbdc81d | |||
| b2a5885787 | |||
| 9886a4feb4 | |||
| dcd04f7064 | |||
| 5773ce8b83 | |||
| 0c3eb19de6 | |||
| 5e72e30d58 | |||
| c9d8ad3d4a | |||
| 62bd4f6d9f | |||
| 15e1d55a77 | |||
| 04cab2ee0c | |||
| fd28868ea8 | |||
| 129e6ad487 | |||
| 082f7229f2 | |||
| 1c6001ed92 | |||
| 2ec48ef1e6 | |||
| 04397f3cb0 | |||
| 8697756083 | |||
| 7be5ec589c | |||
| d3fbf529eb | |||
| e47818b5df | |||
| 201c9ebf4c | |||
| 0626192659 | |||
| 0acdd3f885 | |||
| 6f0fd1072d | |||
| d17579b928 | |||
| 090039ec29 | |||
| df8bbcd00a | |||
| fffc77cc82 | |||
| 9ee5af9fd2 | |||
| 5462f3d341 | |||
| 46dca0d212 | |||
| 603572c796 | |||
| db6c2d9d7c | |||
| b6c6375492 | |||
| 3f5255c116 | |||
| 68f3974aa2 | |||
| 2c062d8d51 | |||
| 1097157f69 | |||
| 21784aa951 | |||
| f980f7285a | |||
| 622b6bc786 | |||
| 61fc0485b7 | |||
| be2af9c871 | |||
| 898e4a45e3 | |||
| e47c6406f8 | |||
| 1d0ed83bad | |||
| 404f6ea9da | |||
| 8d75f867fd | |||
| 83f60e6252 | |||
| c4bd6576d8 | |||
| 12df911162 | |||
| f5a37ee185 | |||
| 92d71ad150 | |||
| 8824b30c4a | |||
| 741e281a37 | |||
| 354295ae7a | |||
| 09af0640c7 | |||
| 1485eeecf6 | |||
| 8b78df6a14 | |||
| 686ee6c246 | |||
| ca8114d9af | |||
| b2392c90c2 | |||
| d207fa67e5 | |||
| 2e41fe756a | |||
| d533ea5c37 | |||
| 4365e176d8 | |||
| 486b03e031 | |||
| 1dbf08327c | |||
| 0d15bb3544 | |||
| e3b48206e9 | |||
| a0e364a50f | |||
| 0db3fc55c6 | |||
| 95c3fca389 | |||
| 68a72fb8fd | |||
| 473410ece2 | |||
| 4f760a790a | |||
| ad7ee4428f | |||
| 92cf756ad2 | |||
| 3d746f08ba | |||
| e272459fc9 | |||
| a793ae52f9 | |||
| f2349a9bdd | |||
| 7082798c03 | |||
| f4fc5fae2b | |||
| 5799e43b3a | |||
| f929d6cc31 | |||
| 9f92efc554 | |||
| 3338b83910 | |||
| a4c104431d | |||
| 31ba521244 | |||
| 50dfe15f09 | |||
| 4b06d19787 | |||
| 66d147eb8b | |||
| d2591922a6 | |||
| bcc6f79373 | |||
| 015edd6053 | |||
| bec562bfb2 | |||
| 01a7c93771 | |||
| 502bae625f | |||
| a34d511922 | |||
| e65aa19109 | |||
| 30585b8de4 | |||
| 0bd4234214 | |||
| db4ceb6d68 | |||
| 1612a5d7cd | |||
| f60f4539b5 | |||
| db7c8a9dfc | |||
| 9d1f4266c2 | |||
| 0614c4fc32 | |||
| 58e452b711 | |||
| b478696bed | |||
| f3584d9eaf | |||
| d9998167f4 | |||
| 874e300220 | |||
| 49e4b90cc3 | |||
| f492f2cd71 | |||
| 2800a282ec | |||
| 593e93304c | |||
| 77b6108ca8 | |||
| 90bf2b6b19 | |||
| dd91d52df4 | |||
| de29317fa6 | |||
| 44faee6208 | |||
| 41ccf19e58 | |||
| 05c390980a | |||
| 4446ed0792 | |||
| 11942da0c0 | |||
| 9a0604a1a8 | |||
| 93ca874e61 | |||
| 9ba21c4346 | |||
| c0e7798cad | |||
| 0aea5a2201 | |||
| 63873ec1d5 | |||
| 23f269d4b3 | |||
| 9ebacb23c4 | |||
| d1e83f46d8 | |||
| 5f2dd23a6e | |||
| d29b24e9a6 | |||
| 4f1415e127 | |||
| c604313c09 | |||
| e6bc14a8de | |||
| 4a5729d371 | |||
| d9ac76a317 | |||
| 867df35d44 | |||
| e946d61b92 | |||
| fa2ffbd70f | |||
| 1123f03134 | |||
| 49e86d08bf | |||
| 5f00826e65 | |||
| 82382f31f1 | |||
| 833cbf7302 | |||
| 4e329adaca | |||
| dbc9e4c3c2 | |||
| d9cff40fd5 | |||
| ef248712d6 | |||
| 9765ba1bac | |||
| afcccaa864 | |||
| 7caef2ceb9 | |||
| cb4480ad78 | |||
| 6388349c16 | |||
| 73a111aeac | |||
| 5869bdc9dd | |||
| ff7f75abed | |||
| 28ac3bd9eb | |||
| 49f07874f8 | |||
| 59779b7f2a | |||
| 677df359ae | |||
| 4e4aca675f | |||
| 76163e6012 | |||
| 85b319825d | |||
| 8edf8a6140 | |||
| acba74142c | |||
| c06f34923e | |||
| bb00342b5d | |||
| 25b43986d3 | |||
| 9b5984182f | |||
| ae9dfb1595 | |||
| 001a4a8675 | |||
| 13a1e92321 | |||
| fb97c8edaf | |||
| ffce59ea7e | |||
| dd7ef2d744 | |||
| a76f840368 | |||
| c4bac7359b | |||
| 67e028502d | |||
| e05b31a76b | |||
| d1b95e369d | |||
| 64a71f25f2 | |||
| 76e906579b | |||
| 23dc66622b | |||
| 997bbd336c | |||
| d8a0225b1a | |||
| ce656ca374 | |||
| dd202b4c72 | |||
| 522ff32432 | |||
| a96cb520dd | |||
| fe9cd52312 | |||
| d4355ad076 | |||
| 057d0eb39e | |||
| 82f35621e2 | |||
| 633856b350 | |||
| 1c0c9004c6 | |||
| 833533adc3 | |||
| 846df6a164 | |||
| f5de9e8a23 | |||
| 404a0ca032 | |||
| 6e8612172b | |||
| aed9e39287 | |||
| 597100d9e3 | |||
| b2775e0811 | |||
| 2425f0dcc7 | |||
| ede60340f6 | |||
| a9d58ab3f3 | |||
| 6d6b6f41c9 | |||
| f5f97e4bfc | |||
| c7ed50a225 | |||
| f843c531b4 | |||
| 2389a7d136 | |||
| e1d0306a29 | |||
| 04cbe3f825 | |||
| 9796ac1c53 | |||
| 5721b9f86d | |||
| aa090a9cd4 | |||
| 03c30bef47 | |||
| c59453f31b | |||
| 49e7f19cb7 | |||
| 469c56f1a6 | |||
| 239c56e77d | |||
| e32ca20604 | |||
| d00ef0af32 | |||
| e616e57be6 | |||
| 5485db8509 | |||
| df75d2917f | |||
| 0478ea5162 | |||
| 433e90072f | |||
| 5c646ea663 | |||
| e095d3f886 | |||
| 9a6315d0b2 | |||
| 8e81f0bb8f | |||
| d6bdebc865 | |||
| 7ddf368fd1 | |||
| 301c6a4430 | |||
| adaf91e383 | |||
| 40de9dfe98 | |||
| 18a8e2358c | |||
| e2a4008742 | |||
| 258633b672 | |||
| 96cc35b84d | |||
| 787efa3c5d | |||
| 848862ae84 | |||
| 6d3c170e96 | |||
| a921523014 | |||
| 29e5133c63 | |||
| 8d4aebe8e7 | |||
| c0139b1b49 | |||
| 920d55ee6d | |||
| 4348b80b02 | |||
| 1a62ed853b | |||
| f858cc7747 | |||
| 394b439a06 | |||
| b515660bac | |||
| 88719df0af | |||
| 495dfa0f59 | |||
| f7372819a1 | |||
| 9d622ecef7 | |||
| 221004354e | |||
| 442baa6aa9 | |||
| 2e4f748093 | |||
| 56a846ab3b | |||
| f67e24b49e | |||
| f40a3e49cb | |||
| 04b815bb49 | |||
| 3292979696 | |||
| 3e24ca9be1 | |||
| 38e5350219 | |||
| 39d5c40945 | |||
| ebcb132acf | |||
| 53447c793a | |||
| 54a2df818b | |||
| 09a3b3bd26 | |||
| f02d4cd21a | |||
| eb650ff089 | |||
| da263b1e56 | |||
| 44ee4aaef7 | |||
| 56874bd418 | |||
| bf1594fdef | |||
| e31821cf92 | |||
| 4efe3b4387 | |||
| 69d0537425 | |||
| 0852e09815 | |||
| 2fc8799241 | |||
| ea01205421 | |||
| 1ad31aa178 | |||
| 349b943a7e | |||
| 268006d027 | |||
| e2bad18153 | |||
| 4749ddf9a8 | |||
| de1c568714 | |||
| 0b90e66ad8 | |||
| 90fe75a764 | |||
| c27fd27789 | |||
| 5580f5ae62 | |||
| d4e94b2fbc | |||
| bb673dd992 | |||
| 2dfacc4858 | |||
| cce4e31b0f | |||
| 99615999b8 | |||
| cfca25d65d | |||
| 665a2cdfd0 | |||
| a2768728d3 | |||
| 2790082705 | |||
| ae8a15d524 | |||
| e39d7b5d4d | |||
| 1ae26ecfa5 | |||
| 1e58912226 | |||
| 87807db64a | |||
| 6221c97283 | |||
| 80226717b6 | |||
| 959f7af2ab | |||
| 2308990661 | |||
| 9f304f372a | |||
| 341580191f | |||
| 07065676f2 | |||
| 47c9dc6e31 | |||
| 2514494d02 | |||
| 1c28c2d475 | |||
| 41a92d56c4 | |||
| 6a6b024314 | |||
| 12c95971a2 | |||
| 62ca3b6331 | |||
| c69f2fd75d | |||
| 0fc45bc57a | |||
| 0b9614f0bd | |||
| e8a073a42c | |||
| 97b33ec9c4 | |||
| f6458870ae | |||
| 665f24db1e | |||
| a59be9d2af | |||
| 1036139cb7 | |||
| f1854e46be | |||
| bfad3e57c7 | |||
| 24ee24325b | |||
| c9f6db312f | |||
| 6f60ba113e | |||
| db112b226e | |||
| a87049e443 | |||
| 730b018b45 | |||
| 60e72f14d8 | |||
| e89b2855ce |
@@ -6,3 +6,6 @@ obj/
|
||||
local.properties
|
||||
*.keystore
|
||||
libs/
|
||||
|
||||
# ignore private scripts and directories, eg. local2github.prv.sh
|
||||
*.prv*
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
[submodule "MessengerProj/jni/messenger-backend"]
|
||||
path = MessengerProj/jni/messenger-backend
|
||||
url = https://github.com/r10s/messenger-backend.git
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
# Delta Chat Changelog
|
||||
|
||||
## v0.1.28
|
||||
2017-04-14
|
||||
|
||||
* Pimp notifications
|
||||
* Bug fixes
|
||||
|
||||
## v0.1.27
|
||||
2017-04-12
|
||||
|
||||
* Use a permanent foreground service for reliable notifications
|
||||
* Monitor the IMAP-IDLE thread and reconnect if IMAP-IDLE seems to hang
|
||||
* Various battery and background optimizations
|
||||
|
||||
## v0.1.25
|
||||
2017-04-04
|
||||
|
||||
* Use system or user selected video player.
|
||||
* Do not connect if not configured (avoids a warning on the first time startup)
|
||||
* Add vertical scrollbar, eg. to settings activities.
|
||||
* Pimp GUI and logo.
|
||||
* Update Korean.
|
||||
|
||||
## v0.1.24
|
||||
2017-03-31
|
||||
|
||||
* Share images and documents from other apps to Delta Chat
|
||||
* Offer to mailto:-link-support to other apps
|
||||
* Ignore implausible sending time of incoming messages; use the receive time in these rare cases
|
||||
* Show errors only when Delta Chat is in foreground
|
||||
* Dynamically adapt video bitrate for longer videos to an attachment-size of max. 25 MB
|
||||
|
||||
## v0.1.23
|
||||
2017-03-28
|
||||
|
||||
* Retry connecting to IMAP if there is not network available on the first try
|
||||
* Notify about new messages if the app is not active for hours, optimize battery consumption
|
||||
|
||||
## v0.1.22
|
||||
2017-03-22
|
||||
|
||||
* Show HTML-only messages
|
||||
* Show connection errors
|
||||
* Add options for SSL/TLS and STARTTLS
|
||||
* Automatic account configuration, if possible
|
||||
* Recode large videos
|
||||
* Add Hungarian translation
|
||||
* Add Korean translation
|
||||
|
||||
## v0.1.21
|
||||
2017-03-10
|
||||
|
||||
* Record and send voice messages
|
||||
* Record and send videos
|
||||
* Send and play music
|
||||
* Send contacts and email addresses
|
||||
* Sending and opening attachments of any type
|
||||
* Share and open commands for all attachments
|
||||
* Accept VCards send to us by other apps
|
||||
* Clickable email addresses
|
||||
* Update Polish translation
|
||||
* Fix tablet startup bug
|
||||
* Close the app when using the lock-app-via-pincode function
|
||||
* Protect data by using a content provider for sharing
|
||||
* Try to clear the task switcher's screenshots when locking the app via pincode
|
||||
* Pimp GUI
|
||||
|
||||
## v0.1.20
|
||||
2017-02-16
|
||||
|
||||
* Avoid unwanted downloads of lots of old messages
|
||||
* Make the "Chats" folder visible if the server hides new folders by default
|
||||
* Fix a crash when the server returns empty folders
|
||||
* Update Polish and Portuguese translations
|
||||
* Use API level 25 (Nougat 7.1) as target
|
||||
|
||||
## v0.1.18
|
||||
2017-02-11
|
||||
|
||||
* Add Polish translation
|
||||
* Use a new default background for chats
|
||||
* Improve typography by using the system font instead of a custom resource font
|
||||
* Remove custom plural handling, use Android's routines instead
|
||||
* Remove unused source code and strings
|
||||
* More fixes of lint errors and warnings
|
||||
|
||||
## v0.1.17
|
||||
2017-02-07
|
||||
|
||||
* Drop two unnecessary permissions: ACCESS_COARSE_LOCATION and ACCESS_FINE_LOCATION
|
||||
* Really add French translation
|
||||
* Update Portuguese translation
|
||||
* Start fixing translation handling of the program
|
||||
* Remove special "foss" build, because the whole program is free now.
|
||||
|
||||
## v0.1.16
|
||||
2017-02-06
|
||||
|
||||
* Add French translation
|
||||
* Fix some lint errors and warnings
|
||||
|
||||
## v0.1.15
|
||||
2017-01-31
|
||||
|
||||
* Prepare for release on [F-Droid](https://f-droid.org/)
|
||||
+13
-26
@@ -24,15 +24,15 @@ tasks.withType(JavaCompile) {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile 'com.android.support:support-v4:23.4.0'
|
||||
compile 'com.android.support:appcompat-v7:25.1.1'
|
||||
compile 'com.googlecode.mp4parser:isoparser:1.0.6'
|
||||
compile 'com.amulyakhare:com.amulyakhare.textdrawable:1.0.1'
|
||||
compile fileTree(dir: "$buildDir/native-libs", include: 'native-libs.jar')
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 23
|
||||
buildToolsVersion '23.0.3'
|
||||
compileSdkVersion 25
|
||||
buildToolsVersion '25.0.2'
|
||||
|
||||
useLibrary 'org.apache.http.legacy'
|
||||
defaultConfig.applicationId = "com.b44t.messenger"
|
||||
@@ -42,6 +42,10 @@ android {
|
||||
targetCompatibility JavaVersion.VERSION_1_7
|
||||
}
|
||||
|
||||
lintOptions {
|
||||
abortOnError false
|
||||
}
|
||||
|
||||
signingConfigs {
|
||||
debug {
|
||||
storeFile file("config/debug.keystore")
|
||||
@@ -70,34 +74,17 @@ android {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
|
||||
foss {
|
||||
debuggable false
|
||||
jniDebuggable false
|
||||
signingConfig signingConfigs.release
|
||||
}
|
||||
}
|
||||
|
||||
defaultConfig.versionCode = 13
|
||||
defaultConfig.versionCode = 28
|
||||
|
||||
sourceSets.main {
|
||||
jniLibs.srcDir 'libs'
|
||||
jni.srcDirs = [] //disable automatic ndk-build call
|
||||
}
|
||||
|
||||
sourceSets.debug {
|
||||
manifest.srcFile 'config/debug/AndroidManifest.xml'
|
||||
}
|
||||
|
||||
sourceSets.release {
|
||||
manifest.srcFile 'config/release/AndroidManifest.xml'
|
||||
}
|
||||
|
||||
sourceSets.foss {
|
||||
manifest.srcFile 'config/foss/AndroidManifest.xml'
|
||||
}
|
||||
|
||||
productFlavors {
|
||||
/*
|
||||
x86 {
|
||||
ndk {
|
||||
abiFilter "x86"
|
||||
@@ -116,6 +103,7 @@ android {
|
||||
}
|
||||
versionCode = 1
|
||||
}
|
||||
*/
|
||||
fat {
|
||||
versionCode = 3
|
||||
}
|
||||
@@ -127,9 +115,8 @@ android {
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 14 // 14: Android 4.0 Ice Cream Sandwich 2011 (Telegram default), 21: Android 5.0 Lollipop 2014 (recommended for InstantRun)
|
||||
targetSdkVersion 23
|
||||
versionName "0.1.4"
|
||||
minSdkVersion 14 // 14: Android 4.0 Ice Cream Sandwich 2011 (Telegram default), 21: Android 5.0 Lollipop 2014 (recommended for InstantRun)
|
||||
targetSdkVersion 25 // 25: Nougat. CAVE: Do NOT target "Andoid O" without checking the background tasks carefully, see https://developer.android.com/preview/behavior-changes.html#back-all . As long as we target "Nougat", everything works as expected even for "Andoid O" or later
|
||||
versionName "0.1.28" // do NOT forget to increase defaultConfig.versionCode!
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="com.b44t.messenger"
|
||||
android:installLocation="auto">
|
||||
|
||||
<uses-feature android:name="android.hardware.location.gps" android:required="false" />
|
||||
<uses-feature android:name="android.hardware.location.network" android:required="false" />
|
||||
<uses-feature android:name="android.hardware.location" android:required="false" />
|
||||
<uses-feature android:name="android.hardware.LOCATION" android:required="false" />
|
||||
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<application
|
||||
android:allowBackup="false"
|
||||
android:icon="@drawable/ic_launcher"
|
||||
android:label="@string/AppNameBeta"
|
||||
android:theme="@style/Theme.MessengerProj.Start"
|
||||
android:name=".ApplicationLoader"
|
||||
android:hardwareAccelerated="@bool/useHardwareAcceleration"
|
||||
android:largeHeap="true">
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -1,17 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.b44t.messenger"
|
||||
android:installLocation="auto">
|
||||
|
||||
<application
|
||||
android:allowBackup="false"
|
||||
android:icon="@drawable/ic_launcher"
|
||||
android:label="@string/AppName"
|
||||
android:theme="@style/Theme.MessengerProj.Start"
|
||||
android:name=".ApplicationLoader"
|
||||
android:hardwareAccelerated="@bool/useHardwareAcceleration"
|
||||
android:largeHeap="true">
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -1,24 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="com.b44t.messenger"
|
||||
android:installLocation="auto">
|
||||
|
||||
<uses-feature android:name="android.hardware.location.gps" android:required="false" />
|
||||
<uses-feature android:name="android.hardware.location.network" android:required="false" />
|
||||
<uses-feature android:name="android.hardware.location" android:required="false" />
|
||||
<uses-feature android:name="android.hardware.LOCATION" android:required="false" />
|
||||
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<application
|
||||
android:allowBackup="false"
|
||||
android:icon="@drawable/ic_launcher"
|
||||
android:label="@string/AppName"
|
||||
android:theme="@style/Theme.MessengerProj.Start"
|
||||
android:name=".ApplicationLoader"
|
||||
android:hardwareAccelerated="@bool/useHardwareAcceleration"
|
||||
android:largeHeap="true">
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -1598,30 +1598,33 @@ ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
|
||||
endif
|
||||
|
||||
LOCAL_SRC_FILES += \
|
||||
./jni.c \
|
||||
./mrjnimain.c \
|
||||
./audio.c \
|
||||
./utils.c \
|
||||
./image.c \
|
||||
./video.c \
|
||||
./gifvideo.cpp \
|
||||
../../../messenger-backend/src/mrchat.c \
|
||||
../../../messenger-backend/src/mrchatlist.c \
|
||||
../../../messenger-backend/src/mrcontact.c \
|
||||
../../../messenger-backend/src/mrimap.c \
|
||||
../../../messenger-backend/src/mrjob.c \
|
||||
../../../messenger-backend/src/mrlog.c \
|
||||
../../../messenger-backend/src/mrloginparam.c \
|
||||
../../../messenger-backend/src/mrmailbox.c \
|
||||
../../../messenger-backend/src/mrmimeparser.c \
|
||||
../../../messenger-backend/src/mrmsg.c \
|
||||
../../../messenger-backend/src/mrosnative.c \
|
||||
../../../messenger-backend/src/mrparam.c \
|
||||
../../../messenger-backend/src/mrpoortext.c \
|
||||
../../../messenger-backend/src/mrsimplify.c \
|
||||
../../../messenger-backend/src/mrsmtp.c \
|
||||
../../../messenger-backend/src/mrsqlite3.c \
|
||||
../../../messenger-backend/src/mrstock.c \
|
||||
../../../messenger-backend/src/mrtools.c \
|
||||
./messenger-backend/src/mrchat.c \
|
||||
./messenger-backend/src/mrchatlist.c \
|
||||
./messenger-backend/src/mrcmdline.c \
|
||||
./messenger-backend/src/mrcontact.c \
|
||||
./messenger-backend/src/mre2ee.c \
|
||||
./messenger-backend/src/mrimap.c \
|
||||
./messenger-backend/src/mrjob.c \
|
||||
./messenger-backend/src/mrloginparam.c \
|
||||
./messenger-backend/src/mrmailbox.c \
|
||||
./messenger-backend/src/mrmailbox_configure.c \
|
||||
./messenger-backend/src/mrmailbox_log.c \
|
||||
./messenger-backend/src/mrmimeparser.c \
|
||||
./messenger-backend/src/mrmsg.c \
|
||||
./messenger-backend/src/mrosnative.c \
|
||||
./messenger-backend/src/mrparam.c \
|
||||
./messenger-backend/src/mrpoortext.c \
|
||||
./messenger-backend/src/mrsaxparser.c \
|
||||
./messenger-backend/src/mrsimplify.c \
|
||||
./messenger-backend/src/mrsmtp.c \
|
||||
./messenger-backend/src/mrsqlite3.c \
|
||||
./messenger-backend/src/mrstock.c \
|
||||
./messenger-backend/src/mrtools.c \
|
||||
./mrwrapper.c
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
+64
-40
@@ -1,3 +1,26 @@
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Messenger Android Frontend
|
||||
* (C) 2013-2016 Nikolai Kudashov
|
||||
* (C) 2017 Björn Petersen
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see http://www.gnu.org/licenses/ .
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
#include <jni.h>
|
||||
#include <ogg/ogg.h>
|
||||
#include <stdio.h>
|
||||
@@ -6,7 +29,7 @@
|
||||
#include <time.h>
|
||||
#include <opusfile.h>
|
||||
#include <math.h>
|
||||
#include "utils.h"
|
||||
#include "mrjnimain.h"
|
||||
|
||||
typedef struct {
|
||||
int version;
|
||||
@@ -115,7 +138,7 @@ static int read_chars(ROPacket *p, unsigned char *str, int nb_chars)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int opus_header_to_packet(const OpusHeader *h, unsigned char *packet, int len) {
|
||||
static int opus_header_to_packet(const OpusHeader *h, unsigned char *packet, int len) {
|
||||
int i;
|
||||
Packet p;
|
||||
unsigned char ch;
|
||||
@@ -219,34 +242,34 @@ static int writeOggPage(ogg_page *page, FILE *os) {
|
||||
return written;
|
||||
}
|
||||
|
||||
const opus_int32 bitrate = 16000;
|
||||
const opus_int32 rate = 16000;
|
||||
const opus_int32 frame_size = 960;
|
||||
const int with_cvbr = 1;
|
||||
const int max_ogg_delay = 0;
|
||||
const int comment_padding = 512;
|
||||
static const opus_int32 bitrate = 16000;
|
||||
static const opus_int32 rate = 16000;
|
||||
static const opus_int32 frame_size = 960;
|
||||
static const int with_cvbr = 1;
|
||||
static const int max_ogg_delay = 0;
|
||||
static const int comment_padding = 512;
|
||||
|
||||
opus_int32 coding_rate = 16000;
|
||||
ogg_int32_t _packetId;
|
||||
OpusEncoder *_encoder = 0;
|
||||
uint8_t *_packet = 0;
|
||||
ogg_stream_state os;
|
||||
FILE *_fileOs = 0;
|
||||
oe_enc_opt inopt;
|
||||
OpusHeader header;
|
||||
opus_int32 min_bytes;
|
||||
int max_frame_bytes;
|
||||
ogg_packet op;
|
||||
ogg_page og;
|
||||
opus_int64 bytes_written;
|
||||
opus_int64 pages_out;
|
||||
opus_int64 total_samples;
|
||||
ogg_int64_t enc_granulepos;
|
||||
ogg_int64_t last_granulepos;
|
||||
int size_segments;
|
||||
int last_segments;
|
||||
static opus_int32 coding_rate = 16000;
|
||||
static ogg_int32_t _packetId;
|
||||
static OpusEncoder *_encoder = 0;
|
||||
static uint8_t *_packet = 0;
|
||||
static ogg_stream_state os;
|
||||
static FILE *_fileOs = 0;
|
||||
static oe_enc_opt inopt;
|
||||
static OpusHeader header;
|
||||
static opus_int32 min_bytes;
|
||||
static int max_frame_bytes;
|
||||
static ogg_packet op;
|
||||
static ogg_page og;
|
||||
static opus_int64 bytes_written;
|
||||
static opus_int64 pages_out;
|
||||
static opus_int64 total_samples;
|
||||
static ogg_int64_t enc_granulepos;
|
||||
static ogg_int64_t last_granulepos;
|
||||
static int size_segments;
|
||||
static int last_segments;
|
||||
|
||||
void cleanupRecorder() {
|
||||
static void cleanupRecorder() {
|
||||
|
||||
ogg_stream_flush(&os, &og);
|
||||
|
||||
@@ -282,7 +305,7 @@ void cleanupRecorder() {
|
||||
memset(&og, 0, sizeof(ogg_page));
|
||||
}
|
||||
|
||||
int initRecorder(const char *path) {
|
||||
static int initRecorder(const char *path) {
|
||||
cleanupRecorder();
|
||||
|
||||
if (!path) {
|
||||
@@ -421,7 +444,7 @@ int initRecorder(const char *path) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int writeFrame(uint8_t *framePcmBytes, unsigned int frameByteCount) {
|
||||
static int writeFrame(uint8_t *framePcmBytes, unsigned int frameByteCount) {
|
||||
int cur_frame_size = frame_size;
|
||||
_packetId++;
|
||||
|
||||
@@ -527,15 +550,15 @@ JNIEXPORT void Java_com_b44t_messenger_MediaController_stopRecord(JNIEnv *env, j
|
||||
}
|
||||
|
||||
//player
|
||||
OggOpusFile *_opusFile;
|
||||
int _isSeekable = 0;
|
||||
int64_t _totalPcmDuration = 0;
|
||||
int64_t _currentPcmOffset = 0;
|
||||
int _finished = 0;
|
||||
static OggOpusFile *_opusFile;
|
||||
static int _isSeekable = 0;
|
||||
static int64_t _totalPcmDuration = 0;
|
||||
static int64_t _currentPcmOffset = 0;
|
||||
static int _finished = 0;
|
||||
static const int playerBuffersCount = 3;
|
||||
static const int playerSampleRate = 48000;
|
||||
|
||||
void cleanupPlayer() {
|
||||
static void cleanupPlayer() {
|
||||
if (_opusFile) {
|
||||
op_free(_opusFile);
|
||||
_opusFile = 0;
|
||||
@@ -546,7 +569,7 @@ void cleanupPlayer() {
|
||||
_finished = 0;
|
||||
}
|
||||
|
||||
int seekPlayer(float position) {
|
||||
static int seekPlayer(float position) {
|
||||
if (!_opusFile || !_isSeekable || position < 0) {
|
||||
return 0;
|
||||
}
|
||||
@@ -559,7 +582,7 @@ int seekPlayer(float position) {
|
||||
return result == OPUS_OK;
|
||||
}
|
||||
|
||||
int initPlayer(const char *path) {
|
||||
static int initPlayer(const char *path) {
|
||||
cleanupPlayer();
|
||||
|
||||
int openError = OPUS_OK;
|
||||
@@ -576,7 +599,7 @@ int initPlayer(const char *path) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
void fillBuffer(uint8_t *buffer, int capacity, int *args) {
|
||||
static void fillBuffer(uint8_t *buffer, int capacity, int *args) {
|
||||
if (_opusFile) {
|
||||
args[1] = max(0, op_pcm_tell(_opusFile));
|
||||
|
||||
@@ -735,7 +758,7 @@ JNIEXPORT jbyteArray Java_com_b44t_messenger_MediaController_getWaveform2(JNIEnv
|
||||
return result;
|
||||
}
|
||||
|
||||
int16_t *sampleBuffer = NULL;
|
||||
static int16_t *sampleBuffer = NULL;
|
||||
|
||||
|
||||
JNIEXPORT jbyteArray Java_com_b44t_messenger_MediaController_getWaveform(JNIEnv *env, jclass class, jstring path) {
|
||||
@@ -819,3 +842,4 @@ JNIEXPORT jbyteArray Java_com_b44t_messenger_MediaController_getWaveform(JNIEnv
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,28 @@
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Messenger Android Frontend
|
||||
* (C) 2013-2016 Nikolai Kudashov
|
||||
* (C) 2017 Björn Petersen
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see http://www.gnu.org/licenses/ .
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
#include <jni.h>
|
||||
#include <utils.h>
|
||||
#include "mrjnimain.h"
|
||||
#include <libyuv.h>
|
||||
#include <android/bitmap.h>
|
||||
#include <cstdint>
|
||||
@@ -53,19 +76,14 @@ typedef struct VideoInfo {
|
||||
AVPacket orig_pkt;
|
||||
};
|
||||
|
||||
jobject makeGlobarRef(JNIEnv *env, jobject object) {
|
||||
if (object) {
|
||||
return env->NewGlobalRef(object);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gifvideoOnJNILoad(JavaVM *vm, JNIEnv *env) {
|
||||
int gifvideoOnJNILoad(JavaVM *vm, JNIEnv *env) { /* called from JNI_OnLoad() */
|
||||
av_register_all();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int open_codec_context(int *stream_idx, AVFormatContext *fmt_ctx, enum AVMediaType type) {
|
||||
|
||||
static int open_codec_context(int *stream_idx, AVFormatContext *fmt_ctx, enum AVMediaType type) {
|
||||
int ret;
|
||||
AVStream *st;
|
||||
AVCodecContext *dec_ctx = NULL;
|
||||
@@ -97,7 +115,7 @@ int open_codec_context(int *stream_idx, AVFormatContext *fmt_ctx, enum AVMediaTy
|
||||
return 0;
|
||||
}
|
||||
|
||||
int decode_packet(VideoInfo *info, int *got_frame) {
|
||||
static int decode_packet(VideoInfo *info, int *got_frame) {
|
||||
int ret = 0;
|
||||
int decoded = info->pkt.size;
|
||||
|
||||
@@ -263,4 +281,5 @@ jint Java_com_b44t_ui_Components_AnimatedFileDrawable_getVideoFrame(JNIEnv *env,
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
} /* extern "C" */
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Messenger Android Frontend
|
||||
* (C) 2013-2016 Nikolai Kudashov
|
||||
* (C) 2017 Björn Petersen
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see http://www.gnu.org/licenses/ .
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
#ifndef __GIFVIDEO_H__
|
||||
#define __GIFVIDEO_H__
|
||||
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
int gifvideoOnJNILoad(JavaVM *vm, JNIEnv *env);
|
||||
|
||||
|
||||
#endif /* __GIFVIDEO_H__ */
|
||||
+52
-15
@@ -1,3 +1,26 @@
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Messenger Android Frontend
|
||||
* (C) 2013-2016 Nikolai Kudashov
|
||||
* (C) 2017 Björn Petersen
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see http://www.gnu.org/licenses/ .
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
#include <jni.h>
|
||||
#include <stdio.h>
|
||||
#include <setjmp.h>
|
||||
@@ -5,21 +28,35 @@
|
||||
#include <android/bitmap.h>
|
||||
#include <libwebp/webp/decode.h>
|
||||
#include <libwebp/webp/encode.h>
|
||||
#include "utils.h"
|
||||
#include "mrjnimain.h"
|
||||
#include "image.h"
|
||||
|
||||
jclass jclass_NullPointerException;
|
||||
jclass jclass_RuntimeException;
|
||||
|
||||
jclass jclass_Options;
|
||||
jfieldID jclass_Options_inJustDecodeBounds;
|
||||
jfieldID jclass_Options_outHeight;
|
||||
jfieldID jclass_Options_outWidth;
|
||||
static jclass jclass_NullPointerException;
|
||||
static jclass jclass_RuntimeException;
|
||||
|
||||
const uint32_t PGPhotoEnhanceHistogramBins = 256;
|
||||
const uint32_t PGPhotoEnhanceSegments = 4;
|
||||
static jclass jclass_Options;
|
||||
static jfieldID jclass_Options_inJustDecodeBounds;
|
||||
static jfieldID jclass_Options_outHeight;
|
||||
static jfieldID jclass_Options_outWidth;
|
||||
|
||||
jclass createGlobarRef(JNIEnv *env, jclass class) {
|
||||
static const uint32_t PGPhotoEnhanceHistogramBins = 256;
|
||||
static const uint32_t PGPhotoEnhanceSegments = 4;
|
||||
|
||||
static void throwException(JNIEnv *env, char *format, ...) {
|
||||
jclass exClass = (*env)->FindClass(env, "java/lang/UnsupportedOperationException");
|
||||
if (!exClass) {
|
||||
return;
|
||||
}
|
||||
char dest[256];
|
||||
va_list argptr;
|
||||
va_start(argptr, format);
|
||||
vsprintf(dest, format, argptr);
|
||||
va_end(argptr);
|
||||
(*env)->ThrowNew(env, exClass, dest);
|
||||
}
|
||||
|
||||
static jclass createGlobalRef(JNIEnv *env, jclass class) {
|
||||
if (class) {
|
||||
return (*env)->NewGlobalRef(env, class);
|
||||
}
|
||||
@@ -27,16 +64,16 @@ jclass createGlobarRef(JNIEnv *env, jclass class) {
|
||||
}
|
||||
|
||||
jint imageOnJNILoad(JavaVM *vm, void *reserved, JNIEnv *env) {
|
||||
jclass_NullPointerException = createGlobarRef(env, (*env)->FindClass(env, "java/lang/NullPointerException"));
|
||||
jclass_NullPointerException = createGlobalRef(env, (*env)->FindClass(env, "java/lang/NullPointerException"));
|
||||
if (jclass_NullPointerException == 0) {
|
||||
return -1;
|
||||
}
|
||||
jclass_RuntimeException = createGlobarRef(env, (*env)->FindClass(env, "java/lang/RuntimeException"));
|
||||
jclass_RuntimeException = createGlobalRef(env, (*env)->FindClass(env, "java/lang/RuntimeException"));
|
||||
if (jclass_RuntimeException == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
jclass_Options = createGlobarRef(env, (*env)->FindClass(env, "android/graphics/BitmapFactory$Options"));
|
||||
jclass_Options = createGlobalRef(env, (*env)->FindClass(env, "android/graphics/BitmapFactory$Options"));
|
||||
if (jclass_Options == 0) {
|
||||
return -1;
|
||||
}
|
||||
@@ -262,7 +299,7 @@ typedef struct my_error_mgr {
|
||||
} *my_error_ptr;
|
||||
|
||||
|
||||
METHODDEF(void) my_error_exit(j_common_ptr cinfo) {
|
||||
METHODDEF(void) my_jpeglib_error_exit(j_common_ptr cinfo) {
|
||||
my_error_ptr myerr = (my_error_ptr) cinfo->err;
|
||||
(*cinfo->err->output_message) (cinfo);
|
||||
longjmp(myerr->setjmp_buffer, 1);
|
||||
@@ -424,7 +461,7 @@ JNIEXPORT void Java_com_b44t_messenger_Utilities_loadBitmap(JNIEnv *env, jclass
|
||||
struct jpeg_decompress_struct cinfo;
|
||||
|
||||
cinfo.err = jpeg_std_error(&jerr.pub);
|
||||
jerr.pub.error_exit = my_error_exit;
|
||||
jerr.pub.error_exit = my_jpeglib_error_exit;
|
||||
|
||||
if (!setjmp(jerr.setjmp_buffer)) {
|
||||
jpeg_create_decompress(&cinfo);
|
||||
|
||||
@@ -1,8 +1,34 @@
|
||||
#ifndef image_h
|
||||
#define image_h
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Messenger Android Frontend
|
||||
* (C) 2013-2016 Nikolai Kudashov
|
||||
* (C) 2017 Björn Petersen
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see http://www.gnu.org/licenses/ .
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
#ifndef __IMAGE_H__
|
||||
#define __IMAGE_H__
|
||||
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
jint imageOnJNILoad(JavaVM *vm, void *reserved, JNIEnv *env);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __IMAGE_H__ */
|
||||
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <jni.h>
|
||||
#include <sys/types.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
#include <openssl/aes.h>
|
||||
#include <unistd.h>
|
||||
#include "utils.h"
|
||||
#include "image.h"
|
||||
|
||||
int gifvideoOnJNILoad(JavaVM *vm, JNIEnv *env);
|
||||
|
||||
jint JNI_OnLoad(JavaVM *vm, void *reserved) { /* this function is called automatically by the JNI when the library gets loaded */
|
||||
JNIEnv *env = 0;
|
||||
srand(time(NULL));
|
||||
|
||||
if ((*vm)->GetEnv(vm, (void **) &env, JNI_VERSION_1_6) != JNI_OK) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (imageOnJNILoad(vm, reserved, env) == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (gifvideoOnJNILoad(vm, env) == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return JNI_VERSION_1_6;
|
||||
}
|
||||
|
||||
void JNI_OnUnload(JavaVM *vm, void *reserved) {
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
JNIEXPORT void Java_com_b44t_messenger_Utilities_aesIgeEncryption(JNIEnv *env, jclass class, jobject buffer, jbyteArray key, jbyteArray iv, jboolean encrypt, int offset, int length) {
|
||||
jbyte *what = (*env)->GetDirectBufferAddress(env, buffer) + offset;
|
||||
unsigned char *keyBuff = (unsigned char *)(*env)->GetByteArrayElements(env, key, NULL);
|
||||
unsigned char *ivBuff = (unsigned char *)(*env)->GetByteArrayElements(env, iv, NULL);
|
||||
|
||||
AES_KEY akey;
|
||||
if (!encrypt) {
|
||||
AES_set_decrypt_key(keyBuff, 32 * 8, &akey);
|
||||
AES_ige_encrypt(what, what, length, &akey, ivBuff, AES_DECRYPT);
|
||||
} else {
|
||||
AES_set_encrypt_key(keyBuff, 32 * 8, &akey);
|
||||
AES_ige_encrypt(what, what, length, &akey, ivBuff, AES_ENCRYPT);
|
||||
}
|
||||
(*env)->ReleaseByteArrayElements(env, key, keyBuff, JNI_ABORT);
|
||||
(*env)->ReleaseByteArrayElements(env, iv, ivBuff, 0);
|
||||
}
|
||||
*/
|
||||
|
||||
JNIEXPORT jstring Java_com_b44t_messenger_Utilities_readlink(JNIEnv *env, jclass class, jstring path) {
|
||||
static char buf[1000];
|
||||
char *fileName = (*env)->GetStringUTFChars(env, path, NULL);
|
||||
int result = readlink(fileName, buf, 999);
|
||||
jstring value = 0;
|
||||
if (result != -1) {
|
||||
buf[result] = '\0';
|
||||
value = (*env)->NewStringUTF(env, buf);
|
||||
}
|
||||
(*env)->ReleaseStringUTFChars(env, path, fileName);
|
||||
return value;
|
||||
}
|
||||
@@ -122,13 +122,13 @@
|
||||
#define LIBETPAN_REENTRANT 1
|
||||
|
||||
/* Define this to the version of libEtPan */
|
||||
#define LIBETPAN_VERSION "1.2-dev-20141203"
|
||||
//#define LIBETPAN_VERSION "1.2-dev-20141203"
|
||||
|
||||
/* Define this to the major version of libEtPan */
|
||||
#define LIBETPAN_VERSION_MAJOR 1
|
||||
//#define LIBETPAN_VERSION_MAJOR 1
|
||||
|
||||
/* Define this to the minor version of libEtPan */
|
||||
#define LIBETPAN_VERSION_MINOR 2
|
||||
//#define LIBETPAN_VERSION_MINOR 2
|
||||
|
||||
/* Define to the sub-directory in which libtool stores uninstalled libraries.
|
||||
*/
|
||||
@@ -144,7 +144,7 @@
|
||||
#define PACKAGE_NAME "libetpan"
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define PACKAGE_STRING "libetpan 1.2"
|
||||
//#define PACKAGE_STRING "libetpan 1.2"
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#define PACKAGE_TARNAME "libetpan"
|
||||
@@ -153,7 +153,7 @@
|
||||
#define PACKAGE_URL ""
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define PACKAGE_VERSION "1.2"
|
||||
//#define PACKAGE_VERSION "1.2"
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#define STDC_HEADERS 1
|
||||
@@ -171,7 +171,7 @@
|
||||
#define USE_SSL 1
|
||||
|
||||
/* Version number of package */
|
||||
#define VERSION "1.2"
|
||||
//#define VERSION "1.2"
|
||||
|
||||
/* Define to `__inline__' or `__inline' if that's what the C compiler
|
||||
calls it, or to nothing if 'inline' is not supported under any name. */
|
||||
|
||||
Submodule
+1
Submodule MessengerProj/jni/messenger-backend added at e2c23e4459
@@ -0,0 +1,77 @@
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Messenger Android Frontend
|
||||
* (C) 2013-2016 Nikolai Kudashov
|
||||
* (C) 2017 Björn Petersen
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see http://www.gnu.org/licenses/ .
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <jni.h>
|
||||
#include <sys/types.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
#include <openssl/aes.h>
|
||||
#include <unistd.h>
|
||||
#include "mrjnimain.h"
|
||||
#include "image.h"
|
||||
#include "gifvideo.h"
|
||||
|
||||
|
||||
jint JNI_OnLoad(JavaVM *vm, void *reserved) { /* this function is called automatically by the JNI when the library gets loaded */
|
||||
JNIEnv *env = 0;
|
||||
srand(time(NULL));
|
||||
|
||||
__android_log_print(ANDROID_LOG_INFO, "DeltaChat", "JNI_OnLoad() ..."); /* please note, that __android_log_print() may not work (eg. on LG X Cam), however, we don't have an option here. */
|
||||
|
||||
if ((*vm)->GetEnv(vm, (void **) &env, JNI_VERSION_1_6) != JNI_OK) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (imageOnJNILoad(vm, reserved, env) == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (gifvideoOnJNILoad(vm, env) == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
__android_log_print(ANDROID_LOG_INFO, "DeltaChat", "JNI_OnLoad() succeeded.");
|
||||
|
||||
return JNI_VERSION_1_6;
|
||||
}
|
||||
|
||||
|
||||
void JNI_OnUnload(JavaVM *vm, void *reserved) {
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jstring Java_com_b44t_messenger_Utilities_readlink(JNIEnv *env, jclass class, jstring path) {
|
||||
static char buf[1000];
|
||||
char *fileName = (*env)->GetStringUTFChars(env, path, NULL);
|
||||
int result = readlink(fileName, buf, 999);
|
||||
jstring value = 0;
|
||||
if (result != -1) {
|
||||
buf[result] = '\0';
|
||||
value = (*env)->NewStringUTF(env, buf);
|
||||
}
|
||||
(*env)->ReleaseStringUTFChars(env, path, fileName);
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Messenger Android Frontend
|
||||
* (C) 2013-2016 Nikolai Kudashov
|
||||
* (C) 2017 Björn Petersen
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see http://www.gnu.org/licenses/ .
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
#ifndef __MRJNIMAIN_H__
|
||||
#define __MRJNIMAIN_H__
|
||||
|
||||
|
||||
#include <android/log.h>
|
||||
#include <jni.h>
|
||||
|
||||
|
||||
#define LOG_TAG "DeltaChat"
|
||||
#ifndef LOG_DISABLED
|
||||
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
|
||||
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
|
||||
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
|
||||
#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
|
||||
#else
|
||||
#define LOGI(...)
|
||||
#define LOGD(...)
|
||||
#define LOGE(...)
|
||||
#define LOGV(...)
|
||||
#endif
|
||||
|
||||
#ifndef max
|
||||
#define max(x, y) ((x) > (y)) ? (x) : (y)
|
||||
#endif
|
||||
#ifndef min
|
||||
#define min(x, y) ((x) < (y)) ? (x) : (y)
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* __MRJNIMAIN_H__*/
|
||||
|
||||
+387
-116
@@ -1,8 +1,8 @@
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Messenger Android Frontend
|
||||
* Copyright (C) 2016 Björn Petersen Software Design and Development
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
* (C) 2017 Björn Petersen
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
@@ -20,15 +20,14 @@
|
||||
*******************************************************************************
|
||||
*
|
||||
* File: mr_wrapper.c
|
||||
* Authors: Björn Petersen
|
||||
* Purpose: The C part of the Java<->C Wrapper, see also MrMailbox.java
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
#include <jni.h>
|
||||
#include <android/log.h>
|
||||
#include "../../../messenger-backend/src/mrmailbox.h"
|
||||
#include "messenger-backend/src/mrmailbox.h"
|
||||
|
||||
|
||||
#define CHAR_REF(a) \
|
||||
@@ -37,49 +36,81 @@
|
||||
#define CHAR_UNREF(a) \
|
||||
if(a) { (*env)->ReleaseStringUTFChars(env, (a), a##Ptr); }
|
||||
|
||||
#define JSTRING_NEW(a) \
|
||||
(*env)->NewStringUTF(env, a? a : "") /*should handle NULL arguments, does not return NULL!*/
|
||||
|
||||
|
||||
/* our log handler */
|
||||
|
||||
static void s_log_callback_(int type, const char* msg)
|
||||
#define JSTRING_NEW(a) jstring_new__(env, (a))
|
||||
static jstring jstring_new__(JNIEnv* env, const char* a)
|
||||
{
|
||||
int prio;
|
||||
|
||||
switch( type ) {
|
||||
case 'd': prio = ANDROID_LOG_DEBUG; break;
|
||||
case 'i': prio = ANDROID_LOG_INFO; break;
|
||||
case 'w': prio = ANDROID_LOG_WARN; break;
|
||||
default: prio = ANDROID_LOG_ERROR; break;
|
||||
if( a==NULL || a[0]==0 ) {
|
||||
return (*env)->NewStringUTF(env, "");
|
||||
}
|
||||
__android_log_print(prio, "DeltaChat", "%s\n", msg); /* on problems, add `-llog` to `Android.mk` */
|
||||
|
||||
/* for non-empty strings, do not use NewStringUTF() as this is buggy on some Android versions.
|
||||
Instead, create the string using `new String(ByteArray, "UTF-8);` which seems to be programmed more properly.
|
||||
(eg. on KitKat a simple "SMILING FACE WITH SMILING EYES" (U+1F60A, UTF-8 F0 9F 98 8A) will let the app crash, reporting 0xF0 is a bad UTF-8 start,
|
||||
see http://stackoverflow.com/questions/12127817/android-ics-4-0-ndk-newstringutf-is-crashing-down-the-app ) */
|
||||
static jclass s_strCls = NULL;
|
||||
static jmethodID s_strCtor = NULL;
|
||||
static jclass s_strEncode = NULL;
|
||||
if( s_strCls==NULL ) {
|
||||
s_strCls = (*env)->NewGlobalRef(env, (*env)->FindClass(env, "java/lang/String"));
|
||||
s_strCtor = (*env)->GetMethodID(env, s_strCls, "<init>", "([BLjava/lang/String;)V");
|
||||
s_strEncode = (*env)->NewGlobalRef(env, (*env)->NewStringUTF(env, "UTF-8"));
|
||||
}
|
||||
|
||||
int a_bytes = strlen(a);
|
||||
jbyteArray array = (*env)->NewByteArray(env, a_bytes);
|
||||
(*env)->SetByteArrayRegion(env, array, 0, a_bytes, a);
|
||||
jstring ret = (jstring) (*env)->NewObject(env, s_strCls, s_strCtor, array, s_strEncode);
|
||||
(*env)->DeleteLocalRef(env, array); /* we have to delete the reference as it is not returned to Java, AFAIK */
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* globl stuff */
|
||||
/* global stuff */
|
||||
|
||||
static JavaVM* s_jvm = NULL;
|
||||
static jclass s_MrMailbox_class = NULL;
|
||||
static jmethodID s_MrCallback_methodID = NULL;
|
||||
static int s_global_init_done = 0;
|
||||
|
||||
|
||||
static void s_init_globals(JNIEnv *env, jclass MrMailbox_class)
|
||||
{
|
||||
/* make sure, the intialisation is done only once */
|
||||
static bool s_global_init_done = 0;
|
||||
if( s_global_init_done ) { return; }
|
||||
s_global_init_done = 1;
|
||||
|
||||
/* init global callback */
|
||||
mrlog_set_handler(s_log_callback_);
|
||||
|
||||
/* prepare calling back a Java function */
|
||||
__android_log_print(ANDROID_LOG_INFO, "DeltaChat", "JNI: s_init_globals()..."); /* low-level logging, mrmailbox_log_*() may not be yet available. However, please note that __android_log_print() may not work (eg. on LG X Cam) */
|
||||
|
||||
(*env)->GetJavaVM(env, &s_jvm); /* JNIEnv cannot be shared between threads, so we share the JavaVM object */
|
||||
s_MrMailbox_class = (*env)->NewGlobalRef(env, MrMailbox_class);
|
||||
s_MrCallback_methodID = (*env)->GetStaticMethodID(env, MrMailbox_class, "MrCallback","(IJJ)J" /*signature as "(param)ret" with I=int, J=long*/ );
|
||||
}
|
||||
|
||||
/* system-specific backend initialisations */
|
||||
mrosnative_init_android(env); /*this should be called before any other "important" routine is called*/
|
||||
|
||||
/* setup threads, only called directly by the backed */
|
||||
|
||||
int mrosnative_setup_thread(mrmailbox_t* mailbox)
|
||||
{
|
||||
if( s_jvm == NULL ) {
|
||||
mrmailbox_log_error(mailbox, 0, "Not ready, cannot setup thread.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
mrmailbox_log_info(mailbox, 0, "Attaching C-thread to Java VM...");
|
||||
JNIEnv* env = NULL;
|
||||
(*s_jvm)->AttachCurrentThread(s_jvm, &env, NULL);
|
||||
mrmailbox_log_info(mailbox, 0, "Attaching ok.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void mrosnative_unsetup_thread(mrmailbox_t* mailbox)
|
||||
{
|
||||
mrmailbox_log_info(mailbox, 0, "Detaching C-thread from Java VM...");
|
||||
(*s_jvm)->DetachCurrentThread(s_jvm);
|
||||
mrmailbox_log_info(mailbox, 0, "DeltaChat", "Detaching done.");
|
||||
}
|
||||
|
||||
|
||||
@@ -112,6 +143,33 @@ static jintArray carray2jintArray_n_carray_free(JNIEnv *env, const carray* ca)
|
||||
}
|
||||
|
||||
|
||||
static uint32_t* jintArray2uint32Pointer(JNIEnv* env, jintArray ja, int* ret_icnt)
|
||||
{
|
||||
uint32_t* ret = NULL;
|
||||
if( env && ja && ret_icnt )
|
||||
{
|
||||
int i, icnt = (*env)->GetArrayLength(env, ja);
|
||||
if( icnt > 0 )
|
||||
{
|
||||
const jint* temp = (*env)->GetIntArrayElements(env, ja, NULL);
|
||||
if( temp )
|
||||
{
|
||||
ret = calloc(icnt, sizeof(uint32_t));
|
||||
if( ret )
|
||||
{
|
||||
for( i = 0; i < icnt; i++ ) {
|
||||
ret[i] = (uint32_t)temp[i];
|
||||
}
|
||||
*ret_icnt = icnt;
|
||||
}
|
||||
(*env)->ReleaseIntArrayElements(env, ja, temp, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* MrMailbox
|
||||
******************************************************************************/
|
||||
@@ -137,15 +195,24 @@ static uintptr_t s_mailbox_callback_(mrmailbox_t* mailbox, int event, uintptr_t
|
||||
jlong l;
|
||||
JNIEnv* env;
|
||||
|
||||
#if 0 /* -- __android_log_print() does not log eg. on LG X Cam - but Javas Log.i() etc. do. So, we do not optimize these calls and just use the Java logging. */
|
||||
if( event==MR_EVENT_INFO || event==MR_EVENT_WARNING ) {
|
||||
__android_log_print(event==MR_EVENT_INFO? ANDROID_LOG_INFO : ANDROID_LOG_WARN, "DeltaChat", "%s", (char*)data2); /* on problems, add `-llog` to `Android.mk` */
|
||||
return 0; /* speed up things for info/warning */
|
||||
}
|
||||
else if( event == MR_EVENT_ERROR ) {
|
||||
__android_log_print(ANDROID_LOG_ERROR, "DeltaChat", "%s", (char*)data2);
|
||||
/* errors are also forwarded to Java to show them in a bubble or so */
|
||||
}
|
||||
#endif
|
||||
|
||||
if( s_jvm==NULL || s_MrMailbox_class==NULL || s_MrCallback_methodID==NULL ) {
|
||||
s_log_callback_('e', "Callback called but JavaVM not ready.");
|
||||
return 0;
|
||||
return 0; /* may happen on startup */
|
||||
}
|
||||
|
||||
(*s_jvm)->GetEnv(s_jvm, &env, JNI_VERSION_1_6); /* as this function may be called from _any_ thread, we cannot use a static pointer to JNIEnv */
|
||||
if( env==NULL ) {
|
||||
s_log_callback_('e', "Callback called but cannot get JNIEnv.");
|
||||
return 0;
|
||||
return 0; /* may happen on startup */
|
||||
}
|
||||
|
||||
l = (*env)->CallStaticLongMethod(env, s_MrMailbox_class, s_MrCallback_methodID, (jint)event, (jlong)data1, (jlong)data2);
|
||||
@@ -162,76 +229,78 @@ JNIEXPORT jlong Java_com_b44t_messenger_MrMailbox_MrMailboxNew(JNIEnv *env, jcla
|
||||
|
||||
/* MrMailbox - open/configure/connect/fetch */
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrMailbox_MrMailboxOpen(JNIEnv *env, jclass c, jlong hMailbox, jstring dbfile, jstring blobdir)
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrMailbox_open(JNIEnv *env, jclass cls, jstring dbfile)
|
||||
{
|
||||
CHAR_REF(dbfile);
|
||||
CHAR_REF(blobdir);
|
||||
jint ret = mrmailbox_open((mrmailbox_t*)hMailbox, dbfilePtr, blobdirPtr);
|
||||
CHAR_UNREF(blobdir);
|
||||
jint ret = mrmailbox_open(get_mrmailbox_t(env, cls), dbfilePtr, NULL);
|
||||
CHAR_UNREF(dbfile)
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void Java_com_b44t_messenger_MrMailbox_MrMailboxClose(JNIEnv *env, jclass c, jlong hMailbox)
|
||||
JNIEXPORT void Java_com_b44t_messenger_MrMailbox_close(JNIEnv *env, jclass cls)
|
||||
{
|
||||
mrmailbox_close((mrmailbox_t*)hMailbox);
|
||||
mrmailbox_close(get_mrmailbox_t(env, cls));
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrMailbox_MrMailboxConfigure(JNIEnv *env, jclass c, jlong hMailbox)
|
||||
JNIEXPORT jstring Java_com_b44t_messenger_MrMailbox_getBlobdir(JNIEnv *env, jclass cls)
|
||||
{
|
||||
return mrmailbox_configure((mrmailbox_t*)hMailbox);
|
||||
mrmailbox_t* ths = get_mrmailbox_t(env, cls);
|
||||
return JSTRING_NEW((ths&&ths->m_blobdir)? ths->m_blobdir : NULL);
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrMailbox_MrMailboxIsConfigured(JNIEnv *env, jclass c, jlong hMailbox)
|
||||
JNIEXPORT void Java_com_b44t_messenger_MrMailbox_configureAndConnect(JNIEnv *env, jclass cls)
|
||||
{
|
||||
return (jint)mrmailbox_is_configured((mrmailbox_t*)hMailbox);
|
||||
mrmailbox_configure_and_connect(get_mrmailbox_t(env, cls));
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrMailbox_MrMailboxConnect(JNIEnv *env, jclass c, jlong hMailbox)
|
||||
JNIEXPORT void Java_com_b44t_messenger_MrMailbox_configureCancel(JNIEnv *env, jclass cls)
|
||||
{
|
||||
return mrmailbox_connect((mrmailbox_t*)hMailbox);
|
||||
mrmailbox_configure_cancel(get_mrmailbox_t(env, cls));
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void Java_com_b44t_messenger_MrMailbox_MrMailboxDisconnect(JNIEnv *env, jclass c, jlong hMailbox)
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrMailbox_isConfigured(JNIEnv *env, jclass cls)
|
||||
{
|
||||
mrmailbox_disconnect((mrmailbox_t*)hMailbox);
|
||||
return (jint)mrmailbox_is_configured(get_mrmailbox_t(env, cls));
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrMailbox_MrMailboxFetch(JNIEnv *env, jclass c, jlong hMailbox)
|
||||
JNIEXPORT void Java_com_b44t_messenger_MrMailbox_connect(JNIEnv *env, jclass cls)
|
||||
{
|
||||
return mrmailbox_fetch((mrmailbox_t*)hMailbox);
|
||||
mrmailbox_connect(get_mrmailbox_t(env, cls));
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jstring Java_com_b44t_messenger_MrMailbox_getErrorDescr(JNIEnv *env, jclass cls)
|
||||
JNIEXPORT void Java_com_b44t_messenger_MrMailbox_disconnect(JNIEnv *env, jclass cls)
|
||||
{
|
||||
char* c = mrmailbox_get_error_descr(get_mrmailbox_t(env, cls));
|
||||
jstring ret = JSTRING_NEW(c);
|
||||
free(c);
|
||||
return ret;
|
||||
mrmailbox_disconnect(get_mrmailbox_t(env, cls));
|
||||
}
|
||||
|
||||
|
||||
/* MrMailbox - handle contacts */
|
||||
|
||||
JNIEXPORT jintArray Java_com_b44t_messenger_MrMailbox_MrMailboxGetKnownContacts(JNIEnv *env, jclass c, jlong hMailbox, jstring query)
|
||||
JNIEXPORT jintArray Java_com_b44t_messenger_MrMailbox_getKnownContacts(JNIEnv *env, jclass cls, jstring query)
|
||||
{
|
||||
CHAR_REF(query);
|
||||
carray* ca = mrmailbox_get_known_contacts((mrmailbox_t*)hMailbox, queryPtr);
|
||||
CHAR_REF(query);
|
||||
carray* ca = mrmailbox_get_known_contacts(get_mrmailbox_t(env, cls), queryPtr);
|
||||
CHAR_UNREF(query);
|
||||
return carray2jintArray_n_carray_free(env, ca);
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jintArray Java_com_b44t_messenger_MrMailbox_MrMailboxGetBlockedContacts(JNIEnv *env, jclass c, jlong hMailbox)
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrMailbox_getBlockedCount(JNIEnv *env, jclass cls)
|
||||
{
|
||||
carray* ca = mrmailbox_get_blocked_contacts((mrmailbox_t*)hMailbox);
|
||||
return mrmailbox_get_blocked_count(get_mrmailbox_t(env, cls));
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jintArray Java_com_b44t_messenger_MrMailbox_getBlockedContacts(JNIEnv *env, jclass cls)
|
||||
{
|
||||
carray* ca = mrmailbox_get_blocked_contacts(get_mrmailbox_t(env, cls));
|
||||
return carray2jintArray_n_carray_free(env, ca);
|
||||
}
|
||||
|
||||
@@ -267,9 +336,18 @@ JNIEXPORT jint Java_com_b44t_messenger_MrMailbox_MrMailboxDeleteContact(JNIEnv *
|
||||
|
||||
/* MrMailbox - handle chats */
|
||||
|
||||
JNIEXPORT jlong Java_com_b44t_messenger_MrMailbox_MrMailboxGetChatlist(JNIEnv *env, jclass c, jlong hMailbox)
|
||||
JNIEXPORT jlong Java_com_b44t_messenger_MrMailbox_MrMailboxGetChatlist(JNIEnv *env, jclass c, jlong hMailbox, jstring query)
|
||||
{
|
||||
return (jlong)mrmailbox_get_chatlist((mrmailbox_t*)hMailbox);
|
||||
jlong ret;
|
||||
if( query ) {
|
||||
CHAR_REF(query);
|
||||
ret = (jlong)mrmailbox_get_chatlist((mrmailbox_t*)hMailbox, queryPtr);
|
||||
CHAR_UNREF(query);
|
||||
}
|
||||
else {
|
||||
ret = (jlong)mrmailbox_get_chatlist((mrmailbox_t*)hMailbox, NULL);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -279,27 +357,69 @@ JNIEXPORT jlong Java_com_b44t_messenger_MrMailbox_MrMailboxGetChat(JNIEnv *env,
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrMailbox_MrMailboxGetChatIdByContactId(JNIEnv *env, jclass c, jlong hMailbox, jint contact_id)
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrMailbox_getChatIdByContactId(JNIEnv *env, jclass cls, jint contact_id)
|
||||
{
|
||||
return (jint)mrmailbox_get_chat_id_by_contact_id((mrmailbox_t*)hMailbox, contact_id);
|
||||
return (jint)mrmailbox_get_chat_id_by_contact_id(get_mrmailbox_t(env, cls), contact_id);
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrMailbox_MrMailboxMarkseenChat(JNIEnv *env, jclass c, jlong hMailbox, jint chat_id)
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrMailbox_markseenMsg(JNIEnv *env, jclass cls, jint msg_id)
|
||||
{
|
||||
return (jlong)mrmailbox_markseen_chat((mrmailbox_t*)hMailbox, chat_id);
|
||||
return (jint)mrmailbox_markseen_msg(get_mrmailbox_t(env, cls), msg_id);
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrMailbox_MrMailboxCreateChatByContactId(JNIEnv *env, jclass c, jlong hMailbox, jint contact_id)
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrMailbox_markseenChat(JNIEnv *env, jclass cls, jint chat_id)
|
||||
{
|
||||
return (jint)mrmailbox_create_chat_by_contact_id((mrmailbox_t*)hMailbox, contact_id);
|
||||
return (jlong)mrmailbox_markseen_chat(get_mrmailbox_t(env, cls), chat_id);
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void Java_com_b44t_messenger_MrMailbox_MrMailboxDeleteChat(JNIEnv *env, jclass c, jlong hMailbox, jint chat_id)
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrMailbox_createChatByContactId(JNIEnv *env, jclass cls, jint contact_id)
|
||||
{
|
||||
mrmailbox_delete_chat((mrmailbox_t*)hMailbox, chat_id);
|
||||
return (jint)mrmailbox_create_chat_by_contact_id(get_mrmailbox_t(env, cls), contact_id);
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrMailbox_createGroupChat(JNIEnv *env, jclass cls, jstring name)
|
||||
{
|
||||
CHAR_REF(name);
|
||||
jint ret = (jint)mrmailbox_create_group_chat(get_mrmailbox_t(env, cls), namePtr);
|
||||
CHAR_UNREF(name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrMailbox_isContactInChat(JNIEnv *env, jclass cls, jint chat_id, jint contact_id)
|
||||
{
|
||||
return (jint)mrmailbox_is_contact_in_chat(get_mrmailbox_t(env, cls), chat_id, contact_id);
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrMailbox_addContactToChat(JNIEnv *env, jclass cls, jint chat_id, jint contact_id)
|
||||
{
|
||||
return (jint)mrmailbox_add_contact_to_chat(get_mrmailbox_t(env, cls), chat_id, contact_id);
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrMailbox_removeContactFromChat(JNIEnv *env, jclass cls, jint chat_id, jint contact_id)
|
||||
{
|
||||
return (jint)mrmailbox_remove_contact_from_chat(get_mrmailbox_t(env, cls), chat_id, contact_id);
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrMailbox_setChatName(JNIEnv *env, jclass cls, jint chat_id, jstring name)
|
||||
{
|
||||
CHAR_REF(name);
|
||||
jint ret = (jint)mrmailbox_set_chat_name(get_mrmailbox_t(env, cls), chat_id, namePtr);
|
||||
CHAR_UNREF(name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void Java_com_b44t_messenger_MrMailbox_deleteChat(JNIEnv *env, jclass cls, jint chat_id)
|
||||
{
|
||||
mrmailbox_delete_chat(get_mrmailbox_t(env, cls), chat_id);
|
||||
}
|
||||
|
||||
|
||||
@@ -320,30 +440,49 @@ JNIEXPORT jstring Java_com_b44t_messenger_MrMailbox_MrMailboxGetMsgInfo(JNIEnv *
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void Java_com_b44t_messenger_MrMailbox_MrMailboxDeleteMsg(JNIEnv *env, jclass c, jlong hMailbox, jint id)
|
||||
JNIEXPORT void Java_com_b44t_messenger_MrMailbox_deleteMsgs(JNIEnv *env, jclass cls, jintArray msg_ids)
|
||||
{
|
||||
mrmailbox_delete_msg((mrmailbox_t*)hMailbox, id);
|
||||
int msg_ids_cnt;
|
||||
const uint32_t* msg_ids_ptr = jintArray2uint32Pointer(env, msg_ids, &msg_ids_cnt);
|
||||
mrmailbox_delete_msgs(get_mrmailbox_t(env, cls), msg_ids_ptr, msg_ids_cnt);
|
||||
free(msg_ids_ptr);
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void Java_com_b44t_messenger_MrMailbox_forwardMsgs(JNIEnv *env, jclass cls, jintArray msg_ids, jint chat_id)
|
||||
{
|
||||
int msg_ids_cnt;
|
||||
const uint32_t* msg_ids_ptr = jintArray2uint32Pointer(env, msg_ids, &msg_ids_cnt);
|
||||
mrmailbox_forward_msgs(get_mrmailbox_t(env, cls), msg_ids_ptr, msg_ids_cnt, chat_id);
|
||||
free(msg_ids_ptr);
|
||||
}
|
||||
|
||||
|
||||
/* MrMailbox - handle config */
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrMailbox_MrMailboxSetConfig(JNIEnv *env, jclass c, jlong hMailbox, jstring key, jstring value)
|
||||
JNIEXPORT void Java_com_b44t_messenger_MrMailbox_setConfig(JNIEnv *env, jclass cls, jstring key, jstring value)
|
||||
{
|
||||
CHAR_REF(key);
|
||||
CHAR_REF(value);
|
||||
jint ret = (jint)mrmailbox_set_config((mrmailbox_t*)hMailbox, keyPtr, valuePtr);
|
||||
mrmailbox_set_config(get_mrmailbox_t(env, cls), keyPtr, valuePtr);
|
||||
CHAR_UNREF(key);
|
||||
CHAR_UNREF(value);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jstring Java_com_b44t_messenger_MrMailbox_MrMailboxGetConfig(JNIEnv *env, jclass c, jlong hMailbox, jstring key, jstring def)
|
||||
JNIEXPORT void Java_com_b44t_messenger_MrMailbox_setConfigInt(JNIEnv *env, jclass cls, jstring key, jint value)
|
||||
{
|
||||
CHAR_REF(key);
|
||||
mrmailbox_set_config_int(get_mrmailbox_t(env, cls), keyPtr, value);
|
||||
CHAR_UNREF(key);
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jstring Java_com_b44t_messenger_MrMailbox_getConfig(JNIEnv *env, jclass cls, jstring key, jstring def)
|
||||
{
|
||||
CHAR_REF(key);
|
||||
CHAR_REF(def);
|
||||
char* temp = mrmailbox_get_config((mrmailbox_t*)hMailbox, keyPtr, defPtr);
|
||||
char* temp = mrmailbox_get_config(get_mrmailbox_t(env, cls), keyPtr, defPtr);
|
||||
jstring ret = JSTRING_NEW(temp);
|
||||
free(temp);
|
||||
CHAR_UNREF(key);
|
||||
@@ -352,10 +491,10 @@ JNIEXPORT jstring Java_com_b44t_messenger_MrMailbox_MrMailboxGetConfig(JNIEnv *e
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrMailbox_MrMailboxGetConfigInt(JNIEnv *env, jclass c, jlong hMailbox, jstring key, jint def)
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrMailbox_getConfigInt(JNIEnv *env, jclass cls, jstring key, jint def)
|
||||
{
|
||||
CHAR_REF(key);
|
||||
jint ret = mrmailbox_get_config_int((mrmailbox_t*)hMailbox, keyPtr, def);
|
||||
jint ret = mrmailbox_get_config_int(get_mrmailbox_t(env, cls), keyPtr, def);
|
||||
CHAR_UNREF(key);
|
||||
return ret;
|
||||
}
|
||||
@@ -363,19 +502,19 @@ JNIEXPORT jint Java_com_b44t_messenger_MrMailbox_MrMailboxGetConfigInt(JNIEnv *e
|
||||
|
||||
/* MrMailbox - misc. */
|
||||
|
||||
JNIEXPORT jstring Java_com_b44t_messenger_MrMailbox_MrMailboxGetInfo(JNIEnv *env, jclass c, jlong hMailbox)
|
||||
JNIEXPORT jstring Java_com_b44t_messenger_MrMailbox_getInfo(JNIEnv *env, jclass cls)
|
||||
{
|
||||
char* temp = mrmailbox_get_info((mrmailbox_t*)hMailbox);
|
||||
char* temp = mrmailbox_get_info(get_mrmailbox_t(env, cls));
|
||||
jstring ret = JSTRING_NEW(temp);
|
||||
free(temp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jstring Java_com_b44t_messenger_MrMailbox_MrMailboxExecute(JNIEnv *env, jclass c, jlong hMailbox, jstring cmd)
|
||||
JNIEXPORT jstring Java_com_b44t_messenger_MrMailbox_cmdline(JNIEnv *env, jclass cls, jstring cmd)
|
||||
{
|
||||
CHAR_REF(cmd);
|
||||
char* temp = mrmailbox_execute((mrmailbox_t*)hMailbox, cmdPtr);
|
||||
char* temp = mrmailbox_cmdline(get_mrmailbox_t(env, cls), cmdPtr);
|
||||
jstring ret = JSTRING_NEW(temp);
|
||||
free(temp);
|
||||
CHAR_UNREF(cmd);
|
||||
@@ -383,6 +522,12 @@ JNIEXPORT jstring Java_com_b44t_messenger_MrMailbox_MrMailboxExecute(JNIEnv *env
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void Java_com_b44t_messenger_MrMailbox_heartbeat(JNIEnv *env, jclass cls)
|
||||
{
|
||||
mrmailbox_heartbeat(get_mrmailbox_t(env, cls));
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrMailbox_MrMailboxAddAddressBook(JNIEnv *env, jclass c, jlong hMailbox, jstring adrbook)
|
||||
{
|
||||
CHAR_REF(adrbook);
|
||||
@@ -427,42 +572,63 @@ JNIEXPORT jlong Java_com_b44t_messenger_MrChatlist_MrChatlistGetSummaryByIndex(J
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
static mrchat_t* get_mrchat_t(JNIEnv *env, jobject obj)
|
||||
{
|
||||
static jfieldID fid = 0;
|
||||
if( fid == 0 ) {
|
||||
jclass cls = (*env)->GetObjectClass(env, obj);
|
||||
fid = (*env)->GetFieldID(env, cls, "m_hChat", "J" /*Signature, J=long*/);
|
||||
}
|
||||
if( fid ) {
|
||||
return (mrchat_t*)(*env)->GetLongField(env, obj, fid);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void Java_com_b44t_messenger_MrChat_MrChatUnref(JNIEnv *env, jclass c, jlong hChat)
|
||||
{
|
||||
mrchat_unref((mrchat_t*)hChat);
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrChat_MrChatGetId(JNIEnv *env, jclass c, jlong hChat)
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrChat_getId(JNIEnv *env, jclass cls)
|
||||
{
|
||||
mrchat_t* ths = (mrchat_t*)hChat; if( ths == NULL ) { return 0; }
|
||||
mrchat_t* ths = get_mrchat_t(env, cls); if( ths == NULL ) { return 0; }
|
||||
return ths->m_id;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrChat_MrChatGetType(JNIEnv *env, jclass c, jlong hChat)
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrChat_getType(JNIEnv *env, jclass cls)
|
||||
{
|
||||
mrchat_t* ths = (mrchat_t*)hChat; if( ths == NULL ) { return 0; }
|
||||
mrchat_t* ths = get_mrchat_t(env, cls); if( ths == NULL ) { return 0; }
|
||||
return ths->m_type;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jstring Java_com_b44t_messenger_MrChat_MrChatGetName(JNIEnv *env, jclass c, jlong hChat)
|
||||
JNIEXPORT jstring Java_com_b44t_messenger_MrChat_getName(JNIEnv *env, jclass cls)
|
||||
{
|
||||
mrchat_t* ths = (mrchat_t*)hChat; if( ths == NULL ) { return JSTRING_NEW(NULL); }
|
||||
mrchat_t* ths = get_mrchat_t(env, cls); if( ths == NULL ) { return JSTRING_NEW(NULL); }
|
||||
return JSTRING_NEW(ths->m_name);
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jstring Java_com_b44t_messenger_MrChat_MrChatGetSubtitle(JNIEnv *env, jclass c, jlong hChat)
|
||||
JNIEXPORT jstring Java_com_b44t_messenger_MrChat_getSubtitle(JNIEnv *env, jclass cls)
|
||||
{
|
||||
const char* temp = mrchat_get_subtitle((mrchat_t*)hChat);
|
||||
const char* temp = mrchat_get_subtitle(get_mrchat_t(env, cls));
|
||||
jstring ret = JSTRING_NEW(temp);
|
||||
free(temp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrChat_getParamInt(JNIEnv *env, jclass cls, jint key, jint def)
|
||||
{
|
||||
mrchat_t* ths = get_mrchat_t(env, cls);
|
||||
return mrparam_get_int(ths? ths->m_param:NULL, key, def);
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jstring Java_com_b44t_messenger_MrChat_MrChatGetDraft(JNIEnv *env, jclass c, jlong hChat) /* returns NULL for "no draft" */
|
||||
{
|
||||
mrchat_t* ths = (mrchat_t*)hChat;
|
||||
@@ -508,20 +674,20 @@ JNIEXPORT jint Java_com_b44t_messenger_MrChat_MrChatSetDraft(JNIEnv *env, jclass
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrChat_MrChatSendText(JNIEnv *env, jclass c, jlong hChat, jstring text)
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrChat_sendText(JNIEnv *env, jclass cls, jstring text)
|
||||
{
|
||||
mrmsg_t* msg = mrmsg_new();
|
||||
msg->m_type = MR_MSG_TEXT;
|
||||
CHAR_REF(text);
|
||||
msg->m_text = textPtr? strdup(textPtr) : NULL;
|
||||
CHAR_UNREF(text);
|
||||
jint msg_id = mrchat_send_msg((mrchat_t*)hChat, msg);
|
||||
jint msg_id = mrchat_send_msg(get_mrchat_t(env, cls), msg);
|
||||
mrmsg_unref(msg);
|
||||
return msg_id;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrChat_MrChatSendMedia(JNIEnv *env, jclass c, jlong hChat, jint type, jstring file, jstring mime, jint w, jint h, jint ms)
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrChat_sendMedia(JNIEnv *env, jclass cls, jint type, jstring file, jstring mime, jint w, jint h, jint ms, jstring author, jstring trackname)
|
||||
{
|
||||
mrmsg_t* msg = mrmsg_new();
|
||||
msg->m_type = type;
|
||||
@@ -535,33 +701,62 @@ JNIEXPORT jint Java_com_b44t_messenger_MrChat_MrChatSendMedia(JNIEnv *env, jclas
|
||||
mrparam_set_int(msg->m_param, 'w', w);
|
||||
mrparam_set_int(msg->m_param, 'h', h);
|
||||
}
|
||||
if( type == MR_MSG_AUDIO || type == MR_MSG_VIDEO ) {
|
||||
if( type == MR_MSG_AUDIO || type == MR_MSG_VOICE || type == MR_MSG_VIDEO ) {
|
||||
mrparam_set_int(msg->m_param, 'd', ms);
|
||||
}
|
||||
jint msg_id = mrchat_send_msg((mrchat_t*)hChat, msg);
|
||||
if( type == MR_MSG_AUDIO ) {
|
||||
CHAR_REF(author);
|
||||
mrparam_set(msg->m_param, 'N', authorPtr);
|
||||
CHAR_UNREF(author);
|
||||
CHAR_REF(trackname);
|
||||
mrparam_set(msg->m_param, 'n', tracknamePtr);
|
||||
CHAR_UNREF(trackname);
|
||||
}
|
||||
jint msg_id = mrchat_send_msg(get_mrchat_t(env, cls), msg);
|
||||
mrmsg_unref(msg);
|
||||
return msg_id;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jintArray Java_com_b44t_messenger_MrMailbox_MrMailboxGetChatMedia(JNIEnv *env, jclass c, jlong hMailbox, jint chat_id, jint msg_type, jint or_msg_type)
|
||||
JNIEXPORT jintArray Java_com_b44t_messenger_MrMailbox_getChatMedia(JNIEnv *env, jclass cls, jint chat_id, jint msg_type, jint or_msg_type)
|
||||
{
|
||||
carray* ca = mrmailbox_get_chat_media((mrmailbox_t*)hMailbox, chat_id, msg_type, or_msg_type);
|
||||
carray* ca = mrmailbox_get_chat_media(get_mrmailbox_t(env, cls), chat_id, msg_type, or_msg_type);
|
||||
return carray2jintArray_n_carray_free(env, ca);
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jintArray Java_com_b44t_messenger_MrMailbox_MrMailboxGetChatMsgs(JNIEnv *env, jclass c, jlong hMailbox, jint chat_id)
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrMailbox_getNextMedia(JNIEnv *env, jclass cls, jint msg_id, jint dir)
|
||||
{
|
||||
carray* ca = mrmailbox_get_chat_msgs((mrmailbox_t*)hMailbox, chat_id);
|
||||
return mrmailbox_get_next_media(get_mrmailbox_t(env, cls), msg_id, dir);
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jintArray Java_com_b44t_messenger_MrMailbox_getChatMsgs(JNIEnv *env, jclass cls, jint chat_id, jint flags, jint marker1before)
|
||||
{
|
||||
carray* ca = mrmailbox_get_chat_msgs(get_mrmailbox_t(env, cls), chat_id, flags, marker1before);
|
||||
return carray2jintArray_n_carray_free(env, ca);
|
||||
}
|
||||
|
||||
|
||||
|
||||
JNIEXPORT jintArray Java_com_b44t_messenger_MrMailbox_MrMailboxGetChatContacts(JNIEnv *env, jclass c, jlong hMailbox, jint chat_id)
|
||||
JNIEXPORT jintArray Java_com_b44t_messenger_MrMailbox_searchMsgs(JNIEnv *env, jclass cls, jint chat_id, jstring query)
|
||||
{
|
||||
carray* ca = mrmailbox_get_chat_contacts((mrmailbox_t*)hMailbox, chat_id);
|
||||
CHAR_REF(query);
|
||||
carray* ca = mrmailbox_search_msgs(get_mrmailbox_t(env, cls), chat_id, queryPtr);
|
||||
CHAR_UNREF(query);
|
||||
return carray2jintArray_n_carray_free(env, ca);
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jintArray Java_com_b44t_messenger_MrMailbox_getUnseenMsgs(JNIEnv *env, jclass cls)
|
||||
{
|
||||
carray* ca = mrmailbox_get_unseen_msgs(get_mrmailbox_t(env, cls));
|
||||
return carray2jintArray_n_carray_free(env, ca);
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jintArray Java_com_b44t_messenger_MrMailbox_getChatContacts(JNIEnv *env, jclass cls, jint chat_id)
|
||||
{
|
||||
carray* ca = mrmailbox_get_chat_contacts(get_mrmailbox_t(env, cls), chat_id);
|
||||
return carray2jintArray_n_carray_free(env, ca);
|
||||
}
|
||||
|
||||
@@ -571,6 +766,20 @@ JNIEXPORT jintArray Java_com_b44t_messenger_MrMailbox_MrMailboxGetChatContacts(J
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
static mrmsg_t* get_mrmsg_t(JNIEnv *env, jobject obj)
|
||||
{
|
||||
static jfieldID fid = 0;
|
||||
if( fid == 0 ) {
|
||||
jclass cls = (*env)->GetObjectClass(env, obj);
|
||||
fid = (*env)->GetFieldID(env, cls, "m_hMsg", "J" /*Signature, J=long*/);
|
||||
}
|
||||
if( fid ) {
|
||||
return (mrmsg_t*)(*env)->GetLongField(env, obj, fid);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void Java_com_b44t_messenger_MrMsg_MrMsgUnref(JNIEnv *env, jclass c, jlong hMsg)
|
||||
{
|
||||
mrmsg_unref((mrmsg_t*)hMsg);
|
||||
@@ -633,9 +842,9 @@ JNIEXPORT jint Java_com_b44t_messenger_MrMsg_MrMsgGetToId(JNIEnv *env, jclass c,
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jstring Java_com_b44t_messenger_MrMsg_MrMsgGetParam(JNIEnv *env, jclass c, jlong hMsg, jint key, jstring def)
|
||||
JNIEXPORT jstring Java_com_b44t_messenger_MrMsg_getParam(JNIEnv *env, jobject obj, jint key, jstring def)
|
||||
{
|
||||
mrmsg_t* ths = (mrmsg_t*)hMsg;
|
||||
mrmsg_t* ths = get_mrmsg_t(env, obj);
|
||||
CHAR_REF(def);
|
||||
char* temp = mrparam_get(ths? ths->m_param:NULL, key, defPtr);
|
||||
jstring ret = JSTRING_NEW(temp);
|
||||
@@ -645,10 +854,68 @@ JNIEXPORT jstring Java_com_b44t_messenger_MrMsg_MrMsgGetParam(JNIEnv *env, jclas
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrMsg_MrMsgGetParamInt(JNIEnv *env, jclass c, jlong hMsg, jint key, jint def)
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrMsg_getParamInt(JNIEnv *env, jobject obj, jint key, jint def)
|
||||
{
|
||||
mrmsg_t* ths = (mrmsg_t*)hMsg;
|
||||
return mrparam_get_int(ths? ths->m_param:NULL, key, def);
|
||||
mrmsg_t* ths = get_mrmsg_t(env, obj);
|
||||
return mrparam_get_int(ths? ths->m_param:NULL, key, def);
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void Java_com_b44t_messenger_MrMsg_setParamInt(JNIEnv *env, jobject obj, jint key, jint value)
|
||||
{
|
||||
mrmsg_t* ths = get_mrmsg_t(env, obj);
|
||||
mrparam_set_int(ths? ths->m_param:NULL, key, value);
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void Java_com_b44t_messenger_MrMsg_saveParamToDisk(JNIEnv *env, jobject obj)
|
||||
{
|
||||
mrmsg_save_param_to_disk(get_mrmsg_t(env, obj));
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrMsg_getBytes(JNIEnv *env, jobject obj)
|
||||
{
|
||||
jint ret = 0;
|
||||
mrmsg_t* ths = get_mrmsg_t(env, obj);
|
||||
if( ths ) {
|
||||
const char* file = mrparam_get(ths->m_param, 'f', NULL);
|
||||
if( file ) {
|
||||
ret = mr_get_filebytes(file);
|
||||
free(file);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jlong Java_com_b44t_messenger_MrMsg_getSummaryCPtr(JNIEnv *env, jobject obj, jlong hChat)
|
||||
{
|
||||
return (jlong)mrmsg_get_summary(get_mrmsg_t(env, obj), (mrchat_t*)hChat);
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrMsg_getSummarytext(JNIEnv *env, jobject obj, jint approx_characters)
|
||||
{
|
||||
return JSTRING_NEW(mrmsg_get_summarytext(get_mrmsg_t(env, obj), approx_characters));
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrMsg_getFilename(JNIEnv *env, jobject obj)
|
||||
{
|
||||
return JSTRING_NEW(mrmsg_get_filename(get_mrmsg_t(env, obj)));
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jlong Java_com_b44t_messenger_MrMsg_getMediainfoCPtr(JNIEnv *env, jobject obj)
|
||||
{
|
||||
return (jlong)mrmsg_get_mediainfo(get_mrmsg_t(env, obj));
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrMsg_isIncreation(JNIEnv *env, jobject obj)
|
||||
{
|
||||
return (jint)mrmsg_is_increation(get_mrmsg_t(env, obj));
|
||||
}
|
||||
|
||||
|
||||
@@ -695,24 +962,24 @@ JNIEXPORT void Java_com_b44t_messenger_MrPoortext_MrPoortextUnref(JNIEnv *env, j
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jstring Java_com_b44t_messenger_MrPoortext_MrPoortextGetTitle(JNIEnv *env, jclass c, jlong hPoortext)
|
||||
JNIEXPORT jstring Java_com_b44t_messenger_MrPoortext_MrPoortextGetText1(JNIEnv *env, jclass c, jlong hPoortext)
|
||||
{
|
||||
mrpoortext_t* ths = (mrpoortext_t*)hPoortext; if( ths == NULL ) { return JSTRING_NEW(NULL); }
|
||||
return JSTRING_NEW(ths->m_title);
|
||||
return JSTRING_NEW(ths->m_text1);
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrPoortext_MrPoortextGetTitleMeaning(JNIEnv *env, jclass c, jlong hPoortext)
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrPoortext_MrPoortextGetText1Meaning(JNIEnv *env, jclass c, jlong hPoortext)
|
||||
{
|
||||
mrpoortext_t* ths = (mrpoortext_t*)hPoortext; if( ths == NULL ) { return 0; }
|
||||
return ths->m_title_meaning;
|
||||
return ths->m_text1_meaning;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jstring Java_com_b44t_messenger_MrPoortext_MrPoortextGetText(JNIEnv *env, jclass c, jlong hPoortext)
|
||||
JNIEXPORT jstring Java_com_b44t_messenger_MrPoortext_MrPoortextGetText2(JNIEnv *env, jclass c, jlong hPoortext)
|
||||
{
|
||||
mrpoortext_t* ths = (mrpoortext_t*)hPoortext; if( ths == NULL ) { return JSTRING_NEW(NULL); }
|
||||
return JSTRING_NEW(ths->m_text);
|
||||
return JSTRING_NEW(ths->m_text2);
|
||||
}
|
||||
|
||||
|
||||
@@ -746,11 +1013,15 @@ JNIEXPORT jstring Java_com_b44t_messenger_MrMailbox_CPtr2String(JNIEnv *env, jcl
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void Java_com_b44t_messenger_MrMailbox_MrStockAddStr(JNIEnv* env, jclass c, jint id, jstring str)
|
||||
JNIEXPORT jlong Java_com_b44t_messenger_MrMailbox_String2CPtr(JNIEnv *env, jclass c, jstring str)
|
||||
{
|
||||
CHAR_REF(str);
|
||||
mrstock_add_str(id, strPtr);
|
||||
CHAR_UNREF(str)
|
||||
char* hStr = NULL;
|
||||
if( str ) {
|
||||
CHAR_REF(str);
|
||||
hStr = strdup(strPtr);
|
||||
CHAR_UNREF(str);
|
||||
}
|
||||
return (jlong)hStr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
#include "utils.h"
|
||||
|
||||
void throwException(JNIEnv *env, char *format, ...) {
|
||||
jclass exClass = (*env)->FindClass(env, "java/lang/UnsupportedOperationException");
|
||||
if (!exClass) {
|
||||
return;
|
||||
}
|
||||
char dest[256];
|
||||
va_list argptr;
|
||||
va_start(argptr, format);
|
||||
vsprintf(dest, format, argptr);
|
||||
va_end(argptr);
|
||||
(*env)->ThrowNew(env, exClass, dest);
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
#ifndef log_h
|
||||
#define log_h
|
||||
|
||||
#include <android/log.h>
|
||||
#include <jni.h>
|
||||
|
||||
#define LOG_TAG "DeltaChat"
|
||||
#ifndef LOG_DISABLED
|
||||
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
|
||||
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
|
||||
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
|
||||
#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
|
||||
#else
|
||||
#define LOGI(...)
|
||||
#define LOGD(...)
|
||||
#define LOGE(...)
|
||||
#define LOGV(...)
|
||||
#endif
|
||||
|
||||
#ifndef max
|
||||
#define max(x, y) ((x) > (y)) ? (x) : (y)
|
||||
#endif
|
||||
#ifndef min
|
||||
#define min(x, y) ((x) < (y)) ? (x) : (y)
|
||||
#endif
|
||||
|
||||
void throwException(JNIEnv *env, char *format, ...);
|
||||
|
||||
#endif
|
||||
@@ -1,6 +1,30 @@
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Messenger Android Frontend
|
||||
* (C) 2013-2016 Nikolai Kudashov
|
||||
* (C) 2017 Björn Petersen
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see http://www.gnu.org/licenses/ .
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
#include <jni.h>
|
||||
#include <libyuv.h>
|
||||
#include <utils.h>
|
||||
#include "mrjnimain.h"
|
||||
|
||||
|
||||
enum COLOR_FORMATTYPE {
|
||||
COLOR_FormatMonochrome = 1,
|
||||
@@ -52,7 +76,7 @@ enum COLOR_FORMATTYPE {
|
||||
COLOR_QCOM_FormatYUV420SemiPlanar = 0x7fa30c00
|
||||
};
|
||||
|
||||
int isSemiPlanarYUV(int colorFormat) {
|
||||
static int isSemiPlanarYUV(int colorFormat) {
|
||||
switch (colorFormat) {
|
||||
case COLOR_FormatYUV420Planar:
|
||||
case COLOR_FormatYUV420PackedPlanar:
|
||||
|
||||
@@ -20,34 +20,35 @@
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <!-- we need it eg. for getActiveNetworkInfo() -->
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
|
||||
<!-- <uses-permission android:name="android.permission.GET_ACCOUNTS" /> - required for AccountManager -->
|
||||
<uses-permission android:name="android.permission.READ_CONTACTS" />
|
||||
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
|
||||
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS"/>
|
||||
<uses-permission android:name="android.permission.READ_PROFILE"/>
|
||||
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS"/>
|
||||
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS"/>
|
||||
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS"/>
|
||||
<!-- <uses-permission android:name="android.permission.WRITE_CONTACTS" /> -->
|
||||
<!-- <uses-permission android:name="android.permission.MANAGE_ACCOUNTS"/> - required for AccountManager in API level <= 22 -->
|
||||
<!-- <uses-permission android:name="android.permission.READ_PROFILE"/> - required for ContactsContract.Profile -->
|
||||
<!-- <uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS"/> required for AbstractThreadedSyncAdapter-->
|
||||
<!-- <uses-permission android:name="android.permission.READ_SYNC_SETTINGS"/> - required for AbstractThreadedSyncAdapter -->
|
||||
<!-- <uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS"/> - seems to be unneeded and is no longer supported by Android, was needed for AbstractAccountAuthenticator, see http://stackoverflow.com/questions/32601456/marshmallow-permission-implementation#36907308 -->
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
||||
<!-- <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> - required for windows using the TYPE_SYSTEM_ALERT flag -->
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE" /> <!-- we need the TelephonyManager to pause the audio player on calls -->
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
|
||||
<uses-permission android:name="android.permission.INSTALL_SHORTCUT" />
|
||||
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
|
||||
<uses-permission android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT"/>
|
||||
<!--<uses-permission android:name="android.permission.CAMERA" />-->
|
||||
<!-- <uses-permission android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT" /> - required for AndroidUtilities.uninstallShortcut() -->
|
||||
<!-- <uses-permission android:name="android.permission.CAMERA" /> - also disabled in T'gram; we're using the camera via an intent only -->
|
||||
|
||||
<application
|
||||
android:name=".ApplicationLoader"
|
||||
android:allowBackup="false"
|
||||
android:hardwareAccelerated="@bool/useHardwareAcceleration"
|
||||
android:icon="@drawable/ic_launcher"
|
||||
android:label="@string/AppName"
|
||||
android:largeHeap="true"
|
||||
android:theme="@style/Theme.MessengerProj.Start"
|
||||
android:manageSpaceActivity="com.b44t.ui.ManageSpaceActivity">
|
||||
@@ -98,22 +99,13 @@
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<data android:mimeType="vnd.android.cursor.item/vnd.com.b44t.messenger.android.profile"/>
|
||||
</intent-filter>
|
||||
<!-- <intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:host="t'gram.me" android:scheme="http" />
|
||||
<data android:host="t'gram.me" android:scheme="https" />
|
||||
<data android:host="t'gram.dog" android:scheme="http" />
|
||||
<data android:host="t'gram.dog" android:scheme="https" />
|
||||
</intent-filter> -->
|
||||
<!-- <intent-filter android:icon="@drawable/ic_launcher" android:priority="1">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<data android:scheme="tg" />
|
||||
</intent-filter> -->
|
||||
<meta-data android:name="android.service.chooser.chooser_target_service" android:value=".TgChooserTargetService" />
|
||||
<action android:name="android.intent.action.SENDTO"/> <!-- VIEW seems to be standard, however, SENDTO is also mentioned in some examples -->
|
||||
<data android:scheme="mailto"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<category android:name="android.intent.category.BROWSABLE"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name="com.b44t.ui.ManageSpaceActivity"
|
||||
@@ -131,15 +123,6 @@
|
||||
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
|
||||
android:exported="true">
|
||||
</activity>
|
||||
<activity
|
||||
android:name="com.b44t.ui.PopupNotificationActivity"
|
||||
android:configChanges="keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"
|
||||
android:excludeFromRecents="true"
|
||||
android:launchMode="singleTask"
|
||||
android:taskAffinity=""
|
||||
android:theme="@style/Theme.MessengerProj.PopupNotification"
|
||||
android:windowSoftInputMode="adjustResize|stateHidden">
|
||||
</activity>
|
||||
|
||||
<receiver
|
||||
android:name=".AutoMessageHeardReceiver"
|
||||
@@ -165,6 +148,7 @@
|
||||
</receiver>
|
||||
-->
|
||||
|
||||
<!-- currently, we do not use the android account system
|
||||
<service android:name=".AuthenticatorService" android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.accounts.AccountAuthenticator"/>
|
||||
@@ -172,7 +156,9 @@
|
||||
<meta-data android:name="android.accounts.AccountAuthenticator"
|
||||
android:resource="@xml/auth"/>
|
||||
</service>
|
||||
-->
|
||||
|
||||
<!-- seems to be not needed, derived from AbstractThreadedSyncAdapter, would need the READ/WRITE_SYNC_SETTINGS
|
||||
<service android:name=".ContactsSyncAdapterService" android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.content.SyncAdapter" />
|
||||
@@ -182,7 +168,11 @@
|
||||
<meta-data android:name="android.provider.CONTACTS_STRUCTURE"
|
||||
android:resource="@xml/contacts" />
|
||||
</service>
|
||||
-->
|
||||
|
||||
<!-- this would implement the "direct share" functionality (the system shows some direct links eg.
|
||||
to the most recent chats when calling "share" from another app, see https://developer.android.com/reference/android/service/chooser/ChooserTargetService.html )
|
||||
however, if we want this feature, we have to implement a ChooserTargetService and add <meta-data android:name="android.service.chooser.chooser_target_service" android:value=".OurChooserTargetService" />
|
||||
<service
|
||||
android:name="com.b44t.messenger.TgChooserTargetService"
|
||||
android:label="@string/AppName"
|
||||
@@ -190,18 +180,18 @@
|
||||
<intent-filter>
|
||||
<action android:name="android.service.chooser.ChooserTargetService" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
</service> -->
|
||||
|
||||
<service android:name=".NotificationsService" android:enabled="true"/>
|
||||
<service android:name=".KeepAliveService" android:enabled="true"/>
|
||||
<service android:name=".NotificationRepeat" android:exported="false"/>
|
||||
<service android:name=".ClearCacheService" android:exported="false"/>
|
||||
<service android:name=".VideoEncodingService" android:enabled="true"/>
|
||||
<service android:name=".MusicPlayerService" android:exported="true" android:enabled="true"/>
|
||||
<!-- Do not expose data through MediaBrowserService, this seems unexpected for an messenger.
|
||||
Instead, the user can use 'save to music' or 'share' explicitly for items not privacy related.
|
||||
<service android:name=".MusicBrowserService" android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.media.browse.MediaBrowserService"/>
|
||||
</intent-filter>
|
||||
</service>
|
||||
</service> -->
|
||||
|
||||
<receiver android:name=".MusicPlayerReceiver" >
|
||||
<intent-filter>
|
||||
@@ -215,9 +205,8 @@
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<receiver android:name=".AppStartReceiver" android:enabled="true">
|
||||
<receiver android:name=".BootCompletedReceiver" android:enabled="true">
|
||||
<intent-filter>
|
||||
<action android:name="com.b44t.start" />
|
||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
@@ -225,10 +214,16 @@
|
||||
<receiver android:name=".WearReplyReceiver" android:enabled="true"/>
|
||||
<!-- <receiver android:name=".NetworkAlarm" android:enabled="true"/> -->
|
||||
|
||||
<!-- seems to be unneeded (bp)
|
||||
<receiver android:name=".ShareBroadcastReceiver" android:enabled="true"/>
|
||||
-->
|
||||
|
||||
<receiver android:name=".TimerReceiver" android:enabled="true"/>
|
||||
|
||||
<receiver android:name=".NotificationDismissReceiver" android:exported="false"/>
|
||||
|
||||
<provider android:name=".AttachmentsContentProvider" android:authorities="${applicationId}.attachments" android:exported="true" />
|
||||
|
||||
<uses-library android:name="com.sec.android.app.multiwindow" android:required="false" />
|
||||
<meta-data android:name="com.sec.android.support.multiwindow" android:value="true" />
|
||||
<meta-data android:name="com.sec.android.multiwindow.DEFAULT_SIZE_W" android:value="632dp" />
|
||||
|
||||
Binary file not shown.
@@ -1,232 +0,0 @@
|
||||
1876;JM;Jamaica;XXX XXXX
|
||||
1869;KN;Saint Kitts & Nevis;XXX XXXX
|
||||
1868;TT;Trinidad & Tobago;XXX XXXX
|
||||
1784;VC;Saint Vincent & the Grenadines;XXX XXXX
|
||||
1767;DM;Dominica;XXX XXXX
|
||||
1758;LC;Saint Lucia;XXX XXXX
|
||||
1721;SX;Sint Maarten;XXX XXXX
|
||||
1684;AS;American Samoa;XXX XXXX
|
||||
1671;GU;Guam;XXX XXXX
|
||||
1670;MP;Northern Mariana Islands;XXX XXXX
|
||||
1664;MS;Montserrat;XXX XXXX
|
||||
1649;TC;Turks & Caicos Islands;XXX XXXX
|
||||
1473;GD;Grenada;XXX XXXX
|
||||
1441;BM;Bermuda;XXX XXXX
|
||||
1345;KY;Cayman Islands;XXX XXXX
|
||||
1340;VI;US Virgin Islands;XXX XXXX
|
||||
1284;VG;British Virgin Islands;XXX XXXX
|
||||
1268;AG;Antigua & Barbuda;XXX XXXX
|
||||
1264;AI;Anguilla;XXX XXXX
|
||||
1246;BB;Barbados;XXX XXXX
|
||||
1242;BS;Bahamas;XXX XXXX
|
||||
998;UZ;Uzbekistan;XX XXXXXXX
|
||||
996;KG;Kyrgyzstan;XXX XXXXXX
|
||||
995;GE;Georgia;XXX XXX XXX
|
||||
994;AZ;Azerbaijan;XX XXX XXXX
|
||||
993;TM;Turkmenistan;XX XXXXXX
|
||||
992;TJ;Tajikistan;XX XXX XXXX
|
||||
977;NP;Nepal;XX XXXX XXXX
|
||||
976;MN;Mongolia;XX XX XXXX
|
||||
975;BT;Bhutan;XX XXX XXX
|
||||
974;QA;Qatar;XX XXX XXX
|
||||
973;BH;Bahrain;XXXX XXXX
|
||||
972;IL;Israel;XX XXX XXXX
|
||||
971;AE;United Arab Emirates;XX XXX XXXX
|
||||
970;PS;Palestine;XXX XX XXXX
|
||||
968;OM;Oman;XXXX XXXX
|
||||
967;YE;Yemen;XXX XXX XXX
|
||||
966;SA;Saudi Arabia;XX XXX XXXX
|
||||
965;KW;Kuwait;XXXX XXXX
|
||||
964;IQ;Iraq;XXX XXX XXXX
|
||||
963;SY;Syria;XXX XXX XXX
|
||||
962;JO;Jordan;X XXXX XXXX
|
||||
961;LB;Lebanon
|
||||
960;MV;Maldives;XXX XXXX
|
||||
886;TW;Taiwan;XXX XXX XXX
|
||||
880;BD;Bangladesh
|
||||
856;LA;Laos;XX XX XXX XXX
|
||||
855;KH;Cambodia
|
||||
853;MO;Macau;XXXX XXXX
|
||||
852;HK;Hong Kong;X XXX XXXX
|
||||
850;KP;North Korea
|
||||
692;MH;Marshall Islands
|
||||
691;FM;Micronesia
|
||||
690;TK;Tokelau
|
||||
689;PF;French Polynesia
|
||||
688;TV;Tuvalu
|
||||
687;NC;New Caledonia
|
||||
686;KI;Kiribati
|
||||
685;WS;Samoa
|
||||
683;NU;Niue
|
||||
682;CK;Cook Islands
|
||||
681;WF;Wallis & Futuna
|
||||
680;PW;Palau
|
||||
679;FJ;Fiji
|
||||
678;VU;Vanuatu
|
||||
677;SB;Solomon Islands
|
||||
676;TO;Tonga
|
||||
675;PG;Papua New Guinea
|
||||
674;NR;Nauru
|
||||
673;BN;Brunei Darussalam;XXX XXXX
|
||||
672;NF;Norfolk Island
|
||||
670;TL;Timor-Leste
|
||||
599;BQ;Bonaire, Sint Eustatius & Saba
|
||||
599;CW;Curaçao
|
||||
598;UY;Uruguay;X XXX XXXX
|
||||
597;SR;Suriname;XXX XXXX
|
||||
596;MQ;Martinique
|
||||
595;PY;Paraguay;XXX XXX XXX
|
||||
594;GF;French Guiana
|
||||
593;EC;Ecuador;XX XXX XXXX
|
||||
592;GY;Guyana
|
||||
591;BO;Bolivia;X XXX XXXX
|
||||
590;GP;Guadeloupe;XXX XX XX XX
|
||||
509;HT;Haiti
|
||||
508;PM;Saint Pierre & Miquelon
|
||||
507;PA;Panama;XXXX XXXX
|
||||
506;CR;Costa Rica;XXXX XXXX
|
||||
505;NI;Nicaragua;XXXX XXXX
|
||||
504;HN;Honduras;XXXX XXXX
|
||||
503;SV;El Salvador;XXXX XXXX
|
||||
502;GT;Guatemala;X XXX XXXX
|
||||
501;BZ;Belize
|
||||
500;FK;Falkland Islands
|
||||
423;LI;Liechtenstein
|
||||
421;SK;Slovakia;XXX XXX XXX
|
||||
420;CZ;Czech Republic;XXX XXX XXX
|
||||
389;MK;Macedonia;XX XXX XXX
|
||||
387;BA;Bosnia & Herzegovina;XX XXX XXX
|
||||
386;SI;Slovenia;XX XXX XXX
|
||||
385;HR;Croatia
|
||||
382;ME;Montenegro
|
||||
381;RS;Serbia;XX XXX XXXX
|
||||
380;UA;Ukraine;XX XXX XX XX
|
||||
378;SM;San Marino;XXX XXX XXXX
|
||||
377;MC;Monaco;XXXX XXXX
|
||||
376;AD;Andorra;XX XX XX
|
||||
375;BY;Belarus;XX XXX XXXX
|
||||
374;AM;Armenia;XX XXX XXX
|
||||
373;MD;Moldova;XX XXX XXX
|
||||
372;EE;Estonia
|
||||
371;LV;Latvia;XXX XXXXX
|
||||
370;LT;Lithuania;XXX XXXXX
|
||||
359;BG;Bulgaria
|
||||
358;FI;Finland
|
||||
357;CY;Cyprus;XXXX XXXX
|
||||
356;MT;Malta;XX XX XX XX
|
||||
355;AL;Albania;XX XXX XXXX
|
||||
354;IS;Iceland;XXX XXXX
|
||||
353;IE;Ireland;XX XXX XXXX
|
||||
352;LU;Luxembourg
|
||||
351;PT;Portugal;X XXXX XXXX
|
||||
350;GI;Gibraltar;XXXX XXXX
|
||||
299;GL;Greenland;XXX XXX
|
||||
298;FO;Faroe Islands;XXX XXX
|
||||
297;AW;Aruba;XXX XXXX
|
||||
291;ER;Eritrea;X XXX XXX
|
||||
290;SH;Saint Helena;XX XXX
|
||||
269;KM;Comoros;XXX XXXX
|
||||
268;SZ;Swaziland;XXXX XXXX
|
||||
267;BW;Botswana;XX XXX XXX
|
||||
266;LS;Lesotho;XX XXX XXX
|
||||
265;MW;Malawi;77 XXX XXXX
|
||||
264;NA;Namibia;XX XXX XXXX
|
||||
263;ZW;Zimbabwe;XX XXX XXXX
|
||||
262;RE;Réunion;XXX XXX XXX
|
||||
261;MG;Madagascar;XX XX XXX XX
|
||||
260;ZM;Zambia;XX XXX XXXX
|
||||
258;MZ;Mozambique;XX XXX XXXX
|
||||
257;BI;Burundi;XX XX XXXX
|
||||
256;UG;Uganda;XX XXX XXXX
|
||||
255;TZ;Tanzania;XX XXX XXXX
|
||||
254;KE;Kenya;XXX XXX XXX
|
||||
253;DJ;Djibouti;XX XX XX XX
|
||||
252;SO;Somalia;XX XXX XXX
|
||||
251;ET;Ethiopia;XX XXX XXXX
|
||||
250;RW;Rwanda;XXX XXX XXX
|
||||
249;SD;Sudan;XX XXX XXXX
|
||||
248;SC;Seychelles;X XX XX XX
|
||||
247;SH;Saint Helena;XXXX
|
||||
246;IO;Diego Garcia;XXX XXXX
|
||||
245;GW;Guinea-Bissau;XXX XXXX
|
||||
244;AO;Angola;XXX XXX XXX
|
||||
243;CD;Congo (Dem. Rep.);XX XXX XXXX
|
||||
242;CG;Congo (Rep.);XX XXX XXXX
|
||||
241;GA;Gabon;X XX XX XX
|
||||
240;GQ;Equatorial Guinea;XXX XXX XXX
|
||||
239;ST;São Tomé & Príncipe;XX XXXXX
|
||||
238;CV;Cape Verde;XXX XXXX
|
||||
237;CM;Cameroon;XXXX XXXX
|
||||
236;CF;Central African Rep.;XX XX XX XX
|
||||
235;TD;Chad;XX XX XX XX
|
||||
234;NG;Nigeria
|
||||
233;GH;Ghana
|
||||
232;SL;Sierra Leone;XX XXX XXX
|
||||
231;LR;Liberia
|
||||
230;MU;Mauritius
|
||||
229;BJ;Benin;XX XXX XXX
|
||||
228;TG;Togo;XX XXX XXX
|
||||
227;NE;Niger;XX XX XX XX
|
||||
226;BF;Burkina Faso;XX XX XX XX
|
||||
225;CI;Côte d`Ivoire;XX XXX XXX
|
||||
224;GN;Guinea;XXX XXX XXX
|
||||
223;ML;Mali;XXXX XXXX
|
||||
222;MR;Mauritania;XXXX XXXX
|
||||
221;SN;Senegal;XX XXX XXXX
|
||||
220;GM;Gambia;XXX XXXX
|
||||
218;LY;Libya;XX XXX XXXX
|
||||
216;TN;Tunisia;XX XXX XXX
|
||||
213;DZ;Algeria;XXX XX XX XX
|
||||
212;MA;Morocco;XX XXX XXXX
|
||||
211;SS;South Sudan;XX XXX XXXX
|
||||
98;IR;Iran;XXX XXX XXXX
|
||||
95;MM;Myanmar
|
||||
94;LK;Sri Lanka;XX XXX XXXX
|
||||
93;AF;Afghanistan;XXX XXX XXX
|
||||
92;PK;Pakistan;XXX XXX XXXX
|
||||
91;IN;India;XXXXX XXXXX
|
||||
90;TR;Turkey;XXX XXX XXXX
|
||||
86;CN;China;XXX XXXX XXXX
|
||||
84;VN;Vietnam
|
||||
82;KR;South Korea
|
||||
81;JP;Japan;XX XXXX XXXX
|
||||
66;TH;Thailand;X XXXX XXXX
|
||||
65;SG;Singapore;XXXX XXXX
|
||||
64;NZ;New Zealand
|
||||
63;PH;Philippines;XXX XXX XXXX
|
||||
62;ID;Indonesia
|
||||
61;AU;Australia;XXX XXX XXX
|
||||
60;MY;Malaysia
|
||||
58;VE;Venezuela;XXX XXX XXXX
|
||||
57;CO;Colombia;XXX XXX XXXX
|
||||
56;CL;Chile;X XXXX XXXX
|
||||
55;BR;Brazil;XX XXXXX XXXX
|
||||
54;AR;Argentina
|
||||
53;CU;Cuba;XXXX XXXX
|
||||
52;MX;Mexico
|
||||
51;PE;Peru;XXX XXX XXX
|
||||
49;DE;Germany
|
||||
48;PL;Poland;XX XXX XXXX
|
||||
47;NO;Norway;XXXX XXXX
|
||||
46;SE;Sweden;XX XXX XXXX
|
||||
45;DK;Denmark;XXXX XXXX
|
||||
44;GB;United Kingdom;XXXX XXXXXX
|
||||
43;AT;Austria
|
||||
42;YL;Y-land
|
||||
41;CH;Switzerland;XX XXX XXXX
|
||||
40;RO;Romania;XXX XXX XXX
|
||||
39;IT;Italy
|
||||
36;HU;Hungary;XXX XXX XXX
|
||||
34;ES;Spain;XXX XXX XXX
|
||||
33;FR;France;X XX XX XX XX
|
||||
32;BE;Belgium;XXX XX XX XX
|
||||
31;NL;Netherlands;X XX XX XX XX
|
||||
30;GR;Greece;XXX XXX XXXX
|
||||
27;ZA;South Africa;XX XXX XXXX
|
||||
20;EG;Egypt;XX XXXX XXXX
|
||||
7;KZ;Kazakhstan;XXX XXX XX XX
|
||||
7;RU;Russian Federation;XXX XXX XXXX
|
||||
1;PR;Puerto Rico;XXX XXX XXXX
|
||||
1;DO;Dominican Rep.;XXX XXX XXXX
|
||||
1;CA;Canada;XXX XXX XXXX
|
||||
1;US;USA;XXX XXX XXXX
|
||||
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,25 @@
|
||||
/*
|
||||
* This is the source code of Telegram for Android v. 3.x.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2016.
|
||||
*/
|
||||
* Messenger Android Frontend
|
||||
* (C) 2013-2016 Nikolai Kudashov
|
||||
* (C) 2017 Björn Petersen
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see http://www.gnu.org/licenses/ .
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
package com.b44t.messenger;
|
||||
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
/*
|
||||
* This is the source code of Telegram for Android v. 3.x.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2016.
|
||||
*/
|
||||
|
||||
package com.b44t.messenger;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
public class AppStartReceiver extends BroadcastReceiver {
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
AndroidUtilities.runOnUIThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ApplicationLoader.startPushService();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,25 @@
|
||||
/*
|
||||
* This is the source code of Telegram for Android v. 3.x.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2016.
|
||||
*/
|
||||
* Messenger Android Frontend
|
||||
* (C) 2013-2016 Nikolai Kudashov
|
||||
* (C) 2017 Björn Petersen
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see http://www.gnu.org/licenses/ .
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
package com.b44t.messenger;
|
||||
|
||||
@@ -18,65 +33,46 @@ import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.NetworkInfo;
|
||||
import android.os.Handler;
|
||||
import android.os.PowerManager;
|
||||
import android.os.SystemClock;
|
||||
import android.util.Log;
|
||||
|
||||
import com.b44t.ui.Components.ForegroundDetector;
|
||||
import com.b44t.ui.SettingsAdvActivity;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class ApplicationLoader extends Application {
|
||||
private static PendingIntent pendingIntent;
|
||||
|
||||
private static Drawable cachedWallpaper;
|
||||
private static int selectedColor;
|
||||
private static boolean isCustomTheme;
|
||||
private static final Object sync = new Object();
|
||||
|
||||
private static int serviceMessageColor;
|
||||
private static int serviceSelectedMessageColor;
|
||||
|
||||
public static volatile Context applicationContext;
|
||||
public static volatile Handler applicationHandler;
|
||||
private static volatile boolean applicationInited = false;
|
||||
|
||||
public static volatile boolean isScreenOn = false;
|
||||
public static volatile boolean mainInterfacePaused = true;
|
||||
|
||||
public static boolean isCustomTheme() {
|
||||
return isCustomTheme;
|
||||
}
|
||||
public static PowerManager.WakeLock backendWakeLock = null;
|
||||
public static PowerManager.WakeLock wakeupWakeLock = null;
|
||||
private static PowerManager.WakeLock stayAwakeWakeLock = null;
|
||||
|
||||
public static int getSelectedColor() {
|
||||
return selectedColor;
|
||||
}
|
||||
|
||||
public static int fontSize;
|
||||
|
||||
public static void reloadWallpaper() {
|
||||
cachedWallpaper = null;
|
||||
serviceMessageColor = 0;
|
||||
ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE).edit().remove("serviceMessageColor").commit();
|
||||
loadWallpaper();
|
||||
}
|
||||
|
||||
private static void calcBackgroundColor() {
|
||||
int result[] = AndroidUtilities.calcDrawableColor(cachedWallpaper);
|
||||
serviceMessageColor = result[0];
|
||||
serviceSelectedMessageColor = result[1];
|
||||
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE);
|
||||
preferences.edit().putInt("serviceMessageColor", serviceMessageColor).putInt("serviceSelectedMessageColor", serviceSelectedMessageColor).commit();
|
||||
}
|
||||
|
||||
public static int getServiceMessageColor() {
|
||||
return serviceMessageColor;
|
||||
}
|
||||
|
||||
public static int getServiceSelectedMessageColor() {
|
||||
return serviceSelectedMessageColor;
|
||||
return 0x44000000; // this color is used as a background for date headlines, empty chat hints and in the drawer
|
||||
}
|
||||
|
||||
public static void loadWallpaper() {
|
||||
@@ -92,20 +88,15 @@ public class ApplicationLoader extends Application {
|
||||
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE);
|
||||
int selectedBackground = preferences.getInt("selectedBackground", 1000001);
|
||||
selectedColor = preferences.getInt("selectedColor", 0);
|
||||
serviceMessageColor = preferences.getInt("serviceMessageColor", 0);
|
||||
serviceSelectedMessageColor = preferences.getInt("serviceSelectedMessageColor", 0);
|
||||
if (selectedColor == 0) {
|
||||
if (selectedBackground == 1000001) {
|
||||
cachedWallpaper = applicationContext.getResources().getDrawable(R.drawable.background_hd);
|
||||
isCustomTheme = false;
|
||||
} else {
|
||||
File toFile = new File(getFilesDirFixed(), "wallpaper.jpg");
|
||||
if (toFile.exists()) {
|
||||
cachedWallpaper = Drawable.createFromPath(toFile.getAbsolutePath());
|
||||
isCustomTheme = true;
|
||||
} else {
|
||||
cachedWallpaper = applicationContext.getResources().getDrawable(R.drawable.background_hd);
|
||||
isCustomTheme = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -118,9 +109,6 @@ public class ApplicationLoader extends Application {
|
||||
}
|
||||
cachedWallpaper = new ColorDrawable(selectedColor);
|
||||
}
|
||||
if (serviceMessageColor == 0) {
|
||||
calcBackgroundColor();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -145,25 +133,56 @@ public class ApplicationLoader extends Application {
|
||||
path.mkdirs();
|
||||
return path;
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
|
||||
}
|
||||
return new File("/data/data/com.b44t.messenger/files"); // EDIT BY MR
|
||||
return new File("/data/data/com.b44t.messenger/files");
|
||||
}
|
||||
|
||||
public static void postInitApplication() {
|
||||
if (applicationInited) {
|
||||
return;
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
applicationContext = getApplicationContext(); // should be set very first as it may be needed eg. for logging
|
||||
|
||||
MrMailbox.log_i("DeltaChat", "*************** ApplicationLoader.onCreate() ***************");
|
||||
System.loadLibrary("messenger.1");
|
||||
new ForegroundDetector(this);
|
||||
applicationHandler = new Handler(applicationContext.getMainLooper());
|
||||
|
||||
// create wake locks
|
||||
try {
|
||||
PowerManager pm = (PowerManager) ApplicationLoader.applicationContext.getSystemService(Context.POWER_SERVICE);
|
||||
|
||||
backendWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "backendWakeLock" /*any name*/);
|
||||
// bakendWakeLock _is_ reference counted by the backend (every acquire() has a release())
|
||||
|
||||
wakeupWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "wakeupWakeLock" /*any name*/);
|
||||
wakeupWakeLock.setReferenceCounted(false);
|
||||
|
||||
stayAwakeWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "stayAwakeWakeLock" /*any name*/);
|
||||
stayAwakeWakeLock.setReferenceCounted(false);
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.e("DeltaChat", "Cannot acquire wakeLock");
|
||||
}
|
||||
|
||||
applicationInited = true;
|
||||
//convertConfig();
|
||||
// create a MrMailbox object; as android stops the App by just killing it, we do never call MrMailboxUnref()
|
||||
// however, we may want to to have a look at onPause() eg. of activities (eg. for flushing data, if needed)
|
||||
MrMailbox.MrCallback(0, 0, 0); // do not remove this call; this makes sure, the function is not removed from build or warnings are printed!
|
||||
MrMailbox.init();
|
||||
|
||||
// start keep-alive service that restarts the app as soon it is terminated
|
||||
// (this is done by just marking the service as START_STICKY which recreates the service as
|
||||
// it goes away which also inititialized the app indirectly by calling this function)
|
||||
applicationContext.startService(new Intent(applicationContext, KeepAliveService.class));
|
||||
|
||||
// init locale
|
||||
try {
|
||||
LocaleController.getInstance();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// track screen on/ff
|
||||
try {
|
||||
final IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
|
||||
filter.addAction(Intent.ACTION_SCREEN_OFF);
|
||||
@@ -176,148 +195,38 @@ public class ApplicationLoader extends Application {
|
||||
try {
|
||||
PowerManager pm = (PowerManager)ApplicationLoader.applicationContext.getSystemService(Context.POWER_SERVICE);
|
||||
isScreenOn = pm.isScreenOn();
|
||||
FileLog.e("messenger", "screen state = " + isScreenOn);
|
||||
//Log.i("DeltaChat", "screen state = " + isScreenOn);
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
|
||||
}
|
||||
|
||||
UserConfig.loadConfig();
|
||||
String deviceModel;
|
||||
String langCode;
|
||||
String appVersion;
|
||||
String systemVersion;
|
||||
String configPath = getFilesDirFixed().toString();
|
||||
|
||||
try {
|
||||
langCode = LocaleController.getLocaleStringIso639();
|
||||
deviceModel = Build.MANUFACTURER + Build.MODEL;
|
||||
PackageInfo pInfo = ApplicationLoader.applicationContext.getPackageManager().getPackageInfo(ApplicationLoader.applicationContext.getPackageName(), 0);
|
||||
appVersion = pInfo.versionName + " (" + pInfo.versionCode + ")";
|
||||
systemVersion = "SDK " + Build.VERSION.SDK_INT;
|
||||
} catch (Exception e) {
|
||||
langCode = "en";
|
||||
deviceModel = "Android unknown";
|
||||
appVersion = "App version unknown";
|
||||
systemVersion = "SDK " + Build.VERSION.SDK_INT;
|
||||
}
|
||||
if (langCode.trim().length() == 0) {
|
||||
langCode = "en";
|
||||
}
|
||||
if (deviceModel.trim().length() == 0) {
|
||||
deviceModel = "Android unknown";
|
||||
}
|
||||
if (appVersion.trim().length() == 0) {
|
||||
appVersion = "App version unknown";
|
||||
}
|
||||
if (systemVersion.trim().length() == 0) {
|
||||
systemVersion = "SDK Unknown";
|
||||
}
|
||||
// create a timer that wakes up the CPU from time to time
|
||||
TimerReceiver.scheduleNextAlarm();
|
||||
|
||||
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Activity.MODE_PRIVATE);
|
||||
boolean enablePushConnection = preferences.getBoolean("pushConnection", true);
|
||||
|
||||
if( preferences.getInt("notify2_"+MrChat.MR_CHAT_ID_DEADDROP, 666)==666 ) {
|
||||
// make sure, the notifications for the "deaddrop" dialog are muted by default
|
||||
SharedPreferences.Editor editor = preferences.edit();
|
||||
// make sure, the notifications for the "deaddrop" dialog are muted by default
|
||||
SharedPreferences notificationPreferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Activity.MODE_PRIVATE);
|
||||
if( notificationPreferences.getInt("notify2_"+MrChat.MR_CHAT_ID_DEADDROP, 666)==666 ) {
|
||||
SharedPreferences.Editor editor = notificationPreferences.edit();
|
||||
editor.putInt("notify2_"+MrChat.MR_CHAT_ID_DEADDROP, 2);
|
||||
editor.commit();
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
MessagesController.getInstance();
|
||||
ConnectionsManager.getInstance().init(deviceModel, systemVersion, appVersion, langCode, configPath, FileLog.getNetworkLogPath(), UserConfig.getClientUserId(), enablePushConnection);
|
||||
if (UserConfig.getCurrentUser() != null) {
|
||||
//MessagesController.getInstance().putUser(UserConfig.getCurrentUser(), true);
|
||||
SendMessagesHelper.getInstance().checkUnsentMessages();
|
||||
}
|
||||
|
||||
ApplicationLoader app = (ApplicationLoader)ApplicationLoader.applicationContext;
|
||||
FileLog.e("messenger", "app initied");
|
||||
|
||||
//ContactsController.getInstance().checkAppAccount();
|
||||
MediaController.getInstance();
|
||||
|
||||
// EDIT BY MR - open my sqlite file (you can inspect the file eg. with "Tools / Android Device Monitor / File Explorer")
|
||||
// open() sqlite file (you can inspect the file eg. with "Tools / Android Device Monitor / File Explorer")
|
||||
// open() should be called before MessagesController.getInstance() as this also initilizes directories based upon getBlobdir().
|
||||
File dbfile = new File(getFilesDirFixed(), "messenger.db");
|
||||
MrMailbox.open(dbfile.getAbsolutePath(), "");
|
||||
MrMailbox.connect();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
|
||||
applicationContext = getApplicationContext();
|
||||
NativeLoader.initNativeLibs(ApplicationLoader.applicationContext);
|
||||
//ConnectionsManager.native_setJava(Build.VERSION.SDK_INT == 14 || Build.VERSION.SDK_INT == 15);
|
||||
new ForegroundDetector(this);
|
||||
|
||||
// EDIT BY MR - create a MrMailbox object; as android stops the App by just killing it, we do never call MrMailboxUnref()
|
||||
// however, we may want to to have a look at onPause() eg. of activities (eg. for flushing data, if needed)
|
||||
MrMailbox.MrCallback(0, 0, 0); // do not remove this call; this makes sure, the function is not removed from build or warnings are printed!
|
||||
MrMailbox.init();
|
||||
MrMailbox.MrStockAddStr(1, LocaleController.getString("NoMessages", R.string.NoMessages));
|
||||
MrMailbox.MrStockAddStr(2, LocaleController.getString("FromSelf", R.string.FromSelf));
|
||||
MrMailbox.MrStockAddStr(3, LocaleController.getString("Draft", R.string.Draft));
|
||||
MrMailbox.MrStockAddStr(4, LocaleController.getString("MemberSg", R.string.MemberSg));
|
||||
MrMailbox.MrStockAddStr(5, LocaleController.getString("MemberPl", R.string.MemberPl));
|
||||
MrMailbox.MrStockAddStr(6, LocaleController.getString("ContactSg", R.string.ContactSg));
|
||||
MrMailbox.MrStockAddStr(7, LocaleController.getString("ContactPl", R.string.ContactPl));
|
||||
MrMailbox.MrStockAddStr(8, LocaleController.getString("Deaddrop", R.string.Deaddrop));
|
||||
MrMailbox.MrStockAddStr(9, LocaleController.getString("AttachPhoto", R.string.AttachPhoto));
|
||||
MrMailbox.MrStockAddStr(10, LocaleController.getString("AttachVideo", R.string.AttachVideo));
|
||||
MrMailbox.MrStockAddStr(11, LocaleController.getString("AttachAudio", R.string.AttachAudio));
|
||||
MrMailbox.MrStockAddStr(12, LocaleController.getString("AttachDocument", R.string.AttachDocument));
|
||||
MrMailbox.MrStockAddStr(13, LocaleController.getString("DefaultStatusText", R.string.DefaultStatusText));
|
||||
MrMailbox.MrStockAddStr(14, LocaleController.getString("SubjectPrefix", R.string.SubjectPrefix));
|
||||
|
||||
applicationHandler = new Handler(applicationContext.getMainLooper());
|
||||
|
||||
startPushService();
|
||||
}
|
||||
|
||||
/*public static void sendRegIdToBackend(final String token) {
|
||||
Utilities.stageQueue.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
UserConfig.pushString = token;
|
||||
UserConfig.registeredForPush = false;
|
||||
UserConfig.saveConfig(false);
|
||||
if (UserConfig.getClientUserId() != 0) {
|
||||
AndroidUtilities.runOnUIThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
MessagesController.getInstance().registerForPush(token);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}*/
|
||||
|
||||
public static void startPushService() {
|
||||
SharedPreferences preferences = applicationContext.getSharedPreferences("Notifications", MODE_PRIVATE);
|
||||
|
||||
if (preferences.getBoolean("pushService", true)) {
|
||||
AlarmManager am = (AlarmManager) applicationContext.getSystemService(Context.ALARM_SERVICE);
|
||||
Intent i = new Intent(applicationContext, ApplicationLoader.class);
|
||||
pendingIntent = PendingIntent.getBroadcast(applicationContext, 0, i, 0);
|
||||
|
||||
am.cancel(pendingIntent);
|
||||
am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 60000, pendingIntent);
|
||||
|
||||
applicationContext.startService(new Intent(applicationContext, NotificationsService.class));
|
||||
} else {
|
||||
stopPushService();
|
||||
MrMailbox.open(dbfile.getAbsolutePath());
|
||||
if( MrMailbox.isConfigured()!=0 ) {
|
||||
MrMailbox.connect();
|
||||
}
|
||||
}
|
||||
|
||||
public static void stopPushService() {
|
||||
applicationContext.stopService(new Intent(applicationContext, NotificationsService.class));
|
||||
// create other default objects
|
||||
SharedPreferences mainPreferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE);
|
||||
fontSize = mainPreferences.getInt("msg_font_size", SettingsAdvActivity.defMsgFontSize());
|
||||
|
||||
PendingIntent pintent = PendingIntent.getService(applicationContext, 0, new Intent(applicationContext, NotificationsService.class), 0);
|
||||
AlarmManager alarm = (AlarmManager)applicationContext.getSystemService(Context.ALARM_SERVICE);
|
||||
alarm.cancel(pintent);
|
||||
alarm.cancel(pendingIntent);
|
||||
ImageLoader.getInstance();
|
||||
MediaController.getInstance();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -330,4 +239,27 @@ public class ApplicationLoader extends Application {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static int lastClassGuid = 1;
|
||||
public static int generateClassGuid() {
|
||||
return lastClassGuid++;
|
||||
}
|
||||
|
||||
public static boolean isNetworkOnline() {
|
||||
try {
|
||||
ConnectivityManager cm = (ConnectivityManager) ApplicationLoader.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
NetworkInfo netInfo = cm.getActiveNetworkInfo();
|
||||
if (netInfo != null && netInfo.isConnected()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void stayAwakeForAMoment()
|
||||
{
|
||||
stayAwakeWakeLock.acquire(1*60*1000); // 1 Minute to wait for "after chat" messages, after that, we sleep most time, see wakeupWakeLock
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Messenger Android Frontend
|
||||
* (C) 2017 Björn Petersen
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see http://www.gnu.org/licenses/ .
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
package com.b44t.messenger;
|
||||
|
||||
import android.content.ContentProvider;
|
||||
import android.content.ContentValues;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
|
||||
|
||||
public class AttachmentsContentProvider extends ContentProvider {
|
||||
|
||||
/* We save all attachments in our private files-directory
|
||||
that cannot be read by other apps.
|
||||
|
||||
So starting, when starting an Intent for viewing (eg. openForView()), we cannot use the paths.
|
||||
Instead, we give a content://-url that results in calls to this class.
|
||||
|
||||
(An alternative would be to copy files to view to a public directory, however, this would
|
||||
lead to duplicate data.
|
||||
Another alterntive would be to write all attachments to a public directory, however, this
|
||||
may lead to security problems as files are system-wide-readable and would also cause problems
|
||||
if the user or another app deletes these files) */
|
||||
|
||||
@Override
|
||||
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
|
||||
File privateFile = new File(MrMailbox.getBlobdir(), uri.getPath());
|
||||
return ParcelFileDescriptor.open(privateFile, ParcelFileDescriptor.MODE_READ_ONLY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int delete(Uri arg0, String arg1, String[] arg2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType(Uri arg0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uri insert(Uri arg0, ContentValues arg1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreate() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor query(Uri arg0, String[] arg1, String arg2, String[] arg3,
|
||||
String arg4) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int update(Uri arg0, ContentValues arg1, String arg2, String[] arg3) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
/*
|
||||
* This is the source code of Telegram for Android v. 3.x.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2016.
|
||||
*/
|
||||
|
||||
package com.b44t.messenger;
|
||||
|
||||
import android.accounts.AbstractAccountAuthenticator;
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountAuthenticatorResponse;
|
||||
import android.accounts.AccountManager;
|
||||
import android.accounts.NetworkErrorException;
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
|
||||
public class AuthenticatorService extends Service {
|
||||
|
||||
private static class Authenticator extends AbstractAccountAuthenticator {
|
||||
private final Context context;
|
||||
|
||||
public Authenticator(Context context) {
|
||||
super(context);
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle addAccount(AccountAuthenticatorResponse response, String accountType, String authTokenType, String[] requiredFeatures, Bundle options)
|
||||
throws NetworkErrorException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle getAccountRemovalAllowed(AccountAuthenticatorResponse response, Account account) throws NetworkErrorException {
|
||||
return super.getAccountRemovalAllowed(response, account);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle confirmCredentials(AccountAuthenticatorResponse response, Account account, Bundle options) throws NetworkErrorException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle editProperties(AccountAuthenticatorResponse response, String accountType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options)
|
||||
throws NetworkErrorException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthTokenLabel(String authTokenType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle hasFeatures(AccountAuthenticatorResponse response,
|
||||
Account account, String[] features)
|
||||
throws NetworkErrorException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle updateCredentials(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options)
|
||||
throws NetworkErrorException {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static Authenticator authenticator = null;
|
||||
|
||||
protected Authenticator getAuthenticator() {
|
||||
if (authenticator == null) {
|
||||
authenticator = new Authenticator(this);
|
||||
}
|
||||
return authenticator;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
if (intent.getAction().equals(AccountManager.ACTION_AUTHENTICATOR_INTENT)) {
|
||||
return getAuthenticator().getIBinder();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,27 +1,44 @@
|
||||
/*
|
||||
* This is the source code of Telegram for Android v. 3.x.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2016.
|
||||
*/
|
||||
* Messenger Android Frontend
|
||||
* (C) 2013-2016 Nikolai Kudashov
|
||||
* (C) 2017 Björn Petersen
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see http://www.gnu.org/licenses/ .
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
package com.b44t.messenger;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.util.Log;
|
||||
|
||||
public class AutoMessageHeardReceiver extends BroadcastReceiver {
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
ApplicationLoader.postInitApplication();
|
||||
|
||||
long dialog_id = intent.getLongExtra("dialog_id", 0);
|
||||
int max_id = intent.getIntExtra("max_id", 0);
|
||||
if (dialog_id == 0 || max_id == 0) {
|
||||
return;
|
||||
}
|
||||
MessagesController.getInstance().markDialogAsRead(dialog_id, max_id, max_id, 0, true, false);
|
||||
MrMailbox.markseenChat((int)dialog_id);
|
||||
NotificationsController.getInstance().removeSeenMessages();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,25 @@
|
||||
/*
|
||||
* This is the source code of Telegram for Android v. 3.x.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2016.
|
||||
*/
|
||||
* Messenger Android Frontend
|
||||
* (C) 2013-2016 Nikolai Kudashov
|
||||
* (C) 2017 Björn Petersen
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see http://www.gnu.org/licenses/ .
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
package com.b44t.messenger;
|
||||
|
||||
@@ -13,12 +28,13 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.RemoteInput;
|
||||
import android.util.Log;
|
||||
|
||||
public class AutoMessageReplyReceiver extends BroadcastReceiver {
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
ApplicationLoader.postInitApplication();
|
||||
|
||||
Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
|
||||
if (remoteInput == null) {
|
||||
return;
|
||||
@@ -32,7 +48,8 @@ public class AutoMessageReplyReceiver extends BroadcastReceiver {
|
||||
if (dialog_id == 0 || max_id == 0) {
|
||||
return;
|
||||
}
|
||||
SendMessagesHelper.getInstance().sendMessageText(text.toString(), dialog_id, null, null, true, null, null);
|
||||
MessagesController.getInstance().markDialogAsRead(dialog_id, max_id, max_id, 0, true, false);
|
||||
SendMessagesHelper.getInstance().sendMessageText(text.toString(), dialog_id, null);
|
||||
MrMailbox.markseenChat((int)dialog_id);
|
||||
NotificationsController.getInstance().removeSeenMessages();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,25 @@
|
||||
/*
|
||||
* This is the source code of Telegram for Android v. 3.x.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2016.
|
||||
*/
|
||||
* Messenger Android Frontend
|
||||
* (C) 2013-2016 Nikolai Kudashov
|
||||
* (C) 2017 Björn Petersen
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see http://www.gnu.org/licenses/ .
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
package com.b44t.messenger;
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Messenger Android Frontend
|
||||
* (C) 2017 Björn Petersen
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see http://www.gnu.org/licenses/ .
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
package com.b44t.messenger;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.util.Log;
|
||||
|
||||
|
||||
public class BootCompletedReceiver extends BroadcastReceiver {
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
MrMailbox.log_i("DeltaChat", "*** BootCompletedReceiver.onReceive()");
|
||||
// there's nothing more to do here as all initialisation stuff is already done in
|
||||
// ApplicationLoader.onCreate() which is called before this broadcast is sended.
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
/*
|
||||
* This is the source code of Telegram for Android v. 3.x.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2016.
|
||||
*/
|
||||
|
||||
package com.b44t.messenger;
|
||||
|
||||
public class BuildVars {
|
||||
public static boolean DEBUG_VERSION = false;
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* This is the source code of Telegram for Android v. 3.x.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2016.
|
||||
*/
|
||||
|
||||
package com.b44t.messenger;
|
||||
|
||||
public class ChatObject {
|
||||
|
||||
public static final int CHAT_TYPE_CHAT = 0;
|
||||
|
||||
public static boolean isNotInChat(TLRPC.Chat chat) {
|
||||
return chat == null || chat instanceof TLRPC.TL_chatEmpty || chat.left || chat.kicked || chat.deactivated;
|
||||
}
|
||||
|
||||
public static boolean isChannel(TLRPC.Chat chat) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isChannel(int chatId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean canWriteToChat(TLRPC.Chat chat) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
/*
|
||||
* This is the source code of Telegram for Android v. 3.x.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2016.
|
||||
*/
|
||||
|
||||
package com.b44t.messenger;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.IntentService;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Build;
|
||||
import android.system.Os;
|
||||
import android.system.StructStat;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class ClearCacheService extends IntentService {
|
||||
|
||||
public ClearCacheService() {
|
||||
super("ClearCacheService");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onHandleIntent(Intent intent) {
|
||||
ApplicationLoader.postInitApplication();
|
||||
|
||||
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE);
|
||||
final int keepMedia = preferences.getInt("keep_media", 2);
|
||||
if (keepMedia == 2) {
|
||||
return;
|
||||
}
|
||||
Utilities.globalQueue.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
long currentTime = System.currentTimeMillis();
|
||||
long diff = 60 * 60 * 1000 * 24 * (keepMedia == 0 ? 7 : 30);
|
||||
final HashMap<Integer, File> paths = ImageLoader.getInstance().createMediaPaths();
|
||||
for (HashMap.Entry<Integer, File> entry : paths.entrySet()) {
|
||||
if (entry.getKey() == FileLoader.MEDIA_DIR_CACHE) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
File[] array = entry.getValue().listFiles();
|
||||
if (array != null) {
|
||||
for (int b = 0; b < array.length; b++) {
|
||||
File f = array[b];
|
||||
if (f.isFile()) {
|
||||
if (f.getName().equals(".nomedia")) {
|
||||
continue;
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
try {
|
||||
StructStat stat = Os.stat(f.getPath());
|
||||
if (stat.st_atime != 0) {
|
||||
if (stat.st_atime + diff < currentTime) {
|
||||
f.delete();
|
||||
}
|
||||
} else if (stat.st_mtime + diff < currentTime) {
|
||||
f.delete();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
} else if (f.lastModified() + diff < currentTime) {
|
||||
f.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,170 +0,0 @@
|
||||
package com.b44t.messenger;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.NetworkInfo;
|
||||
import android.os.PowerManager;
|
||||
|
||||
public class ConnectionsManager {
|
||||
|
||||
public final static int RequestFlagFailOnServerErrors = 2;
|
||||
|
||||
public final static int ConnectionStateConnecting = 1;
|
||||
public final static int ConnectionStateWaitingForNetwork = 2;
|
||||
public final static int ConnectionStateConnected = 3;
|
||||
public final static int ConnectionStateUpdating = 4;
|
||||
|
||||
private long lastPauseTime = System.currentTimeMillis();
|
||||
private boolean appPaused = true;
|
||||
private int lastClassGuid = 1;
|
||||
private PowerManager.WakeLock wakeLock = null;
|
||||
|
||||
private static volatile ConnectionsManager Instance = null;
|
||||
|
||||
public static ConnectionsManager getInstance() {
|
||||
ConnectionsManager localInstance = Instance;
|
||||
if (localInstance == null) {
|
||||
synchronized (ConnectionsManager.class) {
|
||||
localInstance = Instance;
|
||||
if (localInstance == null) {
|
||||
Instance = localInstance = new ConnectionsManager();
|
||||
}
|
||||
}
|
||||
}
|
||||
return localInstance;
|
||||
}
|
||||
|
||||
public ConnectionsManager() {
|
||||
try {
|
||||
PowerManager pm = (PowerManager) ApplicationLoader.applicationContext.getSystemService(Context.POWER_SERVICE);
|
||||
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "lock");
|
||||
wakeLock.setReferenceCounted(false);
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
}
|
||||
|
||||
public int getCurrentTime() {
|
||||
return MrMailbox.getCurrentTime();
|
||||
}
|
||||
|
||||
public void cancelRequest(int token, boolean notifyServer) {
|
||||
//native_cancelRequest(token, notifyServer);
|
||||
}
|
||||
|
||||
public void cleanup() {
|
||||
//native_cleanUp();
|
||||
}
|
||||
|
||||
public int getConnectionState() {
|
||||
return ConnectionStateWaitingForNetwork; // EDIT BY MR - we're always disconnected from the view of the caller
|
||||
/* EDIT BY MR
|
||||
if (connectionState == ConnectionStateConnected && isUpdating) {
|
||||
return ConnectionStateUpdating;
|
||||
}
|
||||
return connectionState;
|
||||
*/
|
||||
}
|
||||
|
||||
public void setPushConnectionEnabled(boolean value) {
|
||||
//native_setPushConnectionEnabled(value);
|
||||
}
|
||||
|
||||
public void init(String deviceModel, String systemVersion, String appVersion, String langCode, String configPath, String logPath, int userId, boolean enablePushConnection) {
|
||||
//native_init(version, layer, apiId, deviceModel, systemVersion, appVersion, langCode, configPath, logPath, userId, enablePushConnection);
|
||||
//checkConnection();
|
||||
BroadcastReceiver networkStateReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
//checkConnection();
|
||||
}
|
||||
};
|
||||
IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
|
||||
ApplicationLoader.applicationContext.registerReceiver(networkStateReceiver, filter);
|
||||
}
|
||||
|
||||
public void resumeNetworkMaybe() {
|
||||
//native_resumeNetwork(true);
|
||||
}
|
||||
|
||||
public void setAppPaused(final boolean value, final boolean byScreenState) {
|
||||
if (!byScreenState) {
|
||||
appPaused = value;
|
||||
FileLog.d("messenger", "app paused = " + value);
|
||||
}
|
||||
if (value) {
|
||||
if (lastPauseTime == 0) {
|
||||
lastPauseTime = System.currentTimeMillis();
|
||||
}
|
||||
//native_pauseNetwork();
|
||||
} else {
|
||||
if (appPaused) {
|
||||
return;
|
||||
}
|
||||
FileLog.e("messenger", "reset app pause time");
|
||||
/*if (lastPauseTime != 0 && System.currentTimeMillis() - lastPauseTime > 5000) {
|
||||
ContactsController.getInstance().checkContacts();
|
||||
}*/
|
||||
lastPauseTime = 0;
|
||||
//native_resumeNetwork(false);
|
||||
}
|
||||
}
|
||||
|
||||
public int generateClassGuid() {
|
||||
return lastClassGuid++;
|
||||
}
|
||||
|
||||
public static boolean isRoaming() {
|
||||
try {
|
||||
ConnectivityManager cm = (ConnectivityManager) ApplicationLoader.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
NetworkInfo netInfo = cm.getActiveNetworkInfo();
|
||||
if (netInfo != null) {
|
||||
return netInfo.isRoaming();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isConnectedToWiFi() {
|
||||
try {
|
||||
ConnectivityManager cm = (ConnectivityManager) ApplicationLoader.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
NetworkInfo netInfo = cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
|
||||
if (netInfo != null && netInfo.getState() == NetworkInfo.State.CONNECTED) {
|
||||
return true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isNetworkOnline() {
|
||||
try {
|
||||
ConnectivityManager cm = (ConnectivityManager) ApplicationLoader.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
NetworkInfo netInfo = cm.getActiveNetworkInfo();
|
||||
if (netInfo != null && (netInfo.isConnectedOrConnecting() || netInfo.isAvailable())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
netInfo = cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
|
||||
|
||||
if (netInfo != null && netInfo.isConnectedOrConnecting()) {
|
||||
return true;
|
||||
} else {
|
||||
netInfo = cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
|
||||
if (netInfo != null && netInfo.isConnectedOrConnecting()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,51 +1,71 @@
|
||||
/*
|
||||
* This is the source code of Telegram for Android v. 1.3.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2016.
|
||||
*/
|
||||
* Messenger Android Frontend
|
||||
* (C) 2017 Björn Petersen
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see http://www.gnu.org/licenses/ .
|
||||
*
|
||||
*******************************************************************************
|
||||
*
|
||||
* File: ContactsController.java
|
||||
* Authors: Björn Petersen
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
package com.b44t.messenger;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentUris;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.BitmapShader;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.Shader;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.provider.ContactsContract;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
|
||||
import com.b44t.ui.Components.AvatarDrawable;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class ContactsController {
|
||||
|
||||
static ContentResolver s_cr;
|
||||
private static final String TAG = "ContactsController";
|
||||
|
||||
public static class Contact {
|
||||
public String name;
|
||||
public String email;
|
||||
}
|
||||
|
||||
private String[] projectionNames = {
|
||||
private final static String[] projectionNames = {
|
||||
ContactsContract.Data.DISPLAY_NAME,
|
||||
ContactsContract.CommonDataKinds.Email.ADDRESS
|
||||
};
|
||||
|
||||
private static volatile ContactsController Instance = null;
|
||||
|
||||
public static ContactsController getInstance() {
|
||||
ContactsController localInstance = Instance;
|
||||
if (localInstance == null) {
|
||||
synchronized (ContactsController.class) {
|
||||
localInstance = Instance;
|
||||
if (localInstance == null) {
|
||||
Instance = localInstance = new ContactsController();
|
||||
}
|
||||
}
|
||||
}
|
||||
return localInstance;
|
||||
}
|
||||
|
||||
public ContactsController() {
|
||||
}
|
||||
|
||||
public String readContactsFromPhoneBook() {
|
||||
public static String readContactsFromPhoneBook() {
|
||||
HashMap<String, String> contactsMap = new HashMap<String, String>();
|
||||
String allContacts = "";
|
||||
try {
|
||||
@@ -72,12 +92,12 @@ public class ContactsController {
|
||||
pCur.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
|
||||
}
|
||||
return allContacts;
|
||||
}
|
||||
|
||||
private boolean hasContactsPermission() {
|
||||
private static boolean hasContactsPermission() {
|
||||
if (Build.VERSION.SDK_INT >= 23) {
|
||||
return ApplicationLoader.applicationContext.checkSelfPermission(android.Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_GRANTED;
|
||||
}
|
||||
@@ -89,14 +109,14 @@ public class ContactsController {
|
||||
return false;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
;
|
||||
} finally {
|
||||
try {
|
||||
if (cursor != null) {
|
||||
cursor.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@@ -134,4 +154,233 @@ public class ContactsController {
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
|
||||
/* Handle contact images
|
||||
**********************************************************************************************/
|
||||
|
||||
static class AvtCacheEntry {
|
||||
public Bitmap m_avatarBitmap;
|
||||
public String m_fallbackName;
|
||||
public boolean m_needsReload;
|
||||
AvtCacheEntry(Bitmap avatarBitmap, String fallbackName) {
|
||||
m_avatarBitmap = avatarBitmap;
|
||||
m_fallbackName = fallbackName;
|
||||
m_needsReload = false;
|
||||
}
|
||||
}
|
||||
|
||||
private final static String[] s_projectionAvatars = new String[]{
|
||||
ContactsContract.Contacts._ID,
|
||||
ContactsContract.Contacts.PHOTO_ID,
|
||||
ContactsContract.CommonDataKinds.Email.ADDRESS
|
||||
//ContactsContract.CommonDataKinds.Email.DISPLAY_NAME,
|
||||
};
|
||||
private static final Object s_sync = new Object();
|
||||
private static HashMap<String, AvtCacheEntry> s_avtCache = new HashMap<>();
|
||||
|
||||
public static void cleanupAvatarCache() {
|
||||
// to detect changes of the avatar images eg. in the Contacts App,
|
||||
// this function should be called whenever the App goes to background or back to foreground.
|
||||
// instead of emptying the cache, we force a reloading (looks smarter - most times, the avatars do not change)
|
||||
synchronized (s_sync) {
|
||||
for (AvtCacheEntry cacheEntry : s_avtCache.values()) {
|
||||
cacheEntry.m_needsReload = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void setupAvatar(final View avtView,
|
||||
final ImageReceiver avtImageReceiver,
|
||||
final AvatarDrawable avtDrawable,
|
||||
MrContact mrContact,
|
||||
MrChat mrChat)
|
||||
{
|
||||
// get email/name to search avatar image for
|
||||
String tempEmail = null;
|
||||
String tempName = "";
|
||||
if (mrContact != null) {
|
||||
tempEmail = mrContact.getAddr();
|
||||
tempName = mrContact.getDisplayName();
|
||||
} else if (mrChat != null) {
|
||||
tempName = mrChat.getName();
|
||||
if (mrChat.getType() == MrChat.MR_CHAT_NORMAL) {
|
||||
int[] contact_ids = MrMailbox.getChatContacts(mrChat.getId());
|
||||
if (contact_ids.length == 1) {
|
||||
MrContact mrc = MrMailbox.getContact(contact_ids[0]);
|
||||
tempEmail = mrc.getAddr();
|
||||
tempName = mrc.getDisplayName();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setupAvatarByStrings(avtView, avtImageReceiver, avtDrawable, tempEmail, tempName);
|
||||
}
|
||||
|
||||
public static void setupAvatarByStrings(final View avtView,
|
||||
final ImageReceiver avtImageReceiver,
|
||||
final AvatarDrawable avtDrawable,
|
||||
String tempEmail,
|
||||
String tempName)
|
||||
{
|
||||
if( tempEmail == null ) {
|
||||
tempEmail = "fallback:" + tempName;
|
||||
}
|
||||
|
||||
final String email = tempEmail;
|
||||
final String fallbackName = tempName;
|
||||
|
||||
// bind e-mail+name address to view object to detect overwrites and discard loading old images (may happen on fast scrolling)
|
||||
// moreover, check if the avatar is in cache
|
||||
AvtCacheEntry cacheEntry;
|
||||
synchronized (s_sync) {
|
||||
avtImageReceiver.m_userDataUnique = email+fallbackName;
|
||||
cacheEntry = s_avtCache.get(email+fallbackName);
|
||||
}
|
||||
|
||||
if( cacheEntry != null )
|
||||
{
|
||||
// can use avatar from cache, very fine
|
||||
if (cacheEntry.m_avatarBitmap != null) {
|
||||
avtImageReceiver.setImageBitmap(cacheEntry.m_avatarBitmap);
|
||||
} else {
|
||||
avtDrawable.setInfoByName(cacheEntry.m_fallbackName);
|
||||
avtImageReceiver.setImage(null, "50_50", avtDrawable, null, false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// avatar is not in cache, empty the image (may be the bitmap of another use as we re-use the objects)
|
||||
avtImageReceiver.setImage(null, "50_50", null, null, false);
|
||||
}
|
||||
|
||||
if( cacheEntry==null || cacheEntry.m_needsReload )
|
||||
{
|
||||
// avatar is not in cache or needs reloading:
|
||||
// load avatar in a working thread (when loaded, we'll add it to cache and invalidate back in the GUI thread)
|
||||
Utilities.searchQueue.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// is the avatar still desired?
|
||||
synchronized (s_sync) {
|
||||
if (!avtImageReceiver.m_userDataUnique.equals(email+fallbackName)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// try to get avatar image from the address book
|
||||
Bitmap tempBitmap = null;
|
||||
if (!email.startsWith("fallback:")) {
|
||||
try {
|
||||
if (s_cr == null) {
|
||||
s_cr = ApplicationLoader.applicationContext.getContentResolver();
|
||||
}
|
||||
Uri uri = Uri.withAppendedPath(ContactsContract.CommonDataKinds.Email.CONTENT_LOOKUP_URI, Uri.encode(email));
|
||||
Cursor pCur = s_cr.query(uri, s_projectionAvatars, null, null, null);
|
||||
if (pCur != null) {
|
||||
if (pCur.getCount() > 0) {
|
||||
while (pCur.moveToNext()) {
|
||||
int contact_id = pCur.getInt(0);
|
||||
int photo_id = pCur.getInt(1);
|
||||
String addr = pCur.getString(2);
|
||||
if (addr.equalsIgnoreCase(email) && contact_id > 0 && photo_id > 0) {
|
||||
Bitmap tempBitmap2 = loadContactPhoto(s_cr, contact_id, photo_id);
|
||||
if (tempBitmap2 != null) {
|
||||
tempBitmap = createRoundBitmap(tempBitmap2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
pCur.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
final Bitmap photoBitmap = tempBitmap;
|
||||
|
||||
AndroidUtilities.runOnUIThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// is the avatar still desired?
|
||||
synchronized (s_sync) {
|
||||
if (!avtImageReceiver.m_userDataUnique.equals(email+fallbackName)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (photoBitmap != null) {
|
||||
avtImageReceiver.setImageBitmap(photoBitmap);
|
||||
} else {
|
||||
avtDrawable.setInfoByName(fallbackName);
|
||||
avtImageReceiver.setImage(null, "50_50", avtDrawable, null, false);
|
||||
}
|
||||
avtView.invalidate();
|
||||
|
||||
synchronized (s_sync) {
|
||||
s_avtCache.put(email+fallbackName, new AvtCacheEntry(photoBitmap, fallbackName));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// from http://stackoverflow.com/questions/2383580/how-do-i-load-a-contact-photo
|
||||
public static Bitmap loadContactPhoto(ContentResolver cr, long contact_id, long photo_id)
|
||||
{
|
||||
// first try using photo_id
|
||||
byte[] photoBytes = null;
|
||||
Uri photoUri = ContentUris.withAppendedId(ContactsContract.Data.CONTENT_URI, photo_id);
|
||||
Cursor c = cr.query(photoUri, new String[] {ContactsContract.CommonDataKinds.Photo.PHOTO}, null, null, null);
|
||||
if( c != null ) {
|
||||
try {
|
||||
if (c.moveToFirst()) {
|
||||
photoBytes = c.getBlob(0);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
;
|
||||
} finally {
|
||||
c.close();
|
||||
}
|
||||
}
|
||||
if (photoBytes != null) {
|
||||
return BitmapFactory.decodeByteArray(photoBytes, 0, photoBytes.length);
|
||||
}
|
||||
|
||||
// second try using contact_id
|
||||
Uri uri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, contact_id);
|
||||
InputStream input = ContactsContract.Contacts.openContactPhotoInputStream(cr, uri);
|
||||
if (input != null) {
|
||||
return BitmapFactory.decodeStream(input);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Paint roundPaint;
|
||||
private static RectF bitmapRect;
|
||||
private static Bitmap createRoundBitmap(Bitmap bitmap) {
|
||||
try {
|
||||
Bitmap result = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
|
||||
result.eraseColor(Color.TRANSPARENT);
|
||||
Canvas canvas = new Canvas(result);
|
||||
BitmapShader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
|
||||
if (roundPaint == null) {
|
||||
roundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
bitmapRect = new RectF();
|
||||
}
|
||||
roundPaint.setShader(shader);
|
||||
bitmapRect.set(0, 0, bitmap.getWidth(), bitmap.getHeight());
|
||||
canvas.drawRoundRect(bitmapRect, bitmap.getWidth(), bitmap.getHeight(), roundPaint);
|
||||
return result;
|
||||
} catch (Throwable e) {
|
||||
;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
/*
|
||||
* This is the source code of Telegram for Android v. 3.x.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2016.
|
||||
*/
|
||||
|
||||
package com.b44t.messenger;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.accounts.OperationCanceledException;
|
||||
import android.app.Service;
|
||||
import android.content.AbstractThreadedSyncAdapter;
|
||||
import android.content.ContentProviderClient;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SyncResult;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
|
||||
public class ContactsSyncAdapterService extends Service {
|
||||
private static SyncAdapterImpl sSyncAdapter = null;
|
||||
|
||||
public ContactsSyncAdapterService() {
|
||||
super();
|
||||
}
|
||||
|
||||
private static class SyncAdapterImpl extends AbstractThreadedSyncAdapter {
|
||||
private Context mContext;
|
||||
|
||||
public SyncAdapterImpl(Context context) {
|
||||
super(context, true);
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) {
|
||||
try {
|
||||
ContactsSyncAdapterService.performSync(mContext, account, extras, authority, provider, syncResult);
|
||||
} catch (OperationCanceledException e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return getSyncAdapter().getSyncAdapterBinder();
|
||||
}
|
||||
|
||||
private SyncAdapterImpl getSyncAdapter() {
|
||||
if (sSyncAdapter == null) {
|
||||
sSyncAdapter = new SyncAdapterImpl(this);
|
||||
}
|
||||
return sSyncAdapter;
|
||||
}
|
||||
|
||||
private static void performSync(Context context, Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult)
|
||||
throws OperationCanceledException {
|
||||
FileLog.d("messenger", "performSync: " + account.toString());
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,25 @@
|
||||
/*
|
||||
* This is the source code of Telegram for Android v. 3.x.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2016.
|
||||
*/
|
||||
* Messenger Android Frontend
|
||||
* (C) 2013-2016 Nikolai Kudashov
|
||||
* (C) 2017 Björn Petersen
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see http://www.gnu.org/licenses/ .
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
package com.b44t.messenger;
|
||||
|
||||
@@ -33,7 +48,7 @@ public class DispatchQueue extends Thread {
|
||||
handler.sendMessageDelayed(msg, delay);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
|
||||
}
|
||||
}
|
||||
*/
|
||||
@@ -43,7 +58,7 @@ public class DispatchQueue extends Thread {
|
||||
syncLatch.await();
|
||||
handler.removeCallbacks(runnable);
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +75,7 @@ public class DispatchQueue extends Thread {
|
||||
handler.postDelayed(runnable, delay);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,7 +85,7 @@ public class DispatchQueue extends Thread {
|
||||
syncLatch.await();
|
||||
handler.removeCallbacksAndMessages(null);
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
/*
|
||||
* This is the source code of Telegram for Android v. 3.x.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2016.
|
||||
*/
|
||||
|
||||
package com.b44t.messenger;
|
||||
|
||||
public class DownloadObject {
|
||||
public TLObject object;
|
||||
public int type;
|
||||
public long id;
|
||||
}
|
||||
@@ -1,10 +1,25 @@
|
||||
/*
|
||||
* This is the source code of Telegram for Android v. 3.x.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2016.
|
||||
*/
|
||||
* Messenger Android Frontend
|
||||
* (C) 2013-2016 Nikolai Kudashov
|
||||
* (C) 2017 Björn Petersen
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see http://www.gnu.org/licenses/ .
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
package com.b44t.messenger;
|
||||
|
||||
@@ -102,7 +117,7 @@ public class Emoji {
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -143,7 +158,7 @@ public class Emoji {
|
||||
}
|
||||
});
|
||||
} catch (Throwable x) {
|
||||
FileLog.e("messenger", "Error loading emoji", x);
|
||||
//Log.i("DeltaChat", "Error loading emoji", x);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,7 +209,7 @@ public class Emoji {
|
||||
public static EmojiDrawable getEmojiDrawable(CharSequence code) {
|
||||
DrawableInfo info = rects.get(code);
|
||||
if (info == null) {
|
||||
FileLog.e("messenger", "No drawable for emoji " + code);
|
||||
//Log.i("DeltaChat", "No drawable for emoji " + code);
|
||||
return null;
|
||||
}
|
||||
EmojiDrawable ed = new EmojiDrawable(info);
|
||||
@@ -419,7 +434,7 @@ public class Emoji {
|
||||
// }
|
||||
// }
|
||||
// } catch (Exception e) {
|
||||
// FileLog.e("messenger", e);
|
||||
//
|
||||
// return cs;
|
||||
// }
|
||||
return s;
|
||||
|
||||
@@ -1,10 +1,25 @@
|
||||
/*
|
||||
* This is the source code of Telegram for Android v. 3.x.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2016.
|
||||
*/
|
||||
* Messenger Android Frontend
|
||||
* (C) 2013-2016 Nikolai Kudashov
|
||||
* (C) 2017 Björn Petersen
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see http://www.gnu.org/licenses/ .
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
package com.b44t.messenger;
|
||||
|
||||
|
||||
@@ -1,428 +0,0 @@
|
||||
/*
|
||||
* This is the source code of Telegram for Android v. 3.x.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2016.
|
||||
*/
|
||||
|
||||
package com.b44t.messenger;
|
||||
|
||||
import java.io.RandomAccessFile;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class FileLoadOperation {
|
||||
|
||||
private static class RequestInfo {
|
||||
private int requestToken;
|
||||
private int offset;
|
||||
}
|
||||
|
||||
private final static int stateIdle = 0;
|
||||
private final static int stateDownloading = 1;
|
||||
private final static int stateFailed = 2;
|
||||
private final static int stateFinished = 3;
|
||||
|
||||
private final static int downloadChunkSize = 1024 * 32;
|
||||
private final static int downloadChunkSizeBig = 1024 * 128;
|
||||
private final static int maxDownloadRequests = 4;
|
||||
private final static int maxDownloadRequestsBig = 2;
|
||||
private final static int bigFileSizeFrom = 1024 * 1024;
|
||||
|
||||
private int datacenter_id;
|
||||
private TLRPC.InputFileLocation location;
|
||||
private volatile int state = stateIdle;
|
||||
private int downloadedBytes;
|
||||
private int totalBytesCount;
|
||||
private int bytesCountPadding;
|
||||
private FileLoadOperationDelegate delegate;
|
||||
private byte[] key;
|
||||
private byte[] iv;
|
||||
private int currentDownloadChunkSize;
|
||||
private int currentMaxDownloadRequests;
|
||||
private int requestsCount;
|
||||
private int renameRetryCount;
|
||||
|
||||
private int nextDownloadOffset;
|
||||
private ArrayList<RequestInfo> requestInfos;
|
||||
private ArrayList<RequestInfo> delayedRequestInfos;
|
||||
|
||||
private File cacheFileTemp;
|
||||
private File cacheFileFinal;
|
||||
private File cacheIvTemp;
|
||||
|
||||
private String ext;
|
||||
private RandomAccessFile fileOutputStream;
|
||||
private RandomAccessFile fiv;
|
||||
private File storePath;
|
||||
private File tempPath;
|
||||
private boolean isForceRequest;
|
||||
|
||||
public interface FileLoadOperationDelegate {
|
||||
void didFinishLoadingFile(FileLoadOperation operation, File finalFile);
|
||||
void didFailedLoadingFile(FileLoadOperation operation, int state);
|
||||
void didChangedLoadProgress(FileLoadOperation operation, float progress);
|
||||
}
|
||||
|
||||
public FileLoadOperation(TLRPC.FileLocation photoLocation, String extension, int size) {
|
||||
/*if (photoLocation instanceof TLRPC.TL_fileEncryptedLocation) {
|
||||
location = new TLRPC.TL_inputEncryptedFileLocation();
|
||||
location.id = photoLocation.volume_id;
|
||||
location.volume_id = photoLocation.volume_id;
|
||||
location.access_hash = photoLocation.secret;
|
||||
location.local_id = photoLocation.local_id;
|
||||
iv = new byte[32];
|
||||
System.arraycopy(photoLocation.iv, 0, iv, 0, iv.length);
|
||||
key = photoLocation.key;
|
||||
datacenter_id = photoLocation.dc_id;
|
||||
} else*/ if (photoLocation instanceof TLRPC.TL_fileLocation) {
|
||||
location = new TLRPC.TL_inputFileLocation();
|
||||
location.volume_id = photoLocation.volume_id;
|
||||
location.local_id = photoLocation.local_id;
|
||||
datacenter_id = photoLocation.dc_id;
|
||||
}
|
||||
totalBytesCount = size;
|
||||
ext = extension != null ? extension : "jpg";
|
||||
}
|
||||
|
||||
public FileLoadOperation(TLRPC.Document documentLocation) {
|
||||
try {
|
||||
/*if (documentLocation instanceof TLRPC.TL_documentEncrypted) {
|
||||
location = new TLRPC.TL_inputEncryptedFileLocation();
|
||||
location.id = documentLocation.id;
|
||||
location.access_hash = documentLocation.access_hash;
|
||||
datacenter_id = documentLocation.dc_id;
|
||||
iv = new byte[32];
|
||||
System.arraycopy(documentLocation.iv, 0, iv, 0, iv.length);
|
||||
key = documentLocation.key;
|
||||
} else*/ if (documentLocation instanceof TLRPC.TL_document) {
|
||||
location = new TLRPC.TL_inputDocumentFileLocation();
|
||||
location.id = documentLocation.id;
|
||||
location.access_hash = documentLocation.access_hash;
|
||||
datacenter_id = documentLocation.dc_id;
|
||||
}
|
||||
totalBytesCount = documentLocation.size;
|
||||
if (key != null) {
|
||||
int toAdd = 0;
|
||||
if (totalBytesCount % 16 != 0) {
|
||||
bytesCountPadding = 16 - totalBytesCount % 16;
|
||||
totalBytesCount += bytesCountPadding;
|
||||
}
|
||||
}
|
||||
ext = FileLoader.getDocumentFileName(documentLocation);
|
||||
int idx;
|
||||
if (ext == null || (idx = ext.lastIndexOf('.')) == -1) {
|
||||
ext = "";
|
||||
} else {
|
||||
ext = ext.substring(idx);
|
||||
}
|
||||
if (ext.length() <= 1) {
|
||||
if (documentLocation.mime_type != null) {
|
||||
switch (documentLocation.mime_type) {
|
||||
case "video/mp4":
|
||||
ext = ".mp4";
|
||||
break;
|
||||
case "audio/ogg":
|
||||
ext = ".ogg";
|
||||
break;
|
||||
default:
|
||||
ext = "";
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
ext = "";
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
state = stateFailed;
|
||||
cleanup();
|
||||
Utilities.stageQueue.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
delegate.didFailedLoadingFile(FileLoadOperation.this, 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void setForceRequest(boolean forceRequest) {
|
||||
isForceRequest = forceRequest;
|
||||
}
|
||||
|
||||
public boolean isForceRequest() {
|
||||
return isForceRequest;
|
||||
}
|
||||
|
||||
public void setPaths(File store, File temp) {
|
||||
storePath = store;
|
||||
tempPath = temp;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
if (state != stateIdle) {
|
||||
return;
|
||||
}
|
||||
currentDownloadChunkSize = totalBytesCount >= bigFileSizeFrom ? downloadChunkSizeBig : downloadChunkSize;
|
||||
currentMaxDownloadRequests = totalBytesCount >= bigFileSizeFrom ? maxDownloadRequestsBig : maxDownloadRequests;
|
||||
requestInfos = new ArrayList<>(currentMaxDownloadRequests);
|
||||
delayedRequestInfos = new ArrayList<>(currentMaxDownloadRequests - 1);
|
||||
state = stateDownloading;
|
||||
if (location == null) {
|
||||
cleanup();
|
||||
Utilities.stageQueue.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
delegate.didFailedLoadingFile(FileLoadOperation.this, 0);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
String fileNameFinal;
|
||||
String fileNameTemp;
|
||||
String fileNameIv = null;
|
||||
if (location.volume_id != 0 && location.local_id != 0) {
|
||||
fileNameTemp = location.volume_id + "_" + location.local_id + ".temp";
|
||||
fileNameFinal = location.volume_id + "_" + location.local_id + "." + ext;
|
||||
if (key != null) {
|
||||
fileNameIv = location.volume_id + "_" + location.local_id + ".iv";
|
||||
}
|
||||
if (datacenter_id == Integer.MIN_VALUE || location.volume_id == Integer.MIN_VALUE || datacenter_id == 0) {
|
||||
cleanup();
|
||||
Utilities.stageQueue.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
delegate.didFailedLoadingFile(FileLoadOperation.this, 0);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
fileNameTemp = datacenter_id + "_" + location.id + ".temp";
|
||||
fileNameFinal = datacenter_id + "_" + location.id + ext;
|
||||
if (key != null) {
|
||||
fileNameIv = datacenter_id + "_" + location.id + ".iv";
|
||||
}
|
||||
if (datacenter_id == 0 || location.id == 0) {
|
||||
cleanup();
|
||||
Utilities.stageQueue.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
delegate.didFailedLoadingFile(FileLoadOperation.this, 0);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
cacheFileFinal = new File(storePath, fileNameFinal);
|
||||
boolean exist = cacheFileFinal.exists();
|
||||
if (exist && totalBytesCount != 0 && totalBytesCount != cacheFileFinal.length()) {
|
||||
cacheFileFinal.delete();
|
||||
}
|
||||
|
||||
if (!cacheFileFinal.exists()) {
|
||||
cacheFileTemp = new File(tempPath, fileNameTemp);
|
||||
if (cacheFileTemp.exists()) {
|
||||
downloadedBytes = (int) cacheFileTemp.length();
|
||||
nextDownloadOffset = downloadedBytes = downloadedBytes / currentDownloadChunkSize * currentDownloadChunkSize;
|
||||
}
|
||||
|
||||
if (BuildVars.DEBUG_VERSION) {
|
||||
FileLog.d("messenger", "start loading file to temp = " + cacheFileTemp + " final = " + cacheFileFinal);
|
||||
}
|
||||
|
||||
if (fileNameIv != null) {
|
||||
cacheIvTemp = new File(tempPath, fileNameIv);
|
||||
try {
|
||||
fiv = new RandomAccessFile(cacheIvTemp, "rws");
|
||||
long len = cacheIvTemp.length();
|
||||
if (len > 0 && len % 32 == 0) {
|
||||
fiv.read(iv, 0, 32);
|
||||
} else {
|
||||
downloadedBytes = 0;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
downloadedBytes = 0;
|
||||
}
|
||||
}
|
||||
try {
|
||||
fileOutputStream = new RandomAccessFile(cacheFileTemp, "rws");
|
||||
if (downloadedBytes != 0) {
|
||||
fileOutputStream.seek(downloadedBytes);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
if (fileOutputStream == null) {
|
||||
cleanup();
|
||||
Utilities.stageQueue.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
delegate.didFailedLoadingFile(FileLoadOperation.this, 0);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
Utilities.stageQueue.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (totalBytesCount != 0 && downloadedBytes == totalBytesCount) {
|
||||
try {
|
||||
onFinishLoadingFile();
|
||||
} catch (Exception e) {
|
||||
delegate.didFailedLoadingFile(FileLoadOperation.this, 0);
|
||||
}
|
||||
} else {
|
||||
startDownloadRequest();
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
try {
|
||||
onFinishLoadingFile();
|
||||
} catch (Exception e) {
|
||||
delegate.didFailedLoadingFile(FileLoadOperation.this, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
Utilities.stageQueue.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (state == stateFinished || state == stateFailed) {
|
||||
return;
|
||||
}
|
||||
state = stateFailed;
|
||||
cleanup();
|
||||
if (requestInfos != null) {
|
||||
for (int a = 0; a < requestInfos.size(); a++) {
|
||||
RequestInfo requestInfo = requestInfos.get(a);
|
||||
if (requestInfo.requestToken != 0) {
|
||||
ConnectionsManager.getInstance().cancelRequest(requestInfo.requestToken, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
delegate.didFailedLoadingFile(FileLoadOperation.this, 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void cleanup() {
|
||||
try {
|
||||
if (fileOutputStream != null) {
|
||||
try {
|
||||
fileOutputStream.getChannel().close();
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
fileOutputStream.close();
|
||||
fileOutputStream = null;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
|
||||
try {
|
||||
if (fiv != null) {
|
||||
fiv.close();
|
||||
fiv = null;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
if (delayedRequestInfos != null) {
|
||||
for (int a = 0; a < delayedRequestInfos.size(); a++) {
|
||||
RequestInfo requestInfo = delayedRequestInfos.get(a);
|
||||
/*if (requestInfo.response != null) {
|
||||
requestInfo.response.disableFree = false;
|
||||
requestInfo.response.freeResources();
|
||||
}*/
|
||||
}
|
||||
delayedRequestInfos.clear();
|
||||
}
|
||||
}
|
||||
|
||||
private void onFinishLoadingFile() throws Exception {
|
||||
if (state != stateDownloading) {
|
||||
return;
|
||||
}
|
||||
state = stateFinished;
|
||||
cleanup();
|
||||
if (cacheIvTemp != null) {
|
||||
cacheIvTemp.delete();
|
||||
cacheIvTemp = null;
|
||||
}
|
||||
if (cacheFileTemp != null) {
|
||||
boolean renameResult = cacheFileTemp.renameTo(cacheFileFinal);
|
||||
if (!renameResult) {
|
||||
if (BuildVars.DEBUG_VERSION) {
|
||||
FileLog.e("messenger", "unable to rename temp = " + cacheFileTemp + " to final = " + cacheFileFinal + " retry = " + renameRetryCount);
|
||||
}
|
||||
renameRetryCount++;
|
||||
if (renameRetryCount < 3) {
|
||||
state = stateDownloading;
|
||||
Utilities.stageQueue.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
onFinishLoadingFile();
|
||||
} catch (Exception e) {
|
||||
delegate.didFailedLoadingFile(FileLoadOperation.this, 0);
|
||||
}
|
||||
}
|
||||
}, 200);
|
||||
return;
|
||||
}
|
||||
cacheFileFinal = cacheFileTemp;
|
||||
}
|
||||
}
|
||||
if (BuildVars.DEBUG_VERSION) {
|
||||
FileLog.e("messenger", "finished downloading file to " + cacheFileFinal);
|
||||
}
|
||||
delegate.didFinishLoadingFile(FileLoadOperation.this, cacheFileFinal);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void startDownloadRequest() {
|
||||
if (state != stateDownloading || totalBytesCount > 0 && nextDownloadOffset >= totalBytesCount || requestInfos.size() + delayedRequestInfos.size() >= currentMaxDownloadRequests) {
|
||||
return;
|
||||
}
|
||||
int count = 1;
|
||||
if (totalBytesCount > 0) {
|
||||
count = Math.max(0, currentMaxDownloadRequests - requestInfos.size() - delayedRequestInfos.size());
|
||||
}
|
||||
|
||||
for (int a = 0; a < count; a++) {
|
||||
if (totalBytesCount > 0 && nextDownloadOffset >= totalBytesCount) {
|
||||
break;
|
||||
}
|
||||
boolean isLast = totalBytesCount <= 0 || a == count - 1 || totalBytesCount > 0 && nextDownloadOffset + currentDownloadChunkSize >= totalBytesCount;
|
||||
//TLRPC.TL_upload_getFile req = new TLRPC.TL_upload_getFile();
|
||||
//req.location = location;
|
||||
//req.offset = nextDownloadOffset;
|
||||
//req.limit = currentDownloadChunkSize;
|
||||
nextDownloadOffset += currentDownloadChunkSize;
|
||||
|
||||
final RequestInfo requestInfo = new RequestInfo();
|
||||
requestInfos.add(requestInfo);
|
||||
requestInfo.offset = nextDownloadOffset;
|
||||
requestInfo.requestToken = 0;/*ConnectionsManager.getInstance().sendRequest(req, new RequestDelegate() {
|
||||
@Override
|
||||
public void run(TLObject response, TLRPC.TL_error error) {
|
||||
requestInfo.response = (TLRPC.TL_upload_file) response;
|
||||
processRequestResult(requestInfo, error);
|
||||
}
|
||||
}, null, (isForceRequest ? ConnectionsManager.RequestFlagForceDownload : 0) | ConnectionsManager.RequestFlagFailOnServerErrors, datacenter_id, requestsCount % 2 == 0 ? ConnectionsManager.ConnectionTypeDownload : ConnectionsManager.ConnectionTypeDownload2, isLast);*/
|
||||
requestsCount++;
|
||||
}
|
||||
}
|
||||
|
||||
public void setDelegate(FileLoadOperationDelegate delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,25 @@
|
||||
/*
|
||||
* This is the source code of Telegram for Android v. 3.x.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2016.
|
||||
*/
|
||||
* Messenger Android Frontend
|
||||
* (C) 2013-2016 Nikolai Kudashov
|
||||
* (C) 2017 Björn Petersen
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see http://www.gnu.org/licenses/ .
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
package com.b44t.messenger;
|
||||
|
||||
@@ -17,20 +32,6 @@ import java.util.concurrent.Semaphore;
|
||||
|
||||
public class FileLoader {
|
||||
|
||||
public interface FileLoaderDelegate {
|
||||
void fileUploadProgressChanged(String location, float progress, boolean isEncrypted);
|
||||
|
||||
void fileDidUploaded(String location, TLRPC.InputFile inputFile, TLRPC.InputEncryptedFile inputEncryptedFile, byte[] key, byte[] iv, long totalFileSize);
|
||||
|
||||
void fileDidFailedUpload(String location, boolean isEncrypted);
|
||||
|
||||
void fileDidLoaded(String location, File finalFile, int type);
|
||||
|
||||
void fileDidFailedLoad(String location, int state);
|
||||
|
||||
void fileLoadProgressChanged(String location, float progress);
|
||||
}
|
||||
|
||||
public static final int MEDIA_DIR_IMAGE = 0;
|
||||
public static final int MEDIA_DIR_AUDIO = 1;
|
||||
public static final int MEDIA_DIR_VIDEO = 2;
|
||||
@@ -38,25 +39,6 @@ public class FileLoader {
|
||||
public static final int MEDIA_DIR_CACHE = 4;
|
||||
|
||||
private HashMap<Integer, File> mediaDirs = null;
|
||||
private volatile DispatchQueue fileLoaderQueue = new DispatchQueue("fileUploadQueue");
|
||||
|
||||
private LinkedList<FileUploadOperation> uploadOperationQueue = new LinkedList<>();
|
||||
private LinkedList<FileUploadOperation> uploadSmallOperationQueue = new LinkedList<>();
|
||||
private LinkedList<FileLoadOperation> loadOperationQueue = new LinkedList<>();
|
||||
private LinkedList<FileLoadOperation> audioLoadOperationQueue = new LinkedList<>();
|
||||
private LinkedList<FileLoadOperation> photoLoadOperationQueue = new LinkedList<>();
|
||||
private ConcurrentHashMap<String, FileUploadOperation> uploadOperationPaths = new ConcurrentHashMap<>();
|
||||
private ConcurrentHashMap<String, FileUploadOperation> uploadOperationPathsEnc = new ConcurrentHashMap<>();
|
||||
private ConcurrentHashMap<String, FileLoadOperation> loadOperationPaths = new ConcurrentHashMap<>();
|
||||
private HashMap<String, Long> uploadSizes = new HashMap<>();
|
||||
|
||||
private FileLoaderDelegate delegate = null;
|
||||
|
||||
private int currentLoadOperationsCount = 0;
|
||||
private int currentAudioLoadOperationsCount = 0;
|
||||
private int currentPhotoLoadOperationsCount = 0;
|
||||
private int currentUploadOperationsCount = 0;
|
||||
private int currentUploadSmallOperationsCount = 0;
|
||||
|
||||
private static volatile FileLoader Instance = null;
|
||||
|
||||
@@ -77,11 +59,7 @@ public class FileLoader {
|
||||
mediaDirs = dirs;
|
||||
}
|
||||
|
||||
public File checkDirectory(int type) {
|
||||
return mediaDirs.get(type);
|
||||
}
|
||||
|
||||
public File getDirectory(int type) {
|
||||
public File getDirectory(int type) { // always returns the cache directory as this is the only one set in mediaDirs[] - we do not use the other directories at the moment
|
||||
File dir = mediaDirs.get(type);
|
||||
if (dir == null && type != MEDIA_DIR_CACHE) {
|
||||
dir = mediaDirs.get(MEDIA_DIR_CACHE);
|
||||
@@ -96,418 +74,15 @@ public class FileLoader {
|
||||
return dir;
|
||||
}
|
||||
|
||||
/*
|
||||
public void checkUploadNewDataAvailable(final String location, final boolean encrypted, final long finalSize) {
|
||||
fileLoaderQueue.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
FileUploadOperation operation;
|
||||
if (encrypted) {
|
||||
operation = uploadOperationPathsEnc.get(location);
|
||||
} else {
|
||||
operation = uploadOperationPaths.get(location);
|
||||
}
|
||||
if (operation != null) {
|
||||
operation.checkNewDataAvailable(finalSize);
|
||||
} else if (finalSize != 0) {
|
||||
uploadSizes.put(location, finalSize);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
*/
|
||||
|
||||
public void uploadFile(final String location, final boolean encrypted, final boolean small) {
|
||||
uploadFile(location, encrypted, small, 0);
|
||||
}
|
||||
|
||||
public void uploadFile(final String location, final boolean encrypted, final boolean small, final int estimatedSize) {
|
||||
if (location == null) {
|
||||
return;
|
||||
}
|
||||
fileLoaderQueue.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (encrypted) {
|
||||
if (uploadOperationPathsEnc.containsKey(location)) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (uploadOperationPaths.containsKey(location)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
int esimated = estimatedSize;
|
||||
if (esimated != 0) {
|
||||
Long finalSize = uploadSizes.get(location);
|
||||
if (finalSize != null) {
|
||||
esimated = 0;
|
||||
uploadSizes.remove(location);
|
||||
}
|
||||
}
|
||||
FileUploadOperation operation = new FileUploadOperation(location, encrypted, esimated);
|
||||
if (encrypted) {
|
||||
uploadOperationPathsEnc.put(location, operation);
|
||||
} else {
|
||||
uploadOperationPaths.put(location, operation);
|
||||
}
|
||||
operation.delegate = new FileUploadOperation.FileUploadOperationDelegate() {
|
||||
@Override
|
||||
public void didFinishUploadingFile(final FileUploadOperation operation, final TLRPC.InputFile inputFile, final TLRPC.InputEncryptedFile inputEncryptedFile, final byte[] key, final byte[] iv) {
|
||||
fileLoaderQueue.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (encrypted) {
|
||||
uploadOperationPathsEnc.remove(location);
|
||||
} else {
|
||||
uploadOperationPaths.remove(location);
|
||||
}
|
||||
if (small) {
|
||||
currentUploadSmallOperationsCount--;
|
||||
if (currentUploadSmallOperationsCount < 1) {
|
||||
FileUploadOperation operation = uploadSmallOperationQueue.poll();
|
||||
if (operation != null) {
|
||||
currentUploadSmallOperationsCount++;
|
||||
operation.start();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
currentUploadOperationsCount--;
|
||||
if (currentUploadOperationsCount < 1) {
|
||||
FileUploadOperation operation = uploadOperationQueue.poll();
|
||||
if (operation != null) {
|
||||
currentUploadOperationsCount++;
|
||||
operation.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (delegate != null) {
|
||||
delegate.fileDidUploaded(location, inputFile, inputEncryptedFile, key, iv, operation.getTotalFileSize());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void didFailedUploadingFile(final FileUploadOperation operation) {
|
||||
fileLoaderQueue.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (encrypted) {
|
||||
uploadOperationPathsEnc.remove(location);
|
||||
} else {
|
||||
uploadOperationPaths.remove(location);
|
||||
}
|
||||
if (delegate != null) {
|
||||
delegate.fileDidFailedUpload(location, encrypted);
|
||||
}
|
||||
if (small) {
|
||||
currentUploadSmallOperationsCount--;
|
||||
if (currentUploadSmallOperationsCount < 1) {
|
||||
FileUploadOperation operation = uploadSmallOperationQueue.poll();
|
||||
if (operation != null) {
|
||||
currentUploadSmallOperationsCount++;
|
||||
operation.start();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
currentUploadOperationsCount--;
|
||||
if (currentUploadOperationsCount < 1) {
|
||||
FileUploadOperation operation = uploadOperationQueue.poll();
|
||||
if (operation != null) {
|
||||
currentUploadOperationsCount++;
|
||||
operation.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void didChangedUploadProgress(FileUploadOperation operation, final float progress) {
|
||||
if (delegate != null) {
|
||||
delegate.fileUploadProgressChanged(location, progress, encrypted);
|
||||
}
|
||||
}
|
||||
};
|
||||
if (small) {
|
||||
if (currentUploadSmallOperationsCount < 1) {
|
||||
currentUploadSmallOperationsCount++;
|
||||
operation.start();
|
||||
} else {
|
||||
uploadSmallOperationQueue.add(operation);
|
||||
}
|
||||
} else {
|
||||
if (currentUploadOperationsCount < 1) {
|
||||
currentUploadOperationsCount++;
|
||||
operation.start();
|
||||
} else {
|
||||
uploadOperationQueue.add(operation);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void cancelLoadFile(TLRPC.Document document) {
|
||||
cancelLoadFile(document, null, null);
|
||||
}
|
||||
|
||||
public void cancelLoadFile(TLRPC.PhotoSize photo) {
|
||||
cancelLoadFile(null, photo.location, null);
|
||||
}
|
||||
|
||||
public void cancelLoadFile(TLRPC.FileLocation location, String ext) {
|
||||
cancelLoadFile(null, location, ext);
|
||||
}
|
||||
|
||||
private void cancelLoadFile(final TLRPC.Document document, final TLRPC.FileLocation location, final String locationExt) {
|
||||
if (location == null && document == null) {
|
||||
return;
|
||||
}
|
||||
fileLoaderQueue.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String fileName = null;
|
||||
if (location != null) {
|
||||
fileName = getAttachFileName(location, locationExt);
|
||||
} else if (document != null) {
|
||||
fileName = getAttachFileName(document);
|
||||
}
|
||||
if (fileName == null) {
|
||||
return;
|
||||
}
|
||||
FileLoadOperation operation = loadOperationPaths.remove(fileName);
|
||||
if (operation != null) {
|
||||
if (MessageObject.isVoiceDocument(document)) {
|
||||
audioLoadOperationQueue.remove(operation);
|
||||
} else if (location != null) {
|
||||
photoLoadOperationQueue.remove(operation);
|
||||
} else {
|
||||
loadOperationQueue.remove(operation);
|
||||
}
|
||||
operation.cancel();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public boolean isLoadingFile(final String fileName) {
|
||||
final Semaphore semaphore = new Semaphore(0);
|
||||
final Boolean[] result = new Boolean[1];
|
||||
fileLoaderQueue.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
result[0] = loadOperationPaths.containsKey(fileName);
|
||||
semaphore.release();
|
||||
}
|
||||
});
|
||||
try {
|
||||
semaphore.acquire();
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
return result[0];
|
||||
}
|
||||
|
||||
public void loadFile(TLRPC.PhotoSize photo, String ext, boolean cacheOnly) {
|
||||
loadFile(null, photo.location, ext, photo.size, false, cacheOnly || (photo != null && photo.size == 0 || photo.location.key != null));
|
||||
}
|
||||
|
||||
public void loadFile(TLRPC.Document document, boolean force, boolean cacheOnly) {
|
||||
loadFile(document, null, null, 0, force, cacheOnly || document != null && document.key != null);
|
||||
}
|
||||
|
||||
public void loadFile(TLRPC.FileLocation location, String ext, int size, boolean cacheOnly) {
|
||||
loadFile(null, location, ext, size, true, cacheOnly || size == 0 || (location != null && location.key != null));
|
||||
}
|
||||
|
||||
private void loadFile(final TLRPC.Document document, final TLRPC.FileLocation location, final String locationExt, final int locationSize, final boolean force, final boolean cacheOnly) {
|
||||
fileLoaderQueue.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String fileName = null;
|
||||
if (location != null) {
|
||||
fileName = getAttachFileName(location, locationExt);
|
||||
} else if (document != null) {
|
||||
fileName = getAttachFileName(document);
|
||||
}
|
||||
if (fileName == null || fileName.contains("" + Integer.MIN_VALUE)) {
|
||||
return;
|
||||
}
|
||||
|
||||
FileLoadOperation operation;
|
||||
operation = loadOperationPaths.get(fileName);
|
||||
if (operation != null) {
|
||||
if (force) {
|
||||
LinkedList<FileLoadOperation> downloadQueue;
|
||||
if (MessageObject.isVoiceDocument(document)) {
|
||||
downloadQueue = audioLoadOperationQueue;
|
||||
} else if (location != null) {
|
||||
downloadQueue = photoLoadOperationQueue;
|
||||
} else {
|
||||
downloadQueue = loadOperationQueue;
|
||||
}
|
||||
if (downloadQueue != null) {
|
||||
int index = downloadQueue.indexOf(operation);
|
||||
if (index != -1) {
|
||||
downloadQueue.remove(index);
|
||||
downloadQueue.add(0, operation);
|
||||
operation.setForceRequest(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
File tempDir = getDirectory(MEDIA_DIR_CACHE);
|
||||
File storeDir = tempDir;
|
||||
int type = MEDIA_DIR_CACHE;
|
||||
|
||||
if (location != null) {
|
||||
operation = new FileLoadOperation(location, locationExt, locationSize);
|
||||
type = MEDIA_DIR_IMAGE;
|
||||
} else if (document != null) {
|
||||
operation = new FileLoadOperation(document);
|
||||
if (MessageObject.isVoiceDocument(document)) {
|
||||
type = MEDIA_DIR_AUDIO;
|
||||
} else if (MessageObject.isVideoDocument(document)) {
|
||||
type = MEDIA_DIR_VIDEO;
|
||||
} else {
|
||||
type = MEDIA_DIR_DOCUMENT;
|
||||
}
|
||||
}
|
||||
if (!cacheOnly) {
|
||||
storeDir = getDirectory(type);
|
||||
}
|
||||
operation.setPaths(storeDir, tempDir);
|
||||
|
||||
final String finalFileName = fileName;
|
||||
final int finalType = type;
|
||||
loadOperationPaths.put(fileName, operation);
|
||||
operation.setDelegate(new FileLoadOperation.FileLoadOperationDelegate() {
|
||||
@Override
|
||||
public void didFinishLoadingFile(FileLoadOperation operation, File finalFile) {
|
||||
if (delegate != null) {
|
||||
delegate.fileDidLoaded(finalFileName, finalFile, finalType);
|
||||
}
|
||||
checkDownloadQueue(document, location, finalFileName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void didFailedLoadingFile(FileLoadOperation operation, int canceled) {
|
||||
checkDownloadQueue(document, location, finalFileName);
|
||||
if (delegate != null) {
|
||||
delegate.fileDidFailedLoad(finalFileName, canceled);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void didChangedLoadProgress(FileLoadOperation operation, float progress) {
|
||||
if (delegate != null) {
|
||||
delegate.fileLoadProgressChanged(finalFileName, progress);
|
||||
}
|
||||
}
|
||||
});
|
||||
int maxCount = force ? 3 : 1;
|
||||
if (type == MEDIA_DIR_AUDIO) {
|
||||
if (currentAudioLoadOperationsCount < maxCount) {
|
||||
currentAudioLoadOperationsCount++;
|
||||
operation.start();
|
||||
} else {
|
||||
if (force) {
|
||||
audioLoadOperationQueue.add(0, operation);
|
||||
} else {
|
||||
audioLoadOperationQueue.add(operation);
|
||||
}
|
||||
}
|
||||
} else if (location != null) {
|
||||
if (currentPhotoLoadOperationsCount < maxCount) {
|
||||
currentPhotoLoadOperationsCount++;
|
||||
operation.start();
|
||||
} else {
|
||||
if (force) {
|
||||
photoLoadOperationQueue.add(0, operation);
|
||||
} else {
|
||||
photoLoadOperationQueue.add(operation);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (currentLoadOperationsCount < maxCount) {
|
||||
currentLoadOperationsCount++;
|
||||
operation.start();
|
||||
} else {
|
||||
if (force) {
|
||||
loadOperationQueue.add(0, operation);
|
||||
} else {
|
||||
loadOperationQueue.add(operation);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void checkDownloadQueue(final TLRPC.Document document, final TLRPC.FileLocation location, final String arg1) {
|
||||
fileLoaderQueue.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
loadOperationPaths.remove(arg1);
|
||||
FileLoadOperation operation;
|
||||
if (MessageObject.isVoiceDocument(document)) {
|
||||
currentAudioLoadOperationsCount--;
|
||||
if (!audioLoadOperationQueue.isEmpty()) {
|
||||
operation = audioLoadOperationQueue.get(0);
|
||||
int maxCount = operation.isForceRequest() ? 3 : 1;
|
||||
if (currentAudioLoadOperationsCount < maxCount) {
|
||||
operation = audioLoadOperationQueue.poll();
|
||||
if (operation != null) {
|
||||
currentAudioLoadOperationsCount++;
|
||||
operation.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (location != null) {
|
||||
currentPhotoLoadOperationsCount--;
|
||||
if (!photoLoadOperationQueue.isEmpty()) {
|
||||
operation = photoLoadOperationQueue.get(0);
|
||||
int maxCount = operation.isForceRequest() ? 3 : 1;
|
||||
if (currentPhotoLoadOperationsCount < maxCount) {
|
||||
operation = photoLoadOperationQueue.poll();
|
||||
if (operation != null) {
|
||||
currentPhotoLoadOperationsCount++;
|
||||
operation.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
currentLoadOperationsCount--;
|
||||
if (!loadOperationQueue.isEmpty()) {
|
||||
operation = loadOperationQueue.get(0);
|
||||
int maxCount = operation.isForceRequest() ? 3 : 1;
|
||||
if (currentLoadOperationsCount < maxCount) {
|
||||
operation = loadOperationQueue.poll();
|
||||
if (operation != null) {
|
||||
currentLoadOperationsCount++;
|
||||
operation.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setDelegate(FileLoaderDelegate delegate) {
|
||||
this.delegate = delegate;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static String getMessageFileName(TLRPC.Message message) {
|
||||
if (message == null) {
|
||||
return "";
|
||||
}
|
||||
if (message instanceof TLRPC.TL_messageService) {
|
||||
/*if (message instanceof TLRPC.TL_messageService) {
|
||||
if (message.action.photo != null) {
|
||||
ArrayList<TLRPC.PhotoSize> sizes = message.action.photo.sizes;
|
||||
if (sizes.size() > 0) {
|
||||
@@ -517,7 +92,7 @@ public class FileLoader {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
} else*/ {
|
||||
if (message.media instanceof TLRPC.TL_messageMediaDocument) {
|
||||
return getAttachFileName(message.media.document);
|
||||
} else if (message.media instanceof TLRPC.TL_messageMediaPhoto) {
|
||||
@@ -528,7 +103,7 @@ public class FileLoader {
|
||||
return getAttachFileName(sizeFull);
|
||||
}
|
||||
}
|
||||
} else if (message.media instanceof TLRPC.TL_messageMediaWebPage) {
|
||||
} /*else if (message.media instanceof TLRPC.TL_messageMediaWebPage) {
|
||||
if (message.media.webpage.photo != null) {
|
||||
ArrayList<TLRPC.PhotoSize> sizes = message.media.webpage.photo.sizes;
|
||||
if (sizes.size() > 0) {
|
||||
@@ -540,7 +115,7 @@ public class FileLoader {
|
||||
} else if (message.media.webpage.document != null) {
|
||||
return getAttachFileName(message.media.webpage.document);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
return "";
|
||||
}
|
||||
@@ -549,7 +124,7 @@ public class FileLoader {
|
||||
if (message == null) {
|
||||
return new File("");
|
||||
}
|
||||
if (message instanceof TLRPC.TL_messageService) {
|
||||
/*if (message instanceof TLRPC.TL_messageService) {
|
||||
if (message.action.photo != null) {
|
||||
ArrayList<TLRPC.PhotoSize> sizes = message.action.photo.sizes;
|
||||
if (sizes.size() > 0) {
|
||||
@@ -559,7 +134,7 @@ public class FileLoader {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
} else*/ {
|
||||
if (message.media instanceof TLRPC.TL_messageMediaDocument) {
|
||||
return getPathToAttach(message.media.document);
|
||||
} else if (message.media instanceof TLRPC.TL_messageMediaPhoto) {
|
||||
@@ -570,7 +145,7 @@ public class FileLoader {
|
||||
return getPathToAttach(sizeFull);
|
||||
}
|
||||
}
|
||||
} else if (message.media instanceof TLRPC.TL_messageMediaWebPage) {
|
||||
} /*else if (message.media instanceof TLRPC.TL_messageMediaWebPage) {
|
||||
if (message.media.webpage.document != null) {
|
||||
return getPathToAttach(message.media.webpage.document);
|
||||
} else if (message.media.webpage.photo != null) {
|
||||
@@ -582,7 +157,7 @@ public class FileLoader {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
return new File("");
|
||||
}
|
||||
|
||||
@@ -1,15 +1,28 @@
|
||||
/*
|
||||
* This is the source code of Telegram for Android v. 3.x.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2016.
|
||||
*/
|
||||
* Messenger Android Frontend
|
||||
* (C) 2013-2016 Nikolai Kudashov
|
||||
* (C) 2017 Björn Petersen
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see http://www.gnu.org/licenses/ .
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
package com.b44t.messenger;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.b44t.messenger.time.FastDateFormat;
|
||||
|
||||
import java.io.File;
|
||||
@@ -22,7 +35,6 @@ public class FileLog {
|
||||
private FastDateFormat dateFormat = null;
|
||||
private DispatchQueue logQueue = null;
|
||||
private File currentFile = null;
|
||||
private File networkFile = null;
|
||||
|
||||
private static volatile FileLog Instance = null;
|
||||
public static FileLog getInstance() {
|
||||
@@ -39,10 +51,7 @@ public class FileLog {
|
||||
}
|
||||
|
||||
public FileLog() {
|
||||
if (!BuildVars.DEBUG_VERSION) {
|
||||
return;
|
||||
}
|
||||
dateFormat = FastDateFormat.getInstance("dd_MM_yyyy_HH_mm_ss", Locale.US);
|
||||
dateFormat = FastDateFormat.getInstance("yyyyMMdd_HHmmss", Locale.US);
|
||||
try {
|
||||
File sdCard = ApplicationLoader.applicationContext.getExternalFilesDir(null);
|
||||
if (sdCard == null) {
|
||||
@@ -66,37 +75,14 @@ public class FileLog {
|
||||
}
|
||||
}
|
||||
|
||||
public static String getNetworkLogPath() {
|
||||
if (!BuildVars.DEBUG_VERSION) {
|
||||
return "";
|
||||
}
|
||||
try {
|
||||
File sdCard = ApplicationLoader.applicationContext.getExternalFilesDir(null);
|
||||
if (sdCard == null) {
|
||||
return "";
|
||||
}
|
||||
File dir = new File(sdCard.getAbsolutePath() + "/logs");
|
||||
dir.mkdirs();
|
||||
getInstance().networkFile = new File(dir, getInstance().dateFormat.format(System.currentTimeMillis()) + "_net.txt");
|
||||
return getInstance().networkFile.getAbsolutePath();
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public static void e(final String tag, final String message, final Throwable exception) {
|
||||
if (!BuildVars.DEBUG_VERSION) {
|
||||
return;
|
||||
}
|
||||
Log.e(tag, message, exception);
|
||||
private static void log(final String what, final String tag, final String message)
|
||||
{
|
||||
if (getInstance().streamWriter != null) {
|
||||
getInstance().logQueue.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
getInstance().streamWriter.write(getInstance().dateFormat.format(System.currentTimeMillis()) + " E/" + tag + "﹕ " + message + "\n");
|
||||
getInstance().streamWriter.write(exception.toString());
|
||||
getInstance().streamWriter.write(getInstance().dateFormat.format(System.currentTimeMillis()) + " " + what + "/" + tag + ": " + message + "\n");
|
||||
getInstance().streamWriter.flush();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
@@ -107,109 +93,14 @@ public class FileLog {
|
||||
}
|
||||
|
||||
public static void e(final String tag, final String message) {
|
||||
if (!BuildVars.DEBUG_VERSION) {
|
||||
return;
|
||||
}
|
||||
Log.e(tag, message);
|
||||
if (getInstance().streamWriter != null) {
|
||||
getInstance().logQueue.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
getInstance().streamWriter.write(getInstance().dateFormat.format(System.currentTimeMillis()) + " E/" + tag + "﹕ " + message + "\n");
|
||||
getInstance().streamWriter.flush();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public static void e(final String tag, final Throwable e) {
|
||||
if (!BuildVars.DEBUG_VERSION) {
|
||||
return;
|
||||
}
|
||||
e.printStackTrace();
|
||||
if (getInstance().streamWriter != null) {
|
||||
getInstance().logQueue.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
getInstance().streamWriter.write(getInstance().dateFormat.format(System.currentTimeMillis()) + " E/" + tag + "﹕ " + e + "\n");
|
||||
StackTraceElement[] stack = e.getStackTrace();
|
||||
for (int a = 0; a < stack.length; a++) {
|
||||
getInstance().streamWriter.write(getInstance().dateFormat.format(System.currentTimeMillis()) + " E/" + tag + "﹕ " + stack[a] + "\n");
|
||||
}
|
||||
getInstance().streamWriter.flush();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void d(final String tag, final String message) {
|
||||
if (!BuildVars.DEBUG_VERSION) {
|
||||
return;
|
||||
}
|
||||
Log.d(tag, message);
|
||||
if (getInstance().streamWriter != null) {
|
||||
getInstance().logQueue.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
getInstance().streamWriter.write(getInstance().dateFormat.format(System.currentTimeMillis()) + " D/" + tag + "﹕ " + message + "\n");
|
||||
getInstance().streamWriter.flush();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
log("E", tag, message);
|
||||
}
|
||||
|
||||
public static void w(final String tag, final String message) {
|
||||
if (!BuildVars.DEBUG_VERSION) {
|
||||
return;
|
||||
}
|
||||
Log.w(tag, message);
|
||||
if (getInstance().streamWriter != null) {
|
||||
getInstance().logQueue.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
getInstance().streamWriter.write(getInstance().dateFormat.format(System.currentTimeMillis()) + " W/" + tag + ": " + message + "\n");
|
||||
getInstance().streamWriter.flush();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
log("W", tag, message);
|
||||
}
|
||||
|
||||
public static void cleanupLogs() {
|
||||
File sdCard = ApplicationLoader.applicationContext.getExternalFilesDir(null);
|
||||
if (sdCard == null) {
|
||||
return;
|
||||
}
|
||||
File dir = new File (sdCard.getAbsolutePath() + "/logs");
|
||||
File[] files = dir.listFiles();
|
||||
if (files != null) {
|
||||
for (int a = 0; a < files.length; a++) {
|
||||
File file = files[a];
|
||||
if (getInstance().currentFile != null && file.getAbsolutePath().equals(getInstance().currentFile.getAbsolutePath())) {
|
||||
continue;
|
||||
}
|
||||
if (getInstance().networkFile != null && file.getAbsolutePath().equals(getInstance().networkFile.getAbsolutePath())) {
|
||||
continue;
|
||||
}
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
public static void i(final String tag, final String message) {
|
||||
log("I", tag, message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
/*
|
||||
* This is the source code of Telegram for Android v. 3.x.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2016.
|
||||
*/
|
||||
|
||||
package com.b44t.messenger;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
|
||||
public class FileUploadOperation {
|
||||
|
||||
public int state = 0;
|
||||
public FileUploadOperationDelegate delegate;
|
||||
private int requestToken = 0;
|
||||
private long totalFileSize = 0;
|
||||
private boolean isEncrypted = false;
|
||||
private int estimatedSize = 0;
|
||||
private FileInputStream stream;
|
||||
|
||||
public interface FileUploadOperationDelegate {
|
||||
void didFinishUploadingFile(FileUploadOperation operation, TLRPC.InputFile inputFile, TLRPC.InputEncryptedFile inputEncryptedFile, byte[] key, byte[] iv);
|
||||
void didFailedUploadingFile(FileUploadOperation operation);
|
||||
void didChangedUploadProgress(FileUploadOperation operation, float progress);
|
||||
}
|
||||
|
||||
public FileUploadOperation(String location, boolean encrypted, int estimated) {
|
||||
isEncrypted = encrypted;
|
||||
estimatedSize = estimated;
|
||||
}
|
||||
|
||||
public long getTotalFileSize() {
|
||||
return totalFileSize;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
if (state == 3) {
|
||||
return;
|
||||
}
|
||||
state = 2;
|
||||
if (requestToken != 0) {
|
||||
ConnectionsManager.getInstance().cancelRequest(requestToken, true);
|
||||
}
|
||||
delegate.didFailedUploadingFile(this);
|
||||
cleanup();
|
||||
}
|
||||
|
||||
private void cleanup() {
|
||||
}
|
||||
|
||||
/*
|
||||
protected void checkNewDataAvailable(final long finalSize) {
|
||||
Utilities.stageQueue.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (estimatedSize != 0 && finalSize != 0) {
|
||||
estimatedSize = 0;
|
||||
totalFileSize = finalSize;
|
||||
totalPartsCount = (int) (totalFileSize + uploadChunkSize - 1) / uploadChunkSize;
|
||||
if (started) {
|
||||
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("uploadinfo", Activity.MODE_PRIVATE);
|
||||
storeFileUploadInfo(preferences);
|
||||
}
|
||||
}
|
||||
if (requestToken == 0) {
|
||||
startUploadRequest();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,25 @@
|
||||
/*
|
||||
* This is the source code of Telegram for Android v. 1.3.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2016.
|
||||
*/
|
||||
* Messenger Android Frontend
|
||||
* (C) 2013-2016 Nikolai Kudashov
|
||||
* (C) 2017 Björn Petersen
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see http://www.gnu.org/licenses/ .
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
package com.b44t.messenger;
|
||||
|
||||
@@ -14,6 +29,7 @@ import android.graphics.Canvas;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffColorFilter;
|
||||
import android.graphics.Rect;
|
||||
@@ -27,6 +43,7 @@ import com.b44t.ui.Components.AnimatedFileDrawable;
|
||||
|
||||
public class ImageReceiver implements NotificationCenter.NotificationCenterDelegate {
|
||||
|
||||
|
||||
public interface ImageReceiverDelegate {
|
||||
void didSetImage(ImageReceiver imageReceiver, boolean set, boolean thumb);
|
||||
}
|
||||
@@ -43,6 +60,11 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
|
||||
public String ext;
|
||||
}
|
||||
|
||||
public String m_userDataUnique = ""; // used to discard images loaded and no longer required as there was a new request
|
||||
// before, we used "private static HashMap<View, String> s_viewBindings = new HashMap<>();" in ContactsController -
|
||||
// however, this was a bad idea as this resulted in _lots_ of objects that were never freed...
|
||||
|
||||
|
||||
private View parentView;
|
||||
private Integer tag;
|
||||
private Integer thumbTag;
|
||||
@@ -349,12 +371,10 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
|
||||
setImageBackup.ext = currentExt;
|
||||
setImageBackup.cacheOnly = currentCacheOnly;
|
||||
}
|
||||
NotificationCenter.getInstance().removeObserver(this, NotificationCenter.didReplacedPhotoInMemCache);
|
||||
clearImage();
|
||||
}
|
||||
|
||||
public boolean onAttachedToWindow() {
|
||||
NotificationCenter.getInstance().addObserver(this, NotificationCenter.didReplacedPhotoInMemCache);
|
||||
if (setImageBackup != null && (setImageBackup.fileLocation != null || setImageBackup.httpUrl != null || setImageBackup.thumbLocation != null || setImageBackup.thumb != null)) {
|
||||
setImage(setImageBackup.fileLocation, setImageBackup.httpUrl, setImageBackup.filter, setImageBackup.thumb, setImageBackup.thumbLocation, setImageBackup.thumbFilter, setImageBackup.size, setImageBackup.ext, setImageBackup.cacheOnly);
|
||||
return true;
|
||||
@@ -463,7 +483,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
|
||||
currentThumbKey = null;
|
||||
}
|
||||
setImage(currentImageLocation, currentHttpUrl, currentFilter, currentThumb, currentThumbLocation, currentThumbFilter, currentSize, currentExt, currentCacheOnly);
|
||||
FileLog.e("messenger", e);
|
||||
|
||||
}
|
||||
canvas.restore();
|
||||
} else {
|
||||
@@ -508,7 +528,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
|
||||
currentThumbKey = null;
|
||||
}
|
||||
setImage(currentImageLocation, currentHttpUrl, currentFilter, currentThumb, currentThumbLocation, currentThumbFilter, currentSize, currentExt, currentCacheOnly);
|
||||
FileLog.e("messenger", e);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -545,7 +565,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
|
||||
currentThumbKey = null;
|
||||
}
|
||||
setImage(currentImageLocation, currentHttpUrl, currentFilter, currentThumb, currentThumbLocation, currentThumbFilter, currentSize, currentExt, currentCacheOnly);
|
||||
FileLog.e("messenger", e);
|
||||
|
||||
}
|
||||
}
|
||||
canvas.restore();
|
||||
@@ -560,7 +580,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
|
||||
drawable.setAlpha(alpha);
|
||||
drawable.draw(canvas);
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -642,7 +662,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
|
||||
checkAlphaAnimation(animationNotReady);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -1036,26 +1056,6 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (id == NotificationCenter.didReplacedPhotoInMemCache) {
|
||||
String oldKey = (String) args[0];
|
||||
if (currentKey != null && currentKey.equals(oldKey)) {
|
||||
currentKey = (String) args[1];
|
||||
currentImageLocation = (TLRPC.FileLocation) args[2];
|
||||
}
|
||||
if (currentThumbKey != null && currentThumbKey.equals(oldKey)) {
|
||||
currentThumbKey = (String) args[1];
|
||||
currentThumbLocation = (TLRPC.FileLocation) args[2];
|
||||
}
|
||||
if (setImageBackup != null) {
|
||||
if (currentKey != null && currentKey.equals(oldKey)) {
|
||||
currentKey = (String) args[1];
|
||||
currentImageLocation = (TLRPC.FileLocation) args[2];
|
||||
}
|
||||
if (currentThumbKey != null && currentThumbKey.equals(oldKey)) {
|
||||
currentThumbKey = (String) args[1];
|
||||
currentThumbLocation = (TLRPC.FileLocation) args[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Messenger Android Frontend
|
||||
* (C) 2017 Björn Petersen
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see http://www.gnu.org/licenses/ .
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
package com.b44t.messenger;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.os.IBinder;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
|
||||
public class KeepAliveService extends Service {
|
||||
|
||||
static KeepAliveService s_this = null;
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
MrMailbox.log_i("DeltaChat", "*** KeepAliveService.onCreate()");
|
||||
// there's nothing more to do here as all initialisation stuff is already done in
|
||||
// ApplicationLoader.onCreate() which is called before this broadcast is sended.
|
||||
s_this = this;
|
||||
setSelfAsForeground();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
// START_STICKY ensured, the service is recreated as soon it is terminted for any reasons.
|
||||
// as ApplicationLoader.onCreate() is called before a service starts, there is no more to do here,
|
||||
// the app is just running fine.
|
||||
MrMailbox.log_i("DeltaChat", "*** KeepAliveService.onStartCommand()");
|
||||
return START_STICKY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void onDestroy() {
|
||||
MrMailbox.log_i("DeltaChat", "*** KeepAliveService.onDestroy()");
|
||||
// the service will be restarted due to START_STICKY automatically, there's nothing more to do.
|
||||
}
|
||||
|
||||
private void setSelfAsForeground() {
|
||||
stopForeground(true);
|
||||
startForeground(FG_NOTIFICATION_ID, createNotification()); // TODO: if we target Android O, we should use startServiceInForeground()
|
||||
}
|
||||
|
||||
static public KeepAliveService getInstance()
|
||||
{
|
||||
return s_this; // may be null
|
||||
}
|
||||
|
||||
/* The notification
|
||||
* A notification is required for a foreground service; and without a foreground service,
|
||||
* Delta Chat won't get new messages reliable
|
||||
**********************************************************************************************/
|
||||
|
||||
public static final int FG_NOTIFICATION_ID = 4142;
|
||||
private Notification createNotification()
|
||||
{
|
||||
// a notification _must_ contain a small icon, a title and a text, see https://developer.android.com/guide/topics/ui/notifiers/notifications.html#Required
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
|
||||
|
||||
if( MrMailbox.isConfigured()!=0) {
|
||||
builder.setContentTitle(LocaleController.formatString("", R.string.PermNotificationTitle, MrMailbox.getConfig("addr", "")));
|
||||
builder.setContentText(getString(R.string.PermNotificationText));
|
||||
}
|
||||
else {
|
||||
builder.setContentTitle(getString(R.string.AppName));
|
||||
builder.setContentText(getString(R.string.AccountNotConfigured));
|
||||
}
|
||||
|
||||
if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN ) {
|
||||
builder.setPriority(NotificationCompat.PRIORITY_MIN);
|
||||
}
|
||||
builder.setWhen(0);
|
||||
builder.setSmallIcon(R.drawable.notification_permanent);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
public void updateForegroundNotification()
|
||||
{
|
||||
// update the notification by simply creating a new notification with the same ID, see https://developer.android.com/training/notify-user/managing.html#Updating
|
||||
NotificationManager nm = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
nm.notify(FG_NOTIFICATION_ID, createNotification());
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,25 @@
|
||||
/*
|
||||
* This is the source code of Telegram for Android v. 3.x.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2016.
|
||||
*/
|
||||
* Messenger Android Frontend
|
||||
* (C) 2013-2016 Nikolai Kudashov
|
||||
* (C) 2017 Björn Petersen
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see http://www.gnu.org/licenses/ .
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
package com.b44t.messenger;
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,675 +0,0 @@
|
||||
/*
|
||||
* This is the source code of Telegram for Android v. 3.x.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2016.
|
||||
*/
|
||||
|
||||
package com.b44t.messenger;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import com.b44t.messenger.query.DraftQuery;
|
||||
import com.b44t.messenger.query.MessagesQuery;
|
||||
import com.b44t.messenger.query.SearchQuery;
|
||||
import com.b44t.ui.ActionBar.BaseFragment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class MessagesController implements NotificationCenter.NotificationCenterDelegate {
|
||||
|
||||
public ArrayList<TLRPC.TL_dialog> dialogs = new ArrayList<>();
|
||||
public ArrayList<TLRPC.TL_dialog> dialogsServerOnly = new ArrayList<>();
|
||||
public ArrayList<TLRPC.TL_dialog> dialogsGroupsOnly = new ArrayList<>();
|
||||
public int nextDialogsCacheOffset;
|
||||
public ConcurrentHashMap<Long, TLRPC.TL_dialog> dialogs_dict = new ConcurrentHashMap<>(100, 1.0f, 2);
|
||||
public HashMap<Long, MessageObject> dialogMessage = new HashMap<>();
|
||||
public HashMap<Long, MessageObject> dialogMessagesByRandomIds = new HashMap<>();
|
||||
public HashMap<Integer, MessageObject> dialogMessagesByIds = new HashMap<>();
|
||||
public HashMap<Long, CharSequence> printingStrings = new HashMap<>();
|
||||
public ConcurrentHashMap<Integer, Integer> onlinePrivacy = new ConcurrentHashMap<>(20, 1.0f, 2);
|
||||
|
||||
private HashMap<String, ArrayList<MessageObject>> reloadingWebpages = new HashMap<>();
|
||||
|
||||
public boolean loadingDialogs = false;
|
||||
public boolean dialogsEndReached = false;
|
||||
|
||||
public int secretWebpagePreview = 2;
|
||||
|
||||
private String uploadingAvatar = null;
|
||||
|
||||
public boolean enableJoined = true;
|
||||
public int fontSize = AndroidUtilities.dp(16);
|
||||
public int ratingDecay;
|
||||
|
||||
public static final int UPDATE_MASK_NAME = 1;
|
||||
public static final int UPDATE_MASK_AVATAR = 2;
|
||||
public static final int UPDATE_MASK_STATUS = 4;
|
||||
public static final int UPDATE_MASK_CHAT_AVATAR = 8;
|
||||
public static final int UPDATE_MASK_CHAT_NAME = 16;
|
||||
public static final int UPDATE_MASK_CHAT_MEMBERS = 32;
|
||||
public static final int UPDATE_MASK_USER_PRINT = 64;
|
||||
public static final int UPDATE_MASK_READ_DIALOG_MESSAGE = 256;
|
||||
public static final int UPDATE_MASK_SELECT_DIALOG = 512;
|
||||
public static final int UPDATE_MASK_NEW_MESSAGE = 2048;
|
||||
public static final int UPDATE_MASK_SEND_STATE = 4096;
|
||||
public static final int UPDATE_MASK_CHANNEL = 8192;
|
||||
public static final int UPDATE_MASK_CHAT_ADMINS = 16384;
|
||||
|
||||
private static volatile MessagesController Instance = null;
|
||||
|
||||
private final Comparator<TLRPC.TL_dialog> dialogComparator = new Comparator<TLRPC.TL_dialog>() {
|
||||
@Override
|
||||
public int compare(TLRPC.TL_dialog dialog1, TLRPC.TL_dialog dialog2) {
|
||||
TLRPC.DraftMessage draftMessage = DraftQuery.getDraft(dialog1.id);
|
||||
int date1 = draftMessage != null && draftMessage.date >= dialog1.last_message_date ? draftMessage.date : dialog1.last_message_date;
|
||||
draftMessage = DraftQuery.getDraft(dialog2.id);
|
||||
int date2 = draftMessage != null && draftMessage.date >= dialog2.last_message_date ? draftMessage.date : dialog2.last_message_date;
|
||||
if (date1 < date2) {
|
||||
return 1;
|
||||
} else if (date1 > date2) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
public static MessagesController getInstance() {
|
||||
MessagesController localInstance = Instance;
|
||||
if (localInstance == null) {
|
||||
synchronized (MessagesController.class) {
|
||||
localInstance = Instance;
|
||||
if (localInstance == null) {
|
||||
Instance = localInstance = new MessagesController();
|
||||
}
|
||||
}
|
||||
}
|
||||
return localInstance;
|
||||
}
|
||||
|
||||
public MessagesController() {
|
||||
ImageLoader.getInstance();
|
||||
//MessagesStorage.getInstance();
|
||||
NotificationCenter.getInstance().addObserver(this, NotificationCenter.FileDidUpload);
|
||||
NotificationCenter.getInstance().addObserver(this, NotificationCenter.FileDidFailUpload);
|
||||
NotificationCenter.getInstance().addObserver(this, NotificationCenter.FileDidLoaded);
|
||||
NotificationCenter.getInstance().addObserver(this, NotificationCenter.FileDidFailedLoad);
|
||||
NotificationCenter.getInstance().addObserver(this, NotificationCenter.messageReceivedByServer);
|
||||
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Activity.MODE_PRIVATE);
|
||||
enableJoined = preferences.getBoolean("EnableContactJoined", true);
|
||||
|
||||
preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE);
|
||||
secretWebpagePreview = preferences.getInt("secretWebpage2", 2);
|
||||
ratingDecay = preferences.getInt("ratingDecay", 2419200);
|
||||
fontSize = preferences.getInt("fons_size", AndroidUtilities.isTablet() ? 18 : 16);
|
||||
}
|
||||
|
||||
public static TLRPC.InputUser getInputUser(TLRPC.User user) {
|
||||
if (user == null) {
|
||||
return new TLRPC.TL_inputUserEmpty();
|
||||
}
|
||||
TLRPC.InputUser inputUser;
|
||||
if (user.id == UserConfig.getClientUserId()) {
|
||||
inputUser = new TLRPC.TL_inputUserSelf();
|
||||
} else {
|
||||
inputUser = new TLRPC.TL_inputUser();
|
||||
inputUser.user_id = user.id;
|
||||
inputUser.access_hash = user.access_hash;
|
||||
}
|
||||
return inputUser;
|
||||
}
|
||||
|
||||
public static TLRPC.InputUser getInputUser(int user_id) {
|
||||
TLRPC.User user = getInstance().getUser(user_id);
|
||||
return getInputUser(user);
|
||||
}
|
||||
|
||||
public static TLRPC.InputPeer getInputPeer(int id) {
|
||||
TLRPC.InputPeer inputPeer;
|
||||
/*if (id < 0) {
|
||||
TLRPC.Chat chat = getInstance().getChat(-id);
|
||||
if (ChatObject.isChannel(chat)) {
|
||||
inputPeer = new TLRPC.TL_inputPeerChannel();
|
||||
inputPeer.channel_id = -id;
|
||||
inputPeer.access_hash = chat.access_hash;
|
||||
} else {
|
||||
inputPeer = new TLRPC.TL_inputPeerChat();
|
||||
inputPeer.chat_id = -id;
|
||||
}
|
||||
} else */ {
|
||||
TLRPC.User user = getInstance().getUser(id);
|
||||
inputPeer = new TLRPC.TL_inputPeerUser();
|
||||
inputPeer.user_id = id;
|
||||
if (user != null) {
|
||||
inputPeer.access_hash = user.access_hash;
|
||||
}
|
||||
}
|
||||
return inputPeer;
|
||||
}
|
||||
|
||||
public static TLRPC.Peer getPeer(int id) {
|
||||
TLRPC.Peer inputPeer;
|
||||
if (id < 0) {
|
||||
inputPeer = new TLRPC.TL_peerChat();
|
||||
inputPeer.chat_id = -id;
|
||||
} else {
|
||||
inputPeer = new TLRPC.TL_peerUser();
|
||||
inputPeer.user_id = id;
|
||||
}
|
||||
return inputPeer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void didReceivedNotification(int id, Object... args) {
|
||||
if (id == NotificationCenter.FileDidUpload) {
|
||||
final String location = (String) args[0];
|
||||
final TLRPC.InputFile file = (TLRPC.InputFile) args[1];
|
||||
|
||||
if (uploadingAvatar != null && uploadingAvatar.equals(location)) {
|
||||
/*TLRPC.TL_photos_uploadProfilePhoto req = new TLRPC.TL_photos_uploadProfilePhoto();
|
||||
req.caption = "";
|
||||
req.crop = new TLRPC.TL_inputPhotoCropAuto();
|
||||
req.file = file;
|
||||
req.geo_point = new TLRPC.TL_inputGeoPointEmpty();*/
|
||||
/*ConnectionsManager.getInstance().sendRequest(req, new RequestDelegate() {
|
||||
@Override
|
||||
public void run(TLObject response, TLRPC.TL_error error) {
|
||||
if (error == null) {
|
||||
TLRPC.User user = getUser(UserConfig.getClientUserId());
|
||||
if (user == null) {
|
||||
user = UserConfig.getCurrentUser();
|
||||
putUser(user, true);
|
||||
} else {
|
||||
UserConfig.setCurrentUser(user);
|
||||
}
|
||||
if (user == null) {
|
||||
return;
|
||||
}
|
||||
TLRPC.TL_photos_photo photo = (TLRPC.TL_photos_photo) response;
|
||||
ArrayList<TLRPC.PhotoSize> sizes = photo.photo.sizes;
|
||||
TLRPC.PhotoSize smallSize = FileLoader.getClosestPhotoSizeWithSize(sizes, 100);
|
||||
TLRPC.PhotoSize bigSize = FileLoader.getClosestPhotoSizeWithSize(sizes, 1000);
|
||||
user.photo = new TLRPC.TL_userProfilePhoto();
|
||||
user.photo.photo_id = photo.photo.id;
|
||||
if (smallSize != null) {
|
||||
user.photo.photo_small = smallSize.location;
|
||||
}
|
||||
if (bigSize != null) {
|
||||
user.photo.photo_big = bigSize.location;
|
||||
} else if (smallSize != null) {
|
||||
user.photo.photo_small = smallSize.location;
|
||||
}
|
||||
//MessagesStorage.getInstance().clearUserPhotos(user.id);
|
||||
ArrayList<TLRPC.User> users = new ArrayList<>();
|
||||
users.add(user);
|
||||
//MessagesStorage.getInstance().putUsersAndChats(users, null, false, true);
|
||||
AndroidUtilities.runOnUIThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
NotificationCenter.getInstance().postNotificationName(NotificationCenter.updateInterfaces, UPDATE_MASK_AVATAR);
|
||||
UserConfig.saveConfig(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});*/
|
||||
}
|
||||
} else if (id == NotificationCenter.FileDidFailUpload) {
|
||||
final String location = (String) args[0];
|
||||
if (uploadingAvatar != null && uploadingAvatar.equals(location)) {
|
||||
uploadingAvatar = null;
|
||||
}
|
||||
} else if (id == NotificationCenter.messageReceivedByServer) {
|
||||
Integer msgId = (Integer) args[0];
|
||||
Integer newMsgId = (Integer) args[1];
|
||||
Long did = (Long) args[3];
|
||||
MessageObject obj = dialogMessage.get(did);
|
||||
if (obj != null && obj.getId() == msgId) {
|
||||
obj.messageOwner.id = newMsgId;
|
||||
obj.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SENT;
|
||||
TLRPC.TL_dialog dialog = dialogs_dict.get(did);
|
||||
if (dialog != null) {
|
||||
if (dialog.top_message == msgId) {
|
||||
dialog.top_message = newMsgId;
|
||||
}
|
||||
}
|
||||
NotificationCenter.getInstance().postNotificationName(NotificationCenter.dialogsNeedReload);
|
||||
}
|
||||
obj = dialogMessagesByIds.remove(msgId);
|
||||
if (obj != null) {
|
||||
dialogMessagesByIds.put(newMsgId, obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
public void cleanup() {
|
||||
ContactsController.getInstance().cleanup();
|
||||
MediaController.getInstance().cleanup();
|
||||
NotificationsController.getInstance().cleanup();
|
||||
SendMessagesHelper.getInstance().cleanup();
|
||||
//SecretChatHelper.getInstance().cleanup();
|
||||
StickersQuery.cleanup();
|
||||
SearchQuery.cleanup();
|
||||
DraftQuery.cleanup();
|
||||
|
||||
reloadingWebpages.clear();
|
||||
reloadingWebpagesPending.clear();
|
||||
dialogs_dict.clear();
|
||||
dialogs_read_inbox_max.clear();
|
||||
dialogs_read_outbox_max.clear();
|
||||
dialogs.clear();
|
||||
channelViewsToSend.clear();
|
||||
channelViewsToReload.clear();
|
||||
dialogsServerOnly.clear();
|
||||
dialogsGroupsOnly.clear();
|
||||
dialogMessagesByIds.clear();
|
||||
dialogMessagesByRandomIds.clear();
|
||||
users.clear();
|
||||
usersByUsernames.clear();
|
||||
chats.clear();
|
||||
dialogMessage.clear();
|
||||
printingUsers.clear();
|
||||
printingStrings.clear();
|
||||
printingStringsTypes.clear();
|
||||
onlinePrivacy.clear();
|
||||
loadingPeerSettings.clear();
|
||||
lastPrintingStringCount = 0;
|
||||
nextDialogsCacheOffset = 0;
|
||||
Utilities.stageQueue.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
gettingUnknownChannels.clear();
|
||||
createdDialogIds.clear();
|
||||
gettingDifference = false;
|
||||
}
|
||||
});
|
||||
blockedUsers.clear();
|
||||
sendingTypings.clear();
|
||||
loadingFullUsers.clear();
|
||||
loadedFullUsers.clear();
|
||||
reloadingMessages.clear();
|
||||
loadingFullChats.clear();
|
||||
loadingFullParticipants.clear();
|
||||
loadedFullParticipants.clear();
|
||||
loadedFullChats.clear();
|
||||
|
||||
currentDeletingTaskTime = 0;
|
||||
currentDeletingTaskMids = null;
|
||||
gettingNewDeleteTask = false;
|
||||
loadingDialogs = false;
|
||||
dialogsEndReached = false;
|
||||
loadingBlockedUsers = false;
|
||||
firstGettingTask = false;
|
||||
updatingState = false;
|
||||
offlineSent = false;
|
||||
registeringForPush = false;
|
||||
uploadingAvatar = null;
|
||||
statusRequest = 0;
|
||||
statusSettingState = 0;
|
||||
|
||||
Utilities.stageQueue.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
//ConnectionsManager.getInstance().setIsUpdating(false);
|
||||
updatesQueueChannels.clear();
|
||||
updatesStartWaitTimeChannels.clear();
|
||||
gettingDifferenceChannels.clear();
|
||||
channelsPts.clear();
|
||||
shortPollChannels.clear();
|
||||
needShortPollChannels.clear();
|
||||
}
|
||||
});
|
||||
|
||||
if (currentDeleteTaskRunnable != null) {
|
||||
Utilities.stageQueue.cancelRunnable(currentDeleteTaskRunnable);
|
||||
currentDeleteTaskRunnable = null;
|
||||
}
|
||||
|
||||
NotificationCenter.getInstance().postNotificationName(NotificationCenter.dialogsNeedReload);
|
||||
}
|
||||
*/
|
||||
|
||||
public TLRPC.User getUser(Integer id) {
|
||||
// EDIT BY MR - additional information should be loaded as needed by the caller
|
||||
TLRPC.User u = new TLRPC.User();
|
||||
u.id = id;
|
||||
return u;
|
||||
}
|
||||
|
||||
public TLRPC.Chat getChat(Integer id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void deleteMessages(ArrayList<Integer> messages, ArrayList<Long> randoms, Object encryptedChat, final int channelId) {
|
||||
|
||||
}
|
||||
|
||||
public MediaController.SearchImage saveGif(TLRPC.Document document) {
|
||||
MediaController.SearchImage searchImage = new MediaController.SearchImage();
|
||||
searchImage.type = 2;
|
||||
searchImage.document = document;
|
||||
searchImage.date = (int) (System.currentTimeMillis() / 1000);
|
||||
searchImage.id = "" + searchImage.document.id;
|
||||
|
||||
ArrayList<MediaController.SearchImage> arrayList = new ArrayList<>();
|
||||
arrayList.add(searchImage);
|
||||
//MessagesStorage.getInstance().putWebRecent(arrayList);
|
||||
/*TLRPC.TL_messages_saveGif req = new TLRPC.TL_messages_saveGif();
|
||||
req.id = new TLRPC.TL_inputDocument();
|
||||
req.id.id = searchImage.document.id;
|
||||
req.id.access_hash = searchImage.document.access_hash;
|
||||
req.unsave = false;
|
||||
ConnectionsManager.getInstance().sendRequest(req, new RequestDelegate() {
|
||||
@Override
|
||||
public void run(TLObject response, TLRPC.TL_error error) {
|
||||
|
||||
}
|
||||
});*/
|
||||
return searchImage;
|
||||
}
|
||||
|
||||
public void cancelTyping(int action, long dialog_id) {
|
||||
}
|
||||
|
||||
public void sendTyping(final long dialog_id, final int action, int classGuid) {
|
||||
}
|
||||
|
||||
public void reloadWebPages(final long dialog_id, HashMap<String, ArrayList<MessageObject>> webpagesToReload) {
|
||||
for (HashMap.Entry<String, ArrayList<MessageObject>> entry : webpagesToReload.entrySet()) {
|
||||
final String url = entry.getKey();
|
||||
final ArrayList<MessageObject> messages = entry.getValue();
|
||||
ArrayList<MessageObject> arrayList = reloadingWebpages.get(url);
|
||||
if (arrayList == null) {
|
||||
arrayList = new ArrayList<>();
|
||||
reloadingWebpages.put(url, arrayList);
|
||||
}
|
||||
arrayList.addAll(messages);
|
||||
/*TLRPC.TL_messages_getWebPagePreview req = new TLRPC.TL_messages_getWebPagePreview();
|
||||
req.message = url;
|
||||
ConnectionsManager.getInstance().sendRequest(req, new RequestDelegate() {
|
||||
@Override
|
||||
public void run(final TLObject response, final TLRPC.TL_error error) {
|
||||
AndroidUtilities.runOnUIThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ArrayList<MessageObject> arrayList = reloadingWebpages.remove(url);
|
||||
if (arrayList == null) {
|
||||
return;
|
||||
}
|
||||
TLRPC.TL_messages_messages messagesRes = new TLRPC.TL_messages_messages();
|
||||
if (!(response instanceof TLRPC.TL_messageMediaWebPage)) {
|
||||
for (int a = 0; a < arrayList.size(); a++) {
|
||||
arrayList.get(a).messageOwner.media.webpage = new TLRPC.TL_webPageEmpty();
|
||||
messagesRes.messages.add(arrayList.get(a).messageOwner);
|
||||
}
|
||||
} else {
|
||||
TLRPC.TL_messageMediaWebPage media = (TLRPC.TL_messageMediaWebPage) response;
|
||||
if (media.webpage instanceof TLRPC.TL_webPage || media.webpage instanceof TLRPC.TL_webPageEmpty) {
|
||||
for (int a = 0; a < arrayList.size(); a++) {
|
||||
arrayList.get(a).messageOwner.media.webpage = media.webpage;
|
||||
if (a == 0) {
|
||||
ImageLoader.saveMessageThumbs(arrayList.get(a).messageOwner);
|
||||
}
|
||||
messagesRes.messages.add(arrayList.get(a).messageOwner);
|
||||
}
|
||||
} else {
|
||||
reloadingWebpagesPending.put(media.webpage.id, arrayList);
|
||||
}
|
||||
}
|
||||
if (!messagesRes.messages.isEmpty()) {
|
||||
//MessagesStorage.getInstance().putMessages(messagesRes, dialog_id, -2, 0, false);
|
||||
NotificationCenter.getInstance().postNotificationName(NotificationCenter.replaceMessagesObjects, dialog_id, arrayList);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});*/
|
||||
}
|
||||
}
|
||||
|
||||
public void loadDialogs(final int offset, final int count, boolean fromCache) {
|
||||
if (loadingDialogs) {
|
||||
return;
|
||||
}
|
||||
loadingDialogs = true;
|
||||
NotificationCenter.getInstance().postNotificationName(NotificationCenter.dialogsNeedReload);
|
||||
FileLog.e("messenger", "load cacheOffset = " + offset + " count = " + count + " cache = " + fromCache);
|
||||
if (fromCache) {
|
||||
//MessagesStorage.getInstance().getDialogs(offset == 0 ? 0 : nextDialogsCacheOffset, count);
|
||||
} else {
|
||||
/*
|
||||
TLRPC.TL_messages_getDialogs req = new TLRPC.TL_messages_getDialogs();
|
||||
req.limit = count;
|
||||
boolean found = false;
|
||||
for (int a = dialogs.size() - 1; a >= 0; a--) {
|
||||
TLRPC.TL_dialog dialog = dialogs.get(a);
|
||||
int lower_id = (int) dialog.id;
|
||||
int high_id = (int) (dialog.id >> 32);
|
||||
if (lower_id != 0 && high_id != 1 && dialog.top_message > 0) {
|
||||
MessageObject message = dialogMessage.get(dialog.id);
|
||||
if (message != null && message.getId() > 0) {
|
||||
req.offset_date = message.messageOwner.date;
|
||||
req.offset_id = message.messageOwner.id;
|
||||
int id;
|
||||
if (message.messageOwner.to_id.channel_id != 0) {
|
||||
id = -message.messageOwner.to_id.channel_id;
|
||||
} else if (message.messageOwner.to_id.chat_id != 0) {
|
||||
id = -message.messageOwner.to_id.chat_id;
|
||||
} else {
|
||||
id = message.messageOwner.to_id.user_id;
|
||||
}
|
||||
req.offset_peer = getInputPeer(id);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
req.offset_peer = new TLRPC.TL_inputPeerEmpty();
|
||||
}
|
||||
*/
|
||||
/*ConnectionsManager.getInstance().sendRequest(req, new RequestDelegate() {
|
||||
@Override
|
||||
public void run(TLObject response, TLRPC.TL_error error) {
|
||||
if (error == null) {
|
||||
//final TLRPC.messages_Dialogs dialogsRes = (TLRPC.messages_Dialogs) response;
|
||||
//processLoadedDialogs(dialogsRes, null, 0, count, 0, false, false);
|
||||
}
|
||||
}
|
||||
});*/
|
||||
}
|
||||
}
|
||||
|
||||
public void markMessageContentAsRead(final MessageObject messageObject) {
|
||||
}
|
||||
|
||||
public void markMessageAsRead(final long dialog_id, final long random_id, int ttl) {
|
||||
}
|
||||
|
||||
public void markDialogAsRead(final long dialog_id, final int max_id, final int max_positive_id, final int max_date, final boolean was, final boolean popup) {
|
||||
}
|
||||
|
||||
public void addUserToChat(final int chat_id, final TLRPC.User user, final TLRPC.ChatFull info, int count_fwd, String botHash, final BaseFragment fragment) {
|
||||
}
|
||||
|
||||
public void changeChatAvatar(int chat_id, TLRPC.InputFile uploadedAvatar) {
|
||||
/*TLObject request;
|
||||
{
|
||||
TLRPC.TL_messages_editChatPhoto req = new TLRPC.TL_messages_editChatPhoto();
|
||||
req.chat_id = chat_id;
|
||||
if (uploadedAvatar != null) {
|
||||
req.photo = new TLRPC.TL_inputChatUploadedPhoto();
|
||||
req.photo.file = uploadedAvatar;
|
||||
req.photo.crop = new TLRPC.TL_inputPhotoCropAuto();
|
||||
} else {
|
||||
req.photo = new TLRPC.TL_inputChatPhotoEmpty();
|
||||
}
|
||||
request = req;
|
||||
}*/
|
||||
/*ConnectionsManager.getInstance().sendRequest(request, new RequestDelegate() {
|
||||
@Override
|
||||
public void run(TLObject response, TLRPC.TL_error error) {
|
||||
if (error != null) {
|
||||
return;
|
||||
}
|
||||
processUpdates((TLRPC.Updates) response, false);
|
||||
}
|
||||
}, ConnectionsManager.RequestFlagInvokeAfter);*/
|
||||
}
|
||||
|
||||
public boolean isDialogMuted(long dialog_id) {
|
||||
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Activity.MODE_PRIVATE);
|
||||
int mute_type = preferences.getInt("notify2_" + dialog_id, 0);
|
||||
if (mute_type == 2) {
|
||||
return true;
|
||||
} else if (mute_type == 3) {
|
||||
int mute_until = preferences.getInt("notifyuntil_" + dialog_id, 0);
|
||||
if (mute_until >= ConnectionsManager.getInstance().getCurrentTime()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void updateInterfaceWithMessages(long uid, ArrayList<MessageObject> messages) {
|
||||
updateInterfaceWithMessages(uid, messages, false);
|
||||
}
|
||||
|
||||
protected static void addNewGifToRecent(TLRPC.Document document, int date) {
|
||||
ArrayList<MediaController.SearchImage> arrayList = new ArrayList<>();
|
||||
MediaController.SearchImage searchImage = new MediaController.SearchImage();
|
||||
searchImage.type = 2;
|
||||
searchImage.document = document;
|
||||
searchImage.date = date;
|
||||
searchImage.id = "" + searchImage.document.id;
|
||||
arrayList.add(searchImage);
|
||||
//MessagesStorage.getInstance().putWebRecent(arrayList);
|
||||
}
|
||||
|
||||
protected void updateInterfaceWithMessages(final long uid, final ArrayList<MessageObject> messages, boolean isBroadcast) {
|
||||
if (messages == null || messages.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean isEncryptedChat = ((int) uid) == 0;
|
||||
MessageObject lastMessage = null;
|
||||
int channelId = 0;
|
||||
boolean updateRating = false;
|
||||
for (int a = 0; a < messages.size(); a++) {
|
||||
MessageObject message = messages.get(a);
|
||||
if (lastMessage == null || (!isEncryptedChat && message.getId() > lastMessage.getId() || (isEncryptedChat || message.getId() < 0 && lastMessage.getId() < 0) && message.getId() < lastMessage.getId()) || message.messageOwner.date > lastMessage.messageOwner.date) {
|
||||
lastMessage = message;
|
||||
if (message.messageOwner.to_id.channel_id != 0) {
|
||||
channelId = message.messageOwner.to_id.channel_id;
|
||||
}
|
||||
}
|
||||
if (message.isOut() && message.isNewGif() && !message.isSending() && !message.isForwarded()) {
|
||||
addNewGifToRecent(message.messageOwner.media.document, message.messageOwner.date);
|
||||
}
|
||||
if (message.isOut() && message.isSent()) {
|
||||
updateRating = true;
|
||||
}
|
||||
}
|
||||
MessagesQuery.loadReplyMessagesForMessages(messages, uid);
|
||||
NotificationCenter.getInstance().postNotificationName(NotificationCenter.didReceivedNewMessages, uid, messages);
|
||||
|
||||
if (lastMessage == null) {
|
||||
return;
|
||||
}
|
||||
TLRPC.TL_dialog dialog = dialogs_dict.get(uid);
|
||||
|
||||
boolean changed = false;
|
||||
|
||||
if (dialog == null) {
|
||||
if (!isBroadcast) {
|
||||
TLRPC.Chat chat = getChat(channelId);
|
||||
if (channelId != 0 && chat == null || chat != null && chat.left) {
|
||||
return;
|
||||
}
|
||||
dialog = new TLRPC.TL_dialog();
|
||||
dialog.id = uid;
|
||||
dialog.unread_count = 0;
|
||||
dialog.top_message = lastMessage.getId();
|
||||
dialog.last_message_date = lastMessage.messageOwner.date;
|
||||
//dialog.flags = ChatObject.isChannel(chat) ? 1 : 0;
|
||||
dialogs_dict.put(uid, dialog);
|
||||
dialogs.add(dialog);
|
||||
dialogMessage.put(uid, lastMessage);
|
||||
if (lastMessage.messageOwner.to_id.channel_id == 0) {
|
||||
dialogMessagesByIds.put(lastMessage.getId(), lastMessage);
|
||||
if (lastMessage.messageOwner.random_id != 0) {
|
||||
dialogMessagesByRandomIds.put(lastMessage.messageOwner.random_id, lastMessage);
|
||||
}
|
||||
}
|
||||
nextDialogsCacheOffset++;
|
||||
changed = true;
|
||||
}
|
||||
} else {
|
||||
if ((dialog.top_message > 0 && lastMessage.getId() > 0 && lastMessage.getId() > dialog.top_message) ||
|
||||
(dialog.top_message < 0 && lastMessage.getId() < 0 && lastMessage.getId() < dialog.top_message) ||
|
||||
!dialogMessage.containsKey(uid) || dialog.top_message < 0 || dialog.last_message_date <= lastMessage.messageOwner.date) {
|
||||
MessageObject object = dialogMessagesByIds.remove(dialog.top_message);
|
||||
if (object != null && object.messageOwner.random_id != 0) {
|
||||
dialogMessagesByRandomIds.remove(object.messageOwner.random_id);
|
||||
}
|
||||
dialog.top_message = lastMessage.getId();
|
||||
if (!isBroadcast) {
|
||||
dialog.last_message_date = lastMessage.messageOwner.date;
|
||||
changed = true;
|
||||
}
|
||||
dialogMessage.put(uid, lastMessage);
|
||||
if (lastMessage.messageOwner.to_id.channel_id == 0) {
|
||||
dialogMessagesByIds.put(lastMessage.getId(), lastMessage);
|
||||
if (lastMessage.messageOwner.random_id != 0) {
|
||||
dialogMessagesByRandomIds.put(lastMessage.messageOwner.random_id, lastMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
sortDialogs(null);
|
||||
}
|
||||
|
||||
if (updateRating) {
|
||||
SearchQuery.increasePeerRaiting(uid);
|
||||
}
|
||||
}
|
||||
|
||||
public void sortDialogs(HashMap<Integer, TLRPC.Chat> chatsDict) {
|
||||
dialogsServerOnly.clear();
|
||||
dialogsGroupsOnly.clear();
|
||||
Collections.sort(dialogs, dialogComparator);
|
||||
for (int a = 0; a < dialogs.size(); a++) {
|
||||
TLRPC.TL_dialog d = dialogs.get(a);
|
||||
int high_id = (int) (d.id >> 32);
|
||||
int lower_id = (int) d.id;
|
||||
if (lower_id != 0 && high_id != 1) {
|
||||
dialogsServerOnly.add(d);
|
||||
/*if (DialogObject.isChannel(d)) {
|
||||
TLRPC.Chat chat = getChat(-lower_id);
|
||||
if (chat != null && (chat.megagroup && chat.editor || chat.creator)) {
|
||||
dialogsGroupsOnly.add(d);
|
||||
}
|
||||
} else*/ if (lower_id < 0) {
|
||||
/*if (chatsDict != null) {
|
||||
TLRPC.Chat chat = chatsDict.get(-lower_id);
|
||||
if (chat != null && chat.migrated_to != null) {
|
||||
dialogs.remove(a);
|
||||
a--;
|
||||
continue;
|
||||
}
|
||||
}*/
|
||||
dialogsGroupsOnly.add(d);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Messenger Android Frontend
|
||||
* Copyright (C) 2016 Björn Petersen Software Design and Development
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
* (C) 2017 Björn Petersen
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
@@ -20,13 +20,14 @@
|
||||
*******************************************************************************
|
||||
*
|
||||
* File: MrChat.java
|
||||
* Authors: Björn Petersen
|
||||
* Purpose: Wrap around mrchat_t
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
package com.b44t.messenger;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
public class MrChat {
|
||||
|
||||
public final static int MR_CHAT_UNDEFINED = 0;
|
||||
@@ -44,20 +45,13 @@ public class MrChat {
|
||||
MrChatUnref(m_hChat);
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return MrChatGetId(m_hChat);
|
||||
}
|
||||
public int getType() {
|
||||
return MrChatGetType(m_hChat);
|
||||
}
|
||||
public native int getId();
|
||||
public native int getType();
|
||||
public native String getName();
|
||||
public native String getSubtitle();
|
||||
|
||||
public String getName() {
|
||||
return MrChatGetName(m_hChat);
|
||||
}
|
||||
|
||||
public String getSubtitle() {
|
||||
return MrChatGetSubtitle(m_hChat);
|
||||
}
|
||||
public static int MR_CHAT_PARAM_UNPROMOTED = 'U';
|
||||
public native int getParamInt(int key, int def);
|
||||
|
||||
public String getDraft() {
|
||||
return MrChatGetDraft(m_hChat);
|
||||
@@ -82,29 +76,18 @@ public class MrChat {
|
||||
return MrChatGetTotalMsgCount(m_hChat);
|
||||
}
|
||||
|
||||
public int sendText(String text) {
|
||||
return MrChatSendText(m_hChat, text);
|
||||
}
|
||||
public native int sendText(String text);
|
||||
|
||||
public int sendMedia(int type, String file, String mime, int w, int h, int time_ms) {
|
||||
return MrChatSendMedia(m_hChat, type, file, mime, w, h, time_ms);
|
||||
}
|
||||
public native int sendMedia(int type, String file, String mime, int w, int h, int time_ms, String author, String trackname);
|
||||
|
||||
private long m_hChat;
|
||||
private long m_hChat; // must not be renamed as referenced by JNI under the name "m_hChat"
|
||||
private native static void MrChatUnref (long hChat);
|
||||
private native static int MrChatGetId (long hChat);
|
||||
private native static int MrChatGetType (long hChat);
|
||||
private native static String MrChatGetName (long hChat);
|
||||
private native static String MrChatGetSubtitle (long hChat);
|
||||
private native static String MrChatGetDraft (long hChat); // returns null for "no draft"
|
||||
private native static long MrChatGetDraftTimestamp (long hChat); // returns 0 for "no draft"
|
||||
private native static int MrChatGetDraftReplyToMsgId (long hChat); // returns 0 for "no draft"
|
||||
private native static int MrChatSetDraft (long hChat, String draft/*NULL=delete*/, long replyToMsgId);
|
||||
private native static int MrChatGetUnseenCount (long hChat);
|
||||
private native static int MrChatGetTotalMsgCount (long hChat);
|
||||
private native static long MrChatGetSummary (long hChat); // returns hPoortext
|
||||
private native static int MrChatSendText (long hChat, String text); // returns message id
|
||||
private native static int MrChatSendMedia (long hChat, int type, String file, String mime, int w, int h, int time_ms);
|
||||
|
||||
|
||||
/* additional functions that are not 1:1 available in the backend
|
||||
@@ -128,7 +111,51 @@ public class MrChat {
|
||||
return ret;
|
||||
}
|
||||
|
||||
public long GetCPtr() {
|
||||
public long getCPtr() {
|
||||
return m_hChat;
|
||||
}
|
||||
|
||||
public TLRPC.DraftMessage getDraftMessageObj() {
|
||||
if( getId() == 0 ) {
|
||||
return null;
|
||||
}
|
||||
TLRPC.DraftMessage ret = new TLRPC.DraftMessage();
|
||||
ret.message = getDraft();
|
||||
if( ret.message==null || ret.message.isEmpty() ) {
|
||||
return null;
|
||||
}
|
||||
ret.date = (int)getDraftTimestamp();
|
||||
ret.reply_to_msg_id = getDraftReplyToMsgId();
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void saveDraft(CharSequence message, TLRPC.Message replyToMessage) {
|
||||
if( message == null || TextUtils.isEmpty(message) ) {
|
||||
setDraft(null, 0);
|
||||
}
|
||||
else {
|
||||
setDraft(message.toString(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
public void cleanDraft()
|
||||
{
|
||||
setDraft(null, 0);
|
||||
}
|
||||
|
||||
public String getNameNAddr()
|
||||
{
|
||||
// returns name of group chats or name+e-mail-address for normal chats
|
||||
String name = "ErrGrpNameNAddr";
|
||||
if( getType()==MR_CHAT_GROUP ) {
|
||||
name = getName();
|
||||
}
|
||||
else {
|
||||
int contacts[] = MrMailbox.getChatContacts(getId());
|
||||
if( contacts.length==1 ) {
|
||||
name = MrMailbox.getContact(contacts[0]).getNameNAddr();
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Messenger Android Frontend
|
||||
* Copyright (C) 2016 Björn Petersen Software Design and Development
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
* (C) 2017 Björn Petersen
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
@@ -20,7 +20,6 @@
|
||||
*******************************************************************************
|
||||
*
|
||||
* File: MrChatlist.java
|
||||
* Authors: Björn Petersen
|
||||
* Purpose: Wrap around mrchatlist_t
|
||||
*
|
||||
******************************************************************************/
|
||||
@@ -48,7 +47,7 @@ public class MrChatlist {
|
||||
}
|
||||
|
||||
public MrPoortext getSummaryByIndex(int index, MrChat chat) {
|
||||
return new MrPoortext(MrChatlistGetSummaryByIndex(m_hChatlist, index, chat.GetCPtr()));
|
||||
return new MrPoortext(MrChatlistGetSummaryByIndex(m_hChatlist, index, chat.getCPtr()));
|
||||
}
|
||||
|
||||
private long m_hChatlist;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Messenger Android Frontend
|
||||
* Copyright (C) 2016 Björn Petersen Software Design and Development
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
* (C) 2017 Björn Petersen
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
@@ -20,7 +20,6 @@
|
||||
*******************************************************************************
|
||||
*
|
||||
* File: MrContact.java
|
||||
* Authors: Björn Petersen
|
||||
* Purpose: Wrap around mrcontact_t
|
||||
*
|
||||
******************************************************************************/
|
||||
@@ -32,6 +31,7 @@ package com.b44t.messenger;
|
||||
public class MrContact {
|
||||
|
||||
public final static int MR_CONTACT_ID_SELF = 1;
|
||||
public final static int MR_CONTACT_ID_LAST_SPECIAL = 9;
|
||||
|
||||
public MrContact(long hContact) {
|
||||
m_hContact = hContact;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Messenger Android Frontend
|
||||
* Copyright (C) 2016 Björn Petersen Software Design and Development
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
* (C) 2017 Björn Petersen
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
@@ -20,7 +20,6 @@
|
||||
*******************************************************************************
|
||||
*
|
||||
* File: MrMailbox.java
|
||||
* Authors: Björn Petersen
|
||||
* Purpose: Wrap around mrmailbox_t
|
||||
*
|
||||
******************************************************************************/
|
||||
@@ -29,86 +28,56 @@
|
||||
package com.b44t.messenger;
|
||||
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.NetworkInfo;
|
||||
import android.util.Log;
|
||||
|
||||
import com.b44t.ui.Components.ForegroundDetector;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
|
||||
public class MrMailbox {
|
||||
|
||||
public static void init () {
|
||||
m_hMailbox = MrMailboxNew();
|
||||
}
|
||||
|
||||
public static int open(String dbfile, String blobdir) {
|
||||
return MrMailboxOpen(m_hMailbox, dbfile, blobdir);
|
||||
}
|
||||
public native static int open(String dbfile);
|
||||
public native static void close();
|
||||
public native static String getBlobdir();
|
||||
|
||||
public static void close() {
|
||||
MrMailboxClose(m_hMailbox);
|
||||
}
|
||||
public native static void configureAndConnect();
|
||||
public native static void configureCancel();
|
||||
|
||||
public static int configure() {
|
||||
return MrMailboxConfigure(m_hMailbox);
|
||||
}
|
||||
public native static int isConfigured();
|
||||
|
||||
public static int isConfigured() {
|
||||
return MrMailboxIsConfigured(m_hMailbox);
|
||||
}
|
||||
public native static void connect();
|
||||
public native static void disconnect();
|
||||
|
||||
public static int connect() {
|
||||
return MrMailboxConnect(m_hMailbox);
|
||||
}
|
||||
public native static void setConfig(String key, String value);
|
||||
public native static void setConfigInt(String key, int value);
|
||||
public native static String getConfig(String key, String def);
|
||||
public native static int getConfigInt(String key, int def);
|
||||
|
||||
public static void disconnect() {
|
||||
MrMailboxDisconnect(m_hMailbox);
|
||||
}
|
||||
|
||||
public static int fetch() {
|
||||
return MrMailboxFetch(m_hMailbox);
|
||||
}
|
||||
|
||||
public native static String getErrorDescr();
|
||||
|
||||
public static int setConfig(String key, String value) {
|
||||
return MrMailboxSetConfig(m_hMailbox, key, value);
|
||||
}
|
||||
|
||||
public static String getConfig(String key, String def) {
|
||||
return MrMailboxGetConfig(m_hMailbox, key, def);
|
||||
}
|
||||
|
||||
public static int getConfigInt(String key, int def) {
|
||||
return MrMailboxGetConfigInt(m_hMailbox, key, def);
|
||||
}
|
||||
|
||||
public static String getInfo() {
|
||||
return MrMailboxGetInfo(m_hMailbox);
|
||||
}
|
||||
|
||||
public static String execute(String cmd) {
|
||||
return MrMailboxExecute(m_hMailbox, cmd);
|
||||
}
|
||||
public native static String getInfo();
|
||||
public native static String cmdline(String cmd);
|
||||
public native static void heartbeat();
|
||||
|
||||
private static long m_hMailbox = 0; // do not rename this, is used in C-part
|
||||
private native static long MrMailboxNew (); // returns hMailbox which must be unref'd after usage (Names as mrmailbox_new don't work due to the additional underscore)
|
||||
private native static int MrMailboxOpen (long hMailbox, String dbfile, String blobdir);
|
||||
private native static void MrMailboxClose (long hMailbox);
|
||||
private native static int MrMailboxConfigure (long hMailbox);
|
||||
private native static int MrMailboxIsConfigured (long hMailbox);
|
||||
private native static int MrMailboxConnect (long hMailbox);
|
||||
private native static void MrMailboxDisconnect (long hMailbox);
|
||||
private native static int MrMailboxFetch (long hMailbox);
|
||||
private native static int MrMailboxSetConfig (long hMailbox, String key, String value); // value may be NULL
|
||||
private native static String MrMailboxGetConfig (long hMailbox, String key, String def); // def may be NULL, returns empty string as NULL
|
||||
private native static int MrMailboxGetConfigInt (long hMailbox, String key, int def); // def may be NULL, returns empty string as NULL
|
||||
private native static String MrMailboxGetInfo (long hMailbox);
|
||||
private native static String MrMailboxExecute (long hMailbox, String cmd);
|
||||
|
||||
private native static long MrMailboxNew(); // returns hMailbox which must be unref'd after usage (Names as mrmailbox_new don't work due to the additional underscore)
|
||||
|
||||
// contacts
|
||||
public static int[] getKnownContacts(String query) {
|
||||
return MrMailboxGetKnownContacts(m_hMailbox, query);
|
||||
}
|
||||
|
||||
public static int[] getBlockedContacts() {
|
||||
return MrMailboxGetBlockedContacts(m_hMailbox);
|
||||
}
|
||||
public native static int[] getKnownContacts(String query);
|
||||
public native static int getBlockedCount();
|
||||
public native static int[] getBlockedContacts();
|
||||
|
||||
public static MrContact getContact(int contact_id) {
|
||||
return new MrContact(MrMailboxGetContact(m_hMailbox, contact_id));
|
||||
@@ -130,8 +99,6 @@ public class MrMailbox {
|
||||
return MrMailboxAddAddressBook(m_hMailbox, adrbook);
|
||||
}
|
||||
|
||||
private native static int[] MrMailboxGetKnownContacts (long hMailbox, String query);
|
||||
private native static int[] MrMailboxGetBlockedContacts(long hMailbox);
|
||||
private native static long MrMailboxGetContact (long hMailbox, int id);// returns hContact which must be unref'd after usage
|
||||
private native static int MrMailboxCreateContact (long hMailbox, String name, String addr);
|
||||
private native static int MrMailboxBlockContact (long hMailbox, int id, int block);
|
||||
@@ -140,53 +107,40 @@ public class MrMailbox {
|
||||
|
||||
|
||||
// chats
|
||||
public static MrChatlist getChatlist() {
|
||||
return new MrChatlist(MrMailboxGetChatlist(m_hMailbox));
|
||||
public static MrChatlist getChatlist(String query) {
|
||||
return new MrChatlist(MrMailboxGetChatlist(m_hMailbox, query));
|
||||
}
|
||||
|
||||
public static MrChat getChat(int contact_id) {
|
||||
return new MrChat(MrMailboxGetChat(m_hMailbox, contact_id));
|
||||
public static MrChat getChat(int chat_id) {
|
||||
return new MrChat(MrMailboxGetChat(m_hMailbox, chat_id));
|
||||
}
|
||||
|
||||
public native static int markseenMsg(int id); // TODO: needs to be implemented
|
||||
public native static int markseenMsg (int msg_id);
|
||||
public native static int markseenChat (int chat_id);
|
||||
|
||||
public static int markseenChat(int id) {
|
||||
return MrMailboxMarkseenChat(m_hMailbox, id);
|
||||
}
|
||||
public native static int getChatIdByContactId (int contact_id);
|
||||
public native static int createChatByContactId(int contact_id); // returns chat_id
|
||||
|
||||
public static int getChatIdByContactId (int contact_id) {
|
||||
return MrMailboxGetChatIdByContactId(m_hMailbox, contact_id);
|
||||
}
|
||||
public native static int createGroupChat (String name);
|
||||
public native static int isContactInChat (int chat_id, int contact_id);
|
||||
public native static int addContactToChat (int chat_id, int contact_id);
|
||||
public native static int removeContactFromChat (int chat_id, int contact_id);
|
||||
public native static int setChatName (int chat_id, String name);
|
||||
|
||||
public static int createChatByContactId(int contact_id) {
|
||||
return MrMailboxCreateChatByContactId(m_hMailbox, contact_id);
|
||||
}
|
||||
public final static int MR_GCM_ADDDAYMARKER = 0x01;
|
||||
public native static int[] getChatMsgs(int chat_id, int flags, int marker1before);
|
||||
|
||||
public static int[] getChatMsgs(int chat_id) {
|
||||
return MrMailboxGetChatMsgs(m_hMailbox, chat_id);
|
||||
}
|
||||
public native static int[] searchMsgs(int chat_id, String query);
|
||||
|
||||
public static int[] getChatMedia(int chat_id, int msg_type, int or_msg_type) {
|
||||
return MrMailboxGetChatMedia(m_hMailbox, chat_id, msg_type, or_msg_type);
|
||||
}
|
||||
public native static int[] getUnseenMsgs();
|
||||
|
||||
public static int[] getChatContacts(int chat_id) {
|
||||
return MrMailboxGetChatContacts(m_hMailbox, chat_id);
|
||||
}
|
||||
public native static int[] getChatMedia(int chat_id, int msg_type, int or_msg_type);
|
||||
public native static int getNextMedia(int msg_id, int dir);
|
||||
public native static int[] getChatContacts(int chat_id);
|
||||
public native static int deleteChat(int chat_id);
|
||||
|
||||
public static int deleteChat(int chat_id) {
|
||||
return MrMailboxDeleteChat(m_hMailbox, chat_id);
|
||||
}
|
||||
|
||||
private native static long MrMailboxGetChatlist (long hMailbox); // returns hChatlist which must be unref'd after usage
|
||||
private native static long MrMailboxGetChatlist (long hMailbox, String query); // returns hChatlist which must be unref'd after usage
|
||||
private native static long MrMailboxGetChat (long hMailbox, int chat_id); // return hChat which must be unref'd after usage
|
||||
private native static int MrMailboxMarkseenChat (long hMailbox, int id);
|
||||
private native static int MrMailboxGetChatIdByContactId (long hMailbox, int contact_id);
|
||||
private native static int MrMailboxCreateChatByContactId(long hMailbox, int contact_id); // returns chat_id
|
||||
private native static int[] MrMailboxGetChatMsgs (long hMailbox, int chat_id);
|
||||
private native static int[] MrMailboxGetChatMedia (long hMailbox, int chat_id, int msg_type, int or_msg_type);
|
||||
private native static int[] MrMailboxGetChatContacts (long hMailbox, int chat_id);
|
||||
private native static int MrMailboxDeleteChat (long hMailbox, int chat_id);
|
||||
|
||||
|
||||
// msgs
|
||||
@@ -198,46 +152,79 @@ public class MrMailbox {
|
||||
return MrMailboxGetMsgInfo(m_hMailbox, id);
|
||||
}
|
||||
|
||||
public static void deleteMsg(int id) {
|
||||
MrMailboxDeleteMsg(m_hMailbox, id);
|
||||
}
|
||||
public native static void deleteMsgs(int msg_ids[]);
|
||||
public native static void forwardMsgs(int msg_ids[], int chat_ids);
|
||||
|
||||
private native static long MrMailboxGetMsg (long hMailbox, int id); // return hMsg which must be unref'd after usage
|
||||
private native static String MrMailboxGetMsgInfo (long hMailbox, int id);
|
||||
private native static void MrMailboxDeleteMsg (long hMailbox, int id);
|
||||
|
||||
// static
|
||||
public native static void MrStockAddStr (int id, String str);
|
||||
public native static String MrGetVersionStr ();
|
||||
public native static String CPtr2String (long hString); // get strings eg. from data1 from the callback
|
||||
|
||||
public native static long String2CPtr (String str);
|
||||
|
||||
/* receive events
|
||||
**********************************************************************************************/
|
||||
|
||||
public final static int MR_EVENT_MSGS_UPDATED = 2000;
|
||||
public final static int MR_EVENT_INFO = 100;
|
||||
public final static int MR_EVENT_WARNING = 300;
|
||||
public final static int MR_EVENT_ERROR = 400; // INFO and WARNING are blocked in the mrwrapper.c
|
||||
|
||||
public final static int MR_EVENT_MSGS_CHANGED = 2000;
|
||||
public final static int MR_EVENT_INCOMING_MSG = 2005;
|
||||
public final static int MR_EVENT_MSG_DELIVERED = 2010;
|
||||
public final static int MR_EVENT_MSG_READ = 2015;
|
||||
|
||||
public final static int MR_EVENT_CHAT_MODIFIED = 2020;
|
||||
|
||||
public final static int MR_EVENT_CONTACTS_CHANGED = 2030;
|
||||
public final static int MR_EVENT_MSG_DELIVERED = 3000;
|
||||
public final static int MR_EVENT_MSG_READ = 3010;
|
||||
public final static int MR_EVENT_CONNECTION_STATE_CHANGED = 3020;
|
||||
|
||||
public final static int MR_EVENT_CONFIGURE_ENDED = 2040;
|
||||
public final static int MR_EVENT_CONFIGURE_PROGRESS = 2041;
|
||||
|
||||
public final static int MR_EVENT_IS_ONLINE = 2080;
|
||||
public final static int MR_EVENT_GET_STRING = 2091;
|
||||
public final static int MR_EVENT_GET_QUANTITIY_STRING = 2092;
|
||||
public final static int MR_EVENT_HTTP_GET = 2100;
|
||||
public final static int MR_EVENT_WAKE_LOCK = 2110;
|
||||
|
||||
|
||||
public static final Object m_lastErrorLock = new Object();
|
||||
public static int m_lastErrorCode = 0;
|
||||
public static String m_lastErrorString = "";
|
||||
public static boolean m_showNextErrorAsToast = true;
|
||||
|
||||
public static long MrCallback(final int event, final long data1, final long data2) // this function is called from within the C-wrapper
|
||||
{
|
||||
switch(event) {
|
||||
case MR_EVENT_CONNECTION_STATE_CHANGED:
|
||||
case MR_EVENT_CONFIGURE_ENDED:
|
||||
AndroidUtilities.runOnUIThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
NotificationCenter.getInstance().postNotificationName(NotificationCenter.connectionStateChanged, (int)data1);
|
||||
NotificationCenter.getInstance().postNotificationName(NotificationCenter.configureEnded, (int)data1);
|
||||
}
|
||||
});
|
||||
return 0;
|
||||
|
||||
case MR_EVENT_MSGS_UPDATED:
|
||||
case MR_EVENT_CONFIGURE_PROGRESS:
|
||||
AndroidUtilities.runOnUIThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
NotificationCenter.getInstance().postNotificationName(NotificationCenter.configureProgress, (int)data1);
|
||||
}
|
||||
});
|
||||
return 0;
|
||||
|
||||
case MR_EVENT_MSGS_CHANGED:
|
||||
case MR_EVENT_INCOMING_MSG:
|
||||
AndroidUtilities.runOnUIThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
reloadMainChatlist();
|
||||
NotificationCenter.getInstance().postNotificationName(NotificationCenter.dialogsNeedReload, event, (int)data1, (int)data2);
|
||||
if( event == MR_EVENT_INCOMING_MSG ) {
|
||||
NotificationsController.getInstance().processNewMessages((int)data1, (int)data2);
|
||||
}
|
||||
}
|
||||
});
|
||||
return 0;
|
||||
@@ -265,6 +252,128 @@ public class MrMailbox {
|
||||
}
|
||||
});
|
||||
return 0;
|
||||
|
||||
case MR_EVENT_CHAT_MODIFIED:
|
||||
AndroidUtilities.runOnUIThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
reloadMainChatlist();
|
||||
NotificationCenter.getInstance().postNotificationName(NotificationCenter.updateInterfaces,
|
||||
UPDATE_MASK_NAME|UPDATE_MASK_CHAT_NAME|
|
||||
UPDATE_MASK_CHAT_MEMBERS|UPDATE_MASK_AVATAR);
|
||||
}
|
||||
});
|
||||
return 0;
|
||||
|
||||
case MR_EVENT_INFO:
|
||||
Log.i("DeltaChat", CPtr2String(data2));
|
||||
if( BuildConfig.BUILD_TYPE.equals("debug") ) {
|
||||
FileLog.i("DeltaChat", CPtr2String(data2)); // TODO: Can be removed as soon as notifications are reliable.
|
||||
}
|
||||
break;
|
||||
|
||||
case MR_EVENT_WARNING:
|
||||
Log.w("DeltaChat", CPtr2String(data2));
|
||||
if( BuildConfig.BUILD_TYPE.equals("debug") ) {
|
||||
FileLog.w("DeltaChat", CPtr2String(data2)); // TODO: Can be removed as soon as notifications are reliable.
|
||||
}
|
||||
break;
|
||||
|
||||
case MR_EVENT_ERROR:
|
||||
Log.e("DeltaChat", CPtr2String(data2));
|
||||
if( BuildConfig.BUILD_TYPE.equals("debug") ) {
|
||||
FileLog.e("DeltaChat", CPtr2String(data2)); // TODO: Can be removed as soon as notifications are reliable.
|
||||
}
|
||||
synchronized (m_lastErrorLock) {
|
||||
m_lastErrorCode = (int)data1;
|
||||
m_lastErrorString = CPtr2String(data2);
|
||||
}
|
||||
AndroidUtilities.runOnUIThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
synchronized (m_lastErrorLock) {
|
||||
if( m_showNextErrorAsToast ) {
|
||||
if(ForegroundDetector.getInstance().isForeground()) {
|
||||
AndroidUtilities.showHint(ApplicationLoader.applicationContext, m_lastErrorString);
|
||||
}
|
||||
}
|
||||
m_showNextErrorAsToast = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
return 0;
|
||||
|
||||
case MR_EVENT_GET_STRING:
|
||||
String s = "ErrStrBadId";
|
||||
switch( (int)data1 ) {
|
||||
// the string-IDs are defined in the backend; as this is the only place where they're used, there is no benefit in creating an enum or sth. like that.
|
||||
case 1: s = ApplicationLoader.applicationContext.getString(R.string.NoMessages); break;
|
||||
case 2: s = ApplicationLoader.applicationContext.getString(R.string.FromSelf); break;
|
||||
case 3: s = ApplicationLoader.applicationContext.getString(R.string.Draft); break;
|
||||
case 7: s = ApplicationLoader.applicationContext.getString(R.string.AttachVoiceMessage); break;
|
||||
case 8: s = ApplicationLoader.applicationContext.getString(R.string.Deaddrop); break;
|
||||
case 9: s = ApplicationLoader.applicationContext.getString(R.string.AttachPhoto); break;
|
||||
case 10: s = ApplicationLoader.applicationContext.getString(R.string.AttachVideo); break;
|
||||
case 11: s = ApplicationLoader.applicationContext.getString(R.string.Audio); break;
|
||||
case 12: s = ApplicationLoader.applicationContext.getString(R.string.AttachDocument); break;
|
||||
case 13: s = ApplicationLoader.applicationContext.getString(R.string.DefaultStatusText); break;
|
||||
case 14: s = ApplicationLoader.applicationContext.getString(R.string.MsgNewGroupDraft); break;
|
||||
case 15: s = ApplicationLoader.applicationContext.getString(R.string.MsgGroupNameChanged); break;
|
||||
case 16: s = ApplicationLoader.applicationContext.getString(R.string.MsgGroupImageChanged); break;
|
||||
case 17: s = ApplicationLoader.applicationContext.getString(R.string.MsgMemberAddedToGroup); break;
|
||||
case 18: s = ApplicationLoader.applicationContext.getString(R.string.MsgMemberRemovedFromToGroup); break;
|
||||
case 19: s = ApplicationLoader.applicationContext.getString(R.string.MsgGroupLeft); break;
|
||||
case 20: s = ApplicationLoader.applicationContext.getString(R.string.Error); break;
|
||||
case 21: s = ApplicationLoader.applicationContext.getString(R.string.ErrSelfNotInGroup); break;
|
||||
case 22: s = ApplicationLoader.applicationContext.getString(R.string.NoNetwork); break;
|
||||
}
|
||||
return String2CPtr(s);
|
||||
|
||||
case MR_EVENT_GET_QUANTITIY_STRING:
|
||||
String sp = "ErrQtyStrBadId";
|
||||
switch( (int)data1 ) {
|
||||
// the string-IDs are defined in the backend; as this is the only place where they're used, there is no benefit in creating an enum or sth. like that.
|
||||
case 4: sp = ApplicationLoader.applicationContext.getResources().getQuantityString(R.plurals.Members, (int)data2, (int)data2); break;
|
||||
case 6: sp = ApplicationLoader.applicationContext.getResources().getQuantityString(R.plurals.Contacts, (int)data2, (int)data2); break;
|
||||
}
|
||||
return String2CPtr(sp);
|
||||
|
||||
case MR_EVENT_IS_ONLINE:
|
||||
return ApplicationLoader.isNetworkOnline()? 1 : 0;
|
||||
|
||||
case MR_EVENT_HTTP_GET:
|
||||
String httpContent = null;
|
||||
try {
|
||||
URL url = new URL(CPtr2String(data1));
|
||||
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
|
||||
try {
|
||||
InputStream inputStream = new BufferedInputStream(urlConnection.getInputStream());
|
||||
|
||||
BufferedReader r = new BufferedReader(new InputStreamReader(inputStream));
|
||||
StringBuilder total = new StringBuilder();
|
||||
String line;
|
||||
while ((line = r.readLine()) != null) {
|
||||
total.append(line).append('\n');
|
||||
}
|
||||
httpContent = total.toString();
|
||||
} finally {
|
||||
urlConnection.disconnect();
|
||||
}
|
||||
}
|
||||
catch(Exception e) {}
|
||||
return String2CPtr(httpContent);
|
||||
|
||||
case MR_EVENT_WAKE_LOCK:
|
||||
if( data1 != 0 ) {
|
||||
ApplicationLoader.backendWakeLock.acquire();
|
||||
}
|
||||
else {
|
||||
if( !ApplicationLoader.wakeupWakeLock.isHeld()) {
|
||||
ApplicationLoader.wakeupWakeLock.acquire(1 * 1000); /* make sure, subsequent release/acquires do not make the CPU sleep */
|
||||
}
|
||||
ApplicationLoader.backendWakeLock.release();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -273,10 +382,83 @@ public class MrMailbox {
|
||||
/* additional functions that are not 1:1 available in the backend
|
||||
**********************************************************************************************/
|
||||
|
||||
public static void log_i(String tag, String msg)
|
||||
{
|
||||
Log.i(tag, msg);
|
||||
if( BuildConfig.BUILD_TYPE.equals("debug") ) {
|
||||
FileLog.i(tag, msg); // TODO: Can be removed as soon as notifications are reliable.
|
||||
}
|
||||
}
|
||||
|
||||
public static MrChatlist m_currChatlist = new MrChatlist(0);
|
||||
public native static int getCurrentTime ();
|
||||
public static void reloadMainChatlist()
|
||||
{
|
||||
m_currChatlist = getChatlist();
|
||||
m_currChatlist = getChatlist(null);
|
||||
}
|
||||
|
||||
public final static int MEDIA_PHOTOVIDEO = 0;
|
||||
public static void getMediaCount(final long uid, final int type, final int classGuid, boolean fromCache) {
|
||||
Utilities.globalQueue.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
int[] media = new int[0];
|
||||
if( type == MEDIA_PHOTOVIDEO ) {
|
||||
media = MrMailbox.getChatMedia((int)uid, MrMsg.MR_MSG_IMAGE, MrMsg.MR_MSG_VIDEO);
|
||||
}
|
||||
|
||||
NotificationCenter.getInstance().postNotificationName(NotificationCenter.mediaCountDidLoaded,
|
||||
uid, media.length, false /*not from cache*/, type, media);
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static String getInviteText() {
|
||||
String url = "https://getdelta.org";
|
||||
String email = getConfig("addr", "");
|
||||
String text = LocaleController.formatString("InviteText", R.string.InviteText, url, email);
|
||||
return text;
|
||||
}
|
||||
|
||||
public static TLRPC.User getUser(Integer id) {
|
||||
TLRPC.User u = new TLRPC.User(); // legacy function, information should be loaded as needed by the caller
|
||||
u.id = id;
|
||||
return u;
|
||||
}
|
||||
|
||||
public static void cancelTyping(int action, long dialog_id) {
|
||||
}
|
||||
|
||||
public static void sendTyping(final long dialog_id, final int action, int classGuid) {
|
||||
}
|
||||
|
||||
public static void markMessageContentAsRead(final MessageObject messageObject) {
|
||||
}
|
||||
|
||||
public static boolean isDialogMuted(long dialog_id) {
|
||||
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Activity.MODE_PRIVATE);
|
||||
int mute_type = preferences.getInt("notify2_" + dialog_id, 0);
|
||||
if (mute_type == 2) {
|
||||
return true;
|
||||
} else if (mute_type == 3) {
|
||||
int mute_until = preferences.getInt("notifyuntil_" + dialog_id, 0);
|
||||
if (mute_until >= MrMailbox.getCurrentTime()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// legacy update masks
|
||||
public static final int UPDATE_MASK_NAME = 1;
|
||||
public static final int UPDATE_MASK_AVATAR = 2;
|
||||
public static final int UPDATE_MASK_STATUS = 4;
|
||||
public static final int UPDATE_MASK_CHAT_AVATAR = 8;
|
||||
public static final int UPDATE_MASK_CHAT_NAME = 16;
|
||||
public static final int UPDATE_MASK_CHAT_MEMBERS = 32;
|
||||
public static final int UPDATE_MASK_SELECT_DIALOG = 512;
|
||||
public static final int UPDATE_MASK_NEW_MESSAGE = 2048;
|
||||
public static final int UPDATE_MASK_SEND_STATE = 4096;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Messenger Android Frontend
|
||||
* Copyright (C) 2016 Björn Petersen Software Design and Development
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
* (C) 2017 Björn Petersen
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
@@ -20,7 +20,6 @@
|
||||
*******************************************************************************
|
||||
*
|
||||
* File: MrMsg.java
|
||||
* Authors: Björn Petersen
|
||||
* Purpose: Wrap around mrmsg_t
|
||||
*
|
||||
******************************************************************************/
|
||||
@@ -28,12 +27,22 @@
|
||||
|
||||
package com.b44t.messenger;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.media.ThumbnailUtils;
|
||||
import android.provider.MediaStore;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class MrMsg {
|
||||
|
||||
private static final String TAG = "MrMsg";
|
||||
|
||||
public final static int MR_MSG_UNDEFINED = 0;
|
||||
public final static int MR_MSG_TEXT = 10;
|
||||
public final static int MR_MSG_IMAGE = 20;
|
||||
public final static int MR_MSG_AUDIO = 40;
|
||||
public final static int MR_MSG_VOICE = 41;
|
||||
public final static int MR_MSG_VIDEO = 50;
|
||||
public final static int MR_MSG_FILE = 60;
|
||||
|
||||
@@ -46,6 +55,9 @@ public class MrMsg {
|
||||
public final static int MR_OUT_DELIVERED = 26;
|
||||
public final static int MR_OUT_READ = 28;
|
||||
|
||||
public final static int MR_MSG_ID_MARKER1 = 1;
|
||||
public final static int MR_MSG_ID_DAYMARKER = 9;
|
||||
|
||||
public MrMsg(long hMsg) {
|
||||
m_hMsg = hMsg;
|
||||
}
|
||||
@@ -84,14 +96,21 @@ public class MrMsg {
|
||||
return MrMsgGetToId(m_hMsg);
|
||||
}
|
||||
|
||||
public String getParam (int key, String def) {
|
||||
return MrMsgGetParam(m_hMsg, key, def);
|
||||
}
|
||||
public int getParamInt(int key, int def) {
|
||||
return MrMsgGetParamInt(m_hMsg, key, def);
|
||||
}
|
||||
public native String getParam(int key, String def);
|
||||
public native int getParamInt(int key, int def);
|
||||
public native void setParamInt(int key, int def);
|
||||
public native void saveParamToDisk();
|
||||
|
||||
private long m_hMsg;
|
||||
public native int getBytes();
|
||||
public MrPoortext getSummary(MrChat chat) { return new MrPoortext(getSummaryCPtr(chat.getCPtr())); }
|
||||
private native long getSummaryCPtr(long hChat);
|
||||
public native String getSummarytext(int approx_characters);
|
||||
public MrPoortext getMediainfo() { return new MrPoortext(getMediainfoCPtr()); }
|
||||
private native long getMediainfoCPtr();
|
||||
public native String getFilename();
|
||||
public native int isIncreation();
|
||||
|
||||
private long m_hMsg; // must not be renamed as referenced by JNI under the name "m_hMsg"
|
||||
private native static void MrMsgUnref (long hMsg);
|
||||
private native static int MrMsgGetId (long hMsg);
|
||||
private native static String MrMsgGetText (long hMsg);
|
||||
@@ -101,8 +120,6 @@ public class MrMsg {
|
||||
private native static int MrMsgGetChatId (long hMsg);
|
||||
private native static int MrMsgGetFromId (long hMsg);
|
||||
private native static int MrMsgGetToId (long hMsg);
|
||||
private native static String MrMsgGetParam (long hMsg, int key, String def);
|
||||
private native static int MrMsgGetParamInt (long hMsg, int key, int def);
|
||||
|
||||
|
||||
/* additional functions that are not 1:1 available in the backend
|
||||
@@ -132,7 +149,6 @@ public class MrMsg {
|
||||
ret.unread = state!=MR_OUT_READ; // the state of outgoing messages
|
||||
ret.media_unread = ret.unread;
|
||||
ret.flags = 0; // posible flags: MESSAGE_FLAG_HAS_FROM_ID, however, this seems to be read only
|
||||
ret.post = false; // ? true=avatar wird in gruppen nicht angezeigt, wird aber in isFromUser() auch überprüft...
|
||||
ret.out = ret.from_id==MrContact.MR_CONTACT_ID_SELF; // true=outgoing message, read eg. in MessageObject.isOutOwner()
|
||||
ret.created_by_mr = true;
|
||||
|
||||
@@ -147,11 +163,21 @@ public class MrMsg {
|
||||
TLRPC.TL_photoSize photoSize = new TLRPC.TL_photoSize();
|
||||
photoSize.w = getParamInt('w', 800);
|
||||
photoSize.h = getParamInt('h', 800);
|
||||
photoSize.size = 0;
|
||||
photoSize.size = 0; // not sure what to use here, maybe `getBytes();`?
|
||||
photoSize.location = new TLRPC.TL_fileLocation();
|
||||
photoSize.location.mr_path = path;
|
||||
photoSize.location.local_id = -ret.id; // this forces the document to be searched in the cache dir
|
||||
photoSize.type = "x";
|
||||
if (photoSize.w <= 100 && photoSize.h <= 100) {
|
||||
photoSize.type = "s";
|
||||
} else if (photoSize.w <= 320 && photoSize.h <= 320) {
|
||||
photoSize.type = "m";
|
||||
} else if (photoSize.w <= 800 && photoSize.h <= 800) {
|
||||
photoSize.type = "x";
|
||||
} else if (photoSize.w <= 1280 && photoSize.h <= 1280) {
|
||||
photoSize.type = "y";
|
||||
} else {
|
||||
photoSize.type = "w";
|
||||
}
|
||||
photo = new TLRPC.TL_photo();
|
||||
photo.sizes.add(photoSize);
|
||||
} catch (Exception e) {
|
||||
@@ -169,37 +195,78 @@ public class MrMsg {
|
||||
ret.message = "<cannot load image>";
|
||||
}
|
||||
}
|
||||
else if( type == MR_MSG_AUDIO || type == MR_MSG_VIDEO ) {
|
||||
else if( type == MR_MSG_AUDIO || type == MR_MSG_VOICE || type == MR_MSG_VIDEO || type == MR_MSG_FILE ) {
|
||||
String path = getParam('f', "");
|
||||
if( !path.isEmpty()) {
|
||||
ret.message = "-1"; // may be misused for video editing information
|
||||
ret.media = new TLRPC.TL_messageMediaDocument();
|
||||
ret.media.caption = "";
|
||||
ret.media.document = new TLRPC.TL_document();
|
||||
ret.media.document.file_name = getFilename();
|
||||
ret.media.document.mr_path = path;
|
||||
if( type == MR_MSG_AUDIO ) {
|
||||
ret.media.document.size = getBytes();
|
||||
if( type == MR_MSG_AUDIO || type == MR_MSG_VOICE ) {
|
||||
TLRPC.TL_documentAttributeAudio attr = new TLRPC.TL_documentAttributeAudio();
|
||||
attr.voice = true; // !voice = music
|
||||
attr.voice = type == MR_MSG_VOICE;
|
||||
attr.duration = getParamInt('d', 0) / 1000;
|
||||
ret.media.document.attributes.add(attr);
|
||||
}
|
||||
else if( type == MR_MSG_VIDEO) {
|
||||
else if( type == MR_MSG_VIDEO ) {
|
||||
File vfile = new File(path);
|
||||
File tfile = new File(MrMailbox.getBlobdir(), vfile.getName()+"-preview.jpg");
|
||||
if( !tfile.exists() ) {
|
||||
try {
|
||||
Bitmap thumb = ThumbnailUtils.createVideoThumbnail(path, MediaStore.Video.Thumbnails.MINI_KIND);
|
||||
TLRPC.PhotoSize size = ImageLoader.scaleAndSaveImage(tfile, thumb, 90, 90, 55, false);
|
||||
size.location.mr_path = tfile.getAbsolutePath();
|
||||
size.type = "s";
|
||||
ret.media.document.thumb = size;
|
||||
|
||||
setParamInt('w', size.w);
|
||||
setParamInt('h', size.h);
|
||||
saveParamToDisk();
|
||||
}
|
||||
catch (Exception e) {}
|
||||
}
|
||||
else {
|
||||
TLRPC.PhotoSize size = new TLRPC.PhotoSize();
|
||||
size.location = new TLRPC.TL_fileLocation();
|
||||
size.location.mr_path = tfile.getAbsolutePath();
|
||||
size.location.local_id = -ret.id;
|
||||
size.w = getParamInt('w', 320);
|
||||
size.h = getParamInt('h', 240);
|
||||
size.type = "s";
|
||||
ret.media.document.thumb = size;
|
||||
}
|
||||
|
||||
TLRPC.TL_documentAttributeVideo attr = new TLRPC.TL_documentAttributeVideo();
|
||||
attr.duration = getParamInt('d', 0) / 1000;
|
||||
attr.w = getParamInt('w', 0);
|
||||
attr.h = getParamInt('h', 0);
|
||||
attr.w = getParamInt('w', 320);
|
||||
attr.h = getParamInt('h', 240);
|
||||
ret.media.document.attributes.add(attr);
|
||||
}
|
||||
else {
|
||||
ret.media.document.mime_type = getParam('m', "application/octet-stream");
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
ret.message = "<path missing>";
|
||||
ret.message = "<file path missing>";
|
||||
}
|
||||
}
|
||||
else {
|
||||
ret.message = String.format("<unsupported message type #%d for id #%d>", type, ret.id);
|
||||
}
|
||||
|
||||
if( !getParam('a', "").equals("") ) {
|
||||
ret.flags |= TLRPC.MESSAGE_FLAG_FWD;
|
||||
ret.fwd_from = new TLRPC.TL_messageFwdHeader();
|
||||
ret.fwd_from.m_name = getParam('A', "");
|
||||
if( ret.fwd_from.m_name.isEmpty() ) {
|
||||
ret.fwd_from.m_name = getParam('a', "");
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Messenger Android Frontend
|
||||
* Copyright (C) 2016 Björn Petersen Software Design and Development
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
* (C) 2017 Björn Petersen
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
@@ -20,7 +20,6 @@
|
||||
*******************************************************************************
|
||||
*
|
||||
* File: MrPoortext.java
|
||||
* Authors: Björn Petersen
|
||||
* Purpose: Wrap around mrpoortext_t
|
||||
*
|
||||
******************************************************************************/
|
||||
@@ -31,10 +30,10 @@ package com.b44t.messenger;
|
||||
|
||||
public class MrPoortext {
|
||||
|
||||
public final static int MR_TITLE_NORMAL = 0;
|
||||
public final static int MR_TITLE_DRAFT = 1;
|
||||
public final static int MR_TITLE_USERNAME = 2;
|
||||
public final static int MR_TITLE_SELF = 3;
|
||||
public final static int MR_TEXT1_NORMAL = 0;
|
||||
public final static int MR_TEXT1_DRAFT = 1;
|
||||
public final static int MR_TEXT1_USERNAME = 2;
|
||||
public final static int MR_TEXT1_SELF = 3;
|
||||
|
||||
public MrPoortext(long hPoortext) {
|
||||
m_hPoortext = hPoortext;
|
||||
@@ -45,16 +44,16 @@ public class MrPoortext {
|
||||
MrPoortextUnref(m_hPoortext);
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return MrPoortextGetTitle(m_hPoortext);
|
||||
public String getText1() {
|
||||
return MrPoortextGetText1(m_hPoortext);
|
||||
}
|
||||
|
||||
public int getTitleMeaning() {
|
||||
return MrPoortextGetTitleMeaning(m_hPoortext);
|
||||
public int getText1Meaning() {
|
||||
return MrPoortextGetText1Meaning(m_hPoortext);
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return MrPoortextGetText(m_hPoortext);
|
||||
public String getText2() {
|
||||
return MrPoortextGetText2(m_hPoortext);
|
||||
}
|
||||
|
||||
public long getTimestamp() {
|
||||
@@ -67,9 +66,9 @@ public class MrPoortext {
|
||||
|
||||
private long m_hPoortext;
|
||||
private native static void MrPoortextUnref (long hPoortext);
|
||||
private native static String MrPoortextGetTitle (long hPoortext);
|
||||
private native static int MrPoortextGetTitleMeaning (long hPoortext);
|
||||
private native static String MrPoortextGetText (long hPoortext);
|
||||
private native static String MrPoortextGetText1 (long hPoortext);
|
||||
private native static int MrPoortextGetText1Meaning (long hPoortext);
|
||||
private native static String MrPoortextGetText2 (long hPoortext);
|
||||
private native static long MrPoortextGetTimestamp (long hPoortext);
|
||||
private native static int MrPoortextGetState (long hPoortext);
|
||||
}
|
||||
|
||||
@@ -1,589 +0,0 @@
|
||||
/*
|
||||
* This is the source code of Telegram for Android v. 3.x.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2016.
|
||||
*/
|
||||
|
||||
package com.b44t.messenger;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.BitmapShader;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.Shader;
|
||||
import android.media.MediaDescription;
|
||||
import android.media.MediaMetadata;
|
||||
import android.media.browse.MediaBrowser;
|
||||
import android.media.session.MediaSession;
|
||||
import android.media.session.PlaybackState;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.os.Process;
|
||||
import android.os.SystemClock;
|
||||
import android.service.media.MediaBrowserService;
|
||||
|
||||
import com.b44t.messenger.audioinfo.AudioInfo;
|
||||
import com.b44t.ui.LaunchActivity;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
public class MusicBrowserService extends MediaBrowserService implements NotificationCenter.NotificationCenterDelegate {
|
||||
|
||||
private static final String AUTO_APP_PACKAGE_NAME = "com.google.android.projection.gearhead";
|
||||
private static final String SLOT_RESERVATION_SKIP_TO_NEXT = "com.google.android.gms.car.media.ALWAYS_RESERVE_SPACE_FOR.ACTION_SKIP_TO_NEXT";
|
||||
private static final String SLOT_RESERVATION_SKIP_TO_PREV = "com.google.android.gms.car.media.ALWAYS_RESERVE_SPACE_FOR.ACTION_SKIP_TO_PREVIOUS";
|
||||
private static final String SLOT_RESERVATION_QUEUE = "com.google.android.gms.car.media.ALWAYS_RESERVE_SPACE_FOR.ACTION_QUEUE";
|
||||
|
||||
private MediaSession mediaSession;
|
||||
private static final String MEDIA_ID_ROOT = "__ROOT__";
|
||||
|
||||
private boolean chatsLoaded;
|
||||
private boolean loadingChats;
|
||||
private ArrayList<Integer> dialogs = new ArrayList<>();
|
||||
private HashMap<Integer, TLRPC.User> users = new HashMap<>();
|
||||
private HashMap<Integer, TLRPC.Chat> chats = new HashMap<>();
|
||||
private HashMap<Integer, ArrayList<MessageObject>> musicObjects = new HashMap<>();
|
||||
private HashMap<Integer, ArrayList<MediaSession.QueueItem>> musicQueues = new HashMap<>();
|
||||
|
||||
public static final String ACTION_CMD = "com.example.android.mediabrowserservice.ACTION_CMD";
|
||||
public static final String CMD_NAME = "CMD_NAME";
|
||||
public static final String CMD_PAUSE = "CMD_PAUSE";
|
||||
|
||||
private Paint roundPaint;
|
||||
private RectF bitmapRect;
|
||||
|
||||
private boolean serviceStarted;
|
||||
|
||||
private int lastSelectedDialog;
|
||||
|
||||
private static final int STOP_DELAY = 30000;
|
||||
|
||||
private DelayedStopHandler delayedStopHandler = new DelayedStopHandler(this);
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
ApplicationLoader.postInitApplication();
|
||||
|
||||
lastSelectedDialog = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Activity.MODE_PRIVATE).getInt("auto_lastSelectedDialog", 0);
|
||||
|
||||
mediaSession = new MediaSession(this, "MusicService");
|
||||
setSessionToken(mediaSession.getSessionToken());
|
||||
mediaSession.setCallback(new MediaSessionCallback());
|
||||
mediaSession.setFlags(MediaSession.FLAG_HANDLES_MEDIA_BUTTONS | MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS);
|
||||
|
||||
Context context = getApplicationContext();
|
||||
Intent intent = new Intent(context, LaunchActivity.class);
|
||||
PendingIntent pi = PendingIntent.getActivity(context, 99, intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
mediaSession.setSessionActivity(pi);
|
||||
|
||||
Bundle extras = new Bundle();
|
||||
extras.putBoolean(SLOT_RESERVATION_QUEUE, true);
|
||||
extras.putBoolean(SLOT_RESERVATION_SKIP_TO_PREV, true);
|
||||
extras.putBoolean(SLOT_RESERVATION_SKIP_TO_NEXT, true);
|
||||
mediaSession.setExtras(extras);
|
||||
|
||||
updatePlaybackState(null);
|
||||
|
||||
NotificationCenter.getInstance().addObserver(this, NotificationCenter.audioPlayStateChanged);
|
||||
NotificationCenter.getInstance().addObserver(this, NotificationCenter.audioDidStarted);
|
||||
NotificationCenter.getInstance().addObserver(this, NotificationCenter.audioDidReset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent startIntent, int flags, int startId) {
|
||||
/*if (startIntent != null) {
|
||||
String action = startIntent.getAction();
|
||||
String command = startIntent.getStringExtra(CMD_NAME);
|
||||
if (ACTION_CMD.equals(action)) {
|
||||
if (CMD_PAUSE.equals(command)) {
|
||||
if (mPlayback != null && mPlayback.isPlaying()) {
|
||||
handlePauseRequest();
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
return START_STICKY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
handleStopRequest(null);
|
||||
delayedStopHandler.removeCallbacksAndMessages(null);
|
||||
mediaSession.release();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BrowserRoot onGetRoot(String clientPackageName, int clientUid, Bundle rootHints) {
|
||||
if (clientPackageName == null || Process.SYSTEM_UID != clientUid && Process.myUid() != clientUid && !clientPackageName.equals("com.google.android.mediasimulator") && !clientPackageName.equals("com.google.android.projection.gearhead")) {
|
||||
return null;
|
||||
}
|
||||
return new BrowserRoot(MEDIA_ID_ROOT, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadChildren(final String parentMediaId, final Result<List<MediaBrowser.MediaItem>> result) {
|
||||
if (!chatsLoaded) {
|
||||
result.detach();
|
||||
if (loadingChats) {
|
||||
return;
|
||||
}
|
||||
loadingChats = true;
|
||||
/*
|
||||
MessagesStorage.getInstance().getStorageQueue().postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
ArrayList<Integer> usersToLoad = new ArrayList<>();
|
||||
ArrayList<Integer> chatsToLoad = new ArrayList<>();
|
||||
SQLiteCursor cursor = MessagesStorage.getInstance().getDatabase().queryFinalized(String.format(Locale.US, "SELECT DISTINCT uid FROM media_v2 WHERE uid != 0 AND mid > 0 AND type = %d", SharedMediaQuery.MEDIA_MUSIC));
|
||||
while (cursor.next()) {
|
||||
int lower_part = (int) cursor.longValue(0);
|
||||
if (lower_part == 0) {
|
||||
continue;
|
||||
}
|
||||
dialogs.add(lower_part);
|
||||
if (lower_part > 0) {
|
||||
usersToLoad.add(lower_part);
|
||||
} else {
|
||||
chatsToLoad.add(-lower_part);
|
||||
}
|
||||
}
|
||||
cursor.dispose();
|
||||
if (!dialogs.isEmpty()) {
|
||||
String ids = TextUtils.join(",", dialogs);
|
||||
cursor = MessagesStorage.getInstance().getDatabase().queryFinalized(String.format(Locale.US, "SELECT uid, data, mid FROM media_v2 WHERE uid IN (%s) AND mid > 0 AND type = %d ORDER BY date DESC, mid DESC", ids, SharedMediaQuery.MEDIA_MUSIC));
|
||||
while (cursor.next()) {
|
||||
NativeByteBuffer data = cursor.byteBufferValue(1);
|
||||
if (data != null) {
|
||||
TLRPC.Message message = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false);
|
||||
data.reuse();
|
||||
if (MessageObject.isMusicMessage(message)) {
|
||||
int did = cursor.intValue(0);
|
||||
message.id = cursor.intValue(2);
|
||||
message.dialog_id = did;
|
||||
ArrayList<MessageObject> arrayList = musicObjects.get(did);
|
||||
ArrayList<MediaSession.QueueItem> arrayList1 = musicQueues.get(did);
|
||||
if (arrayList == null) {
|
||||
arrayList = new ArrayList<>();
|
||||
musicObjects.put(did, arrayList);
|
||||
arrayList1 = new ArrayList<>();
|
||||
musicQueues.put(did, arrayList1);
|
||||
}
|
||||
MessageObject messageObject = new MessageObject(message, null, false);
|
||||
arrayList.add(0, messageObject);
|
||||
MediaDescription.Builder builder = new MediaDescription.Builder().setMediaId(did + "_" + arrayList.size());
|
||||
builder.setTitle(messageObject.getMusicTitle());
|
||||
builder.setSubtitle(messageObject.getMusicAuthor());
|
||||
arrayList1.add(0, new MediaSession.QueueItem(builder.build(), arrayList1.size()));
|
||||
}
|
||||
}
|
||||
}
|
||||
cursor.dispose();
|
||||
if (!usersToLoad.isEmpty()) {
|
||||
ArrayList<TLRPC.User> usersArrayList = new ArrayList<>();
|
||||
//MessagesStorage.getInstance().getUsersInternal(TextUtils.join(",", usersToLoad), usersArrayList);
|
||||
for (int a = 0; a < usersArrayList.size(); a++) {
|
||||
TLRPC.User user = usersArrayList.get(a);
|
||||
users.put(user.id, user);
|
||||
}
|
||||
}
|
||||
if (!chatsToLoad.isEmpty()) {
|
||||
ArrayList<TLRPC.Chat> chatsArrayList = new ArrayList<>();
|
||||
//MessagesStorage.getInstance().getChatsInternal(TextUtils.join(",", chatsToLoad), chatsArrayList);
|
||||
for (int a = 0; a < chatsArrayList.size(); a++) {
|
||||
TLRPC.Chat chat = chatsArrayList.get(a);
|
||||
chats.put(chat.id, chat);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
AndroidUtilities.runOnUIThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
chatsLoaded = true;
|
||||
loadingChats = false;
|
||||
loadChildrenImpl(parentMediaId, result);
|
||||
if (lastSelectedDialog == 0 && !dialogs.isEmpty()) {
|
||||
lastSelectedDialog = dialogs.get(0);
|
||||
}
|
||||
if (lastSelectedDialog != 0) {
|
||||
ArrayList<MessageObject> arrayList = musicObjects.get(lastSelectedDialog);
|
||||
ArrayList<MediaSession.QueueItem> arrayList1 = musicQueues.get(lastSelectedDialog);
|
||||
if (arrayList != null && !arrayList.isEmpty()) {
|
||||
mediaSession.setQueue(arrayList1);
|
||||
if (lastSelectedDialog > 0) {
|
||||
TLRPC.User user = users.get(lastSelectedDialog);
|
||||
if (user != null) {
|
||||
mediaSession.setQueueTitle(ContactsController.formatName(user.first_name, user.last_name));
|
||||
} else {
|
||||
mediaSession.setQueueTitle("DELETED USER");
|
||||
}
|
||||
} else {
|
||||
TLRPC.Chat chat = chats.get(-lastSelectedDialog);
|
||||
if (chat != null) {
|
||||
mediaSession.setQueueTitle(chat.title);
|
||||
} else {
|
||||
mediaSession.setQueueTitle("DELETED CHAT");
|
||||
}
|
||||
}
|
||||
MessageObject messageObject = arrayList.get(0);
|
||||
MediaMetadata.Builder builder = new MediaMetadata.Builder();
|
||||
builder.putLong(MediaMetadata.METADATA_KEY_DURATION, messageObject.getDuration() * 1000);
|
||||
builder.putString(MediaMetadata.METADATA_KEY_ARTIST, messageObject.getMusicAuthor());
|
||||
builder.putString(MediaMetadata.METADATA_KEY_TITLE, messageObject.getMusicTitle());
|
||||
mediaSession.setMetadata(builder.build());
|
||||
}
|
||||
}
|
||||
updatePlaybackState(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
*/
|
||||
} else {
|
||||
loadChildrenImpl(parentMediaId, result);
|
||||
}
|
||||
}
|
||||
|
||||
private void loadChildrenImpl(final String parentMediaId, final Result<List<MediaBrowser.MediaItem>> result) {
|
||||
List<MediaBrowser.MediaItem> mediaItems = new ArrayList<>();
|
||||
|
||||
if (MEDIA_ID_ROOT.equals(parentMediaId)) {
|
||||
for (int a = 0; a < dialogs.size(); a++) {
|
||||
int did = dialogs.get(a);
|
||||
MediaDescription.Builder builder = new MediaDescription.Builder().setMediaId("__CHAT_" + did);
|
||||
TLRPC.FileLocation avatar = null;
|
||||
if (did > 0) {
|
||||
TLRPC.User user = users.get(did);
|
||||
if (user != null) {
|
||||
builder.setTitle(ContactsController.formatName(user.first_name, user.last_name));
|
||||
if (user.photo != null && user.photo.photo_small instanceof TLRPC.TL_fileLocation) {
|
||||
avatar = user.photo.photo_small;
|
||||
}
|
||||
} else {
|
||||
builder.setTitle("DELETED USER");
|
||||
}
|
||||
} else {
|
||||
TLRPC.Chat chat = chats.get(-did);
|
||||
if (chat != null) {
|
||||
builder.setTitle(chat.title);
|
||||
if (chat.photo != null && chat.photo.photo_small instanceof TLRPC.TL_fileLocation) {
|
||||
avatar = chat.photo.photo_small;
|
||||
}
|
||||
} else {
|
||||
builder.setTitle("DELETED CHAT");
|
||||
}
|
||||
}
|
||||
Bitmap bitmap = null;
|
||||
if (avatar != null) {
|
||||
bitmap = createRoundBitmap(FileLoader.getPathToAttach(avatar, true));
|
||||
if (bitmap != null) {
|
||||
builder.setIconBitmap(bitmap);
|
||||
}
|
||||
}
|
||||
if (avatar == null || bitmap == null) {
|
||||
builder.setIconUri(Uri.parse("android.resource://" + getApplicationContext().getPackageName() + "/drawable/contact_blue"));
|
||||
}
|
||||
mediaItems.add(new MediaBrowser.MediaItem(builder.build(), MediaBrowser.MediaItem.FLAG_BROWSABLE));
|
||||
}
|
||||
} else if (parentMediaId != null && parentMediaId.startsWith("__CHAT_")) {
|
||||
int did = 0;
|
||||
try {
|
||||
did = Integer.parseInt(parentMediaId.replace("__CHAT_", ""));
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
ArrayList<MessageObject> arrayList = musicObjects.get(did);
|
||||
if (arrayList != null) {
|
||||
for (int a = 0; a < arrayList.size(); a++) {
|
||||
MessageObject messageObject = arrayList.get(a);
|
||||
MediaDescription.Builder builder = new MediaDescription.Builder().setMediaId(did + "_" + a);
|
||||
builder.setTitle(messageObject.getMusicTitle());
|
||||
builder.setSubtitle(messageObject.getMusicAuthor());
|
||||
mediaItems.add(new MediaBrowser.MediaItem(builder.build(), MediaBrowser.MediaItem.FLAG_PLAYABLE));
|
||||
}
|
||||
}
|
||||
}
|
||||
result.sendResult(mediaItems);
|
||||
}
|
||||
|
||||
private Bitmap createRoundBitmap(File path) {
|
||||
try {
|
||||
BitmapFactory.Options options = new BitmapFactory.Options();
|
||||
options.inSampleSize = 2;
|
||||
Bitmap bitmap = BitmapFactory.decodeFile(path.toString(), options);
|
||||
if (bitmap != null) {
|
||||
Bitmap result = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
|
||||
result.eraseColor(Color.TRANSPARENT);
|
||||
Canvas canvas = new Canvas(result);
|
||||
BitmapShader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
|
||||
if (roundPaint == null) {
|
||||
roundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
bitmapRect = new RectF();
|
||||
}
|
||||
roundPaint.setShader(shader);
|
||||
bitmapRect.set(0, 0, bitmap.getWidth(), bitmap.getHeight());
|
||||
canvas.drawRoundRect(bitmapRect, bitmap.getWidth(), bitmap.getHeight(), roundPaint);
|
||||
return result;
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private final class MediaSessionCallback extends MediaSession.Callback {
|
||||
@Override
|
||||
public void onPlay() {
|
||||
MessageObject messageObject = MediaController.getInstance().getPlayingMessageObject();
|
||||
if (messageObject == null) {
|
||||
onPlayFromMediaId(lastSelectedDialog + "_" + 0, null);
|
||||
} else {
|
||||
MediaController.getInstance().playAudio(messageObject);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSkipToQueueItem(long queueId) {
|
||||
MediaController.getInstance().playMessageAtIndex((int) queueId);
|
||||
handlePlayRequest();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSeekTo(long position) {
|
||||
MessageObject messageObject = MediaController.getInstance().getPlayingMessageObject();
|
||||
if (messageObject != null) {
|
||||
MediaController.getInstance().seekToProgress(messageObject, position / 1000 / (float) messageObject.getDuration());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayFromMediaId(String mediaId, Bundle extras) {
|
||||
String args[] = mediaId.split("_");
|
||||
if (args.length != 2) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
int did = Integer.parseInt(args[0]);
|
||||
int id = Integer.parseInt(args[1]);
|
||||
ArrayList<MessageObject> arrayList = musicObjects.get(did);
|
||||
ArrayList<MediaSession.QueueItem> arrayList1 = musicQueues.get(did);
|
||||
if (arrayList == null || id < 0 || id >= arrayList.size()) {
|
||||
return;
|
||||
}
|
||||
lastSelectedDialog = did;
|
||||
ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Activity.MODE_PRIVATE).edit().putInt("auto_lastSelectedDialog", did).commit();
|
||||
MediaController.getInstance().setPlaylist(arrayList, arrayList.get(id), false);
|
||||
mediaSession.setQueue(arrayList1);
|
||||
if (did > 0) {
|
||||
TLRPC.User user = users.get(did);
|
||||
if (user != null) {
|
||||
mediaSession.setQueueTitle(ContactsController.formatName(user.first_name, user.last_name));
|
||||
} else {
|
||||
mediaSession.setQueueTitle("DELETED USER");
|
||||
}
|
||||
} else {
|
||||
TLRPC.Chat chat = chats.get(-did);
|
||||
if (chat != null) {
|
||||
mediaSession.setQueueTitle(chat.title);
|
||||
} else {
|
||||
mediaSession.setQueueTitle("DELETED CHAT");
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
handlePlayRequest();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
handlePauseRequest();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
handleStopRequest(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSkipToNext() {
|
||||
MediaController.getInstance().playNextMessage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSkipToPrevious() {
|
||||
MediaController.getInstance().playPreviousMessage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayFromSearch(String query, Bundle extras) {
|
||||
if (query == null || query.length() == 0) {
|
||||
return;
|
||||
}
|
||||
query = query.toLowerCase();
|
||||
for (int a = 0; a < dialogs.size(); a++) {
|
||||
int did = dialogs.get(a);
|
||||
if (did > 0) {
|
||||
TLRPC.User user = users.get(did);
|
||||
if (user == null) {
|
||||
continue;
|
||||
}
|
||||
if (user.first_name != null && user.first_name.startsWith(query) || user.last_name != null && user.last_name.startsWith(query)) {
|
||||
onPlayFromMediaId(did + "_" + 0, null);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
TLRPC.Chat chat = chats.get(-did);
|
||||
if (chat == null) {
|
||||
continue;
|
||||
}
|
||||
if (chat.title != null && chat.title.toLowerCase().contains(query)) {
|
||||
onPlayFromMediaId(did + "_" + 0, null);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updatePlaybackState(String error) {
|
||||
long position = PlaybackState.PLAYBACK_POSITION_UNKNOWN;
|
||||
MessageObject playingMessageObject = MediaController.getInstance().getPlayingMessageObject();
|
||||
if (playingMessageObject != null) {
|
||||
position = playingMessageObject.audioProgressSec * 1000;
|
||||
}
|
||||
|
||||
PlaybackState.Builder stateBuilder = new PlaybackState.Builder().setActions(getAvailableActions());
|
||||
int state;
|
||||
if (playingMessageObject == null) {
|
||||
state = PlaybackState.STATE_STOPPED;
|
||||
} else {
|
||||
if (MediaController.getInstance().isDownloadingCurrentMessage()) {
|
||||
state = PlaybackState.STATE_BUFFERING;
|
||||
} else {
|
||||
state = MediaController.getInstance().isAudioPaused() ? PlaybackState.STATE_PAUSED : PlaybackState.STATE_PLAYING;
|
||||
}
|
||||
}
|
||||
|
||||
if (error != null) {
|
||||
stateBuilder.setErrorMessage(error);
|
||||
state = PlaybackState.STATE_ERROR;
|
||||
}
|
||||
stateBuilder.setState(state, position, 1.0f, SystemClock.elapsedRealtime());
|
||||
if (playingMessageObject != null) {
|
||||
stateBuilder.setActiveQueueItemId(MediaController.getInstance().getPlayingMessageObjectNum());
|
||||
} else {
|
||||
stateBuilder.setActiveQueueItemId(0);
|
||||
}
|
||||
|
||||
mediaSession.setPlaybackState(stateBuilder.build());
|
||||
}
|
||||
|
||||
private long getAvailableActions() {
|
||||
long actions = PlaybackState.ACTION_PLAY | PlaybackState.ACTION_PLAY_FROM_MEDIA_ID | PlaybackState.ACTION_PLAY_FROM_SEARCH;
|
||||
MessageObject playingMessageObject = MediaController.getInstance().getPlayingMessageObject();
|
||||
if (playingMessageObject != null) {
|
||||
if (!MediaController.getInstance().isAudioPaused()) {
|
||||
actions |= PlaybackState.ACTION_PAUSE;
|
||||
}
|
||||
actions |= PlaybackState.ACTION_SKIP_TO_PREVIOUS;
|
||||
actions |= PlaybackState.ACTION_SKIP_TO_NEXT;
|
||||
}
|
||||
return actions;
|
||||
}
|
||||
|
||||
private void handleStopRequest(String withError) {
|
||||
delayedStopHandler.removeCallbacksAndMessages(null);
|
||||
delayedStopHandler.sendEmptyMessageDelayed(0, STOP_DELAY);
|
||||
updatePlaybackState(withError);
|
||||
stopSelf();
|
||||
serviceStarted = false;
|
||||
NotificationCenter.getInstance().removeObserver(this, NotificationCenter.audioPlayStateChanged);
|
||||
NotificationCenter.getInstance().removeObserver(this, NotificationCenter.audioDidStarted);
|
||||
NotificationCenter.getInstance().removeObserver(this, NotificationCenter.audioDidReset);
|
||||
}
|
||||
|
||||
private void handlePlayRequest() {
|
||||
delayedStopHandler.removeCallbacksAndMessages(null);
|
||||
if (!serviceStarted) {
|
||||
startService(new Intent(getApplicationContext(), MusicBrowserService.class));
|
||||
serviceStarted = true;
|
||||
}
|
||||
|
||||
if (!mediaSession.isActive()) {
|
||||
mediaSession.setActive(true);
|
||||
}
|
||||
|
||||
MessageObject messageObject = MediaController.getInstance().getPlayingMessageObject();
|
||||
if (messageObject == null) {
|
||||
return;
|
||||
}
|
||||
MediaMetadata.Builder builder = new MediaMetadata.Builder();
|
||||
builder.putLong(MediaMetadata.METADATA_KEY_DURATION, messageObject.getDuration() * 1000);
|
||||
builder.putString(MediaMetadata.METADATA_KEY_ARTIST, messageObject.getMusicAuthor());
|
||||
builder.putString(MediaMetadata.METADATA_KEY_TITLE, messageObject.getMusicTitle());
|
||||
AudioInfo audioInfo = MediaController.getInstance().getAudioInfo();
|
||||
if (audioInfo != null) {
|
||||
Bitmap bitmap = audioInfo.getCover();
|
||||
if (bitmap != null) {
|
||||
builder.putBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART, bitmap);
|
||||
}
|
||||
}
|
||||
mediaSession.setMetadata(builder.build());
|
||||
}
|
||||
|
||||
private void handlePauseRequest() {
|
||||
MediaController.getInstance().pauseAudio(MediaController.getInstance().getPlayingMessageObject());
|
||||
delayedStopHandler.removeCallbacksAndMessages(null);
|
||||
delayedStopHandler.sendEmptyMessageDelayed(0, STOP_DELAY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void didReceivedNotification(int id, Object... args) {
|
||||
updatePlaybackState(null);
|
||||
handlePlayRequest();
|
||||
}
|
||||
|
||||
private static class DelayedStopHandler extends Handler {
|
||||
private final WeakReference<MusicBrowserService> mWeakReference;
|
||||
|
||||
private DelayedStopHandler(MusicBrowserService service) {
|
||||
mWeakReference = new WeakReference<>(service);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
MusicBrowserService service = mWeakReference.get();
|
||||
if (service != null) {
|
||||
MessageObject messageObject = MediaController.getInstance().getPlayingMessageObject();
|
||||
if (messageObject != null && !MediaController.getInstance().isAudioPaused()) {
|
||||
return;
|
||||
}
|
||||
service.stopSelf();
|
||||
service.serviceStarted = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,25 @@
|
||||
/*
|
||||
* This is the source code of Telegram for Android v. 3.x.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2016.
|
||||
*/
|
||||
* Messenger Android Frontend
|
||||
* (C) 2013-2016 Nikolai Kudashov
|
||||
* (C) 2017 Björn Petersen
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see http://www.gnu.org/licenses/ .
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
package com.b44t.messenger;
|
||||
|
||||
@@ -46,10 +61,10 @@ public class MusicPlayerReceiver extends BroadcastReceiver {
|
||||
case KeyEvent.KEYCODE_MEDIA_STOP:
|
||||
break;
|
||||
case KeyEvent.KEYCODE_MEDIA_NEXT:
|
||||
MediaController.getInstance().playNextMessage();
|
||||
MediaController.getInstance().playNextMessage(+1, false);
|
||||
break;
|
||||
case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
|
||||
MediaController.getInstance().playPreviousMessage();
|
||||
MediaController.getInstance().playNextMessage(-1, false);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
@@ -58,11 +73,11 @@ public class MusicPlayerReceiver extends BroadcastReceiver {
|
||||
} else if (intent.getAction().equals(MusicPlayerService.NOTIFY_PAUSE) || intent.getAction().equals(android.media.AudioManager.ACTION_AUDIO_BECOMING_NOISY)) {
|
||||
MediaController.getInstance().pauseAudio(MediaController.getInstance().getPlayingMessageObject());
|
||||
} else if (intent.getAction().equals(MusicPlayerService.NOTIFY_NEXT)) {
|
||||
MediaController.getInstance().playNextMessage();
|
||||
MediaController.getInstance().playNextMessage(+1, false);
|
||||
} else if (intent.getAction().equals(MusicPlayerService.NOTIFY_CLOSE)) {
|
||||
MediaController.getInstance().cleanupPlayer(true, true);
|
||||
} else if (intent.getAction().equals(MusicPlayerService.NOTIFY_PREVIOUS)) {
|
||||
MediaController.getInstance().playPreviousMessage();
|
||||
MediaController.getInstance().playNextMessage(-1, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,25 @@
|
||||
/*
|
||||
* This is the source code of Telegram for Android v. 3.x.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2016.
|
||||
*/
|
||||
* Messenger Android Frontend
|
||||
* (C) 2013-2016 Nikolai Kudashov
|
||||
* (C) 2017 Björn Petersen
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see http://www.gnu.org/licenses/ .
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
package com.b44t.messenger;
|
||||
|
||||
@@ -38,7 +53,6 @@ public class MusicPlayerService extends Service implements NotificationCenter.No
|
||||
private RemoteControlClient remoteControlClient;
|
||||
private AudioManager audioManager;
|
||||
|
||||
private static boolean supportBigNotifications = Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN;
|
||||
private static boolean supportLockScreenControls = Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH;
|
||||
|
||||
@Override
|
||||
@@ -82,7 +96,7 @@ public class MusicPlayerService extends Service implements NotificationCenter.No
|
||||
remoteControlClient.setTransportControlFlags(RemoteControlClient.FLAG_KEY_MEDIA_PLAY | RemoteControlClient.FLAG_KEY_MEDIA_PAUSE | RemoteControlClient.FLAG_KEY_MEDIA_PLAY_PAUSE |
|
||||
RemoteControlClient.FLAG_KEY_MEDIA_STOP | RemoteControlClient.FLAG_KEY_MEDIA_PREVIOUS | RemoteControlClient.FLAG_KEY_MEDIA_NEXT);
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
|
||||
}
|
||||
}
|
||||
createNotification(messageObject);
|
||||
@@ -93,95 +107,70 @@ public class MusicPlayerService extends Service implements NotificationCenter.No
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
private void createNotification(MessageObject messageObject) {
|
||||
String songName = messageObject.getMusicTitle();
|
||||
String authorName = messageObject.getMusicAuthor();
|
||||
private void createNotification(MessageObject messageObject)
|
||||
{
|
||||
AudioInfo audioInfo = MediaController.getInstance().getAudioInfo();
|
||||
|
||||
RemoteViews simpleContentView = new RemoteViews(getApplicationContext().getPackageName(), R.layout.player_small_notification);
|
||||
RemoteViews expandedView = null;
|
||||
if (supportBigNotifications) {
|
||||
expandedView = new RemoteViews(getApplicationContext().getPackageName(), R.layout.player_big_notification);
|
||||
MrPoortext pt = MrMailbox.getMsg(messageObject.getId()).getMediainfo();
|
||||
String authorName = pt.getText1();
|
||||
String songName = pt.getText2();
|
||||
if( songName == null || songName.length()==0 ) {
|
||||
TLRPC.Document document = messageObject.messageOwner.media.document;
|
||||
for (int i = 0; i < document.attributes.size(); i++) {
|
||||
TLRPC.DocumentAttribute attr = document.attributes.get(i);
|
||||
if (attr instanceof TLRPC.TL_documentAttributeAudio) {
|
||||
authorName = attr.performer;
|
||||
songName = attr.title;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Intent intent = new Intent(ApplicationLoader.applicationContext, LaunchActivity.class);
|
||||
intent.setAction("com.b44t.messenger.openplayer");
|
||||
intent.setFlags(32768);
|
||||
PendingIntent contentIntent = PendingIntent.getActivity(ApplicationLoader.applicationContext, 0, intent, 0);
|
||||
if( songName == null || songName.length()==0 ) {
|
||||
// preview of just recorded and not send voice messages
|
||||
authorName = ApplicationLoader.applicationContext.getString(R.string.FromSelf);
|
||||
songName = ApplicationLoader.applicationContext.getString(R.string.AttachVoiceMessage);
|
||||
}
|
||||
|
||||
RemoteViews simpleContentView = new RemoteViews(getApplicationContext().getPackageName(), R.layout.player_small_notification);
|
||||
|
||||
//Intent intent = new Intent(ApplicationLoader.applicationContext, LaunchActivity.class);
|
||||
//intent.setAction("com.b44t.messenger.openchat"+messageObject.getDialogId());
|
||||
//intent.setFlags(32768);
|
||||
//PendingIntent contentIntent = PendingIntent.getActivity(ApplicationLoader.applicationContext, 0, intent, 0);
|
||||
|
||||
Notification notification = new NotificationCompat.Builder(getApplicationContext())
|
||||
.setSmallIcon(R.drawable.player)
|
||||
.setContentIntent(contentIntent)
|
||||
.setSmallIcon(R.drawable.notification_player)
|
||||
//.setContentIntent(contentIntent)
|
||||
.setContentTitle(songName).build();
|
||||
|
||||
notification.contentView = simpleContentView;
|
||||
if (supportBigNotifications) {
|
||||
notification.bigContentView = expandedView;
|
||||
}
|
||||
|
||||
setListeners(simpleContentView);
|
||||
if (supportBigNotifications) {
|
||||
setListeners(expandedView);
|
||||
}
|
||||
|
||||
Bitmap albumArt = audioInfo != null ? audioInfo.getSmallCover() : null;
|
||||
if (albumArt != null) {
|
||||
notification.contentView.setImageViewBitmap(R.id.player_album_art, albumArt);
|
||||
if (supportBigNotifications) {
|
||||
notification.bigContentView.setImageViewBitmap(R.id.player_album_art, albumArt);
|
||||
}
|
||||
notification.contentView.setViewVisibility(R.id.player_album_art, View.VISIBLE);
|
||||
} else {
|
||||
notification.contentView.setImageViewResource(R.id.player_album_art, R.drawable.nocover_small);
|
||||
if (supportBigNotifications) {
|
||||
notification.bigContentView.setImageViewResource(R.id.player_album_art, R.drawable.nocover_big);
|
||||
}
|
||||
notification.contentView.setViewVisibility(R.id.player_album_art, View.GONE);
|
||||
}
|
||||
if (MediaController.getInstance().isDownloadingCurrentMessage()) {
|
||||
notification.contentView.setViewVisibility(R.id.player_pause, View.GONE);
|
||||
notification.contentView.setViewVisibility(R.id.player_play, View.GONE);
|
||||
notification.contentView.setViewVisibility(R.id.player_next, View.GONE);
|
||||
notification.contentView.setViewVisibility(R.id.player_previous, View.GONE);
|
||||
notification.contentView.setViewVisibility(R.id.player_progress_bar, View.VISIBLE);
|
||||
if (supportBigNotifications) {
|
||||
notification.bigContentView.setViewVisibility(R.id.player_pause, View.GONE);
|
||||
notification.bigContentView.setViewVisibility(R.id.player_play, View.GONE);
|
||||
notification.bigContentView.setViewVisibility(R.id.player_next, View.GONE);
|
||||
notification.bigContentView.setViewVisibility(R.id.player_previous, View.GONE);
|
||||
notification.bigContentView.setViewVisibility(R.id.player_progress_bar, View.VISIBLE);
|
||||
}
|
||||
} else {
|
||||
notification.contentView.setViewVisibility(R.id.player_progress_bar, View.GONE);
|
||||
|
||||
{
|
||||
notification.contentView.setViewVisibility(R.id.player_next, View.VISIBLE);
|
||||
notification.contentView.setViewVisibility(R.id.player_previous, View.VISIBLE);
|
||||
if (supportBigNotifications) {
|
||||
notification.bigContentView.setViewVisibility(R.id.player_next, View.VISIBLE);
|
||||
notification.bigContentView.setViewVisibility(R.id.player_previous, View.VISIBLE);
|
||||
notification.bigContentView.setViewVisibility(R.id.player_progress_bar, View.GONE);
|
||||
}
|
||||
|
||||
if (MediaController.getInstance().isAudioPaused()) {
|
||||
notification.contentView.setViewVisibility(R.id.player_pause, View.GONE);
|
||||
notification.contentView.setViewVisibility(R.id.player_play, View.VISIBLE);
|
||||
if (supportBigNotifications) {
|
||||
notification.bigContentView.setViewVisibility(R.id.player_pause, View.GONE);
|
||||
notification.bigContentView.setViewVisibility(R.id.player_play, View.VISIBLE);
|
||||
}
|
||||
} else {
|
||||
notification.contentView.setViewVisibility(R.id.player_pause, View.VISIBLE);
|
||||
notification.contentView.setViewVisibility(R.id.player_play, View.GONE);
|
||||
if (supportBigNotifications) {
|
||||
notification.bigContentView.setViewVisibility(R.id.player_pause, View.VISIBLE);
|
||||
notification.bigContentView.setViewVisibility(R.id.player_play, View.GONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
notification.contentView.setTextViewText(R.id.player_song_name, songName);
|
||||
notification.contentView.setTextViewText(R.id.player_author_name, authorName);
|
||||
if (supportBigNotifications) {
|
||||
notification.bigContentView.setTextViewText(R.id.player_song_name, songName);
|
||||
notification.bigContentView.setTextViewText(R.id.player_author_name, authorName);
|
||||
}
|
||||
notification.flags |= Notification.FLAG_ONGOING_EVENT;
|
||||
startForeground(5, notification);
|
||||
|
||||
@@ -193,7 +182,7 @@ public class MusicPlayerService extends Service implements NotificationCenter.No
|
||||
try {
|
||||
metadataEditor.putBitmap(RemoteControlClient.MetadataEditor.BITMAP_KEY_ARTWORK, audioInfo.getCover());
|
||||
} catch (Throwable e) {
|
||||
FileLog.e("messenger", e);
|
||||
|
||||
}
|
||||
}
|
||||
metadataEditor.apply();
|
||||
@@ -203,12 +192,16 @@ public class MusicPlayerService extends Service implements NotificationCenter.No
|
||||
public void setListeners(RemoteViews view) {
|
||||
PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, new Intent(NOTIFY_PREVIOUS), PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
view.setOnClickPendingIntent(R.id.player_previous, pendingIntent);
|
||||
|
||||
pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, new Intent(NOTIFY_CLOSE), PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
view.setOnClickPendingIntent(R.id.player_close, pendingIntent);
|
||||
|
||||
pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, new Intent(NOTIFY_PAUSE), PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
view.setOnClickPendingIntent(R.id.player_pause, pendingIntent);
|
||||
|
||||
pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, new Intent(NOTIFY_NEXT), PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
view.setOnClickPendingIntent(R.id.player_next, pendingIntent);
|
||||
|
||||
pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, new Intent(NOTIFY_PLAY), PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
view.setOnClickPendingIntent(R.id.player_play, pendingIntent);
|
||||
}
|
||||
|
||||
@@ -1,197 +0,0 @@
|
||||
/*
|
||||
* This is the source code of Telegram for Android v. 1.3.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2016.
|
||||
*/
|
||||
|
||||
package com.b44t.messenger;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.os.Build;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
public class NativeLoader {
|
||||
|
||||
private final static int LIB_VERSION = 1;
|
||||
private final static String LIB_NAME = "messenger." + LIB_VERSION;
|
||||
private final static String LIB_SO_NAME = "lib" + LIB_NAME + ".so";
|
||||
private final static String LOCALE_LIB_SO_NAME = "lib" + LIB_NAME + "loc.so";
|
||||
//private String crashPath = "";
|
||||
|
||||
private static volatile boolean nativeLoaded = false;
|
||||
|
||||
private static File getNativeLibraryDir(Context context) {
|
||||
File f = null;
|
||||
if (context != null) {
|
||||
try {
|
||||
f = new File((String)ApplicationInfo.class.getField("nativeLibraryDir").get(context.getApplicationInfo()));
|
||||
} catch (Throwable th) {
|
||||
th.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (f == null) {
|
||||
f = new File(context.getApplicationInfo().dataDir, "lib");
|
||||
}
|
||||
if (f.isDirectory()) {
|
||||
return f;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean loadFromZip(Context context, File destDir, File destLocalFile, String folder) {
|
||||
try {
|
||||
for (File file : destDir.listFiles()) {
|
||||
file.delete();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
|
||||
ZipFile zipFile = null;
|
||||
InputStream stream = null;
|
||||
try {
|
||||
zipFile = new ZipFile(context.getApplicationInfo().sourceDir);
|
||||
ZipEntry entry = zipFile.getEntry("lib/" + folder + "/" + LIB_SO_NAME);
|
||||
if (entry == null) {
|
||||
throw new Exception("Unable to find file in apk:" + "lib/" + folder + "/" + LIB_NAME);
|
||||
}
|
||||
stream = zipFile.getInputStream(entry);
|
||||
|
||||
OutputStream out = new FileOutputStream(destLocalFile);
|
||||
byte[] buf = new byte[4096];
|
||||
int len;
|
||||
while ((len = stream.read(buf)) > 0) {
|
||||
Thread.yield();
|
||||
out.write(buf, 0, len);
|
||||
}
|
||||
out.close();
|
||||
|
||||
destLocalFile.setReadable(true, false);
|
||||
destLocalFile.setExecutable(true, false);
|
||||
destLocalFile.setWritable(true);
|
||||
|
||||
try {
|
||||
System.load(destLocalFile.getAbsolutePath());
|
||||
//init(context.getCacheDir().getAbsolutePath(), BuildVars.DEBUG_VERSION);
|
||||
nativeLoaded = true;
|
||||
} catch (Error e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
} finally {
|
||||
if (stream != null) {
|
||||
try {
|
||||
stream.close();
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
}
|
||||
if (zipFile != null) {
|
||||
try {
|
||||
zipFile.close();
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static synchronized void initNativeLibs(Context context) {
|
||||
if (nativeLoaded) {
|
||||
return;
|
||||
}
|
||||
|
||||
String crashDir = context.getCacheDir().getAbsolutePath();
|
||||
|
||||
try {
|
||||
String folder;
|
||||
try {
|
||||
if (Build.CPU_ABI.equalsIgnoreCase("armeabi-v7a")) {
|
||||
folder = "armeabi-v7a";
|
||||
} else if (Build.CPU_ABI.equalsIgnoreCase("armeabi")) {
|
||||
folder = "armeabi";
|
||||
} else if (Build.CPU_ABI.equalsIgnoreCase("x86")) {
|
||||
folder = "x86";
|
||||
} else if (Build.CPU_ABI.equalsIgnoreCase("mips")) {
|
||||
folder = "mips";
|
||||
} else {
|
||||
folder = "armeabi";
|
||||
FileLog.e("messenger", "Unsupported arch: " + Build.CPU_ABI);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
folder = "armeabi";
|
||||
}
|
||||
|
||||
String javaArch = System.getProperty("os.arch");
|
||||
if (javaArch != null && javaArch.contains("686")) {
|
||||
folder = "x86";
|
||||
}
|
||||
|
||||
|
||||
File destFile = getNativeLibraryDir(context);
|
||||
if (destFile != null) {
|
||||
destFile = new File(destFile, LIB_SO_NAME);
|
||||
if (destFile.exists()) {
|
||||
FileLog.d("messenger", "load normal lib");
|
||||
try {
|
||||
System.loadLibrary(LIB_NAME);
|
||||
//init(crashDir, BuildVars.DEBUG_VERSION);
|
||||
nativeLoaded = true;
|
||||
return;
|
||||
} catch (Error e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File destDir = new File(context.getFilesDir(), "lib");
|
||||
destDir.mkdirs();
|
||||
|
||||
File destLocalFile = new File(destDir, LOCALE_LIB_SO_NAME);
|
||||
if (destLocalFile.exists()) {
|
||||
try {
|
||||
FileLog.d("messenger", "Load local lib");
|
||||
System.load(destLocalFile.getAbsolutePath());
|
||||
//init(crashDir, BuildVars.DEBUG_VERSION);
|
||||
nativeLoaded = true;
|
||||
return;
|
||||
} catch (Error e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
destLocalFile.delete();
|
||||
}
|
||||
|
||||
FileLog.e("messenger", "Library not found, arch = " + folder);
|
||||
|
||||
if (loadFromZip(context, destDir, destLocalFile, folder)) {
|
||||
return;
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
try {
|
||||
System.loadLibrary(LIB_NAME);
|
||||
//init(crashDir, BuildVars.DEBUG_VERSION);
|
||||
nativeLoaded = true;
|
||||
} catch (Error e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
}
|
||||
|
||||
//private static native void init(String path, boolean enableGoglBreakpad); // not needed
|
||||
//public static native void crash();
|
||||
}
|
||||
@@ -1,10 +1,25 @@
|
||||
/*
|
||||
* This is the source code of Telegram for Android v. 3.x.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2016.
|
||||
*/
|
||||
* Messenger Android Frontend
|
||||
* (C) 2013-2016 Nikolai Kudashov
|
||||
* (C) 2017 Björn Petersen
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see http://www.gnu.org/licenses/ .
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
package com.b44t.messenger;
|
||||
|
||||
@@ -16,72 +31,35 @@ public class NotificationCenter {
|
||||
|
||||
private static int totalEvents = 1;
|
||||
|
||||
public static final int connectionStateChanged = totalEvents++;
|
||||
public static final int configureEnded = totalEvents++;
|
||||
public static final int configureProgress = totalEvents++;
|
||||
public static final int didReceivedNewMessages = totalEvents++;
|
||||
public static final int updateInterfaces = totalEvents++;
|
||||
public static final int dialogsNeedReload = totalEvents++;
|
||||
public static final int closeChats = totalEvents++;
|
||||
public static final int messagesDeleted = totalEvents++;
|
||||
public static final int messagesSentOrRead = totalEvents++;
|
||||
public static final int messageReceivedByAck = totalEvents++;
|
||||
public static final int messageReceivedByServer = totalEvents++;
|
||||
public static final int messageSendError = totalEvents++;
|
||||
public static final int contactsDidLoaded = totalEvents++;
|
||||
public static final int chatDidCreated = totalEvents++;
|
||||
public static final int chatDidFailCreate = totalEvents++;
|
||||
public static final int mediaDidLoaded = totalEvents++;
|
||||
public static final int mediaCountDidLoaded = totalEvents++;
|
||||
public static final int dialogPhotosLoaded = totalEvents++;
|
||||
public static final int removeAllMessagesFromDialog = totalEvents++;
|
||||
public static final int notificationsSettingsUpdated = totalEvents++;
|
||||
public static final int pushMessagesUpdated = totalEvents++;
|
||||
public static final int blockedUsersDidLoaded = totalEvents++;
|
||||
public static final int openedChatChanged = totalEvents++;
|
||||
public static final int stopEncodingService = totalEvents++;
|
||||
public static final int didCreatedNewDeleteTask = totalEvents++;
|
||||
public static final int mainUserInfoChanged = totalEvents++;
|
||||
public static final int updateMessageMedia = totalEvents++;
|
||||
public static final int recentImagesDidLoaded = totalEvents++;
|
||||
public static final int replaceMessagesObjects = totalEvents++;
|
||||
public static final int waveformCalculated = totalEvents++;
|
||||
public static final int didSetPasscode = totalEvents++;
|
||||
//public static final int screenStateChanged = totalEvents++; -- currently not used, but this may get handy
|
||||
public static final int didLoadedReplyMessages = totalEvents++;
|
||||
public static final int didReceivedWebpages = totalEvents++;
|
||||
public static final int didReceivedWebpagesInUpdates = totalEvents++;
|
||||
public static final int stickersDidLoaded = totalEvents++;
|
||||
public static final int didReplacedPhotoInMemCache = totalEvents++;
|
||||
public static final int messagesReadContent = totalEvents++;
|
||||
public static final int userInfoDidLoaded = totalEvents++;
|
||||
public static final int chatSearchResultsAvailable = totalEvents++;
|
||||
public static final int musicDidLoaded = totalEvents++;
|
||||
public static final int didUpdatedMessagesViews = totalEvents++;
|
||||
public static final int needReloadRecentDialogsSearch = totalEvents++;
|
||||
public static final int locationPermissionGranted = totalEvents++;
|
||||
public static final int peerSettingsDidLoaded = totalEvents++;
|
||||
public static final int wasUnableToFindCurrentLocation = totalEvents++;
|
||||
public static final int reloadHints = totalEvents++;
|
||||
public static final int reloadInlineHints = totalEvents++;
|
||||
public static final int newDraftReceived = totalEvents++;
|
||||
|
||||
public static final int httpFileDidLoaded = totalEvents++;
|
||||
public static final int httpFileDidFailedLoad = totalEvents++;
|
||||
|
||||
public static final int messageThumbGenerated = totalEvents++;
|
||||
|
||||
public static final int wallpapersDidLoaded = totalEvents++;
|
||||
public static final int closeOtherAppActivities = totalEvents++;
|
||||
public static final int didUpdatedConnectionState = totalEvents++;
|
||||
public static final int didReceiveSmsCode = totalEvents++;
|
||||
public static final int didReceiveCall = totalEvents++;
|
||||
public static final int emojiDidLoaded = totalEvents++;
|
||||
public static final int appDidLogout = totalEvents++;
|
||||
|
||||
public static final int FileDidUpload = totalEvents++;
|
||||
public static final int FileDidFailUpload = totalEvents++;
|
||||
public static final int FileUploadProgressChanged = totalEvents++;
|
||||
public static final int FileLoadProgressChanged = totalEvents++;
|
||||
public static final int FileDidLoaded = totalEvents++;
|
||||
public static final int FileDidFailedLoad = totalEvents++;
|
||||
public static final int FilePreparingStarted = totalEvents++;
|
||||
public static final int FileNewChunkAvailable = totalEvents++;
|
||||
public static final int FilePreparingFailed = totalEvents++;
|
||||
@@ -93,7 +71,6 @@ public class NotificationCenter {
|
||||
public static final int recordStarted = totalEvents++;
|
||||
public static final int recordStartError = totalEvents++;
|
||||
public static final int recordStopped = totalEvents++;
|
||||
public static final int screenshotTook = totalEvents++;
|
||||
public static final int albumsDidLoaded = totalEvents++;
|
||||
public static final int audioDidSent = totalEvents++;
|
||||
public static final int audioDidStarted = totalEvents++;
|
||||
@@ -173,17 +150,18 @@ public class NotificationCenter {
|
||||
}
|
||||
|
||||
public void postNotificationNameInternal(int id, boolean allowDuringAnimation, Object... args) {
|
||||
if (BuildVars.DEBUG_VERSION) {
|
||||
/*if (BuildConfig.BUILD_TYPE.equals("debug")) {
|
||||
if (Thread.currentThread() != ApplicationLoader.applicationHandler.getLooper().getThread()) {
|
||||
throw new RuntimeException("postNotificationName allowed only from MAIN thread");
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
if (!allowDuringAnimation && animationInProgress) {
|
||||
DelayedPost delayedPost = new DelayedPost(id, args);
|
||||
delayedPosts.add(delayedPost);
|
||||
if (BuildVars.DEBUG_VERSION) {
|
||||
FileLog.e("messenger", "delay post notification " + id + " with args count = " + args.length);
|
||||
}
|
||||
/*if (BuildConfig.BUILD_TYPE.equals("debug")) {
|
||||
Log.i("DeltaChat", "delay post notification " + id + " with args count = " + args.length);
|
||||
}*/
|
||||
return;
|
||||
}
|
||||
broadcasting++;
|
||||
@@ -220,11 +198,11 @@ public class NotificationCenter {
|
||||
}
|
||||
|
||||
public void addObserver(Object observer, int id) {
|
||||
if (BuildVars.DEBUG_VERSION) {
|
||||
/*if (BuildConfig.BUILD_TYPE.equals("debug")) {
|
||||
if (Thread.currentThread() != ApplicationLoader.applicationHandler.getLooper().getThread()) {
|
||||
throw new RuntimeException("addObserver allowed only from MAIN thread");
|
||||
}
|
||||
}
|
||||
}*/
|
||||
if (broadcasting != 0) {
|
||||
ArrayList<Object> arrayList = addAfterBroadcast.get(id);
|
||||
if (arrayList == null) {
|
||||
@@ -245,11 +223,11 @@ public class NotificationCenter {
|
||||
}
|
||||
|
||||
public void removeObserver(Object observer, int id) {
|
||||
if (BuildVars.DEBUG_VERSION) {
|
||||
/*if (BuildConfig.BUILD_TYPE.equals("debug")) {
|
||||
if (Thread.currentThread() != ApplicationLoader.applicationHandler.getLooper().getThread()) {
|
||||
throw new RuntimeException("removeObserver allowed only from MAIN thread");
|
||||
}
|
||||
}
|
||||
}*/
|
||||
if (broadcasting != 0) {
|
||||
ArrayList<Object> arrayList = removeAfterBroadcast.get(id);
|
||||
if (arrayList == null) {
|
||||
|
||||
@@ -1,10 +1,25 @@
|
||||
/*
|
||||
* This is the source code of Telegram for Android v. 3.x.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2016.
|
||||
*/
|
||||
* Messenger Android Frontend
|
||||
* (C) 2013-2016 Nikolai Kudashov
|
||||
* (C) 2017 Björn Petersen
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see http://www.gnu.org/licenses/ .
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
package com.b44t.messenger;
|
||||
|
||||
@@ -18,6 +33,6 @@ public class NotificationDismissReceiver extends BroadcastReceiver {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Context.MODE_PRIVATE);
|
||||
preferences.edit().putInt("dismissDate", intent.getIntExtra("messageDate", 0)).commit();
|
||||
preferences.edit().putInt("dismissDate", intent.getIntExtra("messageDate", 0)).apply();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,25 @@
|
||||
/*
|
||||
* This is the source code of Telegram for Android v. 3.x.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2016.
|
||||
*/
|
||||
* Messenger Android Frontend
|
||||
* (C) 2013-2016 Nikolai Kudashov
|
||||
* (C) 2017 Björn Petersen
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see http://www.gnu.org/licenses/ .
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
package com.b44t.messenger;
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* This is the source code of Telegram for Android v. 1.3.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2016.
|
||||
*/
|
||||
|
||||
package com.b44t.messenger;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.IBinder;
|
||||
|
||||
public class NotificationsService extends Service {
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
FileLog.e("messenger", "service started");
|
||||
ApplicationLoader.postInitApplication();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
return START_STICKY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void onDestroy() {
|
||||
FileLog.e("messenger", "service destroyed");
|
||||
|
||||
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", MODE_PRIVATE);
|
||||
if (preferences.getBoolean("pushService", true)) {
|
||||
Intent intent = new Intent("com.b44t.start");
|
||||
sendBroadcast(intent);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,25 @@
|
||||
/*
|
||||
* This is the source code of Telegram for Android v. 3.x.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2016.
|
||||
*/
|
||||
* Messenger Android Frontend
|
||||
* (C) 2013-2016 Nikolai Kudashov
|
||||
* (C) 2017 Björn Petersen
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see http://www.gnu.org/licenses/ .
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
package com.b44t.messenger;
|
||||
|
||||
|
||||
@@ -1,28 +1,42 @@
|
||||
/*
|
||||
* This is the source code of Telegram for Android v. 1.3.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2016.
|
||||
*/
|
||||
* Messenger Android Frontend
|
||||
* (C) 2013-2016 Nikolai Kudashov
|
||||
* (C) 2017 Björn Petersen
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see http://www.gnu.org/licenses/ .
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
package com.b44t.messenger;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.util.Log;
|
||||
|
||||
public class ScreenReceiver extends BroadcastReceiver {
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
|
||||
FileLog.e("messenger", "screen off");
|
||||
ConnectionsManager.getInstance().setAppPaused(true, true);
|
||||
MrMailbox.log_i("DeltaChat", "*** Screen off");
|
||||
ApplicationLoader.isScreenOn = false;
|
||||
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
|
||||
FileLog.e("messenger", "screen on");
|
||||
ConnectionsManager.getInstance().setAppPaused(false, true);
|
||||
MrMailbox.log_i("DeltaChat", "*** Screen on");
|
||||
ApplicationLoader.isScreenOn = true;
|
||||
}
|
||||
//NotificationCenter.getInstance().postNotificationName(NotificationCenter.screenStateChanged);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
* This is the source code of Telegram for Android v. 3.x.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2016.
|
||||
*/
|
||||
|
||||
package com.b44t.messenger;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
public class ShareBroadcastReceiver extends BroadcastReceiver {
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
String url = intent.getDataString();
|
||||
if (url != null) {
|
||||
Intent shareIntent = new Intent(Intent.ACTION_SEND);
|
||||
shareIntent.setType("text/plain");
|
||||
shareIntent.putExtra(Intent.EXTRA_TEXT, url);
|
||||
Intent chooserIntent = Intent.createChooser(shareIntent, LocaleController.getString("ShareLink", R.string.ShareLink));
|
||||
chooserIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
context.startActivity(chooserIntent);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,25 @@
|
||||
/*
|
||||
* This is the source code of Telegram for Android v. 3.x.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2016.
|
||||
*/
|
||||
* Messenger Android Frontend
|
||||
* (C) 2013-2016 Nikolai Kudashov
|
||||
* (C) 2017 Björn Petersen
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see http://www.gnu.org/licenses/ .
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
package com.b44t.messenger;
|
||||
|
||||
|
||||
@@ -1,10 +1,25 @@
|
||||
/*
|
||||
* This is the source code of Telegram for Android v. 3.x.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2016.
|
||||
*/
|
||||
* Messenger Android Frontend
|
||||
* (C) 2013-2016 Nikolai Kudashov
|
||||
* (C) 2017 Björn Petersen
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see http://www.gnu.org/licenses/ .
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
package com.b44t.messenger;
|
||||
|
||||
@@ -17,19 +32,15 @@ public class TLRPC {
|
||||
public static final int MESSAGE_FLAG_REPLY = 0x00000008;
|
||||
public static final int MESSAGE_FLAG_HAS_FROM_ID = 0x00000100;
|
||||
public static final int MESSAGE_FLAG_HAS_MEDIA = 0x00000200;
|
||||
public static final int MESSAGE_FLAG_EDITED = 0x00008000;
|
||||
|
||||
public static class DraftMessage extends TLObject {
|
||||
public int flags;
|
||||
public boolean no_webpage;
|
||||
public int reply_to_msg_id;
|
||||
public String message;
|
||||
public ArrayList<MessageEntity> entities = new ArrayList<>();
|
||||
public int date;
|
||||
}
|
||||
|
||||
public static class ChatPhoto extends TLObject {
|
||||
public FileLocation photo_small;
|
||||
public FileLocation photo_big;
|
||||
}
|
||||
|
||||
@@ -39,7 +50,6 @@ public class TLRPC {
|
||||
public int duration;
|
||||
public String alt;
|
||||
public InputStickerSet stickerset;
|
||||
public int flags;
|
||||
public boolean voice;
|
||||
public String title;
|
||||
public String performer;
|
||||
@@ -65,177 +75,35 @@ public class TLRPC {
|
||||
public static class TL_documentAttributeFilename extends DocumentAttribute {
|
||||
}
|
||||
|
||||
public static class messages_Messages extends TLObject {
|
||||
public ArrayList<Message> messages = new ArrayList<>();
|
||||
public ArrayList<Chat> chats = new ArrayList<>();
|
||||
public ArrayList<User> users = new ArrayList<>();
|
||||
public int flags;
|
||||
public int pts;
|
||||
public int count;
|
||||
}
|
||||
|
||||
public static class TL_messages_messages extends messages_Messages {
|
||||
}
|
||||
|
||||
public static class Peer extends TLObject {
|
||||
public final int channel_id = 0;
|
||||
public int user_id;
|
||||
public int chat_id;
|
||||
public final int chat_id = 0;
|
||||
}
|
||||
|
||||
public static class TL_peerUser extends Peer {
|
||||
}
|
||||
|
||||
public static class TL_peerChat extends Peer {
|
||||
}
|
||||
|
||||
public static class GeoPoint extends TLObject {
|
||||
public double _long;
|
||||
public double lat;
|
||||
}
|
||||
|
||||
public static class TL_geoPoint extends GeoPoint {
|
||||
}
|
||||
|
||||
public static class TL_messageMediaEmpty extends MessageMedia {
|
||||
}
|
||||
|
||||
public static class TL_messageMediaVenue extends MessageMedia {
|
||||
}
|
||||
|
||||
public static class TL_messageMediaDocument extends MessageMedia {
|
||||
}
|
||||
|
||||
public static class TL_messageMediaContact extends MessageMedia {
|
||||
}
|
||||
|
||||
public static class TL_messageMediaPhoto extends MessageMedia {
|
||||
}
|
||||
|
||||
public static class TL_messageMediaGeo extends MessageMedia {
|
||||
}
|
||||
|
||||
public static class TL_messageMediaWebPage extends MessageMedia {
|
||||
}
|
||||
|
||||
public static class BotInlineResult extends TLObject {
|
||||
public int flags;
|
||||
public String id;
|
||||
public String type;
|
||||
public String title;
|
||||
public String description;
|
||||
public String url;
|
||||
public String thumb_url;
|
||||
public String content_url;
|
||||
public String content_type;
|
||||
public int w;
|
||||
public int h;
|
||||
public int duration;
|
||||
public Photo photo;
|
||||
public Document document;
|
||||
}
|
||||
|
||||
|
||||
public static class PeerNotifySettings extends TLObject {
|
||||
public int flags;
|
||||
public boolean silent;
|
||||
public int mute_until;
|
||||
public String sound;
|
||||
}
|
||||
|
||||
public static class TL_peerNotifySettings extends PeerNotifySettings {
|
||||
}
|
||||
|
||||
public static class TL_messages_stickerSet extends TLObject {
|
||||
public StickerSet set;
|
||||
public ArrayList<TL_stickerPack> packs = new ArrayList<>();
|
||||
public ArrayList<Document> documents = new ArrayList<>();
|
||||
}
|
||||
|
||||
public static class InputGeoPoint extends TLObject {
|
||||
public double lat;
|
||||
public double _long;
|
||||
}
|
||||
|
||||
public static class TL_inputGeoPoint extends InputGeoPoint {
|
||||
}
|
||||
|
||||
public static class Audio extends TLObject {
|
||||
public long id;
|
||||
public int date;
|
||||
public int duration;
|
||||
public String mime_type;
|
||||
public int size;
|
||||
public int dc_id;
|
||||
public int user_id;
|
||||
public byte[] key;
|
||||
public byte[] iv;
|
||||
}
|
||||
|
||||
public static class ChatFull extends TLObject {
|
||||
public int flags;
|
||||
public int id;
|
||||
public String about;
|
||||
public int pinned_msg_id;
|
||||
public ChatParticipants participants;
|
||||
}
|
||||
|
||||
public static class TL_topPeerCategoryPeers extends TLObject {
|
||||
public TopPeerCategory category;
|
||||
public int count;
|
||||
}
|
||||
|
||||
public static class InputUser extends TLObject {
|
||||
public int user_id;
|
||||
public long access_hash;
|
||||
}
|
||||
|
||||
public static class TL_inputUserEmpty extends InputUser {
|
||||
}
|
||||
|
||||
public static class TL_inputUserSelf extends InputUser {
|
||||
}
|
||||
|
||||
public static class TL_inputUser extends InputUser {
|
||||
}
|
||||
|
||||
public static class WebPage extends TLObject {
|
||||
public int flags;
|
||||
public long id;
|
||||
public String url;
|
||||
public String display_url;
|
||||
public String type;
|
||||
public String site_name;
|
||||
public String title;
|
||||
public String description;
|
||||
public Photo photo;
|
||||
public String embed_url;
|
||||
public int embed_width;
|
||||
public int embed_height;
|
||||
public int duration;
|
||||
public String author;
|
||||
public int date;
|
||||
public Document document;
|
||||
}
|
||||
|
||||
public static class TL_webPageEmpty extends WebPage {
|
||||
}
|
||||
|
||||
public static class TL_webPage extends WebPage {
|
||||
}
|
||||
|
||||
public static class InputFileLocation extends TLObject {
|
||||
public long id;
|
||||
public long access_hash;
|
||||
public long volume_id;
|
||||
public int local_id;
|
||||
public long secret;
|
||||
}
|
||||
|
||||
public static class TL_inputDocumentFileLocation extends InputFileLocation {
|
||||
}
|
||||
|
||||
public static class TL_inputFileLocation extends InputFileLocation {
|
||||
}
|
||||
|
||||
public static class User extends TLObject {
|
||||
@@ -243,58 +111,10 @@ public class TLRPC {
|
||||
public String first_name;
|
||||
public String last_name;
|
||||
public String username;
|
||||
public final long access_hash = 0;
|
||||
public String phone;
|
||||
public UserProfilePhoto photo;
|
||||
public UserStatus status;
|
||||
public int flags;
|
||||
public boolean self;
|
||||
public boolean contact;
|
||||
public final boolean mutual_contact = false;
|
||||
public final boolean deleted = false;
|
||||
public final boolean bot = false;
|
||||
public boolean verified;
|
||||
public boolean min;
|
||||
}
|
||||
|
||||
public static class TL_userContact_old2 extends User {
|
||||
}
|
||||
|
||||
public static class MessageAction extends TLObject {
|
||||
public String title;
|
||||
public String address;
|
||||
public ArrayList<Integer> users = new ArrayList<>();
|
||||
public final int channel_id = 0;
|
||||
public Photo photo;
|
||||
public int chat_id;
|
||||
public int user_id;
|
||||
public UserProfilePhoto newUserPhoto;
|
||||
}
|
||||
|
||||
public static class TL_messageActionChatCreate extends MessageAction {
|
||||
}
|
||||
|
||||
public static class TL_messageActionChatEditPhoto extends MessageAction {
|
||||
}
|
||||
|
||||
public static class TL_messageActionChatAddUser extends MessageAction {
|
||||
}
|
||||
|
||||
public static class TL_messageActionChatDeleteUser extends MessageAction {
|
||||
}
|
||||
|
||||
public static class TL_messageActionUserUpdatedPhoto extends MessageAction {
|
||||
}
|
||||
|
||||
public static class TL_messageActionChatDeletePhoto extends MessageAction {
|
||||
}
|
||||
|
||||
public static class TL_messageActionChatEditTitle extends MessageAction {
|
||||
}
|
||||
|
||||
public static class TL_messageActionEmpty extends MessageAction {
|
||||
}
|
||||
|
||||
public static class Video extends TLObject {
|
||||
public long id;
|
||||
public int user_id;
|
||||
@@ -302,24 +122,10 @@ public class TLRPC {
|
||||
public int duration;
|
||||
public int size;
|
||||
public PhotoSize thumb;
|
||||
public int dc_id;
|
||||
public int w;
|
||||
public int h;
|
||||
public String mime_type;
|
||||
public String caption;
|
||||
public byte[] key;
|
||||
public byte[] iv;
|
||||
}
|
||||
|
||||
public static class TopPeerCategory extends TLObject {
|
||||
}
|
||||
|
||||
public static class InputDocument extends TLObject {
|
||||
public long id;
|
||||
public long access_hash;
|
||||
}
|
||||
|
||||
public static class TL_inputDocument extends InputDocument {
|
||||
}
|
||||
|
||||
public static class Document extends TLObject {
|
||||
@@ -342,136 +148,21 @@ public class TLRPC {
|
||||
public static class TL_document extends Document {
|
||||
}
|
||||
|
||||
public static class InputMedia extends TLObject {
|
||||
public InputFile file;
|
||||
public InputFile thumb;
|
||||
public String mime_type;
|
||||
public ArrayList<DocumentAttribute> attributes = new ArrayList<>();
|
||||
public String caption;
|
||||
public InputGeoPoint geo_point;
|
||||
public String title;
|
||||
public String address;
|
||||
public String provider;
|
||||
public String venue_id;
|
||||
public String phone_number;
|
||||
public String first_name;
|
||||
public String last_name;
|
||||
public String url;
|
||||
public String q;
|
||||
}
|
||||
|
||||
public static class TL_inputMediaContact extends InputMedia {
|
||||
}
|
||||
|
||||
public static class TL_inputMediaUploadedThumbDocument extends InputMedia {
|
||||
}
|
||||
|
||||
public static class TL_inputMediaDocument extends InputMedia {
|
||||
public InputDocument id;
|
||||
}
|
||||
|
||||
public static class TL_inputMediaGifExternal extends InputMedia {
|
||||
}
|
||||
|
||||
public static class TL_inputMediaGeoPoint extends InputMedia {
|
||||
}
|
||||
|
||||
public static class TL_inputMediaUploadedPhoto extends InputMedia {
|
||||
}
|
||||
|
||||
public static class TL_inputMediaVenue extends InputMedia {
|
||||
}
|
||||
|
||||
public static class TL_inputMediaUploadedDocument extends InputMedia {
|
||||
}
|
||||
|
||||
public static class TL_inputMediaPhoto extends InputMedia {
|
||||
public InputPhoto id;
|
||||
}
|
||||
|
||||
public static class InputStickerSet extends TLObject {
|
||||
public long id;
|
||||
public long access_hash;
|
||||
public String short_name;
|
||||
}
|
||||
|
||||
public static class TL_inputStickerSetEmpty extends InputStickerSet {
|
||||
}
|
||||
|
||||
public static class TL_inputStickerSetID extends InputStickerSet {
|
||||
}
|
||||
|
||||
public static class TL_inputStickerSetShortName extends InputStickerSet {
|
||||
}
|
||||
|
||||
public static class UserStatus extends TLObject {
|
||||
public int expires;
|
||||
}
|
||||
|
||||
public static class TL_userStatusLastWeek extends UserStatus {
|
||||
}
|
||||
|
||||
public static class TL_userStatusLastMonth extends UserStatus {
|
||||
}
|
||||
|
||||
public static class TL_userStatusRecently extends UserStatus {
|
||||
}
|
||||
|
||||
public static class InputEncryptedFile extends TLObject {
|
||||
public long id;
|
||||
public int parts;
|
||||
}
|
||||
|
||||
public static class UserProfilePhoto extends TLObject {
|
||||
public FileLocation photo_small;
|
||||
public FileLocation photo_big;
|
||||
}
|
||||
|
||||
public static class MessageEntity extends TLObject {
|
||||
public int offset;
|
||||
public int length;
|
||||
public String url;
|
||||
public String language;
|
||||
}
|
||||
|
||||
public static class TL_messageEntityTextUrl extends MessageEntity {
|
||||
}
|
||||
|
||||
public static class TL_messageEntityEmail extends MessageEntity {
|
||||
}
|
||||
|
||||
public static class TL_messageEntityPre extends MessageEntity {
|
||||
}
|
||||
|
||||
public static class TL_messageEntityUrl extends MessageEntity {
|
||||
}
|
||||
|
||||
public static class TL_messageEntityItalic extends MessageEntity {
|
||||
}
|
||||
|
||||
public static class TL_messageEntityMention extends MessageEntity {
|
||||
}
|
||||
|
||||
public static class TL_messageEntityMentionName extends MessageEntity {
|
||||
public int user_id;
|
||||
}
|
||||
|
||||
public static class TL_inputMessageEntityMentionName extends MessageEntity {
|
||||
public InputUser user_id;
|
||||
}
|
||||
|
||||
public static class TL_messageEntityBold extends MessageEntity {
|
||||
}
|
||||
|
||||
public static class TL_messageEntityHashtag extends MessageEntity {
|
||||
}
|
||||
|
||||
public static class TL_messageEntityCode extends MessageEntity {
|
||||
}
|
||||
|
||||
public static class Photo extends TLObject {
|
||||
public long id;
|
||||
public long access_hash;
|
||||
public int user_id;
|
||||
public int date;
|
||||
public String caption;
|
||||
@@ -484,48 +175,22 @@ public class TLRPC {
|
||||
public static class TL_photoEmpty extends Photo {
|
||||
}
|
||||
|
||||
public static class TL_contact extends TLObject {
|
||||
public int user_id;
|
||||
public boolean mutual;
|
||||
}
|
||||
|
||||
public static class ChatParticipants extends TLObject {
|
||||
public int flags;
|
||||
public int chat_id;
|
||||
public ArrayList<ChatParticipant> participants = new ArrayList<>();
|
||||
public int version;
|
||||
}
|
||||
|
||||
public static class ChatParticipant extends TLObject {
|
||||
public int user_id;
|
||||
public int date;
|
||||
}
|
||||
|
||||
public static class Chat extends TLObject {
|
||||
public int flags;
|
||||
public boolean creator;
|
||||
public boolean kicked;
|
||||
public boolean deactivated;
|
||||
public int id;
|
||||
public String title;
|
||||
public final ChatPhoto photo = null;
|
||||
public int date;
|
||||
public int version;
|
||||
public boolean editor;
|
||||
public final boolean broadcast = false;
|
||||
public boolean verified;
|
||||
public final boolean megagroup = false;
|
||||
public boolean left;
|
||||
public final int version = 0;
|
||||
public final boolean editor = false;
|
||||
public String username;
|
||||
public boolean restricted;
|
||||
public boolean signatures;
|
||||
public boolean min;
|
||||
public String address;
|
||||
public final boolean signatures = false;
|
||||
public final boolean min = false;
|
||||
public final String address = null;
|
||||
}
|
||||
|
||||
public static class StickerSet extends TLObject {
|
||||
public long id;
|
||||
public long access_hash;
|
||||
public String title;
|
||||
public int flags;
|
||||
public boolean installed;
|
||||
@@ -535,33 +200,8 @@ public class TLRPC {
|
||||
public int hash;
|
||||
}
|
||||
|
||||
public static class MessagesFilter extends TLObject {
|
||||
}
|
||||
|
||||
public static class TL_inputMessagesFilterDocument extends MessagesFilter {
|
||||
}
|
||||
|
||||
public static class TL_inputMessagesFilterMusic extends MessagesFilter {
|
||||
}
|
||||
|
||||
public static class TL_inputMessagesFilterUrl extends MessagesFilter {
|
||||
}
|
||||
|
||||
public static class TL_inputMessagesFilterVoice extends MessagesFilter {
|
||||
}
|
||||
|
||||
public static class TL_inputMessagesFilterEmpty extends MessagesFilter {
|
||||
}
|
||||
|
||||
public static class TL_inputMessagesFilterPhotoVideo extends MessagesFilter {
|
||||
}
|
||||
|
||||
public static class TL_messageFwdHeader extends TLObject {
|
||||
public int flags;
|
||||
public int from_id;
|
||||
public int date;
|
||||
public int channel_id;
|
||||
public int channel_post;
|
||||
public String m_name;
|
||||
}
|
||||
|
||||
public static class FileLocation extends TLObject {
|
||||
@@ -580,7 +220,7 @@ public class TLRPC {
|
||||
}
|
||||
|
||||
public static class PhotoSize extends TLObject {
|
||||
public String type;
|
||||
public String type; // s, m, x, y, w for small, medium, ... widest
|
||||
public FileLocation location;
|
||||
public int w;
|
||||
public int h;
|
||||
@@ -618,68 +258,15 @@ public class TLRPC {
|
||||
public static class TL_wallPaperSolid extends WallPaper {
|
||||
}
|
||||
|
||||
public static class TL_stickerPack extends TLObject {
|
||||
public ArrayList<Long> documents = new ArrayList<>();
|
||||
}
|
||||
|
||||
public static class InputPhoto extends TLObject {
|
||||
public long id;
|
||||
public long access_hash;
|
||||
}
|
||||
|
||||
public static class TL_inputPhoto extends InputPhoto {
|
||||
}
|
||||
|
||||
public static class InputPeer extends TLObject {
|
||||
public int user_id;
|
||||
public long access_hash;
|
||||
public int chat_id;
|
||||
public int channel_id;
|
||||
}
|
||||
|
||||
public static class TL_inputPeerUser extends InputPeer {
|
||||
}
|
||||
|
||||
public static class TL_inputPeerEmpty extends InputPeer {
|
||||
}
|
||||
|
||||
public static class TL_topPeer extends TLObject {
|
||||
public Peer peer;
|
||||
}
|
||||
|
||||
public static class TL_messages_search extends TLObject {
|
||||
public int flags;
|
||||
public InputPeer peer;
|
||||
public String q;
|
||||
public MessagesFilter filter;
|
||||
public int offset;
|
||||
public int max_id;
|
||||
public int limit;
|
||||
}
|
||||
|
||||
public static class TL_messages_searchGlobal extends TLObject {
|
||||
public String q;
|
||||
public int offset_date;
|
||||
public InputPeer offset_peer;
|
||||
public int offset_id;
|
||||
public int limit;
|
||||
}
|
||||
|
||||
public static class MessageMedia extends TLObject {
|
||||
public byte[] bytes;
|
||||
public Photo photo;
|
||||
public GeoPoint geo;
|
||||
public String title;
|
||||
public String address;
|
||||
public String provider;
|
||||
public String venue_id;
|
||||
public Document document;
|
||||
public String caption;
|
||||
public String phone_number;
|
||||
public String first_name;
|
||||
public String last_name;
|
||||
public int user_id;
|
||||
public WebPage webpage;
|
||||
}
|
||||
|
||||
public static class Message extends TLObject {
|
||||
@@ -687,60 +274,35 @@ public class TLRPC {
|
||||
public int from_id;
|
||||
public Peer to_id;
|
||||
public int date;
|
||||
public MessageAction action;
|
||||
public int reply_to_msg_id;
|
||||
public long reply_to_random_id;
|
||||
public final int reply_to_msg_id = 0;
|
||||
public String message;
|
||||
public MessageMedia media;
|
||||
public int flags;
|
||||
public boolean mentioned;
|
||||
public boolean media_unread;
|
||||
public boolean out;
|
||||
public boolean unread;
|
||||
public ArrayList<MessageEntity> entities = new ArrayList<>();
|
||||
public String via_bot_name;
|
||||
public int views;
|
||||
public int edit_date;
|
||||
public boolean silent;
|
||||
public boolean post;
|
||||
public final int views = 0;
|
||||
public final boolean silent = false;
|
||||
public final boolean post = false;// ? true=avatar wird in gruppen nicht angezeigt, wird aber in isFromUser() auch überprüft...
|
||||
public TL_messageFwdHeader fwd_from;
|
||||
public int via_bot_id;
|
||||
public int send_state = 0; //custom
|
||||
public String attachPath = ""; //custom
|
||||
public HashMap<String, String> params; //custom
|
||||
public long random_id; //custom
|
||||
public long dialog_id; //custom
|
||||
public int ttl; //custom
|
||||
public int destroyTime; //custom
|
||||
public int layer; //custom
|
||||
public TLRPC.Message replyMessage; //custom
|
||||
public final int layer = 0; //custom
|
||||
public boolean created_by_mr;
|
||||
}
|
||||
|
||||
public static class TL_messageEmpty extends Message {
|
||||
}
|
||||
|
||||
public static class TL_message extends Message {
|
||||
}
|
||||
|
||||
public static class TL_messageService extends Message {
|
||||
}
|
||||
|
||||
public static class TL_dialog extends TLObject {
|
||||
final public int flags = 0;
|
||||
public Peer peer;
|
||||
public int top_message;
|
||||
public int unread_count;
|
||||
public PeerNotifySettings notify_settings;
|
||||
public int pts;
|
||||
public final int top_message = 0;
|
||||
public final int unread_count = 0;
|
||||
public final int pts = 0;
|
||||
public DraftMessage draft;
|
||||
public int last_message_date; //custom
|
||||
public long id; //custom
|
||||
}
|
||||
|
||||
public static class TL_chatEmpty extends Chat {
|
||||
}
|
||||
public static class Vector extends TLObject {
|
||||
public ArrayList<Object> objects = new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,172 +0,0 @@
|
||||
/*
|
||||
* This is the source code of Telegram for Android v. 3.x.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2016.
|
||||
*/
|
||||
|
||||
package com.b44t.messenger;
|
||||
|
||||
// ChooserTargetService, see https://developer.android.com/reference/android/service/chooser/ChooserTargetService.html
|
||||
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.content.ComponentName;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Build;
|
||||
import android.service.chooser.ChooserTarget;
|
||||
import android.service.chooser.ChooserTargetService;
|
||||
|
||||
import com.b44t.ui.LaunchActivity;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Semaphore;
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.M)
|
||||
public class TgChooserTargetService extends ChooserTargetService {
|
||||
|
||||
@Override
|
||||
public List<ChooserTarget> onGetChooserTargets(ComponentName targetActivityName, IntentFilter matchedFilter) {
|
||||
final List<ChooserTarget> targets = new ArrayList<>();
|
||||
if (!UserConfig.isClientActivated()) {
|
||||
return targets;
|
||||
}
|
||||
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE);
|
||||
if (!preferences.getBoolean("direct_share", true)) {
|
||||
return targets;
|
||||
}
|
||||
|
||||
ImageLoader imageLoader = ImageLoader.getInstance();
|
||||
final Semaphore semaphore = new Semaphore(0);
|
||||
final ComponentName componentName = new ComponentName(getPackageName(), LaunchActivity.class.getCanonicalName());
|
||||
/*
|
||||
MessagesStorage.getInstance().getStorageQueue().postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ArrayList<Integer> dialogs = new ArrayList<>();
|
||||
ArrayList<TLRPC.Chat> chats = new ArrayList<>();
|
||||
ArrayList<TLRPC.User> users = new ArrayList<>();
|
||||
try {
|
||||
ArrayList<Integer> usersToLoad = new ArrayList<>();
|
||||
usersToLoad.add(UserConfig.getClientUserId());
|
||||
ArrayList<Integer> chatsToLoad = new ArrayList<>();
|
||||
SQLiteCursor cursor = MessagesStorage.getInstance().getDatabase().queryFinalized(String.format(Locale.US, "SELECT did FROM dialogs ORDER BY date DESC LIMIT %d,%d", 0, 30));
|
||||
while (cursor.next()) {
|
||||
long id = cursor.longValue(0);
|
||||
|
||||
int lower_id = (int) id;
|
||||
int high_id = (int) (id >> 32);
|
||||
if (lower_id != 0) {
|
||||
if (high_id == 1) {
|
||||
continue;
|
||||
} else {
|
||||
if (lower_id > 0) {
|
||||
if (!usersToLoad.contains(lower_id)) {
|
||||
usersToLoad.add(lower_id);
|
||||
}
|
||||
} else {
|
||||
if (!chatsToLoad.contains(-lower_id)) {
|
||||
chatsToLoad.add(-lower_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
dialogs.add(lower_id);
|
||||
if (dialogs.size() == 8) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
cursor.dispose();
|
||||
if (!chatsToLoad.isEmpty()) {
|
||||
//MessagesStorage.getInstance().getChatsInternal(TextUtils.join(",", chatsToLoad), chats);
|
||||
}
|
||||
if (!usersToLoad.isEmpty()) {
|
||||
//MessagesStorage.getInstance().getUsersInternal(TextUtils.join(",", usersToLoad), users);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
for (int a = 0; a < dialogs.size(); a++) {
|
||||
Bundle extras = new Bundle();
|
||||
Icon icon = null;
|
||||
String name = null;
|
||||
int id = dialogs.get(a);
|
||||
if (id > 0) {
|
||||
for (int b = 0; b < users.size(); b++) {
|
||||
TLRPC.User user = users.get(b);
|
||||
if (user.id == id) {
|
||||
if (!user.bot) {
|
||||
extras.putLong("dialogId", (long) id);
|
||||
if (user.photo != null && user.photo.photo_small != null) {
|
||||
icon = createRoundBitmap(FileLoader.getPathToAttach(user.photo.photo_small, true));
|
||||
}
|
||||
name = ContactsController.formatName(user.first_name, user.last_name);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int b = 0; b < chats.size(); b++) {
|
||||
TLRPC.Chat chat = chats.get(b);
|
||||
if (chat.id == -id) {
|
||||
if (!ChatObject.isNotInChat(chat) && (!ChatObject.isChannel(chat) || chat.megagroup)) {
|
||||
extras.putLong("dialogId", (long) id);
|
||||
if (chat.photo != null && chat.photo.photo_small != null) {
|
||||
icon = createRoundBitmap(FileLoader.getPathToAttach(chat.photo.photo_small, true));
|
||||
}
|
||||
name = chat.title;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (name != null) {
|
||||
if (icon == null) {
|
||||
icon = Icon.createWithResource(ApplicationLoader.applicationContext, R.drawable.logo_avatar);
|
||||
}
|
||||
targets.add(new ChooserTarget(name, icon, 1.0f, componentName, extras));
|
||||
}
|
||||
}
|
||||
semaphore.release();
|
||||
}
|
||||
});
|
||||
*/
|
||||
try {
|
||||
semaphore.acquire();
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
return targets;
|
||||
}
|
||||
|
||||
/*
|
||||
private Icon createRoundBitmap(File path) {
|
||||
try {
|
||||
Bitmap bitmap = BitmapFactory.decodeFile(path.toString());
|
||||
if (bitmap != null) {
|
||||
Bitmap result = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
|
||||
result.eraseColor(Color.TRANSPARENT);
|
||||
Canvas canvas = new Canvas(result);
|
||||
BitmapShader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
|
||||
if (roundPaint == null) {
|
||||
roundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
bitmapRect = new RectF();
|
||||
}
|
||||
roundPaint.setShader(shader);
|
||||
bitmapRect.set(0, 0, bitmap.getWidth(), bitmap.getHeight());
|
||||
canvas.drawRoundRect(bitmapRect, bitmap.getWidth(), bitmap.getHeight(), roundPaint);
|
||||
return Icon.createWithBitmap(result);
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
*/
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Messenger Android Frontend
|
||||
* (C) 2017 Björn Petersen
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see http://www.gnu.org/licenses/ .
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
package com.b44t.messenger;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlarmManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
|
||||
|
||||
public class TimerReceiver extends BroadcastReceiver {
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
|
||||
// acquire for 3 seconds, this should wake up the threads,
|
||||
// _if_ there is more to do, the backend acquires an additional wakelock using MR_EVENT_WAKE_LOCK
|
||||
ApplicationLoader.wakeupWakeLock.acquire(3*1000); // do this first!
|
||||
MrMailbox.log_i("DeltaChat", "*** TimerReceiver.onReceive()");
|
||||
|
||||
// we assume, the IMAP thread is alive. I cannot imagine, the thread was killed with the App being running.
|
||||
// (if the whole App was killed, the IMAP thread is already started by MrMailbox.connect() if we're here)
|
||||
// (the thread itself will reconnect to the IMAP server as needed)
|
||||
// however, it seems as if the threads sleep longer than ususal, check this by calling heartbeat() manually
|
||||
MrMailbox.heartbeat();
|
||||
|
||||
// create the next alarm in about a minute
|
||||
scheduleNextAlarm();
|
||||
}
|
||||
|
||||
public static void scheduleNextAlarm()
|
||||
{
|
||||
try {
|
||||
Intent intent = new Intent(ApplicationLoader.applicationContext, TimerReceiver.class);
|
||||
PendingIntent alarmIntent = PendingIntent.getBroadcast(ApplicationLoader.applicationContext, 0, intent, 0);
|
||||
|
||||
long triggerAtMillis = System.currentTimeMillis() + 60 * 1000;
|
||||
|
||||
AlarmManager alarmManager = (AlarmManager) ApplicationLoader.applicationContext.getSystemService(Activity.ALARM_SERVICE);
|
||||
if( Build.VERSION.SDK_INT >= 23 ) {
|
||||
// a simple AlarmManager.set() is no longer send in the new DOZE mode
|
||||
alarmManager.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, triggerAtMillis, alarmIntent);
|
||||
}
|
||||
else {
|
||||
alarmManager.set(AlarmManager.RTC_WAKEUP, triggerAtMillis, alarmIntent);
|
||||
}
|
||||
}
|
||||
catch(Exception e) { Log.e("DeltaChat", "Cannot create alarm.", e); }
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,25 @@
|
||||
/*
|
||||
* This is the source code of Telegram for Android v. 3.x.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2016.
|
||||
*/
|
||||
* Messenger Android Frontend
|
||||
* (C) 2013-2016 Nikolai Kudashov
|
||||
* (C) 2017 Björn Petersen
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see http://www.gnu.org/licenses/ .
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
package com.b44t.messenger;
|
||||
|
||||
@@ -16,16 +31,8 @@ import java.io.File;
|
||||
|
||||
public class UserConfig {
|
||||
|
||||
private static TLRPC.User currentUser;
|
||||
public static boolean registeredForPush;
|
||||
public static String pushString = "";
|
||||
public static int lastSendMessageId = -210000;
|
||||
public static int lastLocalId = -210000;
|
||||
public static int lastBroadcastId = -1;
|
||||
public static String contactsHash = "";
|
||||
public static boolean blockedUsersLoaded;
|
||||
private final static Object sync = new Object();
|
||||
public static boolean saveIncomingPhotos;
|
||||
public static String passcodeHash = "";
|
||||
public static byte[] passcodeSalt = new byte[0];
|
||||
public static boolean appLocked;
|
||||
@@ -34,228 +41,38 @@ public class UserConfig {
|
||||
public static int lastPauseTime;
|
||||
public static boolean isWaitingForPasscodeEnter;
|
||||
public static boolean useFingerprint = true;
|
||||
public static String lastUpdateVersion;
|
||||
public static int lastContactsSyncTime;
|
||||
public static int lastHintsSyncTime;
|
||||
public static boolean draftsLoaded;
|
||||
|
||||
public static int migrateOffsetId = -1;
|
||||
public static int migrateOffsetDate = -1;
|
||||
public static int migrateOffsetUserId = -1;
|
||||
public static int migrateOffsetChatId = -1;
|
||||
public static int migrateOffsetChannelId = -1;
|
||||
public static long migrateOffsetAccess = -1;
|
||||
|
||||
public static int getNewMessageId() {
|
||||
int id;
|
||||
synchronized (sync) {
|
||||
id = lastSendMessageId;
|
||||
lastSendMessageId--;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
public static void saveConfig(boolean withFile) {
|
||||
saveConfig(withFile, null);
|
||||
}
|
||||
|
||||
public static void saveConfig(boolean withFile, File oldFile) {
|
||||
public static void saveConfig() {
|
||||
synchronized (sync) {
|
||||
try {
|
||||
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("userconfing", Context.MODE_PRIVATE);
|
||||
SharedPreferences.Editor editor = preferences.edit();
|
||||
editor.putBoolean("registeredForPush", registeredForPush);
|
||||
editor.putString("pushString2", pushString);
|
||||
editor.putInt("lastSendMessageId", lastSendMessageId);
|
||||
editor.putInt("lastLocalId", lastLocalId);
|
||||
editor.putString("contactsHash", contactsHash);
|
||||
editor.putBoolean("saveIncomingPhotos", saveIncomingPhotos);
|
||||
editor.putInt("lastBroadcastId", lastBroadcastId);
|
||||
editor.putBoolean("blockedUsersLoaded", blockedUsersLoaded);
|
||||
editor.putString("passcodeHash1", passcodeHash);
|
||||
editor.putString("passcodeSalt", passcodeSalt.length > 0 ? Base64.encodeToString(passcodeSalt, Base64.DEFAULT) : "");
|
||||
editor.putBoolean("appLocked", appLocked);
|
||||
editor.putInt("passcodeType", passcodeType);
|
||||
editor.putInt("autoLockIn", autoLockIn);
|
||||
editor.putInt("lastPauseTime", lastPauseTime);
|
||||
editor.putString("lastUpdateVersion2", lastUpdateVersion);
|
||||
editor.putInt("lastContactsSyncTime", lastContactsSyncTime);
|
||||
editor.putBoolean("useFingerprint", useFingerprint);
|
||||
editor.putInt("lastHintsSyncTime", lastHintsSyncTime);
|
||||
editor.putBoolean("draftsLoaded", draftsLoaded);
|
||||
|
||||
editor.putInt("migrateOffsetId", migrateOffsetId);
|
||||
if (migrateOffsetId != -1) {
|
||||
editor.putInt("migrateOffsetDate", migrateOffsetDate);
|
||||
editor.putInt("migrateOffsetUserId", migrateOffsetUserId);
|
||||
editor.putInt("migrateOffsetChatId", migrateOffsetChatId);
|
||||
editor.putInt("migrateOffsetChannelId", migrateOffsetChannelId);
|
||||
editor.putLong("migrateOffsetAccess", migrateOffsetAccess);
|
||||
}
|
||||
|
||||
/*
|
||||
if (currentUser != null) {
|
||||
if (withFile) {
|
||||
SerializedData data = new SerializedData();
|
||||
currentUser.serializeToStream(data);
|
||||
String userString = Base64.encodeToString(data.toByteArray(), Base64.DEFAULT);
|
||||
editor.putString("user", userString);
|
||||
data.cleanup();
|
||||
}
|
||||
} else {
|
||||
editor.remove("user");
|
||||
}
|
||||
*/
|
||||
|
||||
editor.commit();
|
||||
if (oldFile != null) {
|
||||
oldFile.delete();
|
||||
}
|
||||
editor.apply();
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isClientActivated() {
|
||||
return true; // EDIT BY MR -- for "real" checking, call MrMailbox.MrMailboxIsConfigured()
|
||||
/* EDIT BY MR
|
||||
synchronized (sync) {
|
||||
return currentUser != null;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
public static int getClientUserId() {
|
||||
return 1; // we are user #1 by definition
|
||||
/* EDIT BY MR
|
||||
synchronized (sync) {
|
||||
return currentUser != null ? currentUser.id : 0;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
public static TLRPC.User getCurrentUser() {
|
||||
synchronized (sync) {
|
||||
if( currentUser==null ) {
|
||||
currentUser = MrContact.contactId2user(1);
|
||||
}
|
||||
return currentUser;
|
||||
}
|
||||
}
|
||||
|
||||
public static void setCurrentUser(TLRPC.User user) {
|
||||
synchronized (sync) {
|
||||
currentUser = MrContact.contactId2user(1); // EDIT BY MR - force the current user to be user #1, normally this function should not be called at all
|
||||
}
|
||||
}
|
||||
|
||||
public static void loadConfig() {
|
||||
synchronized (sync) {
|
||||
/*
|
||||
final File configFile = new File(ApplicationLoader.getFilesDirFixed(), "user.dat");
|
||||
if (configFile.exists()) {
|
||||
try {
|
||||
SerializedData data = new SerializedData(configFile);
|
||||
int ver = data.readInt32(false);
|
||||
if (ver == 1) {
|
||||
int constructor = data.readInt32(false);
|
||||
currentUser = TLRPC.User.TLdeserialize(data, constructor, false);
|
||||
MessagesStorage.lastDateValue = data.readInt32(false);
|
||||
MessagesStorage.lastPtsValue = data.readInt32(false);
|
||||
MessagesStorage.lastSeqValue = data.readInt32(false);
|
||||
registeredForPush = data.readBool(false);
|
||||
pushString = data.readString(false);
|
||||
lastSendMessageId = data.readInt32(false);
|
||||
lastLocalId = data.readInt32(false);
|
||||
contactsHash = data.readString(false);
|
||||
data.readString(false);
|
||||
saveIncomingPhotos = data.readBool(false);
|
||||
//MessagesStorage.lastQtsValue = data.readInt32(false);
|
||||
//MessagesStorage.lastSecretVersion = data.readInt32(false);
|
||||
int val = data.readInt32(false);
|
||||
//if (val == 1) {
|
||||
// MessagesStorage.secretPBytes = data.readByteArray(false);
|
||||
//}
|
||||
//MessagesStorage.secretG = data.readInt32(false);
|
||||
Utilities.stageQueue.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
saveConfig(true, configFile);
|
||||
}
|
||||
});
|
||||
} else if (ver == 2) {
|
||||
int constructor = data.readInt32(false);
|
||||
currentUser = TLRPC.User.TLdeserialize(data, constructor, false);
|
||||
|
||||
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("userconfing", Context.MODE_PRIVATE);
|
||||
registeredForPush = preferences.getBoolean("registeredForPush", false);
|
||||
pushString = preferences.getString("pushString2", "");
|
||||
lastSendMessageId = preferences.getInt("lastSendMessageId", -210000);
|
||||
lastLocalId = preferences.getInt("lastLocalId", -210000);
|
||||
contactsHash = preferences.getString("contactsHash", "");
|
||||
saveIncomingPhotos = preferences.getBoolean("saveIncomingPhotos", false);
|
||||
}
|
||||
if (lastLocalId > -210000) {
|
||||
lastLocalId = -210000;
|
||||
}
|
||||
if (lastSendMessageId > -210000) {
|
||||
lastSendMessageId = -210000;
|
||||
}
|
||||
data.cleanup();
|
||||
Utilities.stageQueue.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
saveConfig(true, configFile);
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
} else
|
||||
*/
|
||||
{
|
||||
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("userconfing", Context.MODE_PRIVATE);
|
||||
registeredForPush = preferences.getBoolean("registeredForPush", false);
|
||||
pushString = preferences.getString("pushString2", "");
|
||||
lastSendMessageId = preferences.getInt("lastSendMessageId", -210000);
|
||||
lastLocalId = preferences.getInt("lastLocalId", -210000);
|
||||
contactsHash = preferences.getString("contactsHash", "");
|
||||
saveIncomingPhotos = preferences.getBoolean("saveIncomingPhotos", false);
|
||||
lastBroadcastId = preferences.getInt("lastBroadcastId", -1);
|
||||
blockedUsersLoaded = preferences.getBoolean("blockedUsersLoaded", false);
|
||||
passcodeHash = preferences.getString("passcodeHash1", "");
|
||||
appLocked = preferences.getBoolean("appLocked", false);
|
||||
passcodeType = preferences.getInt("passcodeType", 0);
|
||||
autoLockIn = preferences.getInt("autoLockIn", 60 * 60);
|
||||
lastPauseTime = preferences.getInt("lastPauseTime", 0);
|
||||
useFingerprint = preferences.getBoolean("useFingerprint", true);
|
||||
lastUpdateVersion = preferences.getString("lastUpdateVersion2", "3.5");
|
||||
lastContactsSyncTime = preferences.getInt("lastContactsSyncTime", (int) (System.currentTimeMillis() / 1000) - 23 * 60 * 60);
|
||||
lastHintsSyncTime = preferences.getInt("lastHintsSyncTime", (int) (System.currentTimeMillis() / 1000) - 25 * 60 * 60);
|
||||
draftsLoaded = preferences.getBoolean("draftsLoaded", false);
|
||||
|
||||
migrateOffsetId = preferences.getInt("migrateOffsetId", 0);
|
||||
if (migrateOffsetId != -1) {
|
||||
migrateOffsetDate = preferences.getInt("migrateOffsetDate", 0);
|
||||
migrateOffsetUserId = preferences.getInt("migrateOffsetUserId", 0);
|
||||
migrateOffsetChatId = preferences.getInt("migrateOffsetChatId", 0);
|
||||
migrateOffsetChannelId = preferences.getInt("migrateOffsetChannelId", 0);
|
||||
migrateOffsetAccess = preferences.getLong("migrateOffsetAccess", 0);
|
||||
}
|
||||
|
||||
/*
|
||||
String user = preferences.getString("user", null);
|
||||
if (user != null) {
|
||||
byte[] userBytes = Base64.decode(user, Base64.DEFAULT);
|
||||
if (userBytes != null) {
|
||||
SerializedData data = new SerializedData(userBytes);
|
||||
currentUser = TLRPC.User.TLdeserialize(data, data.readInt32(false), false);
|
||||
data.cleanup();
|
||||
}
|
||||
}
|
||||
*/
|
||||
setCurrentUser(null);
|
||||
|
||||
String passcodeSaltString = preferences.getString("passcodeSalt", "");
|
||||
if (passcodeSaltString.length() > 0) {
|
||||
@@ -263,7 +80,6 @@ public class UserConfig {
|
||||
} else {
|
||||
passcodeSalt = new byte[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -280,9 +96,9 @@ public class UserConfig {
|
||||
System.arraycopy(passcodeBytes, 0, bytes, 16, passcodeBytes.length);
|
||||
System.arraycopy(passcodeSalt, 0, bytes, passcodeBytes.length + 16, 16);
|
||||
passcodeHash = Utilities.bytesToHex(Utilities.computeSHA256(bytes, 0, bytes.length));
|
||||
saveConfig(false);
|
||||
saveConfig();
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@@ -296,7 +112,7 @@ public class UserConfig {
|
||||
String hash = Utilities.bytesToHex(Utilities.computeSHA256(bytes, 0, bytes.length));
|
||||
return passcodeHash.equals(hash);
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
/*
|
||||
* This is the source code of Telegram for Android v. 3.x.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2016.
|
||||
*/
|
||||
|
||||
package com.b44t.messenger;
|
||||
|
||||
public class UserObject {
|
||||
|
||||
public static boolean isDeleted(TLRPC.User user) {
|
||||
return user == null || user.deleted;
|
||||
}
|
||||
|
||||
public static boolean isUserSelf(TLRPC.User user) {
|
||||
return user.self;
|
||||
}
|
||||
|
||||
public static String getUserName(TLRPC.User user) {
|
||||
return "ErrName"; // use MrContact.getName() instead
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,25 @@
|
||||
/*
|
||||
* This is the source code of Telegram for Android v. 3.x.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2016.
|
||||
*/
|
||||
* Messenger Android Frontend
|
||||
* (C) 2013-2016 Nikolai Kudashov
|
||||
* (C) 2017 Björn Petersen
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see http://www.gnu.org/licenses/ .
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
package com.b44t.messenger;
|
||||
|
||||
@@ -41,7 +56,7 @@ public class Utilities {
|
||||
sUrandomIn.close();
|
||||
random.setSeed(buffer);
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,15 +67,8 @@ public class Utilities {
|
||||
public native static void calcCDT(ByteBuffer hsvBuffer, int width, int height, ByteBuffer buffer);
|
||||
public native static boolean loadWebpImage(Bitmap bitmap, ByteBuffer buffer, int len, BitmapFactory.Options options, boolean unpin);
|
||||
public native static int convertVideoFrame(ByteBuffer src, ByteBuffer dest, int destFormat, int width, int height, int padding, int swap);
|
||||
//private native static void aesIgeEncryption(ByteBuffer buffer, byte[] key, byte[] iv, boolean encrypt, int offset, int length);
|
||||
public native static String readlink(String path);
|
||||
|
||||
/*
|
||||
public static void aesIgeEncryption(ByteBuffer buffer, byte[] key, byte[] iv, boolean encrypt, boolean changeIv, int offset, int length) {
|
||||
aesIgeEncryption(buffer, key, changeIv ? iv : iv.clone(), encrypt, offset, length);
|
||||
}
|
||||
*/
|
||||
|
||||
public static Integer parseInt(String value) {
|
||||
if (value == null) {
|
||||
return 0;
|
||||
@@ -73,7 +81,7 @@ public class Utilities {
|
||||
val = Integer.parseInt(num);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
|
||||
}
|
||||
return val;
|
||||
}
|
||||
@@ -90,19 +98,11 @@ public class Utilities {
|
||||
val = Long.parseLong(num);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
public static String parseIntToString(String value) {
|
||||
Matcher matcher = pattern.matcher(value);
|
||||
if (matcher.find()) {
|
||||
return matcher.group(0);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String bytesToHex(byte[] bytes) {
|
||||
if (bytes == null) {
|
||||
return "";
|
||||
@@ -117,138 +117,17 @@ public class Utilities {
|
||||
return new String(hexChars);
|
||||
}
|
||||
|
||||
public static byte[] hexToBytes(String hex) {
|
||||
if (hex == null) {
|
||||
return null;
|
||||
}
|
||||
int len = hex.length();
|
||||
byte[] data = new byte[len / 2];
|
||||
for (int i = 0; i < len; i += 2) {
|
||||
data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4) + Character.digit(hex.charAt(i + 1), 16));
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
public static boolean isGoodPrime(byte[] prime, int g) {
|
||||
if (!(g >= 2 && g <= 7)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (prime.length != 256 || prime[0] >= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BigInteger dhBI = new BigInteger(1, prime);
|
||||
|
||||
if (g == 2) { // p mod 8 = 7 for g = 2;
|
||||
BigInteger res = dhBI.mod(BigInteger.valueOf(8));
|
||||
if (res.intValue() != 7) {
|
||||
return false;
|
||||
}
|
||||
} else if (g == 3) { // p mod 3 = 2 for g = 3;
|
||||
BigInteger res = dhBI.mod(BigInteger.valueOf(3));
|
||||
if (res.intValue() != 2) {
|
||||
return false;
|
||||
}
|
||||
} else if (g == 5) { // p mod 5 = 1 or 4 for g = 5;
|
||||
BigInteger res = dhBI.mod(BigInteger.valueOf(5));
|
||||
int val = res.intValue();
|
||||
if (val != 1 && val != 4) {
|
||||
return false;
|
||||
}
|
||||
} else if (g == 6) { // p mod 24 = 19 or 23 for g = 6;
|
||||
BigInteger res = dhBI.mod(BigInteger.valueOf(24));
|
||||
int val = res.intValue();
|
||||
if (val != 19 && val != 23) {
|
||||
return false;
|
||||
}
|
||||
} else if (g == 7) { // p mod 7 = 3, 5 or 6 for g = 7.
|
||||
BigInteger res = dhBI.mod(BigInteger.valueOf(7));
|
||||
int val = res.intValue();
|
||||
if (val != 3 && val != 5 && val != 6) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
String hex = bytesToHex(prime);
|
||||
if (hex.equals("C71CAEB9C6B1C9048E6C522F70F13F73980D40238E3E21C14934D037563D930F48198A0AA7C14058229493D22530F4DBFA336F6E0AC925139543AED44CCE7C3720FD51F69458705AC68CD4FE6B6B13ABDC9746512969328454F18FAF8C595F642477FE96BB2A941D5BCD1D4AC8CC49880708FA9B378E3C4F3A9060BEE67CF9A4A4A695811051907E162753B56B0F6B410DBA74D8A84B2A14B3144E0EF1284754FD17ED950D5965B4B9DD46582DB1178D169C6BC465B0D6FF9CA3928FEF5B9AE4E418FC15E83EBEA0F87FA9FF5EED70050DED2849F47BF959D956850CE929851F0D8115F635B105EE2E4E15D04B2454BF6F4FADF034B10403119CD8E3B92FCC5B")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
BigInteger dhBI2 = dhBI.subtract(BigInteger.valueOf(1)).divide(BigInteger.valueOf(2));
|
||||
return !(!dhBI.isProbablePrime(30) || !dhBI2.isProbablePrime(30));
|
||||
}
|
||||
|
||||
public static boolean isGoodGaAndGb(BigInteger g_a, BigInteger p) {
|
||||
return !(g_a.compareTo(BigInteger.valueOf(1)) != 1 || g_a.compareTo(p.subtract(BigInteger.valueOf(1))) != -1);
|
||||
}
|
||||
|
||||
public static boolean arraysEquals(byte[] arr1, int offset1, byte[] arr2, int offset2) {
|
||||
if (arr1 == null || arr2 == null || offset1 < 0 || offset2 < 0 || arr1.length - offset1 != arr2.length - offset2 || arr1.length - offset1 < 0 || arr2.length - offset2 < 0) {
|
||||
return false;
|
||||
}
|
||||
boolean result = true;
|
||||
for (int a = offset1; a < arr1.length; a++) {
|
||||
if (arr1[a + offset1] != arr2[a + offset2]) {
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static byte[] computeSHA1(byte[] convertme, int offset, int len) {
|
||||
try {
|
||||
MessageDigest md = MessageDigest.getInstance("SHA-1");
|
||||
md.update(convertme, offset, len);
|
||||
return md.digest();
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
return new byte[20];
|
||||
}
|
||||
|
||||
public static byte[] computeSHA1(ByteBuffer convertme, int offset, int len) {
|
||||
int oldp = convertme.position();
|
||||
int oldl = convertme.limit();
|
||||
try {
|
||||
MessageDigest md = MessageDigest.getInstance("SHA-1");
|
||||
convertme.position(offset);
|
||||
convertme.limit(len);
|
||||
md.update(convertme);
|
||||
return md.digest();
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
} finally {
|
||||
convertme.limit(oldl);
|
||||
convertme.position(oldp);
|
||||
}
|
||||
return new byte[20];
|
||||
}
|
||||
|
||||
public static byte[] computeSHA1(ByteBuffer convertme) {
|
||||
return computeSHA1(convertme, 0, convertme.limit());
|
||||
}
|
||||
|
||||
public static byte[] computeSHA1(byte[] convertme) {
|
||||
return computeSHA1(convertme, 0, convertme.length);
|
||||
}
|
||||
|
||||
public static byte[] computeSHA256(byte[] convertme, int offset, int len) {
|
||||
try {
|
||||
MessageDigest md = MessageDigest.getInstance("SHA-256");
|
||||
md.update(convertme, offset, len);
|
||||
return md.digest();
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static long bytesToLong(byte[] bytes) {
|
||||
return ((long) bytes[7] << 56) + (((long) bytes[6] & 0xFF) << 48) + (((long) bytes[5] & 0xFF) << 40) + (((long) bytes[4] & 0xFF) << 32)
|
||||
+ (((long) bytes[3] & 0xFF) << 24) + (((long) bytes[2] & 0xFF) << 16) + (((long) bytes[1] & 0xFF) << 8) + ((long) bytes[0] & 0xFF);
|
||||
}
|
||||
|
||||
public static String MD5(String md5) {
|
||||
if (md5 == null) {
|
||||
return null;
|
||||
@@ -262,7 +141,7 @@ public class Utilities {
|
||||
}
|
||||
return sb.toString();
|
||||
} catch (java.security.NoSuchAlgorithmException e) {
|
||||
FileLog.e("messenger", e);
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,57 +1,37 @@
|
||||
/*
|
||||
* This is the source code of Telegram for Android v. 3.x.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2016.
|
||||
*/
|
||||
* Messenger Android Frontend
|
||||
* (C) 2013-2016 Nikolai Kudashov
|
||||
* (C) 2017 Björn Petersen
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see http://www.gnu.org/licenses/ .
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
package com.b44t.messenger;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
public class VideoEditedInfo {
|
||||
public long startTime;
|
||||
public long endTime;
|
||||
public int rotationValue;
|
||||
public int originalWidth;
|
||||
public int originalHeight;
|
||||
public int originalBitrate;
|
||||
public int resultWidth;
|
||||
public int resultHeight;
|
||||
public int bitrate;
|
||||
public int resultBitrate;
|
||||
public String originalPath;
|
||||
|
||||
public String getString() {
|
||||
return String.format(Locale.US, "-1_%d_%d_%d_%d_%d_%d_%d_%d_%s", startTime, endTime, rotationValue, originalWidth, originalHeight, bitrate, resultWidth, resultHeight, originalPath);
|
||||
}
|
||||
|
||||
public boolean parseString(String string) {
|
||||
if (string.length() < 6) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
String args[] = string.split("_");
|
||||
if (args.length >= 10) {
|
||||
startTime = Long.parseLong(args[1]);
|
||||
endTime = Long.parseLong(args[2]);
|
||||
rotationValue = Integer.parseInt(args[3]);
|
||||
originalWidth = Integer.parseInt(args[4]);
|
||||
originalHeight = Integer.parseInt(args[5]);
|
||||
bitrate = Integer.parseInt(args[6]);
|
||||
resultWidth = Integer.parseInt(args[7]);
|
||||
resultHeight = Integer.parseInt(args[8]);
|
||||
for (int a = 9; a < args.length; a++) {
|
||||
if (originalPath == null) {
|
||||
originalPath = args[a];
|
||||
} else {
|
||||
originalPath += "_" + args[a];
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
/*
|
||||
* This is the source code of Telegram for Android v. 3.x.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2016.
|
||||
*/
|
||||
|
||||
package com.b44t.messenger;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Intent;
|
||||
import android.os.IBinder;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import android.support.v4.app.NotificationManagerCompat;
|
||||
|
||||
public class VideoEncodingService extends Service implements NotificationCenter.NotificationCenterDelegate {
|
||||
|
||||
private NotificationCompat.Builder builder = null;
|
||||
private String path = null;
|
||||
private int currentProgress = 0;
|
||||
|
||||
public VideoEncodingService() {
|
||||
super();
|
||||
NotificationCenter.getInstance().addObserver(this, NotificationCenter.FileUploadProgressChanged);
|
||||
NotificationCenter.getInstance().addObserver(this, NotificationCenter.stopEncodingService);
|
||||
}
|
||||
|
||||
public IBinder onBind(Intent arg2) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void onDestroy() {
|
||||
stopForeground(true);
|
||||
NotificationCenter.getInstance().removeObserver(this, NotificationCenter.FileUploadProgressChanged);
|
||||
NotificationCenter.getInstance().removeObserver(this, NotificationCenter.stopEncodingService);
|
||||
FileLog.e("messenger", "destroy video service");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void didReceivedNotification(int id, Object... args) {
|
||||
if (id == NotificationCenter.FileUploadProgressChanged) {
|
||||
String fileName = (String)args[0];
|
||||
if (path != null && path.equals(fileName)) {
|
||||
Float progress = (Float) args[1];
|
||||
Boolean enc = (Boolean) args[2];
|
||||
currentProgress = (int)(progress * 100);
|
||||
builder.setProgress(100, currentProgress, currentProgress == 0);
|
||||
NotificationManagerCompat.from(ApplicationLoader.applicationContext).notify(4, builder.build());
|
||||
}
|
||||
} else if (id == NotificationCenter.stopEncodingService) {
|
||||
String filepath = (String)args[0];
|
||||
if (filepath == null || filepath.equals(path)) {
|
||||
stopSelf();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
path = intent.getStringExtra("path");
|
||||
if (path == null) {
|
||||
stopSelf();
|
||||
return Service.START_NOT_STICKY;
|
||||
}
|
||||
FileLog.e("messenger", "start video service");
|
||||
if (builder == null) {
|
||||
builder = new NotificationCompat.Builder(ApplicationLoader.applicationContext);
|
||||
builder.setSmallIcon(android.R.drawable.stat_sys_upload);
|
||||
builder.setWhen(System.currentTimeMillis());
|
||||
builder.setContentTitle(LocaleController.getString("AppName", R.string.AppName));
|
||||
builder.setTicker(LocaleController.getString("SendingVideo", R.string.SendingVideo));
|
||||
builder.setContentText(LocaleController.getString("SendingVideo", R.string.SendingVideo));
|
||||
}
|
||||
currentProgress = 0;
|
||||
builder.setProgress(100, currentProgress, currentProgress == 0);
|
||||
startForeground(4, builder.build());
|
||||
NotificationManagerCompat.from(ApplicationLoader.applicationContext).notify(4, builder.build());
|
||||
return Service.START_NOT_STICKY;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,25 @@
|
||||
/*
|
||||
* This is the source code of Telegram for Android v. 3.x.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2016.
|
||||
*/
|
||||
* Messenger Android Frontend
|
||||
* (C) 2013-2016 Nikolai Kudashov
|
||||
* (C) 2017 Björn Petersen
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see http://www.gnu.org/licenses/ .
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
package com.b44t.messenger;
|
||||
|
||||
@@ -13,12 +28,13 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.RemoteInput;
|
||||
import android.util.Log;
|
||||
|
||||
public class WearReplyReceiver extends BroadcastReceiver {
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
ApplicationLoader.postInitApplication();
|
||||
|
||||
Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
|
||||
if (remoteInput == null) {
|
||||
return;
|
||||
@@ -32,7 +48,8 @@ public class WearReplyReceiver extends BroadcastReceiver {
|
||||
if (dialog_id == 0 || max_id == 0) {
|
||||
return;
|
||||
}
|
||||
SendMessagesHelper.getInstance().sendMessageText(text.toString(), dialog_id, null, null, true, null, null);
|
||||
MessagesController.getInstance().markDialogAsRead(dialog_id, max_id, max_id, 0, true, false);
|
||||
SendMessagesHelper.getInstance().sendMessageText(text.toString(), dialog_id, null);
|
||||
MrMailbox.markseenChat((int)dialog_id);
|
||||
NotificationsController.getInstance().removeSeenMessages();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,25 @@
|
||||
/*
|
||||
* This is the source code of Telegram for Android v. 3.x.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2016.
|
||||
*/
|
||||
* Messenger Android Frontend
|
||||
* (C) 2013-2016 Nikolai Kudashov
|
||||
* (C) 2017 Björn Petersen
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see http://www.gnu.org/licenses/ .
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
package com.b44t.messenger.browser;
|
||||
|
||||
@@ -13,7 +28,6 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
|
||||
import com.b44t.messenger.FileLog;
|
||||
import com.b44t.ui.LaunchActivity;
|
||||
|
||||
public class Browser {
|
||||
@@ -40,7 +54,7 @@ public class Browser {
|
||||
intent.putExtra(android.provider.Browser.EXTRA_APPLICATION_ID, context.getPackageName());
|
||||
context.startActivity(intent);
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.b44t.messenger.exoplayer;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
/**
|
||||
* A {@link FrameLayout} that resizes itself to match a specified aspect ratio.
|
||||
*/
|
||||
public final class AspectRatioFrameLayout extends FrameLayout {
|
||||
|
||||
/**
|
||||
* The {@link FrameLayout} will not resize itself if the fractional difference between its natural
|
||||
* aspect ratio and the requested aspect ratio falls below this threshold.
|
||||
* <p>
|
||||
* This tolerance allows the view to occupy the whole of the screen when the requested aspect
|
||||
* ratio is very close, but not exactly equal to, the aspect ratio of the screen. This may reduce
|
||||
* the number of view layers that need to be composited by the underlying system, which can help
|
||||
* to reduce power consumption.
|
||||
*/
|
||||
private static final float MAX_ASPECT_RATIO_DEFORMATION_FRACTION = 0.01f;
|
||||
|
||||
private float videoAspectRatio;
|
||||
|
||||
public AspectRatioFrameLayout(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public AspectRatioFrameLayout(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the aspect ratio that this view should satisfy.
|
||||
*
|
||||
* @param widthHeightRatio The width to height ratio.
|
||||
*/
|
||||
public void setAspectRatio(float widthHeightRatio) {
|
||||
if (this.videoAspectRatio != widthHeightRatio) {
|
||||
this.videoAspectRatio = widthHeightRatio;
|
||||
requestLayout();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
if (videoAspectRatio == 0) {
|
||||
// Aspect ratio not set.
|
||||
return;
|
||||
}
|
||||
|
||||
int width = getMeasuredWidth();
|
||||
int height = getMeasuredHeight();
|
||||
float viewAspectRatio = (float) width / height;
|
||||
float aspectDeformation = videoAspectRatio / viewAspectRatio - 1;
|
||||
if (Math.abs(aspectDeformation) <= MAX_ASPECT_RATIO_DEFORMATION_FRACTION) {
|
||||
// We're within the allowed tolerance.
|
||||
return;
|
||||
}
|
||||
|
||||
if (aspectDeformation > 0) {
|
||||
height = (int) (width / videoAspectRatio);
|
||||
} else {
|
||||
width = (int) (height * videoAspectRatio);
|
||||
}
|
||||
super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
|
||||
MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
|
||||
}
|
||||
|
||||
}
|
||||
-33
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.b44t.messenger.exoplayer;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Thrown when a live playback falls behind the available media window.
|
||||
*/
|
||||
public final class BehindLiveWindowException extends IOException {
|
||||
|
||||
public BehindLiveWindowException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public BehindLiveWindowException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,146 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.b44t.messenger.exoplayer;
|
||||
|
||||
import com.b44t.messenger.exoplayer.util.Util;
|
||||
|
||||
import android.media.AudioFormat;
|
||||
import android.media.MediaCodec;
|
||||
import android.media.MediaExtractor;
|
||||
|
||||
/**
|
||||
* Defines constants that are generally useful throughout the library.
|
||||
*/
|
||||
public final class C {
|
||||
|
||||
/**
|
||||
* Represents an unknown microsecond time or duration.
|
||||
*/
|
||||
public static final long UNKNOWN_TIME_US = -1L;
|
||||
|
||||
/**
|
||||
* Represents a microsecond duration whose exact value is unknown, but which should match the
|
||||
* longest of some other known durations.
|
||||
*/
|
||||
public static final long MATCH_LONGEST_US = -2L;
|
||||
|
||||
/**
|
||||
* The number of microseconds in one second.
|
||||
*/
|
||||
public static final long MICROS_PER_SECOND = 1000000L;
|
||||
|
||||
/**
|
||||
* Represents an unbounded length of data.
|
||||
*/
|
||||
public static final int LENGTH_UNBOUNDED = -1;
|
||||
|
||||
/**
|
||||
* The name of the UTF-8 charset.
|
||||
*/
|
||||
public static final String UTF8_NAME = "UTF-8";
|
||||
|
||||
/**
|
||||
* @see MediaCodec#CRYPTO_MODE_AES_CTR
|
||||
*/
|
||||
@SuppressWarnings("InlinedApi")
|
||||
public static final int CRYPTO_MODE_AES_CTR = MediaCodec.CRYPTO_MODE_AES_CTR;
|
||||
|
||||
/**
|
||||
* @see AudioFormat#ENCODING_INVALID
|
||||
*/
|
||||
public static final int ENCODING_INVALID = AudioFormat.ENCODING_INVALID;
|
||||
|
||||
/**
|
||||
* @see AudioFormat#ENCODING_PCM_8BIT
|
||||
*/
|
||||
public static final int ENCODING_PCM_8BIT = AudioFormat.ENCODING_PCM_8BIT;
|
||||
|
||||
/**
|
||||
* @see AudioFormat#ENCODING_PCM_16BIT
|
||||
*/
|
||||
public static final int ENCODING_PCM_16BIT = AudioFormat.ENCODING_PCM_16BIT;
|
||||
|
||||
/**
|
||||
* PCM encoding with 24 bits per sample.
|
||||
*/
|
||||
public static final int ENCODING_PCM_24BIT = 0x80000000;
|
||||
|
||||
/**
|
||||
* PCM encoding with 32 bits per sample.
|
||||
*/
|
||||
public static final int ENCODING_PCM_32BIT = 0x40000000;
|
||||
|
||||
/**
|
||||
* @see AudioFormat#ENCODING_AC3
|
||||
*/
|
||||
@SuppressWarnings("InlinedApi")
|
||||
public static final int ENCODING_AC3 = AudioFormat.ENCODING_AC3;
|
||||
|
||||
/**
|
||||
* @see AudioFormat#ENCODING_E_AC3
|
||||
*/
|
||||
@SuppressWarnings("InlinedApi")
|
||||
public static final int ENCODING_E_AC3 = AudioFormat.ENCODING_E_AC3;
|
||||
|
||||
/**
|
||||
* @see AudioFormat#ENCODING_DTS
|
||||
*/
|
||||
@SuppressWarnings("InlinedApi")
|
||||
public static final int ENCODING_DTS = AudioFormat.ENCODING_DTS;
|
||||
|
||||
/**
|
||||
* @see AudioFormat#ENCODING_DTS_HD
|
||||
*/
|
||||
@SuppressWarnings("InlinedApi")
|
||||
public static final int ENCODING_DTS_HD = AudioFormat.ENCODING_DTS_HD;
|
||||
|
||||
/**
|
||||
* @see AudioFormat#CHANNEL_OUT_7POINT1_SURROUND
|
||||
*/
|
||||
@SuppressWarnings({"InlinedApi", "deprecation"})
|
||||
public static final int CHANNEL_OUT_7POINT1_SURROUND = Util.SDK_INT < 23
|
||||
? AudioFormat.CHANNEL_OUT_7POINT1 : AudioFormat.CHANNEL_OUT_7POINT1_SURROUND;
|
||||
|
||||
/**
|
||||
* @see MediaExtractor#SAMPLE_FLAG_SYNC
|
||||
*/
|
||||
@SuppressWarnings("InlinedApi")
|
||||
public static final int SAMPLE_FLAG_SYNC = MediaExtractor.SAMPLE_FLAG_SYNC;
|
||||
|
||||
/**
|
||||
* @see MediaExtractor#SAMPLE_FLAG_ENCRYPTED
|
||||
*/
|
||||
@SuppressWarnings("InlinedApi")
|
||||
public static final int SAMPLE_FLAG_ENCRYPTED = MediaExtractor.SAMPLE_FLAG_ENCRYPTED;
|
||||
|
||||
/**
|
||||
* Indicates that a sample should be decoded but not rendered.
|
||||
*/
|
||||
public static final int SAMPLE_FLAG_DECODE_ONLY = 0x8000000;
|
||||
|
||||
/**
|
||||
* A return value for methods where the end of an input was encountered.
|
||||
*/
|
||||
public static final int RESULT_END_OF_INPUT = -1;
|
||||
|
||||
/**
|
||||
* A return value for methods where the length of parsed data exceeds the maximum length allowed.
|
||||
*/
|
||||
public static final int RESULT_MAX_LENGTH_EXCEEDED = -2;
|
||||
|
||||
private C() {}
|
||||
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.b44t.messenger.exoplayer;
|
||||
|
||||
/**
|
||||
* Maintains codec event counts, for debugging purposes only.
|
||||
* <p>
|
||||
* Counters should be written from the playback thread only. Counters may be read from any thread.
|
||||
* To ensure that the counter values are correctly reflected between threads, users of this class
|
||||
* should invoke {@link #ensureUpdated()} prior to reading and after writing.
|
||||
*/
|
||||
public final class CodecCounters {
|
||||
|
||||
public int codecInitCount;
|
||||
public int codecReleaseCount;
|
||||
public int inputBufferCount;
|
||||
public int outputFormatChangedCount;
|
||||
public int outputBuffersChangedCount;
|
||||
public int renderedOutputBufferCount;
|
||||
public int skippedOutputBufferCount;
|
||||
public int droppedOutputBufferCount;
|
||||
public int maxConsecutiveDroppedOutputBufferCount;
|
||||
|
||||
/**
|
||||
* Should be invoked from the playback thread after the counters have been updated. Should also
|
||||
* be invoked from any other thread that wishes to read the counters, before reading. These calls
|
||||
* ensure that counter updates are made visible to the reading threads.
|
||||
*/
|
||||
public synchronized void ensureUpdated() {
|
||||
// Do nothing. The use of synchronized ensures a memory barrier should another thread also
|
||||
// call this method.
|
||||
}
|
||||
|
||||
public String getDebugString() {
|
||||
ensureUpdated();
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("cic:").append(codecInitCount);
|
||||
builder.append(" crc:").append(codecReleaseCount);
|
||||
builder.append(" ibc:").append(inputBufferCount);
|
||||
builder.append(" ofc:").append(outputFormatChangedCount);
|
||||
builder.append(" obc:").append(outputBuffersChangedCount);
|
||||
builder.append(" ren:").append(renderedOutputBufferCount);
|
||||
builder.append(" sob:").append(skippedOutputBufferCount);
|
||||
builder.append(" dob:").append(droppedOutputBufferCount);
|
||||
builder.append(" mcdob:").append(maxConsecutiveDroppedOutputBufferCount);
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,116 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.b44t.messenger.exoplayer;
|
||||
|
||||
import com.b44t.messenger.exoplayer.util.Util;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.media.MediaExtractor;
|
||||
|
||||
/**
|
||||
* Compatibility wrapper around {@link android.media.MediaCodec.CryptoInfo}.
|
||||
*/
|
||||
public final class CryptoInfo {
|
||||
|
||||
/**
|
||||
* @see android.media.MediaCodec.CryptoInfo#iv
|
||||
*/
|
||||
public byte[] iv;
|
||||
/**
|
||||
* @see android.media.MediaCodec.CryptoInfo#key
|
||||
*/
|
||||
public byte[] key;
|
||||
/**
|
||||
* @see android.media.MediaCodec.CryptoInfo#mode
|
||||
*/
|
||||
public int mode;
|
||||
/**
|
||||
* @see android.media.MediaCodec.CryptoInfo#numBytesOfClearData
|
||||
*/
|
||||
public int[] numBytesOfClearData;
|
||||
/**
|
||||
* @see android.media.MediaCodec.CryptoInfo#numBytesOfEncryptedData
|
||||
*/
|
||||
public int[] numBytesOfEncryptedData;
|
||||
/**
|
||||
* @see android.media.MediaCodec.CryptoInfo#numSubSamples
|
||||
*/
|
||||
public int numSubSamples;
|
||||
|
||||
private final android.media.MediaCodec.CryptoInfo frameworkCryptoInfo;
|
||||
|
||||
public CryptoInfo() {
|
||||
frameworkCryptoInfo = Util.SDK_INT >= 16 ? newFrameworkCryptoInfoV16() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see android.media.MediaCodec.CryptoInfo#set(int, int[], int[], byte[], byte[], int)
|
||||
*/
|
||||
public void set(int numSubSamples, int[] numBytesOfClearData, int[] numBytesOfEncryptedData,
|
||||
byte[] key, byte[] iv, int mode) {
|
||||
this.numSubSamples = numSubSamples;
|
||||
this.numBytesOfClearData = numBytesOfClearData;
|
||||
this.numBytesOfEncryptedData = numBytesOfEncryptedData;
|
||||
this.key = key;
|
||||
this.iv = iv;
|
||||
this.mode = mode;
|
||||
if (Util.SDK_INT >= 16) {
|
||||
updateFrameworkCryptoInfoV16();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Equivalent to {@link MediaExtractor#getSampleCryptoInfo(android.media.MediaCodec.CryptoInfo)}.
|
||||
*
|
||||
* @param extractor The extractor from which to retrieve the crypto information.
|
||||
*/
|
||||
@TargetApi(16)
|
||||
public void setFromExtractorV16(MediaExtractor extractor) {
|
||||
extractor.getSampleCryptoInfo(frameworkCryptoInfo);
|
||||
numSubSamples = frameworkCryptoInfo.numSubSamples;
|
||||
numBytesOfClearData = frameworkCryptoInfo.numBytesOfClearData;
|
||||
numBytesOfEncryptedData = frameworkCryptoInfo.numBytesOfEncryptedData;
|
||||
key = frameworkCryptoInfo.key;
|
||||
iv = frameworkCryptoInfo.iv;
|
||||
mode = frameworkCryptoInfo.mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an equivalent {@link android.media.MediaCodec.CryptoInfo} instance.
|
||||
* <p>
|
||||
* Successive calls to this method on a single {@link CryptoInfo} will return the same instance.
|
||||
* Changes to the {@link CryptoInfo} will be reflected in the returned object. The return object
|
||||
* should not be modified directly.
|
||||
*
|
||||
* @return The equivalent {@link android.media.MediaCodec.CryptoInfo} instance.
|
||||
*/
|
||||
@TargetApi(16)
|
||||
public android.media.MediaCodec.CryptoInfo getFrameworkCryptoInfoV16() {
|
||||
return frameworkCryptoInfo;
|
||||
}
|
||||
|
||||
@TargetApi(16)
|
||||
private android.media.MediaCodec.CryptoInfo newFrameworkCryptoInfoV16() {
|
||||
return new android.media.MediaCodec.CryptoInfo();
|
||||
}
|
||||
|
||||
@TargetApi(16)
|
||||
private void updateFrameworkCryptoInfoV16() {
|
||||
frameworkCryptoInfo.set(numSubSamples, numBytesOfClearData, numBytesOfEncryptedData, key, iv,
|
||||
mode);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.b44t.messenger.exoplayer;
|
||||
|
||||
import com.b44t.messenger.exoplayer.util.Util;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.media.MediaCodecInfo.CodecCapabilities;
|
||||
|
||||
/**
|
||||
* Contains information about a media decoder.
|
||||
*/
|
||||
@TargetApi(16)
|
||||
public final class DecoderInfo {
|
||||
|
||||
/**
|
||||
* The name of the decoder.
|
||||
* <p>
|
||||
* May be passed to {@link android.media.MediaCodec#createByCodecName(String)} to create an
|
||||
* instance of the decoder.
|
||||
*/
|
||||
public final String name;
|
||||
|
||||
/**
|
||||
* {@link CodecCapabilities} for this decoder.
|
||||
*/
|
||||
public final CodecCapabilities capabilities;
|
||||
|
||||
/**
|
||||
* Whether the decoder supports seamless resolution switches.
|
||||
*
|
||||
* @see android.media.MediaCodecInfo.CodecCapabilities#isFeatureSupported(String)
|
||||
* @see android.media.MediaCodecInfo.CodecCapabilities#FEATURE_AdaptivePlayback
|
||||
*/
|
||||
public final boolean adaptive;
|
||||
|
||||
/**
|
||||
* @param name The name of the decoder.
|
||||
* @param capabilities {@link CodecCapabilities} of the decoder.
|
||||
*/
|
||||
/* package */ DecoderInfo(String name, CodecCapabilities capabilities) {
|
||||
this.name = name;
|
||||
this.capabilities = capabilities;
|
||||
this.adaptive = isAdaptive(capabilities);
|
||||
}
|
||||
|
||||
private static boolean isAdaptive(CodecCapabilities capabilities) {
|
||||
return capabilities != null && Util.SDK_INT >= 19 && isAdaptiveV19(capabilities);
|
||||
}
|
||||
|
||||
@TargetApi(19)
|
||||
private static boolean isAdaptiveV19(CodecCapabilities capabilities) {
|
||||
return capabilities.isFeatureSupported(CodecCapabilities.FEATURE_AdaptivePlayback);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,278 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.b44t.messenger.exoplayer;
|
||||
|
||||
import com.b44t.messenger.exoplayer.upstream.Allocator;
|
||||
import com.b44t.messenger.exoplayer.upstream.NetworkLock;
|
||||
|
||||
import android.os.Handler;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A {@link LoadControl} implementation that allows loads to continue in a sequence that prevents
|
||||
* any loader from getting too far ahead or behind any of the other loaders.
|
||||
* <p>
|
||||
* Loads are scheduled so as to fill the available buffer space as rapidly as possible. Once the
|
||||
* duration of buffered media and the buffer utilization both exceed respective thresholds, the
|
||||
* control switches to a draining state during which no loads are permitted to start. During
|
||||
* draining periods, resources such as the device radio have an opportunity to switch into low
|
||||
* power modes. The control reverts back to the loading state when either the duration of buffered
|
||||
* media or the buffer utilization fall below respective thresholds.
|
||||
* <p>
|
||||
* This implementation of {@link LoadControl} integrates with {@link NetworkLock}, by registering
|
||||
* itself as a task with priority {@link NetworkLock#STREAMING_PRIORITY} during loading periods,
|
||||
* and unregistering itself during draining periods.
|
||||
*/
|
||||
public final class DefaultLoadControl implements LoadControl {
|
||||
|
||||
/**
|
||||
* Interface definition for a callback to be notified of {@link DefaultLoadControl} events.
|
||||
*/
|
||||
public interface EventListener {
|
||||
|
||||
/**
|
||||
* Invoked when the control transitions from a loading to a draining state, or vice versa.
|
||||
*
|
||||
* @param loading Whether the control is now in a loading state.
|
||||
*/
|
||||
void onLoadingChanged(boolean loading);
|
||||
|
||||
}
|
||||
|
||||
public static final int DEFAULT_LOW_WATERMARK_MS = 15000;
|
||||
public static final int DEFAULT_HIGH_WATERMARK_MS = 30000;
|
||||
public static final float DEFAULT_LOW_BUFFER_LOAD = 0.2f;
|
||||
public static final float DEFAULT_HIGH_BUFFER_LOAD = 0.8f;
|
||||
|
||||
private static final int ABOVE_HIGH_WATERMARK = 0;
|
||||
private static final int BETWEEN_WATERMARKS = 1;
|
||||
private static final int BELOW_LOW_WATERMARK = 2;
|
||||
|
||||
private final Allocator allocator;
|
||||
private final List<Object> loaders;
|
||||
private final HashMap<Object, LoaderState> loaderStates;
|
||||
private final Handler eventHandler;
|
||||
private final EventListener eventListener;
|
||||
|
||||
private final long lowWatermarkUs;
|
||||
private final long highWatermarkUs;
|
||||
private final float lowBufferLoad;
|
||||
private final float highBufferLoad;
|
||||
|
||||
private int targetBufferSize;
|
||||
private long maxLoadStartPositionUs;
|
||||
private int bufferState;
|
||||
private boolean fillingBuffers;
|
||||
private boolean streamingPrioritySet;
|
||||
|
||||
/**
|
||||
* Constructs a new instance, using the {@code DEFAULT_*} constants defined in this class.
|
||||
*
|
||||
* @param allocator The {@link Allocator} used by the loader.
|
||||
*/
|
||||
public DefaultLoadControl(Allocator allocator) {
|
||||
this(allocator, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new instance, using the {@code DEFAULT_*} constants defined in this class.
|
||||
*
|
||||
* @param allocator The {@link Allocator} used by the loader.
|
||||
* @param eventHandler A handler to use when delivering events to {@code eventListener}. May be
|
||||
* null if delivery of events is not required.
|
||||
* @param eventListener A listener of events. May be null if delivery of events is not required.
|
||||
*/
|
||||
public DefaultLoadControl(Allocator allocator, Handler eventHandler,
|
||||
EventListener eventListener) {
|
||||
this(allocator, eventHandler, eventListener, DEFAULT_LOW_WATERMARK_MS,
|
||||
DEFAULT_HIGH_WATERMARK_MS, DEFAULT_LOW_BUFFER_LOAD, DEFAULT_HIGH_BUFFER_LOAD);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new instance.
|
||||
*
|
||||
* @param allocator The {@link Allocator} used by the loader.
|
||||
* @param eventHandler A handler to use when delivering events to {@code eventListener}. May be
|
||||
* null if delivery of events is not required.
|
||||
* @param eventListener A listener of events. May be null if delivery of events is not required.
|
||||
* @param lowWatermarkMs The minimum duration of media that can be buffered for the control to
|
||||
* be in the draining state. If less media is buffered, then the control will transition to
|
||||
* the filling state.
|
||||
* @param highWatermarkMs The minimum duration of media that can be buffered for the control to
|
||||
* transition from filling to draining.
|
||||
* @param lowBufferLoad The minimum fraction of the buffer that must be utilized for the control
|
||||
* to be in the draining state. If the utilization is lower, then the control will transition
|
||||
* to the filling state.
|
||||
* @param highBufferLoad The minimum fraction of the buffer that must be utilized for the control
|
||||
* to transition from the loading state to the draining state.
|
||||
*/
|
||||
public DefaultLoadControl(Allocator allocator, Handler eventHandler, EventListener eventListener,
|
||||
int lowWatermarkMs, int highWatermarkMs, float lowBufferLoad, float highBufferLoad) {
|
||||
this.allocator = allocator;
|
||||
this.eventHandler = eventHandler;
|
||||
this.eventListener = eventListener;
|
||||
this.loaders = new ArrayList<>();
|
||||
this.loaderStates = new HashMap<>();
|
||||
this.lowWatermarkUs = lowWatermarkMs * 1000L;
|
||||
this.highWatermarkUs = highWatermarkMs * 1000L;
|
||||
this.lowBufferLoad = lowBufferLoad;
|
||||
this.highBufferLoad = highBufferLoad;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(Object loader, int bufferSizeContribution) {
|
||||
loaders.add(loader);
|
||||
loaderStates.put(loader, new LoaderState(bufferSizeContribution));
|
||||
targetBufferSize += bufferSizeContribution;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregister(Object loader) {
|
||||
loaders.remove(loader);
|
||||
LoaderState state = loaderStates.remove(loader);
|
||||
targetBufferSize -= state.bufferSizeContribution;
|
||||
updateControlState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void trimAllocator() {
|
||||
allocator.trim(targetBufferSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Allocator getAllocator() {
|
||||
return allocator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean update(Object loader, long playbackPositionUs, long nextLoadPositionUs,
|
||||
boolean loading) {
|
||||
// Update the loader state.
|
||||
int loaderBufferState = getLoaderBufferState(playbackPositionUs, nextLoadPositionUs);
|
||||
LoaderState loaderState = loaderStates.get(loader);
|
||||
boolean loaderStateChanged = loaderState.bufferState != loaderBufferState
|
||||
|| loaderState.nextLoadPositionUs != nextLoadPositionUs || loaderState.loading != loading;
|
||||
if (loaderStateChanged) {
|
||||
loaderState.bufferState = loaderBufferState;
|
||||
loaderState.nextLoadPositionUs = nextLoadPositionUs;
|
||||
loaderState.loading = loading;
|
||||
}
|
||||
|
||||
// Update the buffer state.
|
||||
int currentBufferSize = allocator.getTotalBytesAllocated();
|
||||
int bufferState = getBufferState(currentBufferSize);
|
||||
boolean bufferStateChanged = this.bufferState != bufferState;
|
||||
if (bufferStateChanged) {
|
||||
this.bufferState = bufferState;
|
||||
}
|
||||
|
||||
// If either of the individual states have changed, update the shared control state.
|
||||
if (loaderStateChanged || bufferStateChanged) {
|
||||
updateControlState();
|
||||
}
|
||||
|
||||
return currentBufferSize < targetBufferSize && nextLoadPositionUs != -1
|
||||
&& nextLoadPositionUs <= maxLoadStartPositionUs;
|
||||
}
|
||||
|
||||
private int getLoaderBufferState(long playbackPositionUs, long nextLoadPositionUs) {
|
||||
if (nextLoadPositionUs == -1) {
|
||||
return ABOVE_HIGH_WATERMARK;
|
||||
} else {
|
||||
long timeUntilNextLoadPosition = nextLoadPositionUs - playbackPositionUs;
|
||||
return timeUntilNextLoadPosition > highWatermarkUs ? ABOVE_HIGH_WATERMARK :
|
||||
timeUntilNextLoadPosition < lowWatermarkUs ? BELOW_LOW_WATERMARK :
|
||||
BETWEEN_WATERMARKS;
|
||||
}
|
||||
}
|
||||
|
||||
private int getBufferState(int currentBufferSize) {
|
||||
float bufferLoad = (float) currentBufferSize / targetBufferSize;
|
||||
return bufferLoad > highBufferLoad ? ABOVE_HIGH_WATERMARK
|
||||
: bufferLoad < lowBufferLoad ? BELOW_LOW_WATERMARK
|
||||
: BETWEEN_WATERMARKS;
|
||||
}
|
||||
|
||||
private void updateControlState() {
|
||||
boolean loading = false;
|
||||
boolean haveNextLoadPosition = false;
|
||||
int highestState = bufferState;
|
||||
for (int i = 0; i < loaders.size(); i++) {
|
||||
LoaderState loaderState = loaderStates.get(loaders.get(i));
|
||||
loading |= loaderState.loading;
|
||||
haveNextLoadPosition |= loaderState.nextLoadPositionUs != -1;
|
||||
highestState = Math.max(highestState, loaderState.bufferState);
|
||||
}
|
||||
|
||||
fillingBuffers = !loaders.isEmpty() && (loading || haveNextLoadPosition)
|
||||
&& (highestState == BELOW_LOW_WATERMARK
|
||||
|| (highestState == BETWEEN_WATERMARKS && fillingBuffers));
|
||||
if (fillingBuffers && !streamingPrioritySet) {
|
||||
NetworkLock.instance.add(NetworkLock.STREAMING_PRIORITY);
|
||||
streamingPrioritySet = true;
|
||||
notifyLoadingChanged(true);
|
||||
} else if (!fillingBuffers && streamingPrioritySet && !loading) {
|
||||
NetworkLock.instance.remove(NetworkLock.STREAMING_PRIORITY);
|
||||
streamingPrioritySet = false;
|
||||
notifyLoadingChanged(false);
|
||||
}
|
||||
|
||||
maxLoadStartPositionUs = -1;
|
||||
if (fillingBuffers) {
|
||||
for (int i = 0; i < loaders.size(); i++) {
|
||||
Object loader = loaders.get(i);
|
||||
LoaderState loaderState = loaderStates.get(loader);
|
||||
long loaderTime = loaderState.nextLoadPositionUs;
|
||||
if (loaderTime != -1
|
||||
&& (maxLoadStartPositionUs == -1 || loaderTime < maxLoadStartPositionUs)) {
|
||||
maxLoadStartPositionUs = loaderTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyLoadingChanged(final boolean loading) {
|
||||
if (eventHandler != null && eventListener != null) {
|
||||
eventHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
eventListener.onLoadingChanged(loading);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private static class LoaderState {
|
||||
|
||||
public final int bufferSizeContribution;
|
||||
|
||||
public int bufferState;
|
||||
public boolean loading;
|
||||
public long nextLoadPositionUs;
|
||||
|
||||
public LoaderState(int bufferSizeContribution) {
|
||||
this.bufferSizeContribution = bufferSizeContribution;
|
||||
bufferState = ABOVE_HIGH_WATERMARK;
|
||||
loading = false;
|
||||
nextLoadPositionUs = -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.b44t.messenger.exoplayer;
|
||||
|
||||
/**
|
||||
* A {@link TrackRenderer} that does nothing.
|
||||
* <p>
|
||||
* This renderer returns 0 from {@link #getTrackCount()} in order to request that it should be
|
||||
* ignored. {@link IllegalStateException} is thrown from all other methods documented to indicate
|
||||
* that they should not be invoked unless the renderer is prepared.
|
||||
*/
|
||||
public final class DummyTrackRenderer extends TrackRenderer {
|
||||
|
||||
@Override
|
||||
protected boolean doPrepare(long positionUs) throws ExoPlaybackException {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getTrackCount() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MediaFormat getFormat(int track) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isEnded() {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isReady() {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void seekTo(long positionUs) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doSomeWork(long positionUs, long elapsedRealtimeUs) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void maybeThrowError() {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected long getDurationUs() {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected long getBufferedPositionUs() {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.b44t.messenger.exoplayer;
|
||||
|
||||
/**
|
||||
* Thrown when a non-recoverable playback failure occurs.
|
||||
* <p>
|
||||
* Where possible, the cause returned by {@link #getCause()} will indicate the reason for failure.
|
||||
*/
|
||||
public final class ExoPlaybackException extends Exception {
|
||||
|
||||
/**
|
||||
* True if the cause (i.e. the {@link Throwable} returned by {@link #getCause()}) was only caught
|
||||
* by a fail-safe at the top level of the player. False otherwise.
|
||||
*/
|
||||
public final boolean caughtAtTopLevel;
|
||||
|
||||
public ExoPlaybackException(String message) {
|
||||
super(message);
|
||||
caughtAtTopLevel = false;
|
||||
}
|
||||
|
||||
public ExoPlaybackException(Throwable cause) {
|
||||
super(cause);
|
||||
caughtAtTopLevel = false;
|
||||
}
|
||||
|
||||
public ExoPlaybackException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
caughtAtTopLevel = false;
|
||||
}
|
||||
|
||||
/* package */ ExoPlaybackException(Throwable cause, boolean caughtAtTopLevel) {
|
||||
super(cause);
|
||||
this.caughtAtTopLevel = caughtAtTopLevel;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,415 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.b44t.messenger.exoplayer;
|
||||
|
||||
import android.os.Looper;
|
||||
|
||||
/**
|
||||
* An extensible media player exposing traditional high-level media player functionality, such as
|
||||
* the ability to prepare, play, pause and seek.
|
||||
*
|
||||
* <p>Topics covered here are:
|
||||
* <ol>
|
||||
* <li><a href="#Assumptions">Assumptions and player composition</a>
|
||||
* <li><a href="#Threading">Threading model</a>
|
||||
* <li><a href="#State">Player state</a>
|
||||
* </ol>
|
||||
*
|
||||
* <a name="Assumptions"></a>
|
||||
* <h3>Assumptions and player construction</h3>
|
||||
*
|
||||
* <p>The implementation is designed to make no assumptions about (and hence impose no restrictions
|
||||
* on) the type of the media being played, how and where it is stored, or how it is rendered.
|
||||
* Rather than implementing the loading and rendering of media directly, {@link ExoPlayer} instead
|
||||
* delegates this work to one or more {@link TrackRenderer}s, which are injected when the player
|
||||
* is prepared. Hence {@link ExoPlayer} is capable of loading and playing any media for which a
|
||||
* {@link TrackRenderer} implementation can be provided.
|
||||
*
|
||||
* <p>{@link MediaCodecAudioTrackRenderer} and {@link MediaCodecVideoTrackRenderer} can be used for
|
||||
* the common cases of rendering audio and video. These components in turn require an
|
||||
* <i>upstream</i> {@link SampleSource} to be injected through their constructors, where upstream
|
||||
* is defined to denote a component that is closer to the source of the media. This pattern of
|
||||
* upstream dependency injection is actively encouraged, since it means that the functionality of
|
||||
* the player is built up through the composition of components that can easily be exchanged for
|
||||
* alternate implementations. For example a {@link SampleSource} implementation may require a
|
||||
* further upstream data loading component to be injected through its constructor, with different
|
||||
* implementations enabling the loading of data from various sources.
|
||||
*
|
||||
* <a name="Threading"></a>
|
||||
* <h3>Threading model</h3>
|
||||
*
|
||||
* <p>The figure below shows the {@link ExoPlayer} threading model.</p>
|
||||
* <p align="center"><img src="../../../../../images/exoplayer_threading_model.png"
|
||||
* alt="MediaPlayer state diagram"
|
||||
* border="0"/></p>
|
||||
*
|
||||
* <ul>
|
||||
* <li>It is recommended that instances are created and accessed from a single application thread.
|
||||
* An application's main thread is ideal. Accessing an instance from multiple threads is
|
||||
* discouraged, however if an application does wish to do this then it may do so provided that it
|
||||
* ensures accesses are synchronized.
|
||||
* </li>
|
||||
* <li>Registered {@link Listener}s are invoked on the thread that created the {@link ExoPlayer}
|
||||
* instance.</li>
|
||||
* <li>An internal playback thread is responsible for managing playback and invoking the
|
||||
* {@link TrackRenderer}s in order to load and play the media.</li>
|
||||
* <li>{@link TrackRenderer} implementations (or any upstream components that they depend on) may
|
||||
* use additional background threads (e.g. to load data). These are implementation specific.</li>
|
||||
* </ul>
|
||||
*
|
||||
* <a name="State"></a>
|
||||
* <h3>Player state</h3>
|
||||
*
|
||||
* <p>The components of an {@link ExoPlayer}'s state can be divided into two distinct groups. State
|
||||
* accessed by {@link #getSelectedTrack(int)} and {@link #getPlayWhenReady()} is only ever
|
||||
* changed by invoking the player's methods, and are never changed as a result of operations that
|
||||
* have been performed asynchronously by the playback thread. In contrast, the playback state
|
||||
* accessed by {@link #getPlaybackState()} is only ever changed as a result of operations
|
||||
* completing on the playback thread, as illustrated below.</p>
|
||||
* <p align="center"><img src="../../../../../images/exoplayer_state.png"
|
||||
* alt="ExoPlayer state"
|
||||
* border="0"/></p>
|
||||
*
|
||||
* <p>The possible playback state transitions are shown below. Transitions can be triggered either
|
||||
* by changes in the state of the {@link TrackRenderer}s being used, or as a result of
|
||||
* {@link #prepare(TrackRenderer[])}, {@link #stop()} or {@link #release()} being invoked.</p>
|
||||
* <p align="center"><img src="../../../../../images/exoplayer_playbackstate.png"
|
||||
* alt="ExoPlayer playback state transitions"
|
||||
* border="0"/></p>
|
||||
*/
|
||||
public interface ExoPlayer {
|
||||
|
||||
/**
|
||||
* A factory for instantiating ExoPlayer instances.
|
||||
*/
|
||||
public static final class Factory {
|
||||
|
||||
/**
|
||||
* The default minimum duration of data that must be buffered for playback to start or resume
|
||||
* following a user action such as a seek.
|
||||
*/
|
||||
public static final int DEFAULT_MIN_BUFFER_MS = 2500;
|
||||
|
||||
/**
|
||||
* The default minimum duration of data that must be buffered for playback to resume
|
||||
* after a player invoked rebuffer (i.e. a rebuffer that occurs due to buffer depletion, and
|
||||
* not due to a user action such as starting playback or seeking).
|
||||
*/
|
||||
public static final int DEFAULT_MIN_REBUFFER_MS = 5000;
|
||||
|
||||
private Factory() {}
|
||||
|
||||
/**
|
||||
* Obtains an {@link ExoPlayer} instance.
|
||||
* <p>
|
||||
* Must be invoked from a thread that has an associated {@link Looper}.
|
||||
*
|
||||
* @param rendererCount The number of {@link TrackRenderer}s that will be passed to
|
||||
* {@link #prepare(TrackRenderer[])}.
|
||||
* @param minBufferMs A minimum duration of data that must be buffered for playback to start
|
||||
* or resume following a user action such as a seek.
|
||||
* @param minRebufferMs A minimum duration of data that must be buffered for playback to resume
|
||||
* after a player invoked rebuffer (i.e. a rebuffer that occurs due to buffer depletion, and
|
||||
* not due to a user action such as starting playback or seeking).
|
||||
*/
|
||||
public static ExoPlayer newInstance(int rendererCount, int minBufferMs, int minRebufferMs) {
|
||||
return new ExoPlayerImpl(rendererCount, minBufferMs, minRebufferMs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains an {@link ExoPlayer} instance.
|
||||
* <p>
|
||||
* Must be invoked from a thread that has an associated {@link Looper}.
|
||||
*
|
||||
* @param rendererCount The number of {@link TrackRenderer}s that will be passed to
|
||||
* {@link #prepare(TrackRenderer[])}.
|
||||
*/
|
||||
public static ExoPlayer newInstance(int rendererCount) {
|
||||
return new ExoPlayerImpl(rendererCount, DEFAULT_MIN_BUFFER_MS, DEFAULT_MIN_REBUFFER_MS);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface definition for a callback to be notified of changes in player state.
|
||||
*/
|
||||
public interface Listener {
|
||||
/**
|
||||
* Invoked when the value returned from either {@link ExoPlayer#getPlayWhenReady()} or
|
||||
* {@link ExoPlayer#getPlaybackState()} changes.
|
||||
*
|
||||
* @param playWhenReady Whether playback will proceed when ready.
|
||||
* @param playbackState One of the {@code STATE} constants defined in the {@link ExoPlayer}
|
||||
* interface.
|
||||
*/
|
||||
void onPlayerStateChanged(boolean playWhenReady, int playbackState);
|
||||
/**
|
||||
* Invoked when the current value of {@link ExoPlayer#getPlayWhenReady()} has been reflected
|
||||
* by the internal playback thread.
|
||||
* <p>
|
||||
* An invocation of this method will shortly follow any call to
|
||||
* {@link ExoPlayer#setPlayWhenReady(boolean)} that changes the state. If multiple calls are
|
||||
* made in rapid succession, then this method will be invoked only once, after the final state
|
||||
* has been reflected.
|
||||
*/
|
||||
void onPlayWhenReadyCommitted();
|
||||
/**
|
||||
* Invoked when an error occurs. The playback state will transition to
|
||||
* {@link ExoPlayer#STATE_IDLE} immediately after this method is invoked. The player instance
|
||||
* can still be used, and {@link ExoPlayer#release()} must still be called on the player should
|
||||
* it no longer be required.
|
||||
*
|
||||
* @param error The error.
|
||||
*/
|
||||
void onPlayerError(ExoPlaybackException error);
|
||||
}
|
||||
|
||||
/**
|
||||
* A component of an {@link ExoPlayer} that can receive messages on the playback thread.
|
||||
* <p>
|
||||
* Messages can be delivered to a component via {@link ExoPlayer#sendMessage} and
|
||||
* {@link ExoPlayer#blockingSendMessage}.
|
||||
*/
|
||||
public interface ExoPlayerComponent {
|
||||
|
||||
/**
|
||||
* Handles a message delivered to the component. Invoked on the playback thread.
|
||||
*
|
||||
* @param messageType An integer identifying the type of message.
|
||||
* @param message The message object.
|
||||
* @throws ExoPlaybackException If an error occurred whilst handling the message.
|
||||
*/
|
||||
void handleMessage(int messageType, Object message) throws ExoPlaybackException;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The player is neither prepared or being prepared.
|
||||
*/
|
||||
public static final int STATE_IDLE = 1;
|
||||
/**
|
||||
* The player is being prepared.
|
||||
*/
|
||||
public static final int STATE_PREPARING = 2;
|
||||
/**
|
||||
* The player is prepared but not able to immediately play from the current position. The cause
|
||||
* is {@link TrackRenderer} specific, but this state typically occurs when more data needs
|
||||
* to be buffered for playback to start.
|
||||
*/
|
||||
public static final int STATE_BUFFERING = 3;
|
||||
/**
|
||||
* The player is prepared and able to immediately play from the current position. The player will
|
||||
* be playing if {@link #getPlayWhenReady()} returns true, and paused otherwise.
|
||||
*/
|
||||
public static final int STATE_READY = 4;
|
||||
/**
|
||||
* The player has finished playing the media.
|
||||
*/
|
||||
public static final int STATE_ENDED = 5;
|
||||
|
||||
/**
|
||||
* A value that can be passed as the second argument to {@link #setSelectedTrack(int, int)} to
|
||||
* disable the renderer.
|
||||
*/
|
||||
public static final int TRACK_DISABLED = -1;
|
||||
/**
|
||||
* A value that can be passed as the second argument to {@link #setSelectedTrack(int, int)} to
|
||||
* select the default track.
|
||||
*/
|
||||
public static final int TRACK_DEFAULT = 0;
|
||||
|
||||
/**
|
||||
* Represents an unknown time or duration.
|
||||
*/
|
||||
public static final long UNKNOWN_TIME = -1;
|
||||
|
||||
/**
|
||||
* Gets the {@link Looper} associated with the playback thread.
|
||||
*
|
||||
* @return The {@link Looper} associated with the playback thread.
|
||||
*/
|
||||
public Looper getPlaybackLooper();
|
||||
|
||||
/**
|
||||
* Register a listener to receive events from the player. The listener's methods will be invoked
|
||||
* on the thread that was used to construct the player.
|
||||
*
|
||||
* @param listener The listener to register.
|
||||
*/
|
||||
public void addListener(Listener listener);
|
||||
|
||||
/**
|
||||
* Unregister a listener. The listener will no longer receive events from the player.
|
||||
*
|
||||
* @param listener The listener to unregister.
|
||||
*/
|
||||
public void removeListener(Listener listener);
|
||||
|
||||
/**
|
||||
* Returns the current state of the player.
|
||||
*
|
||||
* @return One of the {@code STATE} constants defined in this interface.
|
||||
*/
|
||||
public int getPlaybackState();
|
||||
|
||||
/**
|
||||
* Prepares the player for playback.
|
||||
*
|
||||
* @param renderers The {@link TrackRenderer}s to use. The number of renderers must match the
|
||||
* value that was passed to the {@link ExoPlayer.Factory#newInstance} method.
|
||||
*/
|
||||
public void prepare(TrackRenderer... renderers);
|
||||
|
||||
/**
|
||||
* Returns the number of tracks exposed by the specified renderer.
|
||||
*
|
||||
* @param rendererIndex The index of the renderer.
|
||||
* @return The number of tracks.
|
||||
*/
|
||||
public int getTrackCount(int rendererIndex);
|
||||
|
||||
/**
|
||||
* Returns the format of a track.
|
||||
*
|
||||
* @param rendererIndex The index of the renderer.
|
||||
* @param trackIndex The index of the track.
|
||||
* @return The format of the track.
|
||||
*/
|
||||
public MediaFormat getTrackFormat(int rendererIndex, int trackIndex);
|
||||
|
||||
/**
|
||||
* Selects a track for the specified renderer.
|
||||
*
|
||||
* @param rendererIndex The index of the renderer.
|
||||
* @param trackIndex The index of the track. A negative value or a value greater than or equal to
|
||||
* the renderer's track count will disable the renderer.
|
||||
*/
|
||||
public void setSelectedTrack(int rendererIndex, int trackIndex);
|
||||
|
||||
/**
|
||||
* Returns the index of the currently selected track for the specified renderer.
|
||||
*
|
||||
* @param rendererIndex The index of the renderer.
|
||||
* @return The selected track. A negative value or a value greater than or equal to the renderer's
|
||||
* track count indicates that the renderer is disabled.
|
||||
*/
|
||||
public int getSelectedTrack(int rendererIndex);
|
||||
|
||||
/**
|
||||
* Sets whether playback should proceed when {@link #getPlaybackState()} == {@link #STATE_READY}.
|
||||
* If the player is already in this state, then this method can be used to pause and resume
|
||||
* playback.
|
||||
*
|
||||
* @param playWhenReady Whether playback should proceed when ready.
|
||||
*/
|
||||
public void setPlayWhenReady(boolean playWhenReady);
|
||||
|
||||
/**
|
||||
* Whether playback will proceed when {@link #getPlaybackState()} == {@link #STATE_READY}.
|
||||
*
|
||||
* @return Whether playback will proceed when ready.
|
||||
*/
|
||||
public boolean getPlayWhenReady();
|
||||
|
||||
/**
|
||||
* Whether the current value of {@link ExoPlayer#getPlayWhenReady()} has been reflected by the
|
||||
* internal playback thread.
|
||||
*
|
||||
* @return True if the current value has been reflected. False otherwise.
|
||||
*/
|
||||
public boolean isPlayWhenReadyCommitted();
|
||||
|
||||
/**
|
||||
* Seeks to a position specified in milliseconds.
|
||||
*
|
||||
* @param positionMs The seek position.
|
||||
*/
|
||||
public void seekTo(long positionMs);
|
||||
|
||||
/**
|
||||
* Stops playback. Use {@code setPlayWhenReady(false)} rather than this method if the intention
|
||||
* is to pause playback.
|
||||
* <p>
|
||||
* Calling this method will cause the playback state to transition to
|
||||
* {@link ExoPlayer#STATE_IDLE}. The player instance can still be used, and
|
||||
* {@link ExoPlayer#release()} must still be called on the player if it's no longer required.
|
||||
* <p>
|
||||
* Calling this method does not reset the playback position. If this player instance will be used
|
||||
* to play another video from its start, then {@code seekTo(0)} should be called after stopping
|
||||
* the player and before preparing it for the next video.
|
||||
*/
|
||||
public void stop();
|
||||
|
||||
/**
|
||||
* Releases the player. This method must be called when the player is no longer required.
|
||||
* <p>
|
||||
* The player must not be used after calling this method.
|
||||
*/
|
||||
public void release();
|
||||
|
||||
/**
|
||||
* Sends a message to a specified component. The message is delivered to the component on the
|
||||
* playback thread. If the component throws a {@link ExoPlaybackException}, then it is
|
||||
* propagated out of the player as an error.
|
||||
*
|
||||
* @param target The target to which the message should be delivered.
|
||||
* @param messageType An integer that can be used to identify the type of the message.
|
||||
* @param message The message object.
|
||||
*/
|
||||
public void sendMessage(ExoPlayerComponent target, int messageType, Object message);
|
||||
|
||||
/**
|
||||
* Blocking variant of {@link #sendMessage(ExoPlayerComponent, int, Object)} that does not return
|
||||
* until after the message has been delivered.
|
||||
*
|
||||
* @param target The target to which the message should be delivered.
|
||||
* @param messageType An integer that can be used to identify the type of the message.
|
||||
* @param message The message object.
|
||||
*/
|
||||
public void blockingSendMessage(ExoPlayerComponent target, int messageType, Object message);
|
||||
|
||||
/**
|
||||
* Gets the duration of the track in milliseconds.
|
||||
*
|
||||
* @return The duration of the track in milliseconds, or {@link ExoPlayer#UNKNOWN_TIME} if the
|
||||
* duration is not known.
|
||||
*/
|
||||
public long getDuration();
|
||||
|
||||
/**
|
||||
* Gets the current playback position in milliseconds.
|
||||
*
|
||||
* @return The current playback position in milliseconds.
|
||||
*/
|
||||
public long getCurrentPosition();
|
||||
|
||||
/**
|
||||
* Gets an estimate of the absolute position in milliseconds up to which data is buffered.
|
||||
*
|
||||
* @return An estimate of the absolute position in milliseconds up to which data is buffered,
|
||||
* or {@link ExoPlayer#UNKNOWN_TIME} if no estimate is available.
|
||||
*/
|
||||
public long getBufferedPosition();
|
||||
|
||||
/**
|
||||
* Gets an estimate of the percentage into the media up to which data is buffered.
|
||||
*
|
||||
* @return An estimate of the percentage into the media up to which data is buffered. 0 if the
|
||||
* duration of the media is not known or if no estimate is available.
|
||||
*/
|
||||
public int getBufferedPercentage();
|
||||
|
||||
}
|
||||
@@ -1,230 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.b44t.messenger.exoplayer;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
/**
|
||||
* Concrete implementation of {@link ExoPlayer}.
|
||||
*/
|
||||
/* package */ final class ExoPlayerImpl implements ExoPlayer {
|
||||
|
||||
private static final String TAG = "ExoPlayerImpl";
|
||||
|
||||
private final Handler eventHandler;
|
||||
private final ExoPlayerImplInternal internalPlayer;
|
||||
private final CopyOnWriteArraySet<Listener> listeners;
|
||||
private final MediaFormat[][] trackFormats;
|
||||
private final int[] selectedTrackIndices;
|
||||
|
||||
private boolean playWhenReady;
|
||||
private int playbackState;
|
||||
private int pendingPlayWhenReadyAcks;
|
||||
|
||||
/**
|
||||
* Constructs an instance. Must be invoked from a thread that has an associated {@link Looper}.
|
||||
*
|
||||
* @param rendererCount The number of {@link TrackRenderer}s that will be passed to
|
||||
* {@link #prepare(TrackRenderer[])}.
|
||||
* @param minBufferMs A minimum duration of data that must be buffered for playback to start
|
||||
* or resume following a user action such as a seek.
|
||||
* @param minRebufferMs A minimum duration of data that must be buffered for playback to resume
|
||||
* after a player invoked rebuffer (i.e. a rebuffer that occurs due to buffer depletion, and
|
||||
* not due to a user action such as starting playback or seeking).
|
||||
*/
|
||||
@SuppressLint("HandlerLeak")
|
||||
public ExoPlayerImpl(int rendererCount, int minBufferMs, int minRebufferMs) {
|
||||
Log.i(TAG, "Init " + ExoPlayerLibraryInfo.VERSION);
|
||||
this.playWhenReady = false;
|
||||
this.playbackState = STATE_IDLE;
|
||||
this.listeners = new CopyOnWriteArraySet<>();
|
||||
this.trackFormats = new MediaFormat[rendererCount][];
|
||||
this.selectedTrackIndices = new int[rendererCount];
|
||||
eventHandler = new Handler() {
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
ExoPlayerImpl.this.handleEvent(msg);
|
||||
}
|
||||
};
|
||||
internalPlayer = new ExoPlayerImplInternal(eventHandler, playWhenReady, selectedTrackIndices,
|
||||
minBufferMs, minRebufferMs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Looper getPlaybackLooper() {
|
||||
return internalPlayer.getPlaybackLooper();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addListener(Listener listener) {
|
||||
listeners.add(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeListener(Listener listener) {
|
||||
listeners.remove(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPlaybackState() {
|
||||
return playbackState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepare(TrackRenderer... renderers) {
|
||||
Arrays.fill(trackFormats, null);
|
||||
internalPlayer.prepare(renderers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTrackCount(int rendererIndex) {
|
||||
return trackFormats[rendererIndex] != null ? trackFormats[rendererIndex].length : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MediaFormat getTrackFormat(int rendererIndex, int trackIndex) {
|
||||
return trackFormats[rendererIndex][trackIndex];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelectedTrack(int rendererIndex, int trackIndex) {
|
||||
if (selectedTrackIndices[rendererIndex] != trackIndex) {
|
||||
selectedTrackIndices[rendererIndex] = trackIndex;
|
||||
internalPlayer.setRendererSelectedTrack(rendererIndex, trackIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSelectedTrack(int rendererIndex) {
|
||||
return selectedTrackIndices[rendererIndex];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayWhenReady(boolean playWhenReady) {
|
||||
if (this.playWhenReady != playWhenReady) {
|
||||
this.playWhenReady = playWhenReady;
|
||||
pendingPlayWhenReadyAcks++;
|
||||
internalPlayer.setPlayWhenReady(playWhenReady);
|
||||
for (Listener listener : listeners) {
|
||||
listener.onPlayerStateChanged(playWhenReady, playbackState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getPlayWhenReady() {
|
||||
return playWhenReady;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPlayWhenReadyCommitted() {
|
||||
return pendingPlayWhenReadyAcks == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void seekTo(long positionMs) {
|
||||
internalPlayer.seekTo(positionMs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
internalPlayer.stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void release() {
|
||||
internalPlayer.release();
|
||||
eventHandler.removeCallbacksAndMessages(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(ExoPlayerComponent target, int messageType, Object message) {
|
||||
internalPlayer.sendMessage(target, messageType, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void blockingSendMessage(ExoPlayerComponent target, int messageType, Object message) {
|
||||
internalPlayer.blockingSendMessage(target, messageType, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getDuration() {
|
||||
return internalPlayer.getDuration();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getCurrentPosition() {
|
||||
return internalPlayer.getCurrentPosition();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getBufferedPosition() {
|
||||
return internalPlayer.getBufferedPosition();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBufferedPercentage() {
|
||||
long bufferedPosition = getBufferedPosition();
|
||||
long duration = getDuration();
|
||||
return bufferedPosition == ExoPlayer.UNKNOWN_TIME || duration == ExoPlayer.UNKNOWN_TIME ? 0
|
||||
: (int) (duration == 0 ? 100 : (bufferedPosition * 100) / duration);
|
||||
}
|
||||
|
||||
// Not private so it can be called from an inner class without going through a thunk method.
|
||||
/* package */ void handleEvent(Message msg) {
|
||||
switch (msg.what) {
|
||||
case ExoPlayerImplInternal.MSG_PREPARED: {
|
||||
System.arraycopy(msg.obj, 0, trackFormats, 0, trackFormats.length);
|
||||
playbackState = msg.arg1;
|
||||
for (Listener listener : listeners) {
|
||||
listener.onPlayerStateChanged(playWhenReady, playbackState);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ExoPlayerImplInternal.MSG_STATE_CHANGED: {
|
||||
playbackState = msg.arg1;
|
||||
for (Listener listener : listeners) {
|
||||
listener.onPlayerStateChanged(playWhenReady, playbackState);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ExoPlayerImplInternal.MSG_SET_PLAY_WHEN_READY_ACK: {
|
||||
pendingPlayWhenReadyAcks--;
|
||||
if (pendingPlayWhenReadyAcks == 0) {
|
||||
for (Listener listener : listeners) {
|
||||
listener.onPlayWhenReadyCommitted();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ExoPlayerImplInternal.MSG_ERROR: {
|
||||
ExoPlaybackException exception = (ExoPlaybackException) msg.obj;
|
||||
for (Listener listener : listeners) {
|
||||
listener.onPlayerError(exception);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user