Android Tutorial [B4X] [B4XPages] Pleroma / Mastodon Client

Roughly speaking, Mastodon is an open source, distributed, social network a bit similar to Twitter:

Pleroma is a lightweight implementation of Mastodon with some extensions: https://blog.soykaf.com/post/what-is-pleroma/

i_view64_FAQWSjENvw.png


I'm building an open source client for Pleroma / Mastodon. It will be a good demonstration of B4X features. There are already several products that came out of this project, including B4XPages framework, which is one of the most important features added to B4X.

The focus is on the mobile clients. The B4J client is very useful for development.



It is based on B4XPages and all of the code is shared between the three platforms.
Most of the code is based on components that can be reused in other apps.

Features:
  • The rich text content is displayed using BCTextEngine + BBListItem. BBListItem is based on BBCodeView, without the ScrollView and built for lazy loading where only the visible lines are drawn.
  • The text is drawn asynchronously (in the background).
  • The list itself is a xCLV.
  • Items are loaded when needed and the layouts are reused.
  • A lot of work was done related to images. Loading hundreds of images from the internet with no control on their size is a challenging task.
    • Images usage is carefully tracked.
    • Unused images are removed from the cache and are recycled in B4A.
    • Images are loaded asynchronously in B4A and B4i.
    • Images are downsampled if larger than the maximum allowed size.
  • The html from the feed is parsed using MiniHtmlParser class. The output is a tree of nodes. The tree is then converted to BBCode (only a few tags are supported).
  • Supports images, animated gifs and videos. Video playback is only implemented in B4A and B4i.
Classes:
  • ListOfStatus - A class that manages a list of statuses. Does many things including: managing the feed reader, the status views, the visibility of all elements and the zoomable image view. Note that the list can appear inside a dialog and in the main page.
  • B4XMainPage - Main page.
  • ImagesCache - Manages the images, including downloading from the internet, managing a cache and updating the reference counters.
  • BitmapsAsync - Class that loads images asynchronously (in B4A and B4i). This is now implemented as a library.
  • StatusView - The status custom view.
  • BBListItem - A modified version of BBCodeView, mainly without the built-in ScrollView which is not needed here.
  • MiniHtmlParser - Html parser. Implemented as a library.
  • TextUtils - Converts the parsed html data to BBCode.
  • PleromaFeed - Downloads and parses the Pleroma / Mastodon feeds.
  • ViewsCache - Manages the video players
  • RequestsManager - Cross platform class that can be used to cancel currently running HttpJob requests.
  • OAuth - Implements the authentication.
  • DrawerManager - Manages the left drawer.
  • AccountView - Shows the account item. Can appear inside the list or in a dialog.
  • StubView - A simple view that can be added to the statuses list (currently only used to show the "no more items" item but can be extended).
  • StackManager - Manages the stack of timelines. Used for the implementation of the back feature and more.
  • HtmlToRuns - Converts the parsed html tree to text runs for BCTextEngine.
This project depends on several recent libraries. To make things simpler, the cross platform libraries are attached.
You will also need to download other resources as explained in these links:

- B4XGifView v1.11+: https://www.b4x.com/android/forum/threads/b4x-b4xgifview-cross-platform-animated-gif-view.118550/
- (B4A) ExoPlayer v1.42+: https://www.b4x.com/android/forum/threads/exoplayer-mediaplayer-videoview-alternative.72652/#content
- WebP: https://www.b4x.com/android/forum/threads/b4x-webp-images.119990/#post-750224
- KSCrash (B4i - if using local builder): https://www.b4x.com/android/forum/t...erful-crash-reports-framework.120644/#content


The performance is very good. Better than several other clients I've tested. Make sure to test performance in release mode.

Compiled APK: www.b4x.com/android/files/Pleroma.apk

Warning: Some of the content is for adults only. Don't download if under 18 or are offended from such images. This is a distributed, open source network which means that the content is not moderated.
Don't post any image in the forum that is not appropriate for kids.


Source code: https://github.com/AnywhereSoftware/B4X-Pleroma
 
Last edited:

Erel

Administrator
Staff member
Licensed User
V1.07 released:
  • Timelines stack. Currently only tags are handled internally.
  • Account dialog displayed when clicking on an avatar.
  • WebView dialog displayed when clicking on an external link (@users will also show in this dialog until implemented properly).
  • Back button.
  • Crash reports in B4i.
  • Many more small improvements.

1596039134416.png
 

AnandGupta

Well-Known Member
Licensed User
For now it only does one thing, it shows the public feed. Some of the media types ,such as videos, are still not supported.
I think, this should be Some of the media types ,such as videos, are still not supported.

This is becoming one of the best example to study for B4XPages and Cross Platform, not to mention download from net and lazy loading 👍

Regards,

Anand
 

Erel

Administrator
Staff member
Licensed User
v1.08

1596723687338.png


Many improvements including:
  • Support for users and mentioned users links.
  • The "account view" is displayed in a dialog when the avatar is clicked and as the first message when the user link is clicked.
  • URLs are underlined when the user touches them (remember that there is no WebView here).
  • Round avatars. Based on: https://www.b4x.com/android/forum/threads/b4x-round-clipping-panel.120961/#post-756162
  • Custom emojies - inline images. This is done with BCTextEngine views feature.
  • Outline for images placeholders.
 

Erel

Administrator
Staff member
Licensed User
v1.09

1597238753231.png


1597238772281.png


  • The parsed html is converted to text runs directly. Previously the html was first converted to BBCode. This improves the performance and also allows more customization.
  • The left drawer shows the navigation history.
  • Clicking on "reply to" or on the time label opens the thread view in a dialog.
  • Jpeg orientation attribute is respected (relevant to B4A).
  • Many small improvements and bug fixes.
Source code is now on github: https://github.com/AnywhereSoftware/B4X-Pleroma
 

Erel

Administrator
Staff member
Licensed User
The best way to describe this app is with "turtles all the way down":

1597241022990.png


The remote feed is downloaded with OkHttpUtils2.
It is parsed with MiniHtmlParser.
The parsed html is converted to text runs with HtmlToRuns class.
The text runs are sent to BCTextEngine which first makes all its measurements and prepares the rich text to be drawn.
When the item becomes visible, the text is drawn with BitmapCreator (this is done internally in BCTextEngine).
BitmapCreator makes drawings by mutating an internal buffer of bytes. You cannot go much lower than this :)
 

AnandGupta

Well-Known Member
Licensed User
Downloaded latest from Github.
Got error log, in opening
B4XMainPage - 107: Cannot access private member: extrawidth

I checked and I have B4XDrawer 1.53.

Commenting the line, works Ok. So, may be we need new B4XDrawer version where it is not private.

Regards,

Anand
 

asales

Well-Known Member
Licensed User
If it crashes then post the logs.
B4X:
*** Service (starter) Create ***
** Service (starter) Start **
** Activity (main) Create, isFirst = true **
Version:1.10
** Activity (main) Resume **
*** Service (httputils2service) Create ***
** Service (httputils2service) Start **
textutils_parsestatus (java line: 809)
java.lang.RuntimeException: Cannot parse: null as boolean
    at anywheresoftware.b4a.BA.parseBoolean(BA.java:629)
    at anywheresoftware.b4a.BA.ObjectToBoolean(BA.java:699)
    at b4a.pleroma.textutils._parsestatus(textutils.java:809)
    at b4a.pleroma.pleromafeed._fillstatuses(pleromafeed.java:548)
    at b4a.pleroma.pleromafeed._parsetimelines(pleromafeed.java:647)
    at b4a.pleroma.pleromafeed$ResumableSub_DownloadTimelines.resume(pleromafeed.java:434)
    at anywheresoftware.b4a.BA.checkAndRunWaitForEvent(BA.java:267)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:207)
    at anywheresoftware.b4a.keywords.Common$11.run(Common.java:1178)
    at android.os.Handler.handleCallback(Handler.java:751)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:154)
    at android.app.ActivityThread.main(ActivityThread.java:6123)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:757)
Moto G4 - Android 7.0
 

Johan Hormaza

Well-Known Member
Licensed User
Now I have this problem on Android. What will it be?
--------- beginning of crash
--------- beginning of system
--------- beginning of main
*** Service (starter) Create ***
** Service (starter) Start **
** Activity (main) Create, isFirst = true **
Version:1.10
** Activity (main) Resume **
*** Service (httputils2service) Create ***
** Service (httputils2service) Start **
textutils_parsestatus (java line: 809)
java.lang.RuntimeException: Cannot parse: null as boolean
at anywheresoftware.b4a.BA.parseBoolean(BA.java:629)
at anywheresoftware.b4a.BA.ObjectToBoolean(BA.java:699)
at b4a.pleroma.textutils._parsestatus(textutils.java:809)
at b4a.pleroma.pleromafeed._fillstatuses(pleromafeed.java:548)
at b4a.pleroma.pleromafeed._parsetimelines(pleromafeed.java:647)
at b4a.pleroma.pleromafeed$ResumableSub_DownloadTimelines.resume(pleromafeed.java:434)
at anywheresoftware.b4a.BA.checkAndRunWaitForEvent(BA.java:267)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:207)
at anywheresoftware.b4a.keywords.Common$11.run(Common.java:1178)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:201)
at android.app.ActivityThread.main(ActivityThread.java:6864)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:873)
 

asales

Well-Known Member
Licensed User
Anyway, I've released v1.11. Can you try it and see if it fixes the issue?
Works fine. No crash.

Did it happen immediately when you opened the app?
In the previous version (1.10) I see the first screen with the "Made with ♥ in B4X" and the crash happens after this.
If I disable the internet connection, I see the first screen, but there is no crash (and course not load the feed).
 
Top