[APP][DEV][16/10-1.0][29/11-2.0-BETA] BuildBox [Rom-Kitchen/Ota][4.0+] - Android Apps and Games

BuildBox
The main intend of this application is to provide an easy to use, but powerful way to serve updates and addons for developers to their users, but it doesn't stop there, it also can be used by the user itself as batch flashing tool for files on the internal or external sd (openrecoveryscript supporting recovery and root are prerequisite).
But please keep in mind, this is still beta stage, so far all is stable, but the code itself needs refactoring still and some additional features i want to add are still missing, also the included images are far from being great.
Why i built this?
Most of the current alternatives public available seemed not as powerful as they could be, because of the fact that they are closed source i started to build something similar myself from scratch.
What does it serve?
Tabbed UI
Nested lists within the tabs (in theory infinite levels of nesting [but for usability i wouldn't recommend more than 5 steps])
Detail views with many optional fields, like description, changelog, developers, images,...
Completely remotly configured content using json
Optional Md5 verfification
Download queue
Changelist of added, removed, updated & downgraded items
Sorting of download queue by drag & drop
Concurrent downloads to achieve full use of bandwidth (configurable amount)
Backup and restore of download queues
Support of every host with direct link capabilities
Support of hosts with up to 5 redirects (note: still direct link redirects, download webpages don't get handled)
Internal retry or resume (if supported by the server) functionality to avoid broken downloads because of unstable connections (up to 5 retries)
Direct install of apks
"External" link handling
Direct flash capabilities (if an openrecoveryscript supporting recovery is installed)
Adding of zips from storage to the queue
Backup/wipe options before flashing
Queue filter to only flash Successful/Done (Successful=downloaded+md5sum correct, Done=donwloaded+no md5sum provided) downloads (md5mismatches can optional be taken in as well)
OTA updates
Configurable interval for update check
Update version filter to avoid multiple notifications per version
New version check on startup
Image recycling and scaling (if an image is used more than once [identified by it's url], it will be downloaded only once and simply reused, also it will be scaled to the fitting size of the view to take as less bandwidth and ram as possible)
more to come...
Why json and not xml?
Xml is pretty good for local configuration, but json is the way to go when it comes to remote content.
It is highly mutable, lightweight and easy to use. Also the possibility for typos and errors is much less than with xml, because simple brackets and key value pairs are used instead of tags.
Last but not least, json files are about half of the sice of xml files if the same content is provided and the possible use of a webservice to provide it is pretty simple.
How to use as rom developer?
The application uses build.prop properties to configure rom update url, content url, rom version and default download directoy.
For update and content url there are also string resources present (to be able to publish the app to the play store to provide the rom itself with it e.g.).
All of this properties are optional (if they are not provided default values are taken).
Build.prop sample
Code:
buildbox.downloaddir=/storage/sdcard0/TestRom
buildbox.version=1.0.3c1
buildbox.updateurl=http://www.test.com/Rom.json
buildbox.contenturl=http://www.test.com/Content.json
Common content description
At the content json all root items will be shown as tabs, everything inside them are listitems.
Every item containing another list of items must contain the "children" property.
Every item containing a detail item must contain the "detail" property instead.
Key Value pair description
Common properties:
Code:
"title": "some value" -> this is the title of the chapter/listitem/detailitem (depends on the item type) (if the detailview doesn't contain a title property it will be taken from it's parent)
"device": "GT-I9300" -> this value is used to filter content which is only available for specific devices, it is compared with the ro.product.model build.prop property (because it is almost untouched by moders)
"thumbnailurl": "some url" -> this is the thumbnail shown at a listitem, it will be loaded asynchronous
"children": [ { some child items } ] -> this property is used to identify that this item contains another list
"detail" : { some detail properties } -> this property is used to identify this item as last item before a detail view is shown
Additional detail properties:
Code:
"version": "some version" -> sets the version (must not be inside the detail item, can also be inside his parent)
"description": "some text" -> sets the description (basic html notation can be used for formating)
"type": "zip" -> possible values are zip, apk, web, other, this will override the basic behaviour of parsing the mime type and will directly threaten it as the provided type [if external is used and the url property is given the url property will be taken for opening instead of the first webpages link])
"md5": "a md5sum" -> sets the md5sum of the package (only used for download verification if provided)
"url": "some url" -> the url where the item can be downloaded from
"webpages": [ "some url",
"some other url",
....
] -> if no url provided the first item of this array will be taken as external link, but in common provided as hyperlinks on the detail view to support pages
"images": [ "some url",
"some other url",
....
] -> used to show screenshots,... within the detail view (also loaded asynchronous)
"changelog": [ "a change",
"another change",
......
] -> to show a changelog, also supports html notation
"developers": [ { "some developer name": "" },
{ "another developer name": "some donation or profile page" },
......
] -> used to show the realted developers, if a donation or profile url is given the name will be shown as hyperlink, if it's empty as plain text
Server File Samples
Content.json:
Code:
[{
"title":"Apps",
"device":"GT-I9300", [B]//optional, compared with the ro.product.model build.prop property, to shows items for specific devices only (can be put at every level inside the nesting of an item, except inside a detail item)[/B]
"thumbnailurl":"http://ms-team-hd.tectas.eu/images/Apps.png",
"children": [
{"title":"4.2 Camera/Gallery",
"detail":
{"description":"Aosp Camera from android 4.2 with sphere photo feature",
"url":"http://ms-team-hd.tectas.eu/download.php?file=Addons/Apps/4.2Camera_App.zip",
"md5":"10cfc3983156d42a9dbafe7bc8265257"
}
},
{"title":"4.2 Clock",
"detail": {
"url":"http://ms-team-hd.tectas.eu/download.php?file=Addons/Apps/4.2-Clock_App.zip",
"md5":"8334f1ed2ec79efbe4199a86fda7ee58"
}
},
{"title":"4.2 Keyboard",
"detail": {
"url":"http://ms-team-hd.tectas.eu/download.php?file=Addons/Apps/4.2Keyboard_App.zip",
"md5":"de0d134795217b21ccbeb0f1b7dd3cdd"
}
}
]
},{
"title":"Bloat",
"thumbnailurl":"http://ms-team-hd.tectas.eu/images/Bloat.png",
"children": [
{"title":"Calculator",
"detail":
{"webpages": [
"http://ms-team-hd.tectas.eu/download.php?file=Addons/Bloat/Calculator_App.zip"
],
"md5":"6adbc0077f7aac1f25ed584cff5c4d0e"
}
},
{"title":"SPlanner",
"detail": {
"url":"http://ms-team-hd.tectas.eu/download.php?file=Addons/Bloat/SPlanner_App.zip",
"md5":"2949654d704a59cdbd17b7227b825d37"
}
}
]
},{
"title":"Themes",
"thumbnailurl":"http://ms-team-hd.tectas.eu/images/Themes.png",
"children": [{
"title":"Battery Mods",
"thumbnailurl":"http://ms-team-hd.tectas.eu/images/Battery.png",
"children": [
{"title":"Blue Battery",
"thumbnailurl":"http://ms-team-hd.tectas.eu/Addons/Battery/Images/BlueBattery.png",
"detail":
{"description":"Stock battery icon in blue made by raubkatze",
"url":"http://ms-team-hd.tectas.eu/download.php?file=Addons/Battery/BlueBattery_Mod.zip",
"md5":"f1bc5f90dc284df34fb0c8d2d9044330"
}
},
{"title":"Blue Battery Percentage",
"thumbnailurl":"http://ms-team-hd.tectas.eu/Addons/Battery/Images/BlueBatteryPercentage.png",
"detail": {
"description":"Stock battery icon in blue with percentage made by thisiskindacrap",
"url":"http://ms-team-hd.tectas.eu/download.php?file=Addons/Battery/BlueBatteryPercentage_Mod.zip"
}
},
{"title":"Blue Battery Circle",
"thumbnailurl":"http://ms-team-hd.tectas.eu/Addons/Battery/Images/BlueCircle.png",
"detail": {
"description":"Blue circle battericon with percentage in the center made by raubkatze",
"url":"http://ms-team-hd.tectas.eu/download.php?file=Addons/Battery/BlueCircle_Mod.apk", //apk extension will be read and the install dialog will pop up
"md5":"c43c2734846ced3db5ed5987d5647bae"
}
}
]
},{
"title":"Framework Themes",
"thumbnailurl":"http://ms-team-hd.tectas.eu/images/Apps.png",
"children": [{
"title":"Elegant Theme",
"detail": {
"describtion":"Eye-Candy Theme by ThilinaC",
"url":"https://docs.google.com/uc?export=download&confirm=no_antivirus&id=0B8AYcerB14i3YVBmTEM4b0tzOVU",
"md5":"5e0d5a4578f01cfa8b357e79193f070b"
}
},{
"title":"MS Team Blackbean Theme",
"detail": {
"description":"Black and white theme made by alvin551",
"url":"https://docs.google.com/uc?export=download&confirm=no_antivirus&id=0B8AYcerB14i3VmUwWTVKdWZ6UWM",
"md5":"93442e1fb4197e554ebdb1c8ff9c52a1"
}
},{
"title":"MS Team HD Theme",
"detail": {
"description":"Holo style theme. The theme is not originally created by MS Team HD, it uses parts of many other themes. All credits to the creators of the themes this is based on.",
"url":"http://ms-team-hd.tectas.eu/download.php?file=Addons/Themes/MS-Team-HD_Theme.zip",
"md5":"15eec7c80db7acbaccd939f827d806e9"
}
}
]
},{
"title":"Multiwondow Themes",
"children": [{
"title":"Multiwindow Blackbean",
"detail": {
"description":"Multiwindow theme made by alvin551",
"url":"http://ms-team-hd.tectas.eu/download.php?file=Addons/Themes/Flashbar-BlackBean_Mod.zip",
"md5":"4be1c0da1d77121de9627dd2570fee00"
}
},{
"title":"Multiwindow Black Glass",
"detail": {
"url":"http://ms-team-hd.tectas.eu/download.php?file=Addons/Themes/Flashbar-Glass-Black_Mod.zip",
"md5":"b8befba0558fdd954c8c73563761565c"
}
},{
"title":"Multiwindow Blue Glass",
"detail": {
"url":"http://ms-team-hd.tectas.eu/download.php?file=Addons/Themes/Flashbar-Glass-Blue_Mod.zip",
"md5":"d98c0cd04fc3240b372a78911a09c865"
}
}
]
}
]
}
]
Rom.json (which contains basically nothing less than a detailitem, means all optional properties used here can also be used at detail items within the Content.json):
Code:
{
"title": "MS Team HD", [B]//optional if parent item is present[/B]
"version": "9.0.1", [B]//optional[/B]
"description": "test", [B]//optional[/B]
"type": "zip", [B]//optional[/B]
"md5": "75a3a73d3ac941cc83f90dd80d000477", [B]//optional[/B]
"url": "http://ms-team-hd.tectas.eu/download.php?file=Rom/MS-Team-HD_9.0.1_XXEMA2.7z", [B]//optional[/B]
"webpages" : [
"http://forum.xda-developers.com/showthread.php?t=1886332",
"http://ms-team-hd.tectas.eu"
], [B]//optional[/B]
"images": [
"http://ms-team-hd.tectas.eu/Winscp-Screenshot.png"
], [B] //optional[/B]
"changelog": [
"change1",
"change2"
], [B]//optional[/B]
"developers": [
{ "tester": "" },
{ "tester2": "http://test" }
] [B]//optional[/B]
}
NOTE: if you simply want to take and alter this examples, remove the comments (everthing starting with //) they are not supported within json.
Is it open source?
Yes, the java packges are licensed under lgpl, which means they can be integrated within every other application without publishing the source, only if the code inside the packages themself is altered the code has to be published. I have chosen this approach in the open sense of android, everyone is allowed to fork/clone my github repository and do whatever he likes with the code, i just want possible fixes or enhancements to be public available for everyone (also fell free to send me pull requests if you like), that's at least my view of what open source means, all should work together to make the best out of something, if they like to, otherwise, take what is already served or find someone able to do the needed changes.
Wait, two repositories? Why the hell...
Well, it's pretty simple, the library part already includes everything which is needed to get the work done, except of one thing, the main activity. It "only" includes an generic abstract activity which serves the fitting implementations to get it's job done without taking into account how the main activity is build up (be it tabed, with lists or whatever). To make your own UI set up on this activity it serves abstract methods you have to implement to handle e.g. viewing the download queue, updating it while downloading,...
But that's as well only a nice to have and should give you more possibilities if you want to use them, if your fine with the tabed UI I built, simply take the application repository, override the resources you like (if you want to) and your already done. I also splitted it up for easier maintenance, the library part is generic and if something needs to be done another way you're able to by simply deriving from the given interfaces or classes itself within your application, the application itself is always specific (even when the differences can be close to none), so i would have to integrate the changes of the library part allover again to the different branches, if it would be included in one single repository, that way all is detached and much easier to maintain.
Common Information
The source itself can be found here (Application), here (library) and here (gradle base for android studio), feel free to send me pull requests
The generic apk is also available at the play store (NOTE: don't flash files from it unless you use a GT-I9300, also note the broken downloads are intended to show the different states).
Changelog
The full list of commits can be viewed here (application) and here (library)
1.0:
Changelist support (listing of updated, added, removed and downgraded packages at startup)
no additional file or work needed, except the present version property at items which should be able to show as downgraded or updated, everything else is done by the app itself
0.9.7.1:
Fixed Index out of bounds crash
Fixed 2 nullpointer crashes
Started to add changelist of content support (changelist of added or removed items from the remoterepository)
0.9.7:
Improved install logic
Improved build.prop property reading
Fixed wrong finished state at service while downloads still processing
0.9.6:
Fixed showing of restore menu item directly after backup;
Fixed caching/loading of download queue onStop/onRestart;
Fixed removing of cached queue onDestroy;
Fixed crash at add file dialog if it is closed before choosing an activity;
Fixed wrong "all finished respond" of service while still processing;
0.9.5:
Completely revised the structure of buildbox (is now splitted into 2 repositories, one for the library [includes the whole logic, main views,...] and one for the implementation of the main activity and for resource overriding [MainActivity, TabAdapter, ...)
Added device filter property (can be applied at every level except at the detail items) (uses the ro.product.model build.prop property for comparsion)
Many fixes and enhancements
0.9.3:
Fixed adding files from storage
Fixed crash at startup without internet connection available
0.9.2:
Apk handling fix
Recovery script fix
0.9.1:
Revised Install procedure for apks (thx to lowveld for the hint)
Fixed root shell command execution (sry)
small additional changes
​
XDA:DevDB Information
BuildBox, a App for the No Device
Contributors
Tectas, http://forum.xda-developers.com/member.php?u=4189659
Version Information
Status: Stable
Current Stable Version: 1.0
Stable Release Date: 2013-10-17
Current Beta Version: 2.0
Beta Release Date: 2013-11-29
Created 2013-11-26
Last Updated 2013-11-29

Reserved
Beta Changelog (To get automatic updates of the beta via play store, join the BuildBox Community and use the opt-in link)
The full list of commits of the test branch can be viewed here (application/2.0-dev branch) and here (library/2.0-dev branch)
2.0:
OnDemand loding of json items (means not the full list must be provided as one file, it can contain urls to other json files which get loaded on demand)
complete overhaul of UI - dropped tabs, g+ dropdown instead, sidebar not present yet, but in the lane already

Hello.!
i m due to make a rom next month, was thinking where to start, guess u solved the problem

anu.cool said:
Hello.!
i m due to make a rom next month, was thinking where to start, guess u solved the problem
Click to expand...
Click to collapse
Happy i could help you decide^^
If you have any thoughts for enhancement, just tell

Beta Added
Like said, 2.0 is BETA, it's not properly working yet (backstack doesn't work completely yet) and not everything is present what should yet (sidebar), the basic features from 1.0 are still functional though.
Beta Changelog
The full list of commits can be viewed here (application) and here (library)
2.0:
OnDemand loding of json items (means not the full list must be provided as one file/webserviceresponse, it can contain urls to other json files which get loaded on demand)
complete overhaul of UI - dropped tabs, g+ dropdown instead, sidebar not present yet, but in the lane already

New beta is ready to download, backstack is fixed.

Tectas said:
New beta is ready to download, backstack is fixed.
Click to expand...
Click to collapse
How do we get on the beta channel for this app?
Sent from my SGH-I337 using Tapatalk

Sc4ryB3ar said:
How do we get on the beta channel for this app?
Sent from my SGH-I337 using Tapatalk
Click to expand...
Click to collapse
Just switch to the downloads tab, there is the beta download as well.
Gesendet von meinem GT-I9300 mit Tapatalk

BuildBox community added with beta testing over play store opt in.
BuildBox Community

Related

[DEV][LIBRARY][2.0.2] Android Async TaskManager

Android Async TaskManager
AsyncTask is a great tool, allowing one to run background tasks while interacting with the UI before, while and after. However it does come with a few issues, mostly related to the way Android act when a user flips the screen or in other ways creates a detachment of the UI. AsyncTask is not equipped to handle these circumstances.
TaskManager is an extension of AsyncTask which fixes it's issues (Based on an idea of Santiago Lezica) and on top of that, provides additional features.
Source & Documentation
https://github.com/SpazeDog/taskmanager
Features
Makes sure that UI inteaction waits until the UI is pressent
Makes sure that flipping the screen does not produce multiple instances running the same tasks
Adds a new inteaction to AsyncTask onUIReady() and onUIPause() which is invoked whenever the UI is detached and re-attached
Compatible with both native fragments and the support library
Helper methods that makes it easy to use it in both Activities and Fragments
Deviates
Like mentioned above, this is based on the idea of Santiago Lezica whom made a pretty decent example. There was however a few things that bothered me, which made me decide to build my own from scratch.
The tasks should only be handled by the Task class and not be divided between the Task and the Manager. The Managers job should only be to keep track of the UI status and then report to the Tasks whenever this changes. It is then up to the Task what action should be taken depending on the current state.
I was missing the onUIReady() and onUIPause() methods which helps deal with attachment and detachment of the UI from within each individual task. Usefull to handle things like Progress Dialogs.
Using onActivityCreated() and onDetach() in the Manager does not work properly. They execute upon screen flip, but not on application pause and resume, which is also an attachment and detachment of the UI.
It is fine to include the AsyncTask onProgressUpdate() method, but without including publishProgress(), you can't really use it for anything.
The onPreExecute() method should be managed via the pending method like the rest of the methods, otherwise you will end up with a lot of application crashes.
If one should decide to built an application for newer Android versions only, there is no reason to use the support library, so there should be support for both.
I also wanted something that could return the current object. getActivity() is fine when working in an Activity, but this should also be able to run from within fragments. So a getObject() was added.
How it works
Take a look at Santiago's blog
Code:
public class MyActivity extends Activity {
private ProgressDialog mProgressDialog;
@[URL="http://forum.xda-developers.com/member.php?u=439709"]override[/URL]
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
new Task<Context, Void, Boolean>(this, "nameOfMyAsyncLoader") {
@[URL="http://forum.xda-developers.com/member.php?u=439709"]override[/URL]
protected void onUIReady() {
((MyActivity) getObject()).mProgressDialog = ProgressDialog.show( (Activity) getActivityObject(), "", "Loading...");
}
@[URL="http://forum.xda-developers.com/member.php?u=439709"]override[/URL]
protected void doInBackground(Context... params) {
return someMethod( params[0] );
}
@[URL="http://forum.xda-developers.com/member.php?u=439709"]override[/URL]
protected void onPostExecute(Boolean result) {
((MyActivity) getObject()).mProgressDialog.dismiss();
if ( result ) {
...
} else {
...
}
}
}.execute( getApplicationContext() );
}
}
No mater if you execute this from within an Activity, Fragment or the same using the Support Library, you just parse this to the constructor. If you execute it from within a fragment, you need to make sure that you parsed a Tag Name when you added it with FragmentManager. TaskManager does not save instances of the object you parse, it just saves the information needed for it to find it again. With fragments, this means Tag Names. Without it, getObject() will return NULL on Fragments.
Download Pre-built Jar
2.0.2 (2013-06-28) (MD5: 88dbced8ebc4db9dea1b9cf12ab0da40)
[Default Mirror] SourceForge.net

[RHBROMS][Android Test Automation Tool][Tutorials] ROBOTIUM v5.2.1 with Recorder v2.0

{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
Presents
Table of Contents:
1. Robotium
2. What all we need before we get it started?
3. How to setup Robotium using Eclipse ADT with source code of Android Application?
3a. Basic Android Test Project with source code
4. How to setup Robotium using Eclipse ADT without source code of Android Application?
4a. Basic Android Test Project without source code
5. What is JUnit Test Suite and why we need it with Robotium?
6. How to Data-Drive Robotium Scripts?
7. Issues or challenges with Robotium
Please skip to second post If you are reading this post for the first time​
ROBOTIUM 5.2.1 Released​
New Features and bug Fix details:​
unlockScreen() - Unlocks the screen lock.
getCurrentViews(Class<T> classToFilterBy, boolean includeSubclasses) - New parameter includeSubclasses set to true if also subclasses should be returned.
scrollToSide(Side side, float scrollPosition, int stepCount) - Added parameter stepCount to allow for users to decide the speed of the scroll.
scrollViewToSide(View view, Side side, float scrollPosition, int stepCount) - Added parameter stepCount to allow for users to decide the speed of the scroll.
Bugs fixed:
Issue-600 - ViewFetcher, getRecentDecorView fails on Samsung S4 with MultiWindow support
Issue-579 - Screenshots do not get saved
Issue-589 - waitForFragment on vers < 3.0
Issue-615 - ScrollToSide opens the navigation bar
I hope you will enjoy this release!
Link To Download: CLICK HERE
Robotium Recorder 2.0 is released!
From,
Renas Reda
Founder and CEO at Robotium Tech
We're excited to announce the release of Robotium Recorder 2.0. Thanks to all the feedback that we've received, we've been able to make hundreds of improvements since it first launched. It's now compatible with more apps and is optimized to generate even smarter tests than before.
New in Robotium Recorder 2.0:
- Improved click and gesture support.
- Click to Assert™ has been further refined and is now performing optimally in a broad range of apps.
- Record click and drag coordinates by selecting the option in "Settings".
- Full support for GL apps and games by enabling touch and drag coordinates.
- After a test case has been saved it can now be executed directly from Robotium Recorder by clicking "Run Test".
Robotium Recorder 2.0 comes with a new trial period, so even if you have consumed the trial of the old version you are now able to try this new version as well.
To update Robotium Recorder, in Eclipse go to Help --> "Check for updates"
Details on how to install explained in the Old posts below.​
````````````````````````````````````````````````````````````````````````````````````````````````````` ````````````````````````````````````````````````````
OLD POSTS
:victory:ROBOTIUM 5.0.1 Got Released !!! :victory:
Robotium Rec. Latest Update: 1.4.11 (23/01/14)
Robotium Recorder updates are releasing almost daily.. The first update what I got was 1.2.95 and now we have the latest update as 1.4.5 (22/01/14). I will be updating this post as I find new updates...
Click to expand...
Click to collapse
Renas Reda
Founder and maintainer of Robotium
said,
We're happy to announce the release of Robotium 5.0.1! Included in this release is a new Config class, where Robotium Developers can change various things like default timeouts, screenshot location, screenshot type, scrolling, and web element click behaviour.
We’ve been working hard on improving the various click methods by testing numerous popular apps under sub-par performances to add further logic to the click methods and thus reduce click issues. In the last year we’ve gone through the whole code base and improved various areas. This is an update we recommend for everyone using older Robotium versions.
Click to expand...
Click to collapse
The new changes in 5.0.1 are as follows,
NOTE: The package name has been changed to com.robotium.solo. You’ll need to update the import line at the top of your current test classes from com.jayway.android.solo to com.robotium.solo.
New functionality in Robotium 5.0.1:
pressSoftKeyboardNextButton() - Presses the next button on the soft keyboard.
waitForEmptyActivityStack(int timeout) - Waits until the Activity stack is empty.
New Class com.robotium.solo.Solo.Config:
int timeout_large - The timeout length of the waitFor methods. Default length is 20 000 milliseconds.
int timeout_small - The timeout length of the get, is, set, assert, enter and click methods. Default length is 10 000 milliseconds.
String screenshotSavePath - The screenshot save path. Default save path is /sdcard/Robotium-Screenshots/.
ScreenshotFileType screenshotFileType - The screenshot file type, JPEG or PNG. Use ScreenshotFileType.JPEG or ScreenshotFileType.PNG. Default file type is JPEG.
boolean shouldScroll - Set to true if the get, is, set, enter, type and click methods should scroll. Default value is true.
boolean useJavaScriptToClickWebElements - Set to true if JavaScript should be used to click WebElements. Default value is false.
Improvements:
All the click methods. Improved behaviour in unfavorable situations.
The waitForDialogToOpen & waitForDialogToClose methods. Now recognises all dialogs.
The internal View handling class.
TakeScreenshot() now supports GLSurfaceViews with OpenGL ES 3.0.
See the Javadoc for an example on how to use the new Config class.
We hope you will enjoy this release!
https://code.google.com/p/robotium/downloads/list
This will be a Full Tutorial on Robotium Android Automation Tool
I will be updating this thread as I get time. SO NO ETA's.
Click to expand...
Click to collapse
If anybody wants to use / copy this tutorial to their Website or Blog please feel free to contact me at my personal email id: [email protected]
or at our official Website: www.rhbroms.com
Click to expand...
Click to collapse
Please Click on Thanks button if this tutorial by me had helped you for some extent !!!
Click to expand...
Click to collapse
User Guide for Robotium Recorder ( Skip this guide if you are reading this post for the first time and move on with the second post..)
Link to Robotium Official website: Click Here
Prerequisites:
Install Robotium Recorder, if not already installed.
Connect a device (recommended) or start an emulator with external storage.
Start Robotium Recorder
Start Robotium Recorder from the toolbar: Eclipse > New > Other > Android - Robotium Recorder.
Robotium Recorder can also be started by right clicking an existing app or test project and from the opened menu select: Robotium Recorder > New Robotium Test.
Record test cases from a workspace project
From Robotium Recorder it's possible to select either a binary (APK file) or a workspace project to record test cases from. In the screenshot below a workspace project has been selected. Enter a test project name and click "Next".
Record test cases from a binary APK
To record test cases from an APK, click "select apk". A file browser will be opened where the APK can be selected. Robotium Recorder will automatically sign the APK with the local debug certificate.
Once the signing process has finished the "Next" button will be enabled.
Start recording
Clicking Next on the previous screen will show the recording screen.
In the left bottom corner there is Setting menu with three options:
a. Use sleeps - choose if sleeps should be used to playback test cases in the same speed as they were recorded. Can be useful for slower apps like bandwidth intensive or hybrid apps.
b. Keep app data - choose if app data is to be kept when starting a new recording session.
c. Identify class over string - default View identifier is always the resource ID. In the event a resource ID is missing it's possible to choose if a View class identifier is to be used over a string identifier (the text displayed by the View).
Click "New Robotium Test".
If an APK is selected, Robotium Recorder will first install the re-signed APK on the device or emulator.
When installation of the workspace project or APK is done the recording will be started.
The app is executed on the device or emulator and recording of user actions starts.
The recorded steps are shown in the test step table (as seen below)
If a test step is selected in the table the "Delete step" and "Take screenshot" buttons will be enabled.
1. Select any step in the table and click on "Delete step" to delete it.
2. Click "Take screenshot" to add a screenshot step after the selected step.
To stop the recording click "Stop Recording".
To save the test case click "Save", enter a test case name, and click "Ok".
If the test project already exists it will save the test case in that project. Otherwise it will first create the test project and then save the test case. Either start a new recording or close Robotium Recorder by clicking "Finish".
To see the saved test case(s) expand the test project and look in the src folder. The whole test project or a specific test case can be executed by right clicking it and selecting Run As > Android JUnit Test.
​
Credits,
My Parents - For the best support.
@Swaroop Bandagadde - For the best support.
Renas Reda(Founder of Robotium Test Automation Tool) - For liking my tutorial and for the best support.
My Other Works:
1. SELENIUM TEST AUTOMATION TOOL
2. MONKEYRUNNER TEST AUTOMATION TOOL
ROBOTIUM
1. Robotium​
Robotium is an open-source test framework for writing automated Black-box test cases for Android applications (Native/3rd party). With Robotium we can write function, system and acceptance test scenarios.
Robotium can be used both for testing of apps where source code is available and apps where only APK (Android Application Package) file is available and the implementation will be discussed in 4th chapter.
Robotium frame work released under Apache License 2.0. Its founder and main developer is Renas Reda. Latest Version of Robotium is 4.3.1(At the point of writing this book). The home page of Robotium is located under the following URL Robotium Home Page
Robotium extends the Android test framework to make it simpler to write tests. The main class for testing with Robotium is Solo.
Solo is initialized with the instrumentation of the test case and the first activity to test.
2. What all we need before we get it started?
We need the below:
1. Windows 7/8 OS
2. Java 6
3. Eclipse ADT
4. Android device running min android version 2.3.4*
5. Robotium Jar files (Robotium-solo-4.3.1.jar and Robotium-solo-4.3.1-javadoc.jar)
6. POI Jar files
7. Source code of the app to be tested*
*Are not mandatory.​
DOWNLOADS:
SimpleCalc app sourcecode: SimpleCalc
Robotium jar files : file1 and file2
POI jar files: POI.zip
How to setup Robotium using Eclipse ADT with source code of Android Application?
3. How to setup Robotium using Eclipse ADT with source code of Android Application?​
1.Open Eclipse ADT.
2.Import the source code of the application (to be tested) to eclipse.
3.I have given a source code which is written by me for testing purpose, you can find it here. [To import the project go to File ->Import -> select General -> Archive file -> Click on finish button]
4. Remove all the Errors as well as Lint warnings that might be present in the project by right clicking on the project (SimpleCalc) -> properties -> Android Lint Preferences -> Click on Ignore all button.
5. Create new Android Test project (Go to File -> New -> Other.. -> Select Android Test Project and give the project name as SimpleCalc-test). Details shown from the below screen shots:
NOTE: Select the option “An existing Android project” and select SimpleCalc project and click on Next button, this means you are going to test SimpleCalc app which is given by me.
6. Now right click on the empty package file that you get (Project_Name -> src -> Package) and select new Junit test case as show in below screen shot.
7. Now you will see a window where in you have to specify the Name of Junit test case as shown below (give it as TestCase_1):
8. Now you have to create new folder with name Robotium
9. Inside the Robotium folder paste the downloaded Robotium jar files.
10. Now go to Java Build Path by right clicking on the project -> properties and add the Robotium jar file as shown below:
11. Now click on the dropdown list of the Robotium jar file and select javadoc option as shown below:
12. Click on edit button and use the Robotium-solo-4.3.1-javadoc file as shown in the below screen shot:
13. Now go to Order and Export tab and click on select all button as shown below and click ok button:
Basic Android Test Project with Source Code
3a. Basic Android Test Project with Source Code​
1. Now your project will somewhat look like below:
2. Now we have to do some editing work to make this test case work as shown below:
package com.rhb.simplecalc.test;
import com.jayway.android.robotium.solo.Solo;
import com.rhb.simplecalc.MainActivity; // we have to import this class for testing our SimpleCalc application
import android.test.ActivityInstrumentationTestCase2; // You can run any test method on the UI thread
public class TestCase1 extends ActivityInstrumentationTestCase2<MainActivity> {
private Solo solo; // solo is the main class of Robotium
public TestCase1() {
super(MainActivity.class); // Activity name of the class that you want to test.
// TODO Auto-generated constructor stub
}
@override
public void setUp() throws Exception {
solo = new Solo(getInstrumentation(), getActivity());
}
public void test() throws Exception{
// check that we have the right activity
solo.assertCurrentActivity("wrong activiy", MainActivity.class);
// enter the value “12” into first edit text
solo.enterText(0, "12");
// enter the value “2” into first edit text
solo.enterText(1, "2");
// Click on the first button
solo.clickOnButton(0);
// searchForText has a timeout of 5 seconds
assertTrue(solo.waitForText("24"));
}
@override
public void tearDown() throws Exception {
solo.finishOpenedActivities(); // finishes all opened activities
}
}
Click to expand...
Click to collapse
3. To Run the test just right click on the SimpleCalc-Test project -> Run As -> Android JUnit Test
4. Now you will see a tab of JUnit where in you will see your test results(Passed/Failed).
5. On the below Screen Shot I have shown you how the JUnit results are shown when the test is pass.
6. As you can see from the above screen shot clearly that our test is pass and the color indication is Green. If in case our test gets failed the color will be changed to Red as shown in below screen shot:
7. And the Fail reason will be shown at the Failure Trace as you can see from the above screen shot. Here I have purposely commented on the both edittext fields so that I can show you how the failed test case report will be.
8. Now the thing is how to take out the report? It’s easy, there are 3 ways of doing it they are:
8(a). By taking Logcat.
8(b). By Clicking on the Test Run History -> Export option you will get a xml file of the test report, and lastly.
8(c). Pushing the Test report to a text or excel file to the device.
9. Now we will see how to test the application when we don’t have source code with us in the next chapter.
How to setup Robotium using Eclipse ADT without source code of Android Application?
4. How to setup Robotium using Eclipse ADT without source code of Android Application?​
1. To get it started first let us see what is an apk file, why we need it? How to install it to a device?
2. Android application package file (APK) is the file format used to distribute and install application software and middleware onto Google's Android operating system. APK files are ZIP file formatted packages based on the JAR file format, with .apk file extensions.
3. We need apk file to test our application without having the source code. Now the question is from where do I get the apk file? It’s Easy just go to workspace of eclipse -> open the folder called SimpleCalc -> bin -> SimpleCalc.apk (~279KB).
4. To install SimpleCalc.apk file we are going to use a simple adb (Android Debug Bridge) command. The syntax for install an apk file is as below:
adb install [path of the apk file]
Click to expand...
Click to collapse
NOTE: Before Installing an apk file the important thing is to make sure that your device is in debugging mode and your device is connected to your Computer System. To enable debug mode in to your device go to Settings -> Developer options -> check mark Android debugging option.
Basic Android Test Project without source code
4a. Basic Android Test Project without source code​
1. Now as we are done with installing our apk file to device the next thing is very important, that is we have to create a new android test project so for this we have to keep at least one project open (It can be any project) and then only we can proceed else we will get an error saying which is show as below:
2. Now go to file -> new -> other -> Android Test Project -> give a name as SimpleCalcAPK-Test -> Select Test Target as “An existing Android project” -> Finish.
3. Now you will find a project with an empty package ready for creation of JUnit tests without source code.
4. Right click on the empty project -> new -> JUnit Test Case and give a name as ApkTestCase_1. Now you will see JUnit test case as below:
5. Now edit the above code as show below:
package com.rhb.simplecalc.test.test;
import com.jayway.android.robotium.solo.Solo;
import android.test.ActivityInstrumentationTestCase2;
public class ApkTestCase_1 extends ActivityInstrumentationTestCase2 {
public ApkTestCase_1() {
super(MainActivity);
// TODO Auto-generated constructor stub
}
private static final String LAUNCHER_ACTIVITY_FULL_CLASSNAME = "com.rhb.Simplecalc.MainActivity";
private static Class MainActivity; // name of the activity class
static{
try {
MainActivity = Class
.forName(LAUNCHER_ACTIVITY_FULL_CLASSNAME);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
private Solo solo;
public void test() throws Exception{
solo.enterText(0, "12");
solo.enterText(1, "2");
solo.clickOnButton(0);
assertTrue(solo.waitForText("24"));
}
protected void setUp() throws Exception {
super.setUp();
}
protected void tearDown() throws Exception {
super.tearDown();
}
}
Click to expand...
Click to collapse
6. As soon as you Run this test you will get an Error saying “Process crashed” as shown below:
7. Solution for this is we have to just change the below lines from AndroidMenifest.xml file :
HTML:
<instrumentation
android:name="android.test.InstrumentationTestRunner"
android:targetPackage="com.rhb.simplecalc.test" />
Change it to:
HTML:
<instrumentation
android:name="android.test.InstrumentationTestRunner"
android:targetPackage="com.rhb.simplecalc" />
NOTE: The “targetPackage” will be the package called by the test which tests the functionality of the application in that called package.
8. Now copy paste the below code to test SimpleCalc application without source code:
package com.rhb.simplecalc.test.test;
import com.jayway.android.robotium.solo.Solo;
import android.test.ActivityInstrumentationTestCase2;
public class ApkTestCase_1 extends ActivityInstrumentationTestCase2 {
public ApkTestCase_1() throws ClassNotFoundException {
super(MainActivity);
// TODO Auto-generated constructor stub
}
private static final String LAUNCHER_ACTIVITY_FULL_CLASSNAME = "com.rhb.simplecalc.MainActivity"; // name of the package with activity name here com.rhb.simplecalc is the package name and MainActivity is the activity name to be executed.
private static Class MainActivity; // name of the activity class
static{
try {
MainActivity = Class
.forName(LAUNCHER_ACTIVITY_FULL_CLASSNAME);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
private Solo solo;
protected void setUp() throws Exception {
solo = new Solo(getInstrumentation(), getActivity());
}
public void test() throws Exception{
// solo.assertCurrentActivity("wrong activiy", MainActivity);
solo.enterText(0, "1");
solo.enterText(1, "2");
solo.clickOnButton(0);
assertTrue(solo.waitForText("2"));
}
protected void tearDown() throws Exception {
super.tearDown();
}
}
Click to expand...
Click to collapse
10. Now Run the project by right clicking on the project -> RunAs -> Android Junit Test and see the test results in the Junit tab.
What is JUnit Test Suite and why we need it in Robotium?
5. What is JUnit Test Suite and why we need it in Robotium?​
1.JUnit Test Suite is a collection of multiple unit tests each of which shall test the functionality of a Robotium script.
2.Android sdk comes built in with android jUnit which is different from the normal jUnit however the structure of android jUnit resembles that of regular JUnit. This is the reason why we need JUnit suit to call all the Robotium scripts and thereby used in android automation.
3.One JUnit suite shall call multiple activities of the application and therefore for bigger applications. It is possible to have multiple JUnit suits and we can further have a collection of these suites under a suite of suits(collection of individual JUnit suits).
4.Now we will write a simple JUnit test for our application which is as below:
As I said before normal JUnit Suite is different and android JUnit is different we have to do some modifications on the coding part to make JUnit suite work on android, which is as below:
package com.rhb.simplecalc.test.test;
import android.test.AndroidTestCase; // to make JUnitSuite work with android
public class JunitSuite extends AndroidTestCase {
@Override
public void setUp() throws Exception {
super.setUp();
}
// first JUnit Suite that will call ApkTestCase_1 class
public void Test() throws Exception {
ApkTestCase_1 a = new ApkTestCase_1();
a.setUp();
a.test();
a.tearDown();
}
@Override
public void tearDown() throws Exception {
super.tearDown();
}
}
Click to expand...
Click to collapse
5.Now I will show you how to create Main Suite which intern calls all the subsuites which are present in the test project.
package com.rhb.simplecalc.test.test;
import junit.framework.Test;
import junit.framework.TestSuite;
public class MainSuite extends TestSuite {
public static Test suite () {
TestSuite suite = new TestSuite();
JunitSuite test = new JunitSuite();
test.setName("Suite1");
suite.addTest(test);
return suite;
}
}
Click to expand...
Click to collapse
6.Now as we are done with creating of JUnit Suite we will continue with creation of Data Driven testing in the next chapter.
How to Data-Drive Robotium Scripts?
6. How to Data-Drive Robotium Scripts? ​
1.We go for data driven testing when we have some modules that need to be tested for multiple values. For example in a application which has a login page with username and password field we have to test these edit text boxes for multiple inputs, it can be a number or it also can be a string or both together.
2.In our SimpleCalc application we have two edit text fields so we will see how to extract data from an Excel file and push the same to our application.
3.First we will create an excel file with some data present in it to test our application. (An Excel file for testing our app is attached here)
4.To extract data from Excel we use “FileInputStream” Class by which we can create/delete and modify a file.
5.Before we get it started some important things to be concentrated on are we have to keep the excel file inside the device and not on the PC because android Robotium doesn’t support the accessing of the files which are stored on to the computer system and not on the Device.
6.So first thing is to push the Excel file to the device. Just go to DDMS tab in eclipse and click on the push icon -> click on browse -> select the Test.xls file that I have provided. The screen shot for this is as shown below:
7.After pushing the Test.xls file to your device or Emulator the next thing what you have to do is add POI jar files to your build path. The link for these jar files can be found at first post.
8.Just create a new folder and name it as POI and add the Jar files to build path after adding them to build path it should look like below:
9.After successfully adding of the poi jar files its time to write program for accessing the data from excel file to our application.
10.The code for accessing data from excel file is as below:
public void test() throws Exception, IOException,
FileNotFoundException,InvalidFormatException {
String cellval1;
String cellval2;
FileInputStream fis= new FileInputStream(Environment.getExternalStorageDirectory() + "/Test.xls");
Workbook wb = WorkbookFactory.create(fis); // creates object for workbook Test.xls
Sheet ws = wb.getSheet("Sheet1"); // opens Sheet1 from workbook Test.xls
int rc = ws.getLastRowNum(); // counts the number of rows which are used
for(int i=1; i<=rc; i++)
{
Row r = ws.getRow(i); // ponts to the i'th ROW
for (int j=0;j==0;j++){
{
Cell c = r.getCell(j); // points to the j'th Column
cellval1=c.getStringCellValue(); // gets the data from J'th cell
Cell c1 = r.getCell(j+1); // ponts to the J+1'th column
cellval2=c1.getStringCellValue(); // gets the data from J+1'th cell
solo.clearEditText(0);
solo.enterText(0, cellval1); // pulls data from cellval1 and pushes it on to first editText box
solo.clearEditText(1);
solo.enterText(1, cellval2); // pulls data from cellval2 and pushes it on to second editText box
solo.clickOnButton(0);
}
}
}
}
Click to expand...
Click to collapse
11.Now when you run the code you will get the output as below:
12.Now as you can see from the above Screen Shot that the values from our excel sheet has been taken properly and after this the test should fail because we have given the second value as a special char and hence the test fails as shown below:
13.As we have finished with Data Driven Testing with Robotium we will now move with our last chapter where in we see what all issues I found while working with Robotium.
Issues with Robotium
7. Issues with Robotium
​
1. Reporting capability is limited to JUnit Reports in XML format.
2. Writing into excel or text file is a bit clumsy at present.
3. Identifying Excel file for script parameters is manual in nature (Pushing Excel files to the device manually using DDMS).
4. Data whether text or number is taken as a string and fed to the script.
5. No Option of Record and Playback ( Now available ).
6. Robotium doesn’t work with TestNG suite and Eclipse Kepler at present.
7. Robotium is dependent on Android JUnit for execution control.
***************************************************************************************************************************************************************************************
Very Clear from Basics
Excellent mix of concepts and practical explanation.
Swaroop Bandagadde said:
Excellent mix of concepts and practical explanation.
Click to expand...
Click to collapse
Thanks for guiding me.. !!:good::good:
Ravi H Basawa said:
7. Issues with Robotium
​
1. Reporting capability is limited to JUnit Reports in XML format.
2. writing into excel or text file is a bit clumsy at present.
3. Identifying Excel file for script parameters is manual in nature (Pushing Excel files to the device manually using DDMS).
4. Data whether text or number is taken as a string and fed to the script.
5. No Option of Record and Playback.
6. Robotium doesn’t work with TestNG suite and Eclipse Kepler at present.
7. Robotium is dependent on Android JUnit for execution control.
***************************************************************************************************************************************************************************************
Click to expand...
Click to collapse
A very Nice thread.. Rated 5 star
Rohit02 said:
A very Nice thread.. Rated 5 star
Click to expand...
Click to collapse
Thank you so much.. It means a lot to me.. :good:
Is it neccessary to have knowledge of android sdk before using robotium
hello,
I am doing poc on robotium can anybody help me in doing POC of some scenario's
1.app foreground background
2.lock and unlock device
3.kill app /restart app
4.network toggling
adityaroy612 said:
hello,
I am doing poc on robotium can anybody help me in doing POC of some scenario's
1.app foreground background
2.lock and unlock device
3.kill app /restart app
4.network toggling
Click to expand...
Click to collapse
Hi,
If you are using device and not emulator, Your device need to be rooted.
you have to pull settings.apk from the device and resign it back. Now write your script and run. It will work.
I am going to write a tutorial on testing of native apps with Robotium soon.
Thanks:good:

[App][Code project][5.0+]Rom Control app for devs

Hello ya'all,
This is gonna be a long op, I dunno where to start...
Sooooo... a while ago a friend (@tdunham) asked if we could share a settings app we made for our rom(s) (future rom(s).... as we are lazy bums). Since we mostly aimlessly wander around xda and help other devs instead of releasing our stuff, we figured... what the hell, we might as well make it into a source code project in a java-unexpirienced-dev format. So here we go!
About the project:
This app has a main function of coordinating content resolver entries between user end (your rom control app) and mods end (when you use content resolver to reitrieve settings storage database entry keys in various modded system apps).
Basically, you create a preference item, such as switch preference f.e, and when the user switches it, an entry is being overwritten in Settings.System. From there, your modded apps, according to your mods, can read the value and do some stuff...
Needless to say that this app requires, among many other things, your ability to mod system apps to use content resolver. If this doesn't mean anything to you, you're in a wrong place.
If you wish to learn more about modding smali using content resolver, you need to first get introduced to 2 amazing threads:
1. Creating and Understanding smali mods by @Goldie - if you are not fluent in that thread, you will not need this app.
2. Galaxy s5 unified mods and guides thread by @tdunham - not all guides there are using content resolver, but lately more and more are. In any case it's a great place to ask questions, learn and contribute.
Nuff said about modding, now to the project
Project characteristics:
The project is a source code project. Meaning we are not providing an application and you will not be using it by decompiling it with apktool. There are so many reasons for that that I don't know where to start. Mainly - it's bad enough samsung has made hackers out of all of us and we need to decompile and backdoor their system apps to mod them. What we can provide in source code - we will. We strongly believe in the freedom of code and we share it unconditionally (almost).
Now what is that "almost? part? Simple... You do NOT need to credit us in any of your work, you do NOT need to thank us, you do NOT need to ask permission to use this project in your rom, you also do NOT need to donate to us (you also can't, we don't have a donate button). YOU DO NEED TO RESPECT THE FREEDOM OF CODE! That means that this code is given to you under the GNU GPL (General Public License). You can review it fully here.
The most relevant part to our discussion is as following:
...For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights...
Click to expand...
Click to collapse
That being said, the only thing that is required of you is that you keep sharing the code. We are not going to run around xda and "police" people using the code and not providing source. We rely on your word, that by agreeing to use the open source, you will keep it public and provide your sources as well for others to use. This VOIDS xda rule number 12, stating that each dev owns their work. Becasue the rule also states that work that is provided by a lisence that negates exclusivity, is therefore not exclusive. Any work based on this code is not to be held exclusive. And if another developer wants to use an app you built based on this code, you have an obligation to provide your sources and to keep those updated to most recent version of the app you release in order to be compliant.
Thread rules and disclaimaers:
The code is 100% original and written by us (myself and @wuby986) for this specific project. All the classes imported from public open source repositories are annotated with original developer signature and our modifications are annotated and dated as well.
To answer most asked question so far - we don't know how it is different from a custom settings app by ficeto. We have never used it in our roms and we have nerver seen it's code (neither have you). Both apps share the same idea of integrating preferences into settings db using content resolver. You are free to use any app you like. We are not saying which app is better or worse. This is seriously not a competition.
This project requires extensive knowledge in android development. As mentioned above, if you don't know how to mod system, this app is of no use to you. We will not be answering questions about smali mods.
This project requires basic knowledge in operating android studio. You need to have it installed and operational in order to work with the code. You need to have android sdk and all the support libraries updated.
This project requires SOME coding expirience or AT LEAST an open mind to getting a crash course. You will not be required to do heavy java lifting to use this app, but it would help if you knew alittle bit.
We cannot teach you how to use android studio, debug problems related to it and so on. We will provide basic instructions as to how to add items to the navigation drawer list, how to add preference fragments with ease, we will explain the idea of out code and different preferences to you. Beyond that - it's on you. We cannot and will not teach you to be a programmer. If you want to know more - the web is wide and google is your friend.
We cannot debug your code problems. This thread is for development discussion related to the project itself. If you need some requests, questions regarding exsisting code, remarks, improvements, you're more than welcome to join a github project and commit your code for everyone's benefit.
Nuff said about rules, moving forward:
Project sources:
Github source for the Rom Control application is here
Github source for the template to add preference fragment for this specific app is here
Initial instructions:
Download and install Android Studio and android sdk for your platform. Make sure all are updated
Go to the preference fragment repository and download the master as zip. Extract the zip contents into /your android adt directory/android-studio/plugins/android/lib/templates/other/
Reopen android studio
File > New > Project from Version Control > Git
The git repository is https://github.com/daxgirl/CustomSettingsForDevs.git
Specify your parent directory and directory to contain the project (will be suggested by studio)
Clone from git
Done you have the project on your pc. Wait for it to sync and build gradle.
The next couple of posts will explain extensively how to operate the app and create customize it to your rom's needs.
XDA:DevDB Information
[App][Code project][5.0+]Rom Control app for devs, App for all devices (see above for details)
Contributors
daxgirl, wuby986
Version Information
Status: Testing
Current Stable Version: 1.0
Created 2015-06-30
Last Updated 2016-04-12
Basic info and app structure
Basic info and app structure:
This application is Navigation Drawer application material design style. It uses app cpmpat in order to use the pager adapter. This can make theming alittle bit tricky, but we provided 2 themes for now which you can modify in styles.
Navigation drawer opens from the left and it contains for now example of navigation items list. For now we have 4 preference fragments and the last items is to set theme. You can add or remove fragments as you wish. The process will be fully explained.
The fragments in the main view container are being replaced based on a position of clicked item in the navigation drawer list. Remember (we will get back to it again), positions in any array begin from 0. That means that for now we have 0,1,2,3,4 items in the arrays that construct the navigation items list. When we add one, we will need to add a title and an icon (both in corresponding positions) and also add our new fragment to a special method which makes the selected items to show specific fragment. We will discuss it at lenght.
For now application contains only preference fragments. If you feel confident and know what you're doing, you can add all kinda fragments and navigation items (even more activities). We concentrate here on preference fragments, because this is the essence.
Each navigation fragment has a java class which extends PreferenceFragment and an xml file inside res/xml folder, where the preferences exist for each fragment. Once launched for the first time, each fragment will create a shared preferences file inside our "home" directory. Our directory is in /data/data/com.wubydax.romcontrol/. There you will find several files and dirs. One of them is called shared_prefs. Inside it each fragment will host it's preference xml file. The name of this file will be identical (by our design) to the name of the xml file for that fragment in /res/xml folder. Once the fragment displayed for the first time, the shared preferences file for it is created and being populated by the default values you set. We will explain later which preferences must have defaultValue set and which preferences MUST NOT.
If you open the java class for any PreferenceFragment, f.e. UIPrefsFragment.java, you will see that the code is very small. That is because we wanted to make things easier for you and we created a class called HandlePreferenceFragment.java, which manages all the work of the fragments.
When you create a new Preference Fragment using a template for android studio we provided, The fragment and it's xml file are created for you automatically. All you will have to do is add it to the item selector in the navigation drawer, of course give it a name and an icon, and you can gop ahead and populate the xml file with preferences. You will not need to touch java anymore if you don't want to.
We have the usual preferences that you know of, like SwitchPreference, CheckboxPreference, ListPreference etc, and we have our own "special" preferences to make your life easier. Those are IntentDialogPreference (to choose an app and write it's intent to the database for you to use in your mods to open apps), FilePreference (to control some booleans by creating and deleting file), we have 2 special kinds of PreferenceScreens: one for running shell scripts and one for creating intent to open apps from the control app. Those preferences will have special kind of keys, which we will demonstrate. You will not need to flash your scripts when flashing your rom. All your scripts will be managed in the assets folder and copied on run time to our home directory and executed from there. You don't need to worry about permissions, all is taken care of. Just place your scripts inside the assets folder before you compile the sources. Sae thing with opening apps as intents, all you need to do is put a main activity full name as PreferenceScreen key. Everything else is taken care of, including displaying icon. The preference will not show at all if the user doen's have an app installed. So no crashes upon clicking on non existing intents. They will just vanish from the list.
The preference files inside the project on github contains BOGUS preferences to use as an example. We will go over all of them (most contained inside first fragment - UIPrefsFragment). They are all active. But they should not trigger any mod, as you should not have those keys in your database. You can see f.e. that preference fragment "Useful apps" has like 5 preferences for app intent. some of them have bogus intent. They will not display when you run your app. They are therer to demonstrate that if the app doesn't exist, you should not worry about FC of Rom Control. It takes care of itself.
The first time the app boots it asks for root permissions. If the device is not rooted or permissions not granted, the app will never run. You all run rooted and modded roms, this app is not for stock. If you wish to disable this function, we will provide that option.
Reboot menu - on the right upper corner of the action bar you will see a reboot icon. Clicking it will show a display of 5 reboot actions: reboot, hotboot, reboot recovery, reboot download, reboot systemui. Youc an access those easily no matter what fragment you're in. Clicking outside of them or clicking back button will make the menu disappear. clicking on one of them will result in immidiate reboot function. Those are root related finctions. We can make them no root dependant once you all use an app in your /system/priv-app. Which, btw, is where we recommend it goes.
How does it work?
For the first time an app is opened (or any time an ap is opened), there is a special method inside HandlePreferenceFragment that is called initAllKeys();. This method goes over all the preferences contained inside the shared preferences for that fragment. One by one it checks their key name, checks if they are of type boolean (true or false), of tipe integer (number) or of type string (words). Then it checks what preference they belong to. It checks if the key for that preference exists in your settings storage database, if it does not - it creates all keys. If the key exists in the database but is different from what the app has - it replaces the one in the app preferences with what you have in your system. That is why it's important for most preferences to set the defaultValue that you wish to be the default, beucase the first time the app launches, it will create all the keys in the system database. once the process is done(you will not see or feel it), your preferences are yours to control. Once a user clicks on Checkbox, if it's selected (isChecked), it writes 1 to the key for that preference inside the Settings.System. and vice versa. Any change in the preferences is being registered immidiately. So your mods can be updated (provided you have observers, of course, or else you might need to reboot apps, just like you always did). Inside the class HandlePreferenceFragment there is a method updateDatabase. it is being called from a method that "wacthes"/"listens" to any change in preference.
That is, basically, all. This is how it works. Everything else is cosmetics made for your convinience and mostly based on your requests. F.e. running shell scripts, FilePreference, App picker preferences was requested by other developers to be included so we had to find a way to build in. Now you can all enjoy. Any further requests are welcome.
Overall structure in studio:
One you have opened the project in studio, you have the following structure tree on your left. Make sure you have chosen the "project" tab (far left edge of the screen) to see it:
Inside the libs folder we have the roottools jar made by the amazing @Stericson and the next folder that is of interest is the src/main. This is where the app as you know it (from apktool) is hosted. You can see inside the res folder all our resources.
If you need to change the icon for the app you need to place it inside mipmap folders. It's called ic_launcher.png. For nice app icons generator visit here . Inside the values-21 folder there is the styles.xml file that you need to edit if you want to change theme colors. Nice site for coherent material palette is here and google documentation is here.
In the main drawables folder you will find those:
As you can see there are two images there that are relevant to you: header_image and header_image_light (for both themes). Thopse are the header images for the navigation drawer. You can replace them with your own. The reference to them is inside /layout/fragment_navigation_drawer.xml as you can see here:
.
Here it's used as an attribute. You can read more about using attrs in android docs. Just replace the images and keep the names.
Inside of the resolution dependant drawable folders you can find the images for the items in the navigation drawer:
Here you can replace, move and add your own. Good resources for icons are: here and here and you can find many more out there.
Inside the assets folder we have a folder named scripts. It's important the name remains "scripts".
It's used in java code to copy the assets on runtime to our home dir. Inside scripts you put your shell scripts that you wish to run using the script running method. scripts have to be called with .sh in the end. When you create a PreferenceScreen that needs to run scripts, you give it a key like this: android:key = "script#nameofourscript". You do not add the .sh in the key. Look at the example inside ui_prefs.xml in PreferenceScreen with key android:key = "script#test". This runs the script that is currently found in assets. which basically writes into a file on your sdcard. Here you can put scripts as complex a you like. The code checkes for the exit code of the script. as long as it is 0, it will print a toast "executed successfully" upon clicking your preference. To try it run the app on your phone and click on a preference screen with summary "Click see what happens". Make sure your scripts are well formed and test them before including. Remember that you're under sudo. Linux shell will execute anything under sudo without asking.
Inside the /res/xml folder are our preference xml files. This will be your main playground. In those files we will be adding the preference items to appear in each of your fragments.
And finally for the java classes:
Here is where all the work is being done in real time. If you don't have expirience, you won't have to go there besides when you need to add the more nav drawer items.
Adding a new fragment and navigation drawer list item:
1. Provided you read the OP instructions and cloned the Rom Control Preference Fragment template repository into /your android adt directory/android-studio/plugins/android/lib/templates/other/, you need to restart android studio and we are ready to go.
2. Right click on the main java package of out application and navigate to New > Fragment > Fragment (6thGear Preference Fragment) like you can see on the picture below:
Once you click on adding the fragment the foloowing window will open:
As you can see the initial names are: for fragment - BlankFragment and for xml blank_prefs. You can change it as you like. BUT! Leave the word Fragment. Once you change the FIRST part of the fragment name, the first part of the prefs file name will be changed automatically. See the img below:
So we have chosen to create a new fragment called PowerMenuFragent and below that we have the preference xml name. the name is automatically generated as you put in your class name for the fragment. The java naming convention states that a class must begin with capital letter and all meaningful words in class name must also begin with capital letter. The xml name generator will split the word Fragment from your class name and make the other words into xml legal name form separated by under score and will add _prefs in the end. So it becomes power_menu_prefs.xml.
Click "finish" and you have a new fragment class and a new xml file for it inside /xml folder. The fragment will look like this:
You don't need to edit it. It's done in template. It instantiates the class called HandlePreferenceFragment and refers to it's main methods. For more infor you can read my annotations in the HPF class.
Your new xml file is now empty and contains an empty preference screen like so:
We will populate it with preferences later.
Now we need to make this new fragment REACHABLE for user. So we need to add an item to the navigation drawer sections. Let's do that:
1. Open /values/strings.xml and find an array of strings. we will add our new item name in a place we want. In this case I will add it after the Framework section (in blue):
Code:
<string-array name="nav_drawer_items">
<item>SystemUI Mods</item>
<item>Phone Mods</item>
<item>Framework and General</item>
[COLOR="Blue"][B]<item>Power Menu</item>[/B][/COLOR]
<item>Useful Apps</item>
<item>Set Theme</item>
</string-array>
2. Now you will need a new icon to appear to the left of the section name in nav drawer. You can add your own icon at this point. It's a good practice to add images for all resolutions. But who are we kidding? You're making a rom for one device. So to remind you, s4, note3, s5 are xxhdpi and note4, s6 are xxxhdpi. I will use existing icon called ic_reboot.png for this section.
3. Now we need to get our hands dirty and go into java alittle. Open MainViewActivity and find the following method. This method is well annotated for your use. So you can refer to it every time you add an item for reference of how-to. Observe the new blue item:
Code:
//Creates a list of NavItem objects to retrieve elements for the Navigation Drawer list of choices
public List<NavItem> getMenu() {
List<com.wubydax.romcontrol.NavItem> items = new ArrayList<>();
/*String array of item names is located in strings.xml under name nav_drawer_items
* If you wish to add more items you need to:
* 1. Add item to nav_drawer_items array
* 2. Add a valid material design icon/image to dir drawable
* 3. Add that image ID to the integer array below (int[] mIcons
* 4. The POSITION of your new item in the string array MUST CORRESPOND to the position of your image in the integer array mIcons
* 5. Create new PreferenceFragment or your own fragment or a method that you would like to invoke when a user clicks on your new item
* 6. Continue down this file to a method onNavigationDrawerItemSelected(int position) - next method
* 7. Add an action based on position. Remember that positions in array are beginning at 0. So if your item is number 6 in array, it will have a position of 5... etc
* 8. You need to add same items to the int array in NavigationDrawerFragment, which has the same method*/
String[] mTitles = getResources().getStringArray(R.array.nav_drawer_items);
int[] mIcons =
{R.drawable.ic_ui_mods,
R.drawable.ic_phone_mods,
R.drawable.ic_general_framework,
[B][COLOR="Blue"]R.drawable.ic_reboot,[/COLOR][/B]
R.drawable.ic_apps,
R.drawable.ic_settings};
for (int i = 0; i < mTitles.length && i < mIcons.length; i++) {
com.wubydax.romcontrol.NavItem current = new com.wubydax.romcontrol.NavItem();
current.setText(mTitles[i]);
current.setDrawable(mIcons[i]);
items.add(current);
}
return items;
}
As you can see I added a line R.drawable.ic_reboot. What is it? This is an equivalent to public id in smali. It is in fact an integer. So it appears inside integer array called mIcons. Our respurces in android are referenced by capital R. then we have the resource type, in this case - drawable, and then the item name (without extension). Note the order of the id in the array, I added my string after the framework string. So I also add the id for the drawable after the id of the framework drawable. This is vital to understand, as the list is being populated on runtime based on items positions. Items in an array are separated by comma.
4. Now open NavigationDrawerFragment class and you will find the same method there. Please add the same id in the same way there. You MUST do so in both classes every time.
5. Now we go back to the MainViewActivity and we find the following method. it will be right after the getMenu() method we just edited. The method is called onNavigationDrawerItemSelected(int position). This method is responsible for performing action based on which navigation drawer item is clicked by a user. Positions are the positions of items in the List of our objects. So we have so far 6 items out arrays (strings and drawable id integers). That means their positions are 0,1,2,3,4,5 respectively. Look at the method as it appears in the original code:
Code:
@Override
public void onNavigationDrawerItemSelected(int position) {
/* update the main content by replacing fragments
* See more detailed instructions on the thread or in annotations to the previous method*/
setTitle(getMenu().get(position).getText());
switch (position) {
case 0:
getFragmentManager().beginTransaction().addToBackStack(null).replace(R.id.container, new UIPrefsFragment()).commitAllowingStateLoss();
break;
case 1:
getFragmentManager().beginTransaction().addToBackStack(null).replace(R.id.container, new PhonePrefsFragment()).commitAllowingStateLoss();
break;
case 2:
getFragmentManager().beginTransaction().addToBackStack(null).replace(R.id.container, new FrameworksGeneralFragment()).commitAllowingStateLoss();
break;
case 3:
getFragmentManager().beginTransaction().addToBackStack(null).replace(R.id.container, new AppLinksFragment()).commitAllowingStateLoss();
break;
case 4:
showThemeChooserDialog();
break;
}
}
Here we have switch case based on position of an item. This is the same as saying: if the position of an item is 0, perform this action, else, if the position is 1, perform that action and so on. Only in this case we say: compiler, switch cases based on integer - in case 0: do something, in case 1: do something else. So we need to add an item after the framework section. Framework section has position of 2 (it's item number 3). So now we add our new fragment like so:
Code:
@Override
public void onNavigationDrawerItemSelected(int position) {
/* update the main content by replacing fragments
* See more detailed instructions on the thread or in annotations to the previous method*/
setTitle(getMenu().get(position).getText());
switch (position) {
case 0:
getFragmentManager().beginTransaction().addToBackStack(null).replace(R.id.container, new UIPrefsFragment()).commitAllowingStateLoss();
break;
case 1:
getFragmentManager().beginTransaction().addToBackStack(null).replace(R.id.container, new PhonePrefsFragment()).commitAllowingStateLoss();
break;
case 2:
getFragmentManager().beginTransaction().addToBackStack(null).replace(R.id.container, new FrameworksGeneralFragment()).commitAllowingStateLoss();
break;
[COLOR="blue"][B]case 3:
getFragmentManager().beginTransaction().addToBackStack(null).replace(R.id.container, new PowerMenuFragment()).commitAllowingStateLoss();
break;[/B][/COLOR]
case [COLOR="blue"][B]4[/B][/COLOR]:
getFragmentManager().beginTransaction().addToBackStack(null).replace(R.id.container, new AppLinksFragment()).commitAllowingStateLoss();
break;
case [COLOR="blue"][B]5[/B][/COLOR]:
showThemeChooserDialog();
break;
}
}
Note how the new case is now number 3 and the positions of the following cases need to be increased.
Now we can run our app and and there is our new section item:
That's it for this post. Post #3 we will talk about different preference kinds we have and how to use them.
Till then...
To be continued.....​
Handling different kinds of preferences:
Now we roll with populating our preference fragments. Each preference fragment is unique for your needs, depends on your use, your modded apps and categories. All we do, as mentioned above, is provide you with preferences to communicate with your modded system apps using ContentResolver class.
For each preference I will explain:
Does it write preferences into shared preferences? and if it does...
What kind of object it writes to shared preferences of our app?
What kind of value we then write into SettingsSystem database?
What kind of key it uses and why?
SwitchPreference/CheckboxPreference:
Images:
You MUST provide defaultValue for ANY switch preference you create
It writes boolean (true or false) into the shared preferences
We copy it as integer (1 or 0) into the Settings.System database
It mush have a unique key, none of existent in databse. It must be the same key as you use in your mod for that function. F.e. statusbar_clock_visibility. Clock can be either visible or invisible. So switch preference will serve us good here. Also will checkbox preference. In your mod when you retrieve and integer using ContentResolver you specify the default value (if the key is not found). You have to specify the same default value here. If in smaly it was 0x1,. then in the app it must be android:defaultValue = "true". YOU MUST SPECIFY DEFAULT!
In preference xml inside your empty PreferenceScreen claws, you add this:
Code:
<SwitchPreference
android:defaultValue="true"
android:key="clock_visibility"
android:summaryOff="Clock is hidden"
android:summaryOn="Clock is visible"
android:title="Set Clock Visibility" />
Code:
<CheckBoxPreference
android:defaultValue="false"
android:key="brightness_visibility"
android:summaryOff="Brightness slider hidden"
android:summaryOn="Brightness slider is visible"
android:title="Notification Brightness Visibility" />
This is all you need. The key will work automatically. The first time the user runs your app it will look for that key in the database, if it finds it, it will copy the value into our app and the switch will be set accordingly, if it does not find it, it will copy the defaultvalue of your preference to the database.
Of course the proper way of using strings for title and summary is by using string resources. In android studio you can create strings resources after you have typed the string. F.e. click on one of the strings, like for title, and on your keyboard press alt+enter. You will be given an option to extract string resource. That is all up to you. If your app is only in english, you don't really need to do that.
ListPreference:
Usually you would create list preference by specifying <ListPreference..../>. We had added some functionality to native android preferences for List and EditText. So we have our own classes that extend those preferences. So when we create a list preference we use our own class, so the preference looks like this:
Code:
<com.wubydax.romcontrol.prefs.MyListPreference
android:defaultValue="2"
android:entries="@array/clock_position_entries"
android:entryValues="@array/clock_position_values"
android:key="any_clock_position"
android:title="Status Bar Clock Position" />
Once you open < in studio and start typing com..... it will give you the options of preferences existing in our app. Just choose the one you need and it will create the name for it. Don't worry if you mistype, it will not compile.
List preference in android persists string. That means that it writes object of string type into the shared preferences. You need to create 2 string arrays for each list preference. One for Entries - what is displayed in the dialog as single choice items for user. and One is for entryValues (what is being written into the preferences). You can from your mod read them as integers or strings using content resolver. f.e., if your values are 200, 300, 400, android will persist them as strings. But when you restrieve them from database in your systemui smali mod, f.e., you can call either getInt (to get them as integers) or getString to get them as strings. Of course strings array like bread, milk, cookies cannot be retrieved as integer. But a string 200 can be either.
When you retrieve a default value in your smali mod, you retrieve f.e. 200. so YOU NEED TO SET 200 as defaultValue. Or in the above case, it's 2. YOU MUST SPECIFY THE DEFAULT STRING!
You do not specify summary for this preference, we take care of it in code. like so:
EditTextPreference:
Code:
Code:
<com.wubydax.romcontrol.prefs.MyEditTextPreference
android:defaultValue="simpletext"
android:key="carrier_text"
android:title="Set Custom Carrier Text" />
This preference also persists string. It also writes string into the database. You retrieve it only as string. Because you can't control what user types. You don't want your modded systemui to crash because a user inputted "bread" and you are trying to read it as integer.
YOU MUST SPECIFY THE DEFAULT STRING for EditTextPreference.
ColorPickerPreference:
Writes and integer into the sharedpreferences and we retrieve integer into the database.
Color integers are special. I will not go into how and why. I have created a utility helper app for devs for this purpose. The app's main function is to convert hex string to integers or to reverse smali hex string. You can find an apk and explanations how to use it here.
Remember, YOU MUST-MUST-MUST SPECIFY defaultValue for ColorPicker in our app!!! and YOU MUST USE ACTUAL INTEGERS to do so properly. Just trust us on that. It's no biggie. You use our app for hex converter to both create your default smali hex value and to create an integer for this app.
The code for ColorPickerPreference:
Code:
<com.wubydax.romcontrol.prefs.ColorPickerPreference
alphaSlider="true"
android:defaultValue="-16777215"
android:key="clock_color"
android:title="Choose Clock Color" />
As you can see this android:defaultValue="-16777215" is an actual integer for color black. You get it by using our app. You put 000000 into the first text field and click the button. The integer that you get is -16777215. We also have color preview available. It's a very useful tool. Use it and you can never go wrong with neither integers nor smali inverse hex values for your default color.
Now note the special attribute called "alphaSlider" in the code. This is a boolean type. By default it's false. Meaning you can create color picker preference with or withour transparency option.
SeekBarPreference - the SLIDER:
Writes integer of the slideer progress into the database. The moment your finger has stopped tracking the bar, an integer is being registered into the sharedpreference and then being retrieved into the databasse.
Code:
<com.wubydax.romcontrol.prefs.SeekBarPreference
min="0"
unitsRight="Kb/s"
android:defaultValue="10"
android:key="network_traffic_autohide_threshold"
android:max="100"
android:title="Autohide Threshold" />
YOU MUST SET DEFAULT VALUE!!!! IN INTEGER!
You can specify special values such as unitsRight, like "%" or "Kb/s" and so on. You can specify the min and the max value. You probably better not specify the summary. But you can if you want.
IntentDialogPreference - App Chooser:
Code:
<com.wubydax.romcontrol.prefs.IntentDialogPreference
includeSearch="true"
setSeparatorString="\##"
android:key="choosen_app_gear"
android:title="Choose App" />
This is a very special preference kind. It was created by request from @rompnit. They use intents from database to open apps in certain mods. You will have to ask them on @tdunham thread how and when they use it. We created this preference from scratch specifically for them. This is a completely custom kind of android preference. It displays a dialog of all your LAUNCHABLE apps (apps that have default launch intent that can be retrieved by using PackageManager method getLaunchIntentForPackage. In other words - all apps that appear in your launcher will appear on the dialog.
What happens when you click on an app? What is being written into preferences is a special kind of string. The srting might look like this: com.android.settings/com.android.settings.Settings or it might look like this com.android.settings##com.android.settings.Settings... this is what you need to create basic intent. You need package name and activity name. What separates them is up to you. You will need to split them in your smali mod into package name and activity name to create intent. We have created 2 special attributes for this preference:
1. setSeparatorString =this is what will separate the package name from the class name. The default (if you don't specify) is "/". Remember that if you use chars that must be escaped in xml, f.e. like hash(#), you need to escfape them by backslash, like so setSeparatorString = "\##".
2. includeSearch - this is a boolean type of attribute. It is false by default. If you specify true, the search field will appear on the dialog above the apps list, allowing your users to search for an app by name inside the list adapter. We also included a list alphabetical indexer. So it's up to you if it's necessary.
Once the app is chosen, the summary for the preference is set to the app name and the icon on the right side will be the app icon.
Your database will contain now the basic component for the intent. What you do with it in your smali is up to you.
DO NOT SET DEFAULT VALUE FOR THIS PREFERENCE!!!
FilePreference:
This is very special kind of preference requested by @tdunham. What is does it creates and deletes file with a certain name in our home files dir. It is located at /data/data/com.wubydax.romcontrol/files
Code:
<com.wubydax.romcontrol.prefs.FilePreference
android:key=[COLOR="red"]"testfile"[/COLOR]
android:summaryOff="File doesn't exist"
android:summaryOn="File exists"
android:title="Test File Preference" />
The reason this is used by some devs, apparently, is when you need to mod smali file, which originates in a class that does not take context as parameter. Without context you cannot call the ContentResolver, so you cannot retrieve from the database. So what you can do instead is create a boolean condition based on existence or non existence of a certain file. File class does not require context. All it needs is to be instantiated as object and be given a string as path. For exampple:
Code:
[COLOR="Green"]File[/COLOR] [COLOR="Blue"]file[/COLOR] = new [COLOR="green"]File[/COLOR]("[COLOR="Purple"]/data/data/com.wubydax.romcontrol/testfile[/COLOR]");
means that object file of class File is a file located at /data/data/com.wubydax.romcontrol/ and called "testfile". In java class File you have a method (boolean) which is called "exists". So a condition can be made like this:
Code:
if(file.exists){
int i = 1;
} else {
i = 0;
}
So you can create a boolean method that will return 0 or 1 based on existence of the file at certain location.
This is the idea behind this preference.
The key for this preference is THE NAME OF THE FILE.
YOU DO NOT SPECIFY THE DEFAULT!!!
The preference looks like switch preference. But it acts differently. Youc an specify summaryOn and Off as you need. It does not write into database. It just creates and deletes the file.
Script executing PreferenceScreen:
As entioned above you can create PreferenceScreen which will execute shell scripts upon click. Example:
Code:
<PreferenceScreen
android:key=[COLOR="Red"]"script#test"[/COLOR]
android:summary="Click see what happens"
android:title="New Preference Screen" />
Note the key format. It has to begin with script#! The part after the hash (#) is the name of the script you wish to execute, in this case the script is test.sh which you can find in the source you pulled inside assets folder..
Where are the scripts??? You put them inside assets folder (see post #2). You name your scripts f.e. test.sh script (has to end with .sh). But you do not add the .sh extension to the string (we do that in code).
Every time your app launches it checks for scripts in the assets folder. It wants to make sure all the scripts ar being copied to our home dir. Inside files folder there we create a folder called scripts. All your scripts will be automatically copied there from assets, given permission 0755 and ready to be executed.
Wgen a user clicks on a Script Executing PreferenceScreen, the app looks if a script with that name exists in our files dir. If it does, it attemts to execute it. I have explained in post #2. We also check just in case that the script is executable. There is native java method to do that. So if you or your user just add a script to the scripts folder in home directory and forgot to make it 0755, we do that for you in java with this method:
Code:
if (script.exists()) {
[COLOR="Blue"][B]boolean isChmoded = script.canExecute() ? true : false;
if (!isChmoded) {
script.setExecutable(true);
}[/B][/COLOR]
Command command = new Command(0, pathToScript) {
@Override
public void commandCompleted(int id, int exitcode) {
super.commandCompleted(id, exitcode);
if (exitcode != 0) {
Toast.makeText(c, String.valueOf(exitcode), Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(c, "Executed Successfully", Toast.LENGTH_SHORT).show();
}
}
};
try {
RootTools.getShell(true).add(command);
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
} catch (RootDeniedException e) {
e.printStackTrace();
}
}
Make suer your scripts are of valid shell format, test them separately before you put them in the app. Be careful, all the scripts are being executed under sudo. Means anything you write shall be done. Do not make mistakes in your script. Adding su to your scripts is not necessary. We execute them as root anyway.
So...
Create a shell script and test it on your device
Place it inside the assets folder of your app
Call it f.e. killbill.sh
Create a PreferenceScreen entry and givie it a key android:key = "script#killbill"
Compile the app
Clicking on that preference should execute killbill.sh which will now be foind in /data/data/com.wibydax.romcontrol/files/scripts/killbill.sh and have permissions 0755.
DO NOT SET DEFAULT FOR PreferenceScreen EVER!!!
Intent opening Preference Screen:
Code:
<PreferenceScreen
android:key=[COLOR="Red"]"com.wubydax.gearreboot.RebootActivity"[/COLOR]
android:summary="Opens TWSwipe app to help you choose a different swipe activity"
android:title="Reset TWSwipe Action" />
This is a regular preference screen, so it would seem, but it has a special function. Usually, in order to open an intent with PreferenceScreen, you need to specify a whole lot of intent rules, like action, target class, target package and so on. We have made your life easy. If you want to link to an app from your rom control application, all you need to do is to specify the activity you wish to run as a key to this preference.
You are not allowed to use "." in any other preference key. If you use "." the app will read it as possible intent. If it cannot resolve it, it will make it disappear from the list.
This kind of preference is fully automated. Once the app reads the key, it does all the work for you, it sets the icon for the preference as the app icon, it creates a viable intent.
If the user doesn't have an app that you link to installed, the app will never appear in the preferences. So the user can never click on it. Because otherwise it would give FC to the app.
Nested PreferenceScreen:
If you include regular preference screen, you never need to set a key. Preference screen that envelops the items inside of it will always lead to a nested preference screen that has some included preferences. and so on. We have a loop running through your entire preference tree and detecting all your preference screen and differentiating them by their abilities (being script executing, being intents and so on).
Nested Preference Screen would look like this:
Code:
[COLOR="Red"]<PreferenceScreen
android:summary="New Preference screen"
android:title="New Preference Screen">[/COLOR] [COLOR="Green"]<-- Start of nested preference screen[/COLOR]
<PreferenceCategory android:title="new category" />
<CheckBoxPreference
android:key="text_checkbox"
android:title="Checkbox" />
<SwitchPreference
android:key="test_switch"
android:title="Switch" />
[COLOR="Red"]</PreferenceScreen>[/COLOR] [COLOR="Green"]<-- End of nested preference screen[/COLOR]
Inside of it you can have more preferences and more preference screens.
PreferenceCategory:
Preference category is an enveloping kinda preference. It is different in color and appearence then the rest. It makes sub-portions of preference screen look separate from each other and easier to identify. F.e.:
Code:
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
[COLOR="Red"] <PreferenceCategory android:title="Status Bar Mods">[/COLOR] [COLOR="Green"]<-- start of preference category[/COLOR]
<SwitchPreference
android:defaultValue="true"
android:key="clock_visibility"
android:summaryOff="Clock is hidden"
android:summaryOn="Clock is visible"
android:title="Set Clock Visibility" />
<CheckBoxPreference
android:defaultValue="false"
android:key="brightness_visibility"
android:summaryOff="Brightness slider hidden"
android:summaryOn="Brightness slider is visible"
android:title="Notification Brightness Visibility" />
<com.wubydax.romcontrol.prefs.MyListPreference
android:defaultValue="2"
android:entries="@array/clock_position_entries"
android:entryValues="@array/clock_position_values"
android:key="any_clock_position"
android:title="Status Bar Clock Position" />
<com.wubydax.romcontrol.prefs.MyEditTextPreference
android:defaultValue="simpletext"
android:key="carrier_text"
android:title="Set Custom Carrier Text"
/>
<com.wubydax.romcontrol.prefs.ColorPickerPreference
alphaSlider="true"
android:defaultValue="-16777215"
android:key="clock_color"
android:title="Choose Clock Color" />
<PreferenceScreen
android:key="script#test"
android:summary="Click see what happens"
android:title="New Preference Screen" />
<com.wubydax.romcontrol.prefs.SeekBarPreference
min="0"
unitsRight="Kb/s"
android:defaultValue="10"
android:icon="@null"
android:key="network_traffic_autohide_threshold"
android:max="100"
android:title="Autohide Threshold" />
<PreferenceScreen
android:summary="New Preference screen"
android:title="New Preference Screen">
<PreferenceCategory android:title="new category" />
<CheckBoxPreference
android:key="text_checkbox"
android:title="Checkbox" />
<SwitchPreference
android:key="test_switch"
android:title="Switch" />
</PreferenceScreen>
<com.wubydax.romcontrol.prefs.IntentDialogPreference
includeSearch="true"
setSeparatorString="\##"
android:key="choosen_app_gear"
android:title="Choose App" />
<com.wubydax.romcontrol.prefs.FilePreference
android:key="testfile"
android:summaryOff="File doesn't exist"
android:summaryOn="File exists"
android:title="Test File Preference" />
[COLOR="red"]</PreferenceCategory>[/COLOR] [COLOR="Green"]<-- end of PreferenceCategory[/COLOR]
</PreferenceScreen>
This is it for now, more per demand and need. Have fun!​
General tips and tricks
Some tips and tricks
Running app and debugging:
Android studio provides you with built in logcat. Not only that you can debug the app you're working on, you can debug any app you're modding too. Just need to specify the filter for the logcat and the package name. Dig in and you will find some cool features.
You need to have unknown souces enabled and usb debugging enabled to run your compiled app directly on your device.
1. You can install and run this app as user app. It does not need to be system app. For now no features require it. You can of course include it as system app in your rom. We recommend pulling the base.apk from data folder and pushing to /system/priv-app
2. You do not need USB cable to debug and run your app from studio. There is anifty app I am using. You can download it here https://play.google.com/store/apps/details?id=com.ttxapps.wifiadb&hl=en. All you need to do is open the command line on your pc and type adb connect <ip number of your phone in the network>:5555. The app will provide you with an IP number.
Now studio will recognize your device as USB debugging device even though it's not connected with usb cable. I just hate cables.......
Including key specific functions:
For now all our work is done automatically for us. You click a preference and the work is done. But what if you have a key that you want to do alittle more with than just write into database? I will give you an example.
We have a SwitchPreference in our app that enables/disables call recording. That mod requires restart of InCallUI.apk. Now you can of course restart it by creating a Script Running PreferenceScreen item called Reboot InCallUI and it will be fine. That's what you have been doing so far. But let me show you what you can do now that you own your source code.
We have two ways to kill that app. Silently (without user knowing - very cool) or informing the user. Let me show you how it would be done.
Let's say you create a preference for call recording:
Code:
<[COLOR="red"]SwitchPreference[/COLOR]
android:defaultValue="true"
android:key="[COLOR="Red"]toggle_call_recording[/COLOR]"
android:summaryOff="Call recording is disabled"
android:summaryOn="Call recording is enabled"
android:title="Enable/Disable Call Recording" />
The two things we need to know is the key and the class instance of preference - which is SwitchPreference.
Let us go to the java class HandlePreferenceFragments and find a method called public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key){}}. In android studio you can search through class by pressing ctrl+f.
In that method we have switch by the preference class name (INSTANCE). So we have this case:
Code:
case "SwitchPreference":
SwitchPreference s = (SwitchPreference) pf.findPreference(key);
s.setChecked(sharedPreferences.getBoolean(key, true));
break;
What this means is: if the preference is of kind SwitchPreference, when the preference is changes, do something..... So.... let us do something with our SPECIFIC switch preference for our SPPECIFIC key!!!
Let us try this:
The silent way:
Code:
case "SwitchPreference":
SwitchPreference s = (SwitchPreference) pf.findPreference(key);
s.setChecked(sharedPreferences.getBoolean(key, true));
[COLOR="Blue"][B]if (key.equals("toggle_call_recording")) {
Command c = new Command(0, "pkill com.android.incallui");
try {
RootTools.getShell(true).add(c);
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
} catch (RootDeniedException e) {
e.printStackTrace();
}
}[/B][/COLOR]
break;
This will kill the InCallUI every time the user switches that switch. So what happened here? The user switched the switch, the boolean got written to the database (in a different method), then the app relevant to this key was restarted. Next time a user makes a call - the call recording will be updated!!!
Now let us do it in a no silent way:
Let us inform the user. We have a little method in that class called public void appRebootRequired(final String pckgName) { ...}. Let us try to use it...
So let us go back to our onSharedPreferencesChanged method and instaed of the condition we used silently, we do something like this:
Code:
case "SwitchPreference":
SwitchPreference s = (SwitchPreference) pf.findPreference(key);
s.setChecked(sharedPreferences.getBoolean(key, true));
[COLOR="blue"][B]if (key.equals("toggle_call_recording")) {
appRebootRequired("com.android.incallui");
}[/B][/COLOR]
break;
The user clicks on the preference and see what happens:
Now for InCallUI it might be better to restart the app silently. Since the change is not visible to user anyway. But if you need to restart systemui, then it might be better to inform the user. So all you need to do is instead of passing a string "com.android.incallui" pass a string "com.android systemui". The method will do everything automatically. See how the dialog changes:
Adding more than one special key
If you need to add more than one special key (see popst #3 for instructions and explanations), you have 2 options:
1. We can go on with the if/else conditions, like so:
Code:
case "SwitchPreference":
SwitchPreference s = (SwitchPreference) pf.findPreference(key);
s.setChecked(sharedPreferences.getBoolean(key, true));
[COLOR="blue"][B] if (key.equals("toggle_call_recording")) {
appRebootRequired("com.android.incallui");
} else if (key.equals("some_other_key")) {
//do something you want
} else if (key.equals("again_some_key")) {
//do something different
}[/B][/COLOR]
break;
2. Or we make a switch for that based on key. Like so:
Code:
case "SwitchPreference":
SwitchPreference s = (SwitchPreference) pf.findPreference(key);
s.setChecked(sharedPreferences.getBoolean(key, true));
[COLOR="Blue"][B]switch (key){
case("toggle_call_recording"):
appRebootRequired("com.android.incallui");
break;
case("toggle_clock_visibility"):
appRebootRequired("com.android.systemui");
break;
case("some_other_key"):
//do something
break;
case("some_other_different_key"):
//do something different
break;
}[/B][/COLOR]
break;
Please note:
You can add the specific conditions to any preferences
You need to add them to the same preference instance as the preference that the key belongs to. Right now I showed how to do it for switch preference. You can do the same for any preference. If the key belongs to checkbox preference, you need to put the conditions inside the case of the "CheckBoxPreference" and so on
You need to make sure your condition comes AFTER our built in lines. Like in this case I added it after the initiation of the object and setChecked
You need to finish your conditions BEFORE the main break; of the case.
More to come at later time and per demand...
Huge THANK YOU @daxgirl & @Wuby986 for this!! Folks will love this app!!
Awesome!! Glad to see you have finally released it. I'm sure it'll be fantastic!!
HIZZAH!!! Kudos to wuby and daxgirl!!!
And just when I thought I could take a break from Android.....
The Sickness said:
And just when I thought I could take a break from Android.....
Click to expand...
Click to collapse
You??? Duh.......
Sent from my awesome g920f powered by 6thGear
Thebear j koss said:
View attachment 3384150
HIZZAH!!! Kudos to wuby and daxgirl!!!
Click to expand...
Click to collapse
Mostly to daxgirl
She will say no, but is true
The Sickness said:
And just when I thought I could take a break from Android.....
Click to expand...
Click to collapse
Eheehhehe there is always a good reason to start again
Delivered as promised, great work you 2, thanks a million bunch to you both & to your great testers.
PS : @daxgirl @Wuby986 any chance this app will have the phone make us coffee in the morning ! ( kidding, Sorry )
@daxgirl and @Wuby986 you guys really rock? thanks, thanks and thanks! ?
claude96 said:
Delivered as promised, great work you 2, thanks a million bunch to you both & to your great testers.
PS : @daxgirl @Wuby986 any chance this app will have the phone make us coffee in the morning ! ( kidding, Sorry )
Click to expand...
Click to collapse
Over the past couple weeks @tdunham and @ rompnit definitely tried to make us do that. .. the answer is... of you can make your coffee machine get context and use content resolver, we will deliver the toggle to trigger your morning pleasure
Sent from my awesome g920f powered by 6thGear
daxgirl said:
Over the past couple weeks @tdunham and @ rompnit definitely tried to make us do that. .. the answer is... of you can make your coffee machine get context and use content resolver, we will deliver the toggle to trigger your morning pleasure
Sent from my awesome g920f powered by 6thGear
Click to expand...
Click to collapse
@daxgirl I'm sure if anyone can !, you can, but unfortunately my coffee machine doesn't speak android at all:crying:, anyway thanks a million bunch for all your great work & help & all ( best of luck with the new upcoming rom btw:good: )
claude96 said:
@daxgirl I'm sure if anyone can !, you can, but unfortunately my coffee machine doesn't speak android at all:crying:, anyway thanks a million bunch for all your great work & help & all ( best of luck with the new upcoming rom btw:good: )
Click to expand...
Click to collapse
Thanks! We really appreciate!
As for the rom. .. it will be awhile I guess...
In a mean while I will get back to writing instructions.
Some screenies added to the op...
Sent from my awesome g920f powered by 6thGear
daxgirl said:
Thanks! We really appreciate!
As for the rom. .. it will be awhile I guess...
In a mean while I will get back to writing instructions.
Some screenies added to the op...
Sent from my awesome g920f powered by 6thGear
Click to expand...
Click to collapse
You're most welcome, and thank you of course ( pics ( app ) looks great btw )
PS : about your rom, a word to the wise ( if I may ! ), just make it bug free as much as possible ( witch is no problem for you I'm sure ), don't throw everything in it at 1st ( users will always want more and new stuff of course, normal ! ), again thanks a million and best of luck, keep up the great work.
Amazing! Now I need to fold up my sleeves and start learning something.
Sent from my SM-N9005 using Tapatalk
claude96 said:
You're most welcome, and thank you of course ( pics ( app ) looks great btw )
PS : about your rom, a word to the wise ( if I may ! ), just make it bug free as much as possible ( witch is no problem for you I'm sure ), don't throw everything in it at 1st ( users will always want more and new stuff of course, normal ! ), again thanks a million and best of luck, keep up the great work.
Click to expand...
Click to collapse
This is a wonderful idea and this is exactly our intention always. We are not for being the best or the fastest or the most unique. We are all that in our hearts It's just we are too jumpy from thing to thing... and we never manage to finish a rom between all our ideas... I am starting to think we might not have been meant to
kmokhtar79 said:
Amazing! Now I need to fold up my sleeves and start learning something.
Sent from my SM-N9005 using Tapatalk
Click to expand...
Click to collapse
My dear friend, if anyone can, YOU CAN!!! I have every faith in you!!!
Second post with instructions now contains an explanation of basic idea and how the app works... The rest after I wake up. It's almost 5am here and I am semi conscious... See ya guys tomorrow!
great, good job as always, i was thinking about one thing: when we add a new mod we learned to put our "key" in settings system database, so my idea is:there is a way to make a general observer that read all the "key" in system database so as to update our choices in real time?

[dexdump] εxodus >TRACKERS< apk static analysis

>TRACKERS< apk static analysis was already available, on android, with AddonsDetectors ; thanks to non-profit εxodus, we have an open source, multi-platform tool, to analyze embedded trackers in apk, on android & PCs, using dexdump.
With it, Rom-developers can scan their already built apps, like webview or Turbo (DeviceHealthServices Google LLC), to countercheck their 'integrity'.
Analysis is based on cross examination of εxodusJSON & dexdump*apk. On android, dexdump can be found in /system/bin https://exodus-privacy.eu.org/media/static_analysis.png
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
For Playstore installed apps only , you can straight use open-source εxodus.apk https://play.google.com/store/apps/details?id=org.eu.exodus_privacy.exodusprivacy, or directly query online.
On Android, check pilot apk ClassyShark3xodus.apk to cross-analyze classes with 361 Exodus' trackers; LongPress touch, on "launch-able (via icons)" packages_list, displays all full classes.
: added unique permission READ_EXTERNAL_STORAGE to scan *.apk, including ones not yet installed with any FileManager.
: included app_PackagesInfo.apk to scan ALL installed packages (via 2°screen/3dots)
: simple mime +fastscroll +icons
: sub-stats via About/3dots
: sharedUserid and permission.READ_LOGS detection
: search & basic quickToggle switch option
Click to expand...
Click to collapse
Edit : NOW ON F-Droid https://f-droid.org/en/packages/com.oF2pks.classyshark3xodus/​
Press on class to get synthetic viewer.
No internet required + zero permissions !
KitKat: due to missing getCodeCacheDir()/api21 ClassySharks can crash after multiple successive attempts
Click to expand...
Click to collapse
On PCs with python3 (&virtualenv), check exodus-standalone to scan any kind of apps package: *apk.
Otherwise with bash (& attached aapt-dexdump_Linux64.tar.gz with lib64/libc++.so) and working grep -P (pcre) you can also perform any apk like (latest Playstore) firefox61.0.2:
./dexdump firefox.apk | grep "Class descriptor" | sed 's/ Class descriptor : //' | grep / | sed 's/\//./g' |sort | uniq > tt.txt
curl -s https://reports.exodus-privacy.eu.org/api/trackers | grep -Po '"code_signature":.*?[^\\]",' | sed 's/"code_signature": //' | sed 's/"",/".",/' | sed 's/|/",\n"/g' | sed 's/"//' | sed 's/",//' | sort | uniq | sed -n '1!p' | xargs -I {} grep {} tt.txt
or simply use attached today signatures :
cat signatures20182408.txt | xargs -I {} grep {} tt.txt
To get more info on apk :
./aapt d badging firefox.apk
On android copy firefox.apk on sdcard
cd sdcard && curl32 -s https://reports.exodus-privacy.eu.org/api/trackers | grep64 --buffer-size=10000K -o '"code_signature":.*?[^\\]",' | sed 's/"code_signature": //' | sed 's/"",/".",/' | sed 's/|/",\n"/g' | sed 's/"//' | sed 's/",//' | sort | uniq | sed -n '1!p' > signatures.txt
--> code signature of these trackers in firefox
Code:
Adjust...com.adjust.sdk. *41
Google Analytics...com.google.android.gms.analytics. *112
Google Firebase Analytics...com.google.android.gms.measurement. *125
LeanPlum...com.leanplum. *262
[εxodus-STANDALONE: python exodus_analyze.py firefox.apk]
Code:
=== Information
- APK path: firefox.apk
- APK sum: 31ca22d9977f14b0cf13fa0075ac2acc96070491086498819f1c9adbf92223a8
- App version: 61.0.2
- App version code: 2015574793
- App UID: 0992532694558859C09D4071243035F6FE5A20EC
- App name: Firefox
- App package: org.mozilla.firefox
- App permissions: 32
- android.permission.GET_ACCOUNTS
- android.permission.ACCESS_NETWORK_STATE
- android.permission.MANAGE_ACCOUNTS
- android.permission.USE_CREDENTIALS
- android.permission.AUTHENTICATE_ACCOUNTS
- android.permission.WRITE_SYNC_SETTINGS
- android.permission.WRITE_SETTINGS
- android.permission.READ_SYNC_STATS
- android.permission.READ_SYNC_SETTINGS
- org.mozilla.firefox_fxaccount.permission.PER_ACCOUNT_TYPE
- com.google.android.c2dm.permission.RECEIVE
- org.mozilla.firefox.permission.C2D_MESSAGE
- com.samsung.android.providers.context.permission.WRITE_USE_APP_FEATURE_SURVEY
- android.permission.CHANGE_WIFI_STATE
- android.permission.ACCESS_WIFI_STATE
- android.permission.ACCESS_COARSE_LOCATION
- android.permission.ACCESS_FINE_LOCATION
- android.permission.ACCESS_NETWORK_STATE
- android.permission.INTERNET
- android.permission.RECEIVE_BOOT_COMPLETED
- android.permission.READ_EXTERNAL_STORAGE
- android.permission.WRITE_EXTERNAL_STORAGE
- com.android.launcher.permission.INSTALL_SHORTCUT
- com.android.launcher.permission.UNINSTALL_SHORTCUT
- com.android.browser.permission.READ_HISTORY_BOOKMARKS
- android.permission.WAKE_LOCK
- android.permission.VIBRATE
- android.permission.DOWNLOAD_WITHOUT_NOTIFICATION
- android.permission.SYSTEM_ALERT_WINDOW
- android.permission.NFC
- android.permission.RECORD_AUDIO
- android.permission.CAMERA
- Certificates: 1
- Issuer: countryName=US, stateOrProvinceName=California, localityName=Mountain View, organizationName=Mozilla Corporation, organizationalUnitName=Release Engineering, commonName=Release Engineering
Subject: countryName=US, stateOrProvinceName=California, localityName=Mountain View, organizationName=Mozilla Corporation, organizationalUnitName=Release Engineering, commonName=Release Engineering
Fingerprint: 920f4876a6a57b4a6a2f4ccaf65f7d29ce26ff2c
Serial: 1282604424
=== Found trackers: 4
- Google Firebase Analytics
- LeanPlum
- Google Analytics
- Adjust
./aapt d badging firefox.apk
Code:
package: name='org.mozilla.firefox' versionCode='2015574793' versionName='61.0.2' platformBuildVersionName=''
install-location:'internalOnly'
sdkVersion:'16'
targetSdkVersion:'23'
uses-permission: name='android.permission.GET_ACCOUNTS'
uses-permission: name='android.permission.ACCESS_NETWORK_STATE'
uses-permission: name='android.permission.MANAGE_ACCOUNTS'
uses-permission: name='android.permission.USE_CREDENTIALS'
uses-permission: name='android.permission.AUTHENTICATE_ACCOUNTS'
uses-permission: name='android.permission.WRITE_SYNC_SETTINGS'
uses-permission: name='android.permission.WRITE_SETTINGS'
uses-permission: name='android.permission.READ_SYNC_STATS'
uses-permission: name='android.permission.READ_SYNC_SETTINGS'
uses-permission: name='org.mozilla.firefox_fxaccount.permission.PER_ACCOUNT_TYPE'
uses-permission: name='com.google.android.c2dm.permission.RECEIVE'
uses-permission: name='org.mozilla.firefox.permission.C2D_MESSAGE'
uses-permission: name='com.samsung.android.providers.context.permission.WRITE_USE_APP_FEATURE_SURVEY'
uses-permission: name='android.permission.CHANGE_WIFI_STATE'
uses-permission: name='android.permission.ACCESS_WIFI_STATE'
uses-permission: name='android.permission.ACCESS_COARSE_LOCATION'
uses-permission: name='android.permission.ACCESS_FINE_LOCATION'
uses-permission: name='android.permission.ACCESS_NETWORK_STATE'
uses-permission: name='android.permission.INTERNET'
uses-permission: name='android.permission.RECEIVE_BOOT_COMPLETED'
uses-permission: name='android.permission.READ_EXTERNAL_STORAGE'
uses-permission: name='android.permission.WRITE_EXTERNAL_STORAGE'
uses-permission: name='com.android.launcher.permission.INSTALL_SHORTCUT'
uses-permission: name='com.android.launcher.permission.UNINSTALL_SHORTCUT'
uses-permission: name='com.android.browser.permission.READ_HISTORY_BOOKMARKS'
uses-permission: name='android.permission.WAKE_LOCK'
uses-permission: name='android.permission.VIBRATE'
uses-permission: name='android.permission.DOWNLOAD_WITHOUT_NOTIFICATION'
uses-permission: name='android.permission.SYSTEM_ALERT_WINDOW'
uses-permission: name='android.permission.NFC'
uses-permission: name='android.permission.RECORD_AUDIO'
uses-permission: name='android.permission.CAMERA'
application-label:'Firefox'
application-label-af:'Firefox'
application-label-am:'Firefox'
application-label-an:'Firefox'
application-label-ar:'Firefox'
application-label-as:'Firefox'
application-label-ast:'Firefox'
application-label-az:'Firefox'
application-label-az-AZ:'Firefox'
application-label-be:'Firefox'
application-label-bg:'Firefox'
application-label-bn-BD:'Firefox'
application-label-bn-IN:'Firefox'
application-label-br:'Firefox'
application-label-bs:'Firefox'
application-label-ca:'Firefox'
application-label-cak:'Firefox'
application-label-cs:'Firefox'
application-label-cy:'Firefox'
application-label-da:'Firefox'
application-label-de:'Firefox'
application-label-dsb:'Firefox'
application-label-el:'Firefox'
application-label-en-AU:'Firefox'
application-label-en-GB:'Firefox'
application-label-en-IN:'Firefox'
application-label-en-ZA:'Firefox'
application-label-eo:'Firefox'
application-label-es:'Firefox'
application-label-es-AR:'Firefox'
application-label-es-CL:'Firefox'
application-label-es-ES:'Firefox'
application-label-es-MX:'Firefox'
application-label-es-US:'Firefox'
application-label-et:'Firefox'
application-label-et-EE:'Firefox'
application-label-eu:'Firefox'
application-label-eu-ES:'Firefox'
application-label-fa:'Firefox'
application-label-ff:'Firefox'
application-label-fi:'Firefox'
application-label-fr:'Firefox'
application-label-fr-CA:'Firefox'
application-label-fy-NL:'Firefox'
application-label-ga-IE:'Firefox'
application-label-gd:'Firefox'
application-label-gl:'Firefox'
application-label-gl-ES:'Firefox'
application-label-gn:'Firefox'
application-label-gu-IN:'Firefox'
application-label-hi:'Firefox'
application-label-hi-IN:'Firefox'
application-label-hr:'Firefox'
application-label-hsb:'Firefox'
application-label-hu:'Firefox'
application-label-hy-AM:'Firefox'
application-label-in:'Firefox'
application-label-is:'Firefox'
application-label-is-IS:'Firefox'
application-label-it:'Firefox'
application-label-iw:'Firefox'
application-label-ja:'Firefox'
application-label-ka:'Firefox'
application-label-ka-GE:'Firefox'
application-label-kab:'Firefox'
application-label-kk:'Firefox'
application-label-kk-KZ:'Firefox'
application-label-km-KH:'Firefox'
application-label-kn:'Firefox'
application-label-kn-IN:'Firefox'
application-label-ko:'Firefox'
application-label-ky-KG:'Firefox'
application-label-lo:'Firefox'
application-label-lo-LA:'Firefox'
application-label-lt:'Firefox'
application-label-lv:'Firefox'
application-label-mai:'Firefox'
application-label-mk-MK:'Firefox'
application-label-ml:'Firefox'
application-label-ml-IN:'Firefox'
application-label-mn-MN:'Firefox'
application-label-mr:'Firefox'
application-label-mr-IN:'Firefox'
application-label-ms:'Firefox'
application-label-ms-MY:'Firefox'
application-label-my:'Firefox'
application-label-my-MM:'Firefox'
application-label-nb:'Firefox'
application-label-nb-NO:'Firefox'
application-label-ne-NP:'Firefox'
application-label-nl:'Firefox'
application-label-nn-NO:'Firefox'
application-label-oc:'Firefox'
application-label-or:'Firefox'
application-label-pa-IN:'Firefox'
application-label-pl:'Firefox'
application-label-pt:'Firefox'
application-label-pt-BR:'Firefox'
application-label-pt-PT:'Firefox'
application-label-rm:'Firefox'
application-label-ro:'Firefox'
application-label-ru:'Firefox'
application-label-si-LK:'Firefox'
application-label-sk:'Firefox'
application-label-sl:'Firefox'
application-label-son:'Firefox'
application-label-sq:'Firefox'
application-label-sq-AL:'Firefox'
application-label-sr:'Firefox'
application-label-sv:'Firefox'
application-label-sv-SE:'Firefox'
application-label-sw:'Firefox'
application-label-ta:'Firefox'
application-label-ta-IN:'Firefox'
application-label-te:'Firefox'
application-label-te-IN:'Firefox'
application-label-th:'Firefox'
application-label-tl:'Firefox'
application-label-tr:'Firefox'
application-label-trs:'Firefox'
application-label-uk:'Firefox'
application-label-ur:'Firefox'
application-label-ur-PK:'Firefox'
application-label-uz:'Firefox'
application-label-uz-UZ:'Firefox'
application-label-vi:'Firefox'
application-label-wo:'Firefox'
application-label-xh:'Firefox'
application-label-zam:'Firefox'
application-label-zh-CN:'Firefox'
application-label-zh-HK:'Firefox'
application-label-zh-TW:'Firefox'
application-label-zu:'Firefox'
application-icon-160:'res/drawable-hdpi-v4/icon.png'
application-icon-213:'res/drawable-hdpi-v4/icon.png'
application-icon-240:'res/drawable-hdpi-v4/icon.png'
application-icon-320:'res/drawable-xhdpi-v4/icon.png'
application-icon-480:'res/drawable-xxhdpi-v4/icon.png'
application-icon-640:'res/drawable-xxxhdpi-v4/icon.png'
application-icon-65535:'res/drawable-xxxhdpi-v4/icon.png'
application: label='Firefox' icon='res/drawable-hdpi-v4/icon.png'
feature-group: label=''
uses-gl-es: '0x20000'
uses-feature-not-required: name='android.hardware.audio.low_latency'
uses-feature-not-required: name='android.hardware.camera'
uses-feature-not-required: name='android.hardware.camera.any'
uses-feature-not-required: name='android.hardware.camera.autofocus'
uses-feature-not-required: name='android.hardware.location'
uses-feature-not-required: name='android.hardware.location.gps'
uses-feature-not-required: name='android.hardware.microphone'
uses-feature-not-required: name='android.hardware.nfc'
uses-feature: name='android.hardware.touchscreen'
uses-feature: name='android.hardware.wifi'
uses-implied-feature: name='android.hardware.wifi' reason='requested android.permission.ACCESS_WIFI_STATE permission, and requested android.permission.CHANGE_WIFI_STATE permission'
main
other-activities
other-receivers
other-services
supports-screens: 'small' 'normal' 'large' 'xlarge'
supports-any-density: 'true'
locales: '--_--' 'af' 'am' 'an' 'ar' 'as' 'ast' 'az' 'az-AZ' 'be' 'bg' 'bn-BD' 'bn-IN' 'br' 'bs' 'ca' 'cak' 'cs' 'cy' 'da' 'de' 'dsb' 'el' 'en-AU' 'en-GB' 'en-IN' 'en-ZA' 'eo' 'es' 'es-AR' 'es-CL' 'es-ES' 'es-MX' 'es-US' 'et' 'et-EE' 'eu' 'eu-ES' 'fa' 'ff' 'fi' 'fr' 'fr-CA' 'fy-NL' 'ga-IE' 'gd' 'gl' 'gl-ES' 'gn' 'gu-IN' 'hi' 'hi-IN' 'hr' 'hsb' 'hu' 'hy-AM' 'in' 'is' 'is-IS' 'it' 'iw' 'ja' 'ka' 'ka-GE' 'kab' 'kk' 'kk-KZ' 'km-KH' 'kn' 'kn-IN' 'ko' 'ky-KG' 'lo' 'lo-LA' 'lt' 'lv' 'mai' 'mk-MK' 'ml' 'ml-IN' 'mn-MN' 'mr' 'mr-IN' 'ms' 'ms-MY' 'my' 'my-MM' 'nb' 'nb-NO' 'ne-NP' 'nl' 'nn-NO' 'oc' 'or' 'pa-IN' 'pl' 'pt' 'pt-BR' 'pt-PT' 'rm' 'ro' 'ru' 'si-LK' 'sk' 'sl' 'son' 'sq' 'sq-AL' 'sr' 'sv' 'sv-SE' 'sw' 'ta' 'ta-IN' 'te' 'te-IN' 'th' 'tl' 'tr' 'trs' 'uk' 'ur' 'ur-PK' 'uz' 'uz-UZ' 'vi' 'wo' 'xh' 'zam' 'zh-CN' 'zh-HK' 'zh-TW' 'zu'
densities: '160' '213' '240' '320' '480' '640' '65535'
native-code: 'armeabi-v7a'
For odex /system packages; check
-PC: {baksmali list classes} on *.odex or {dextra} on *.vdex http://newandroidbook.com/tools/dextra.html
-android: {oatdump --oat-file=} on *.odex
For android check attached Magisk systemless module with aapt32 curl32 (curl 7.43.0-DEV Android 6.0.1 armv7-a-neon) and grep64 (pcre2grep version 10.22 2016-07-29)
More info for: "tracking software on smartphones" https://theintercept.com/2017/11/24...stine-trackers-found-in-popular-android-apps/
Related tools: https://github.com/ashishb/android-security-awesome
So you make this app now on fdroid? Could there be a way to have it also display all classes not already defined.
Like, 2 options:
1- show classes detected by Exodus signatures
2-
show classes not detected by Exodus signatures
and not com.android.*
and not com.google.*
and not com.firstpartypackage.*
And then a search option
That would be like a way to find new stuff.
Oh, and another complementary tool you might be interested in is called Dexplorer
https://play.google.com/store/apps/details?id=com.dexplorer
I love that you made this. It's raw output and styling gives a feel that "I'm analyzing something" and "wow! Look at all of that crap!"
The only thing I might change on the branding is the icon and name. The only reason I recognized it was because it had Exodus in the name. Maybe 10 other people in the world would make that connection. Just an opinion.
Or give it a snazzy tagline like "The World Famous Zuckerberg NSA Cryptominer Detector- GDPR Edition". That will turn heads.
Thanks!
ClassySharkExodus upgrade to latest ExodusPrivacy database is on the go on F-Droid: 202
More info https://gitlab.com/oF2pks/3xodusprivacy-toolbox
LongPress gives access to all classes.
jawz101 said:
...
show classes not detected by Exodus signatures
...
And then a search option
...
Click to expand...
Click to collapse
For xda Only, attached in first post is edition with search option; also attached is app_PackagesInfo which includes additional full scan option (plus sorted permissions, with '=3' when granted). I will finalize these cosmetics on F-Droid later.
@jawz101 , btw; Etip Exodus wip database is now accessible: https://etip.exodus-privacy.eu.org/trackers/export , thx for your previous extractions.
EDIT : added basic quick Toggle to switch between full & Exodus classes list without recalculation.
Just discovered this on fdroid. Cool app
Hello
ClassyShark3xodus conflicts with PackageInstaller when opening an APK. It asks every time if I want to open with PackageInstaller or ClassyShark3xodus even though I choose Always for PackageInstaller. There are no defaults set for ClassyShark3xodus and defaults are set for PackageInstaller.
I'm using ClassyShark3xodus 1.0-7 from F-Droid on my OnePlus 7 Pro (see sig).
yochananmarqos said:
ClassyShark3xodus conflicts with PackageInstaller when opening an APK. It asks every time if I want to open with PackageInstaller or ClassyShark3xodus even though I choose Always for PackageInstaller. There are no defaults set for ClassyShark3xodus and defaults are set for PackageInstaller.
I'm using ClassyShark3xodus 1.0-7 from F-Droid on my OnePlus 7 Pro (see sig).
Click to expand...
Click to collapse
For the conflict, it is solely related to manifest intent declaration : https://bitbucket.org/oF2pks/fdroid...oid/app/src/main/AndroidManifest.xml#lines-34.
Uninstall ClassyShark and try F-Droid safe Stanley app (same process intent) to countercheck your PackageInstaller behaviour.
If you don't have Magisk installed, then it looks like a bug in Oneplus rom: ClassyShark (& Stanley) doesn't use any privileged rights (conversely to PackageInstaller) nor su; I suggest a bug report on Oneplus forum (?).
With Magisk "remounts", it's possible PackageInstaller get loose : give a try to foss GhostCommander to check what happens with [OpenWith] .apk option and PackageInstaller selected.
btw I wish you could post on xda the json of OP7pro from my deviceInfos fdroid app https://forum.xda-developers.com/android/apps-games/appfoss-googleserviceframework-gsf-t3849908 ; so I could see OP7pro generics (they are no private infos in the json).
oF2pks said:
For the conflict, it is solely related to manifest intent declaration : https://bitbucket.org/oF2pks/fdroid...oid/app/src/main/AndroidManifest.xml#lines-34.
Uninstall ClassyShark and try F-Droid safe Stanley app (same process intent) to countercheck your PackageInstaller behaviour.
If you don't have Magisk installed, then it looks like a bug in Oneplus rom: ClassyShark (& Stanley) doesn't use any privileged rights (conversely to PackageInstaller) nor su; I suggest a bug report on Oneplus forum (?).
With Magisk "remounts", it's possible PackageInstaller get loose : give a try to foss GhostCommander to check what happens with [OpenWith] .apk option and PackageInstaller selected.
btw I wish you could post on xda the json of OP7pro from my deviceInfos fdroid app https://forum.xda-developers.com/android/apps-games/appfoss-googleserviceframework-gsf-t3849908 ; so I could see OP7pro generics (they are no private infos in the json).
Click to expand...
Click to collapse
No, I don't have Magisk installed. I'm waiting on my unlock code.
I attached the json file from Kaltura.
yochananmarqos said:
No, I don't have Magisk installed. I'm waiting on my unlock code.
I attached the json file from Kaltura.
Click to expand...
Click to collapse
(thx for json, I wish more xda users could throw their json so I could update the app: initially, I thought xda could be interested to settle a global coherent central database (for forums headers ? @MikeChannon ) to help cross-development through similar devices (OEM kernel , soc ...)).
I have uploaded new softened ClassyShark3xodus(202) in post#1 ; normally Oneplus PackageInstaller.apk should use this in manifest:
<intent-filter android:priority="1-99">​<action android:name="android.intent.action.VIEW" />​​<category android:name="android.intent.category.INSTALL_PACKAGE" />​<category android:name="android.intent.category.DEFAULT" />​​ <data android:scheme="content" />​<data android:scheme="file" />​<data android:mimeType="application/vnd.android.package-archive" />​</intent-filter>​
you can check apk's manifest.xml (and many more...) with attached app_PackagesInfo-debug13.apk.
NEW in xda/debug post#1:
ClassyShark3xodus : file sha256 (as shown in fdroid' index.xml)
app_PackagesInfo : signature decryption cert with sha1/256
Awesome project, please keep it up! Exodus is good, but too slow to run from phone, and it only works with apps from PlayStore. Regards.
Suggestions
I'm poking through the apps on my system, but it took me a while to find the legend; I expected the first menu item to be a list of supported trackers, not a general about popup. Having looked at it for a while now, I've got a large number of comments regarding issues, usability, style, observations, suggestions, etc. Most of them are fairly minor, just renaming menu items and small tweaks for usability, but some documentation is needed in-app.
rename menu item to 'about'
move legend to its own menu item (Related: 1, 2, 11, 14)
format the legend text so it appears the same as the items in the main screen (or use a picture) (Related: 2, 11, 14)
change the urls in the about menu to be clickable
don't highlight package names in white, it looks weird
for gray background on system apps, make the entire background (margins/padding) of the outer element gray, not just the text part. Alternatively, just changed the text color.
consider making the popup screen when tapping an app into a horizontally scrollable view; the hashes/fingerprints don't have to break onto a separate line from the label sha256.
add margins to the screen that pops up on tap; after the loading animation goes away, the letters seem to be only 1px from the window edge, there should be a border of at least 5px around the entire window
Changing the sort method should be labeled as such, I didn't know the funny arrow meant sort until I tapped it
The 'super' label in the menu makes no sense. It should be renamed to Permissions or PackageInfo or Trackers or some such, depending on the view.
In PackageInfo view, there should be something to explain the asterisk and snowflake before the permission label, as well as the ^✓ after it. The nulls should be removed. Consider changing this entire section to a table with headers (*, ☸, permission, group, dangerous, instant, privileged, development, appop, preinstalled, etc) with an explanation of exactly what dangerous, development, *, ☸, and other less obvious terms mean, either on-tap or in a legend somewhere. (Related: 14, 2)
When you tap an app, the information should be cached until the app is closed, to prevent waiting for the work to be done again.
PackageInfo and manifest should be exportable (Related: 15, 17)
Legend for the list of trackers symbols (°, ?, ², μ) (Related: 11, 2)
Having a full package explorer is hardly necessary, but it might be nice to be able to unzip the apk to the sdcard for exploring with another app, along with the list of trackers found in the app and the list of activities, other metadata. (Related: 13, 17)
Firefox Nightly (org.mozilla.fennec_aurora) shows up as having a shared userid, however the package it lists (org.mozilla.fennec.sharedID) doesn't appear to be installed. The other Mozilla apps installed are Klar (org.mozilla.klar), Firefox Lite (org.mozilla.rocket), and Firefox Preview (org.firefox.fenix), none of which are shown as sharing userids.
I can't make selections to copy from various popups to the clipboard. (Related: 13, 15, 16)
After processing an app, save the results for it (more than just #12) until the app is updated.
After processing an app, update the main view; maybe have different symbols or app colors to indicate if an app has been analyzed, and further if any signatures were found.
Yes, it's a long list. Feel free to ignore me, I won't get offended.
New version uploaded: ClassyShark3xodus216-debugSoft.apk with latest Exodus database (216) update and dynamic|☢ androidManifest.xml for primary screen (longclick), 2nd screen will still use static|✇ parser. (more info: https://forum.xda-developers.com/showpost.php?p=80190710&postcount=5798)
@yochananmarqos , this xda edition is softened, can you confirm if working on Oneplus7 without interfering with PackageInstaller.apk ?
App_PackagesInfo is also updated with same manifest dynamic1/static2 behavior.
hi @Efreak2004 , sorry for delay and thank for your interest; here are few I can tell:
-11 In PackageInfo view, there should be something to explain the asterisk and snowflake before the permission label, as well as the ^✓ after it. The nulls should be removed. Consider changing this entire section to a table with headers (*, ☸, permission, group, dangerous, instant, privileged, development, appop, preinstalled, etc) with an explanation of exactly what dangerous, development, *, ☸, and other less obvious terms mean, either on-tap or in a legend somewhere. (Related: 14, 2)
indeed , I have to finalize that with 7#
-12 When you tap an app, the information should be cached until the app is closed, to prevent waiting for the work to be done again.
the app generates extra-huge cache (~Gb): I even decided to use a "brute force" removal of them.
-13 PackageInfo and manifest should be exportable (Related: 15, 17)
use longpress 11#
-14 Legend for the list of trackers symbols (°, ?, ², μ) (Related: 11, 2)
https://gitlab.com/oF2pks/3xodusprivacy-toolbox
° for missing: Amazon new active tracker AWS Kinesis is missing
² for Etip stand-by: Mozilla/Telemetry is now in Etip https://etip.exodus-privacy.eu.org/
µ for micro non-intrusive: Acra;
? when uncertain.
(will be added to menu.)
-15 Having a full package explorer is hardly necessary, but it might be nice to be able to unzip the apk to the sdcard for exploring with another app, along with the list of trackers found in the app and the list of activities, other metadata. (Related: 13, 17)
use apps_packages Infos attached in post #1 or https://f-droid.org/en/packages/com.oF2pks.applicationsinfo/
my idea is also to dub with Chairlock (with root/su possible permission removal and more...). I may add this functionality; Xplore already do that.
-16 Firefox Nightly (org.mozilla.fennec_aurora) shows up as having a shared userid, however the package it lists (org.mozilla.fennec.sharedID) doesn't appear to be installed. The other Mozilla apps installed are Klar (org.mozilla.klar), Firefox Lite (org.mozilla.rocket), and Firefox Preview (org.firefox.fenix), none of which are shown as sharing userids.
this is Mozilla decision : I show these, because permissions can be silently granted to others apps that would use same sharedID; in case of Firefox, sharedID is defined but doesn't seem to be used by any other(?).
-17 I can't make selections to copy from various popups to the clipboard. (Related: 13, 15, 16)
use longpress in SubTotals (others popups are wip 11#)
-18 After processing an app, save the results for it (more than just #12) until the app is updated.
(the app generates extra-huge cache (~Gb): I even use a "brute force" removal of them. ) extensive analysis should be done with dexdump (or other) command https://gitlab.com/oF2pks/3xodusprivacy-toolbox ,
-19 After processing an app, update the main view; maybe have different symbols or app colors to indicate if an app has been analyzed, and further if any signatures were found.
(the app generates extra-huge cache (~Gb): I even use a "brute force" removal of them. ) will never have enough "free" time for that : imho, such behavior should be part of aosp inner rom (omnirom ?).
oF2pks said:
this xda edition is softened, can you confirm if working on Oneplus7 without interfering with PackageInstaller.apk ?
Click to expand...
Click to collapse
Confirmed.
Sent from my OnePlus 7 Pro using XDA Labs
willing to develop App_PackagesInfo further? I'd suggest some simple yet "cool" menu additions: enable/disable app, view in Yalp or Play Market (in addition to F-Droid) and (maybe) stop the app.
And also not so trivial: adding apps lists to save and load just as https://f-droid.org/wiki/page/com.projectsexception.myapplist.open does.
What does it mean if the application name is displayed in orange, and what if in black (most names are black)?
Exodus database new release (eof269)
New soft (no [android:scheme="content"]) build is up in #1st post, Exodus database new release (eof269): 344 (304+40 signatures for 258+34 recensed trackers.)
(this debug edition is now using xdaShark3xodus name since eof236)
CubaoX said:
What does it mean if the application name is displayed in orange, and what if in black (most names are black)?
Click to expand...
Click to collapse
Devs can decide to define/use a common [ShareUserId] for multiple apps (with also same cert); thus permissions declared & granted in one app can be silently acquired in others using that same ShareUserId: these apps with ShareUserId activated, are shown in orange with corresponding string.
General doc is "behind" primary line in 3dots' 1st screen : tap on {344 exoTrackers(292)}.
ildar_prophet said:
willing to develop App_PackagesInfo further? ...
Click to expand...
Click to collapse
@ildar_prophet further improvements will move to Chairlock https://forum.xda-developers.com/android/apps-games/appfoss4-1-chairlock-complete-t3956991
Exodus database new release (eof357)
@SkandaH (@MishaalRahman ) following latest xda#news on appZygote/Selinux, I've uploaded up-to-date ClassyShark3xodus_357 with appZygote service detection : if any, a toast will popup at start & refresh and service name will also be displayed in 2nd screen (apk sub-totals).
post#1: https://forum.xda-developers.com/attachments/classyshark3xodus357-debugsoft-apk.5224635/
Following https://cs.android.com/search?q=FLAG_USE_APP_ZYGOTE , such isolated process is documented in frameworks/base/framework-minus-apex/android_common/xref30/srcjars.xref/com/android/internal/R.java as:
/**
* <p>
* @ attr description
* If true, and this is an {@link android.R.attr#isolatedProcess} service, the service
* will be spawned from an Application Zygote, instead of the regular Zygote.
* <p>
* The Application Zygote will first pre-initialize the application's class loader. Then,
* if the application has defined the {@link android.R.attr#zygotePreloadName} attribute,
* the Application Zygote will call into that class to allow it to perform
* application-specific preloads (such as loading a shared library). Therefore,
* spawning from the Application Zygote will typically reduce the service
* launch time and reduce its memory usage. The downside of using this flag
* is that you will have an additional process (the app zygote itself) that
* is taking up memory. Whether actual memory usage is improved therefore strongly
* depends on the number of isolated services that an application starts,
* and how much memory those services save by preloading and sharing memory with
* the app zygote. Therefore, it is recommended to measure memory usage under
* typical workloads to determine whether it makes sense to use this flag.
*
* <p>May be a boolean value, such as "<code>true</code>" or
* "<code>false</code>".
*
* @ attr name android:useAppZygote
*/
public static final int AndroidManifestService_useAppZygote=18;
/**
(Let me know of any suggestions for upcoming official release on F-Droid.)
@yochananmarqos , I fixed bugs on this xda debug flavor: screen shortcuts and *.apk file direct scanning via GhostCommander/OpenWith (since Manifest is softened...)
Hi, @oF2pks!
Thank you for your ClassyShark3xodus app!
I downloaded it from F-droid, and have been
using it on a Note9/Android 10 & Note20 Ultra/Android 11. It is an awesome utility to find out what apps are doing on your phone!
What are "Permissions: misses" (in the "Super" panel, listed in the three-button menu)?
Thanks!
Exodus database new release (eof422)
New soft (no android:scheme="content") build is up in #1st post, Exodus database new release (eof422): 528+34 signatures for 403+31 identified trackers.
Nota: you have to uninstall previous xda debug flavor due to signature change for it, in AndroidStudio (_ArticFox ?).
jsusang said:
...What are "Permissions: misses" (in the "Super" panel, listed in the three-button menu)?
...
Click to expand...
Click to collapse
These are declared permissions in an apk that are missing on your device for both global framework-res.apk (Android) & all other installed apps.
As example, on android11, Playstore (com.android.vending) will miss android.permission.BLUETOOTH_SCAN which only appears in android12/framework-res.apk (like ~17 new others in API level 31)
Some can also miss because of deprecation like android.permission.ACCESS_SUPERUSER.
As for "Permissions: duplicates", be aware the result depends on the active filter: only relevant when Permissions are sorted by Name...
Hi, @oF2pks!
When I open Classyshark (https://f-droid.org/en/packages/com.oF2pks.classyshark3xodus/), this toast message appears from AppZygote:
Code:
appZygote:
com.android.chromeorg.chromium.content.app.SandboxedProcessService0
I have a Samsung smartphone with Android 11.
What is the meaning of this warning? Did I install an hacked apk? Did I get a malware or something like that? I downloaded it from f-droid.

[TOOL] ADB-Overlay [2.2.2.0 - .Net 6]

Heyho together,
after my P9-Lite and P10-Lite toolkit i thought, it's time to build a more generic version. Here it is, the ADB-Overlay!
The main point of this project is to serve a GUI for ADB. Currently, there is a File-Explorer, Remote-Desktop, Shell interface and APK installer implemented. You can also READ the contacts if your device is rooted and has sqlite3 installed. But a picture tells more as 1000 words... So here is a preview of what you'll get.
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
But anyways, i'm not responsible for any damage done to your device! For example, if you delete some files/folders on root lvl etc.
Component Info
Remote-Desktop:
Left-Click = Touch
Right-Click = Swipe with duration
The keyboard is nearly fully supported, i have written a kind of WPF -> Android key-mapper. So even combos like SHIFT+A-Z, SHIFT+0-9, ALT+A-Z and ALT+0-9 should work. The base for the key-mapping is a 102 keys keyboard with en-GB or de-DE layout. If you have another setup, some keys may on other positions.
The screenshots will be created under "ADB-Overlay\Screenshots\Screenshot.yyyy-MM-dd_HHmmss.(bmp | gif | jpg | png | tiff | wmp)".
-
If the device is booted in the recovery, the Remote-Desktop is only a viewer, because the recoveries doesn't support "input tap x y" nor "input keyevent XXX".
Shell:
The input box supports CTRL-A-Z, so you'll have the ability to send for example CTRL+C to stop a remote process. If you want use Copy & Paste onto the input box, use the Right-Click menu.
Tested OS
Win 7 | 8 | 8.1 | 10 | 11 (32Bit/64Bit in VM-Ware)
Win 7 | 8 | 8.1 | 10 | 11 (64Bit Native)
Tested Devices
Android Emulator some Versions (min. 2.x) in AVD
Android x86
HTC Sensation -/ XE (non-/rooted)
HTC One M9 (non-/rooted)
Huawei P9 Lite (VNS-L21, 22, 23, 31, etc.) (non-/rooted)
Huawei P10 Lite (WAS-LX1A, etc.) (non-/rooted)
Huawei Mate 9 (THX to @Tecalote)
Huawei Mate 10 Lite (THX to @Chisetdel31260)
Huawei P9 (EVA-al10) (THX to @reynard1)
Sony Xperia X (THX to @FoxTheLegend)
Pixel 4 (THX to @squabbi)
Requirements
Android: min. 2.x
Platform: x86/x64 (Windows)
Frameworks: min. .NET 6 / .NET 6 Desktop Runtime x86/x64
(Installed ADB/Fastboot driver)
Download
Mirror: See attachments
Mirror #1: My FTP [USR/PW=ADB-Overlay]
Mirror #2: GoogleDrive
Mirror #3: Dropbox
Mirror #4: Mega
DO NOT MIRROR MY FILES! DO NOT COPY MY THREADS!
Bug-Tracker
If you can't use the SDK-Updater or the Version is 0.0, just close the ADB-Overlay delete the "platform-tools" directory and restart the ADB-Overlay.
If the device won't connect via W-/Lan, check which version of android you are running... the latest version "SP2A.220505.002, May 2022" seems to break "Developer settings -> USB-Debugging -> Debug over W-/Lan"... To get it working anyways, just open a cmd prompt in the "platform-tools" folder, connect your device via USB and execute the following command: "adb tcpip 12345" (or some other port). After that, you should be able to connect your device via W-/Lan.
App Freeze
If the ADB-Overlay freezes during startup or by connecting a rooted device, the solution is to update the su binary. I encountered this problem yesterday on an older device running Android N. After an update to Magisk Canary [build 21005] the problem was solved.
Changelog
DD.MM.YYYY | (A) = Added | (C) = Changed | (D) = Deleted | (F) = Fixed | (R) = Recoded | (U) Updated
----------------------------------------------------------------------------------------------------------------------------------------------------
30.04.2022 [2.2.2.0]
(F) The SDK updater.
27.04.2022 [2.2.1.0]
(F) A freeze which occured on some FTP-Servers which doesn't implement RFC 959 properly.
11.04.2022 [2.2.0.0]
(U) General improvements in terms of speed and connectivity.
(U) The FTP config is now AES-256 encrypted for better security.
29.11.2021 [2.1.0.0]
(U) To .Net 6
(U) General improvements in terms of speed and connectivity.
25.07.2021 [2.0.2.0]
(A) ADB-Sideload
(U) ADB and Fastboot binaries.
(F) Some transfer issues (Binary <-> Socket)
(F) The platform-tools updater.
12.01.2021 [2.0.1.0]
(F) All freezes on the Tree-/ListView.
(A) ColumnHeader sorting on the Explorer and Apk-Manager ListView.
(A) Sort options for all header not only Name, Size, Date and Type.
(C) Sorting happens now in the background (So no more freezes here too.).
.-Older changes-.
12.12.2020 [2.0.0.0 - .Net 5]
Switched to .Net 5.0
(F) FTP-Updater timeout issue
(C) Brotli compression to .Net native
17.09.2020 [1.18.46.0]
(A) sendrecv_v2 for Android 11
(A) Brotli compression for file transfers on Android 11
29.03.2020 [1.17.46.0]
(A) Cut (via Context-Menu and "Ctrl+X")
(A) Copy (by default and via Drag'n'Drop by holding "Ctrl" during drop)
(A) Move (via Drag'n'Drop by holding "Shift" during drop)
(NOTE: Move is now enabled for on-device, device-to-device, local-to-device and device-to-local transfers.)
(C) The copy window, it will now display "Copy" or "Move" depending on the current operation.
16.03.2020 [1.16.46.2]
(F) The updater buttons, now they are also disabled during an download/check.
15.03.2020 [1.16.46.1]
(F) File/Folder interaction with those which contains "\s _ - ' , * & ~ | < > ( ) [ ] { }" in their names.
07.03.2020 [1.16.46.0]
(C) The synchronous IO to fully asynchronous IO.
(A) The Edit-Window, this will temporary download the file and open it locally in an application defined for this file type or with the "OpenAs" dialog.
(C) The UI, buttons which can't be used are now "grayed out".
12.02.2020 [1.15.46.1]
(F) The re-connection bug on the FTP-View. (Which also caused the updater to fail.)
(F) The (2 sec) freezes after copy/delete/tar.
(C) The info bar, added the modify date.
31.01.2020 [1.14.46.0]
(F/A) The timestamps for access, changed, modify.
(C) The "Properties Window", added the mentioned fields and resized the height a bit.
(A) Create File on the FTP-View.
30.12.2019 [1.13.46.0]
(F) The FTP TLS/SSL problem, now all procedures (implicit/explicit) should work without problems. (I tested this the last days with multiple servers, also the proxy's socks4/a|5 should now work with TLS/SSL.)
(U) All 3 explorers, they relay now on an shared generic base explorer which implements most of the features for all 3 views. So it's guaranteed that all views will behave the same.
(U) All 3 explorer views, changed the spacing's and the "edit textbox" (on rename) a bit, so that they look a bit more like the default explorer.
(A) IComparable<T> and IEquatable<T> to all List-/TreeViewItems so you get a pre-sort during item parsing. (I thought it would work a bit nicer, but hey, now it's implemented^^)
(R) Optimized the item (file/folder) parser for both Android & FTP.
18.12.2019 [1.12.46.1]
(F) The broken SDK-Updater, where you saw in the log file a "BindingException".
(F) The "SocketException" on app close. Reason for this was, that i disposed the "DeviceMonitor" after i killed the adb-server, but the monitor tried to check in some cases (10 sec refresh rate) for changes, after the server was already down.
(A) The "remount" option for mounts to the properties window. (You'll get also a little warning, each time you attempt to remount a mount point.)
(C) Resized the properties and the updater windows a bit.
17.12.2019 [1.11.46.0]
(F) The remote desktop for 16-Bit devices.
(R) Root detection
(R) Mount detection (added support for Android 2.x)
(R) The properties view, as mentioned, there is now a more valuable overview.
14.12.2019 [1.10.46.0]
(A) A version banner to the title bar.
(R) Nearly the whole caching logic inside the local ,Android and FTP explorer.
(R) The mount ([Device]) overview, now you'll see all mounts returned from "mount" and the assigned "df" data, if available. (The next build will include a more valuable overview in the PropertiesWindow. Like the mount options etc.)
(R) The remote desktop, i moved the "color correction" inside the pixel-buffer copy process. This will save a lot of time and boost the FPS in my TWRP up to 80++ per sec.. (That was so much, that .Net even couldn't dispose the sockets so fast as i requested a new one... This ended in an waiting queue overflow... So i decided to limit the FPS to 30-40 this is enough to have a clean view.) - Also NOTE: BOOTED IN ANDROID, WILL DECREASE THE FPS TO 2-3 DEPENDING ON THE RESOLUTION OF YOUR DEVICE! THE ONLY SOLUTION FOR THIS IS, START ADB WITH ROOT RIGHTS. (I added a internal switch, which will detect if adb runs as root, if so, i don't relay on the frame-buffer-service of adb. Instead, i use the bare metal (/sys/class/graphics/fb0/) to get the correct buffer values and then i read directly from "/dev/graphics/fb0".) AGAIN, NOTE: THIS WILL NOT RAISE THE FPS UP TO 80++, BUT THE FPS WILL INCREASE UP TO 15-25.
11.12.2019 [1.9.46.1] (HotFix)
(A) The mistakenly removed overwrite protection on item rename. (Android)
(R) The Copy & Delete view, the media-scanner, if activated, will now only run once at the end of an copy or delete action.
(R) Sym-/Directory/File detection, there was in rare cases a wrong detection where a SymDirectory was treated as an SymFile.
(F) The "Create New Textfile" action. (Android)
10.12.2019 [1.9.46.0]
(F) An ArgumentNullException which was raised during "mount" parsing. (On the "device" view.)
(F) The renaming issue, where you got, "The element couldn't be renamed!", if the name hasn't changed.
(A) Windows shortcuts to the TreeView of the Windows explorer. (Even the original one hasn't that feature )
(A) Hiding the ".lnk" extension on any Windows shortcut.
(A) Internal auto updates to the remote explorers (Android/FTP). So you have a kind of "pseudo" FileSystemWatcher.
(A) The re-sorting of the items after an rename action.
(D) Some code duplication. (Saved all together ~12 kb)
(R) Unnecessary refreshes and replaced them with internal cache logic's.
02.12.2019 [1.8.46.0]
(F) An ObjectDisposedException which was sometimes raised after symlink parsing and/or file transfers.
(C) The channeling on the ADBSocket, from an ConcurrentDictionary to an simple array with locks, this increased the transfer speed.
(U) The dlls to the latest versions.
24.07.2019 [1.7.46.0]
(R) The config files, both, the config.xml and the config.ftp.xml got an structure update. The old/current config files will be migrated to the latest version. So there should be no data loss in any way.
(A) A version banner to the Android and FTP view
(C) The adb directory from "ADB-Overlay\adb" to "ADB-Overlay\platform-tools"
(A) The SDK-Updater
(A) Auto-SDK-Update - If activated, this will check once every 24h for an update, but only on startup of the ADB-Overlay. (NO Tasks or something)
Info
The updater will only check "https://dl.google.com/android/repository/repository-11.xml". This XML gets downloaded and parsed, if the "platform-tools" version is newer as the used one, you'll get an popup which offers the download for the latest version.
The Auto-SDK-Update is by default disabled.
28.06.2019 [1.6.46.0]
(F) A memory leak which occurred by removing a device (Android View -> Closing an tab)
(F) A memory leak which occurred by removing a server (FTP View -> Closing an tab)
(R) Improved the directory parsing speed
(A) A progress bar to the copy window (green during transfer and on completion | red on failure or cancellation)
04.06.2019 [1.5.46.0]
(C) The versioning:
1 = Major
5 = Minor
46 = Framework Version (4.6)
0 = Hotfix
(A) A few speed improvements to the Remote-Desktop.
(A) The updater/-menu
(A) Auto-Update - If activated, this will check once every 24h for an update, but only on startup of the ADB-Overlay. (NO Tasks or something)
Info
The updater will only check my FTP for a ".version" file. This gets downloaded and parsed, if the version is newer as the used one, you'll get an popup which offers the download for the latest version. (NO logs and NO telemetry!)
The Auto-Update is by default disabled.
28.05.2019 [0.0.0.5]
(A) The "APK Manager" to the Android -> Tools menu
(A) {<-} & {->} buttons to the addressbar
(A) The "Install" option to the remote explorer -> ListViewItem context menu (only shown if the item is a apk)
(R) Added the missing options to the APK Installer (e.g. Downgrade, Test-Package, etc.)
(R) Optimized the "symlink" parsing
01.05.2019 [0.0.0.4]
(F) An exception which was raised after you tried to open any "Tool" on an disconnected device.
(A) A Battery Monitor to the Android -> Tools menu
29.04.2019 [0.0.0.3]
(A) Remote-Viewer when booted in the recovery
(A) A screenshot format selector (bmp | gif | jpg | png | tiff | wmp) to the Remote-Desktop
(A) A color correction switch to the Remote-Desktop
(A) Links to the German forum post
20.04.2019 [0.0.0.2]
(F) An issue during item renaming - Reason was maybe the switch from .NET 4 to .NET 4.6, seems the UI updates on textboxes are no longer only on focus got/lost, instead they are now after any change.
(A) Contextmenu (Listview) -> New -> Text Document
(A) Replacements for "New Directory", "Group (New)", "Server (New)" to the german language, so you get now after such an action the correct "Neuer Ordner", "Neue Gruppe", "Neuer Server".
(C) The FTP Copy/Delete action, you can now close the control connection and leave only those windows open until they are done. Both, the Copy and Delete action using now their own connection which is no longer bound to the control connection.
(C) Moved the "Keep Alive" checkbox (FTP -> Servermanager -> Account) to FTP -> Servermanager -> Connection
13.04.2019 [0.0.0.1]
Initial release
Great job. my huawei mate 10 lite is recognized. currently my smartphone is on rom original stock rne - l21c432b340 emui 8.0 not rooted. and my PC is a windows 7 64.
Works for my Xperia X - and thanks for your help!
I'm flattered to be in your contacts screenshot I was still using your prototype you had sent to me years ago!
Works very well on my Pixel 4!
squabbi said:
I'm flattered to be in your contacts screenshot I was still using your prototype you had sent to me years ago!
Works very well on my Pixel 4!
Click to expand...
Click to collapse
Hey Bro
long time not seen. Hehe yeah the good old Multi-Explorer ;p - Still using it my self, it's more or less my playground before i implement things in this tool.
If you want and have some spare time we can modify this beauty. I also reworked nearly the whole AndroidCtrl.dll, there you have now solid filestreams, strongly typed FilesystemInfos (Like the one from the .NET fw) and lots of other handy stuff. Like framebuffer access in Android and recovery mode. I also implemented a ADBridge class which is an instanced wrapper for the 2 static ADB classes (binary/socket).
Best Regards,
Sebastian
this is what im looking for a while
Thank you very much
here is some suggestion
1.better ui
2.edit build prop in the realtime
btw my phone is Huawei P9(eva-al10) rooted android 8.0 work very well
k1ll3r8e said:
Hey Bro
long time not seen. Hehe yeah the good old Multi-Explorer ;p - Still using it my self, it's more or less my playground before i implement things in this tool.
If you want and have some spare time we can modify this beauty. I also reworked nearly the whole AndroidCtrl.dll, there you have now solid filestreams, strongly typed FilesystemInfos (Like the one from the .NET fw) and lots of other handy stuff. Like framebuffer access in Android and recovery mode. I also implemented a ADBridge class which is an instanced wrapper for the 2 static ADB classes (binary/socket).
Best Regards,
Sebastian
Click to expand...
Click to collapse
Sounds great! I'm looking to get back into toolkit making later this year, I'm keen to see the improvments to your library! :good:
Great job. we can navigate and copy files efficiently.
Only one thing is missing. Why not keep file timestamp for last access and modifie dates? or let us choose the option to keep it or not.
skyrail01 said:
Great job. we can navigate and copy files efficiently.
Only one thing is missing. Why not keep file timestamp for last access and modifie dates? or let us choose the option to keep it or not.
Click to expand...
Click to collapse
Heyho,
which Android version are you using and on which action (pull/push) does the timestamps get lost?
Normally i preserve the timestamps but on some Android versions the "timestamp" field in the ADB-Protocol is ignored.
Maybe i can set the timestamps on an other way, but therefore i need to know the version.
Regards,
Sebastian
PS:
Some code where i set the timestamps
Upload
Code:
public void Close(DateTime fileCreationTime)
{
if (_ch?.IsConnected ?? false)
{
if (CanWrite)
{
int o = 0, w;
byte[] d = new byte[8];
d.SetUInt32LE((UInt32)SyncCmd.DONE, 0);
d.SetUInt32LE(ToUnixTime(fileCreationTime), 4);
//...
}
_ch.Close();
}
}
Download
Code:
//...
using (FileStream dfs = destination.Open(FileMode.Create, FileAccess.Write))
{
using (AFileStream sfs = OpenRead())
{
sfs.CopyTo(dfs, DMAX, msg, cancellationToken);
ct = sfs.CreationTime;
}
}
//...
if (msg.State == TransferState.Done)
{
destination.CreationTime = ct;
transferEventHandler?.Invoke(Client.ID, new FileTransferEventArgs(Client.ID, msg));
return true;
}
//...
Thank you really great program keep it up
Hey,
I am operating under lineageOS 16 on Galaxy S5 (klte), using adb 1.0.39 on windows 10 64-bits, either via wifi or usb connect.
I check file dates under Windows, in console mode with far manager (M: last write time, C: creation time, A: last access time).
I am using linux command ls -l under adb shell from Windows command line to list files pushed to Android.
When pushing files from Windows to Android, only M is preserved, with a 2 hours offset (ES file explorer tells it is modified date) Maybe daylight issue or bad timezone.
When pulling files from Android, only C is preserved
When I pull back to Windows, files pushed to Android, all original date is lost.
But I am pretty sure we can preserve last access, modified and creation date as I could see Adbexplorer (another project) pull files keeping M and A (adb pull -a).
Hope I give you enough details.
k1ll3r8e said:
Heyho,
which Android version are you using and on which action (pull/push) does the timestamps get lost?
Normally i preserve the timestamps but on some Android versions the "timestamp" field in the ADB-Protocol is ignored.
Maybe i can set the timestamps on an other way, but therefore i need to know the version.
Regards,
Sebastian
PS:
Some code where i set the timestamps
Upload
Code:
public void Close(DateTime fileCreationTime)
{
if (_ch?.IsConnected ?? false)
{
if (CanWrite)
{
int o = 0, w;
byte[] d = new byte[8];
d.SetUInt32LE((UInt32)SyncCmd.DONE, 0);
d.SetUInt32LE(ToUnixTime(fileCreationTime), 4);
//...
}
_ch.Close();
}
}
Download
Code:
//...
using (FileStream dfs = destination.Open(FileMode.Create, FileAccess.Write))
{
using (AFileStream sfs = OpenRead())
{
sfs.CopyTo(dfs, DMAX, msg, cancellationToken);
ct = sfs.CreationTime;
}
}
//...
if (msg.State == TransferState.Done)
{
destination.CreationTime = ct;
transferEventHandler?.Invoke(Client.ID, new FileTransferEventArgs(Client.ID, msg));
return true;
}
//...
Click to expand...
Click to collapse
skyrail01 said:
Hey,
I am operating under lineageOS 16 on Galaxy S5 (klte), using adb 1.0.39 on windows 10 64-bits, either via wifi or usb connect.
I check file dates under Windows, in console mode with far manager (M: last write time, C: creation time, A: last access time).
I am using linux command ls -l under adb shell from Windows command line to list files pushed to Android.
When pushing files from Windows to Android, only M is preserved, with a 2 hours offset (ES file explorer tells it is modified date) Maybe daylight issue or bad timezone.
When pulling files from Android, only C is preserved
When I pull back to Windows, files pushed to Android, all original date is lost.
But I am pretty sure we can preserve last access, modified and creation date as I could see Adbexplorer (another project) pull files keeping M and A (adb pull -a).
Hope I give you enough details.
Click to expand...
Click to collapse
Heyho,
THX for that info, i'll check the "adbd" source which LOS uses, maybe there is the prob. According to "adb pull -a" i'll also have a look at the adb source, because i think they do some "touch" stuff. Because the ADB-Protocol it self only supports creation/last modified time. In the source is a another "struct" for "STA2" (stat 2) command. But i have never seen a adb binary which supports this. (All binaries use the "STAT" command.)
EDIT 1:
Just checked the adb source again, seems they changed it a bit...
(This is the current STAT (v1) header)
Code:
# cmd name STAT or STA2 // 4 bytes
st->st_mode = msg.stat_v1.mode; // 4 bytes
st->st_size = msg.stat_v1.size; // 4 bytes
st->st_ctime = msg.stat_v1.mtime; // 4 bytes
st->st_mtime = msg.stat_v1.mtime; // 4 bytes
My HTC-One M9, Sensation, VM-Ware (Kitkat - Nougat) none of them has a 20 byte header. ALL of them return a 16 byte header.
Code:
CMD // 4 bytes
Mode // 4 bytes
Size // 4 bytes
CTime // 4 bytes
So it seems the protocol is highly inconsistent... I'll check how much time gets lost by calling touch on each file, because, currently i open a sync channel via an smart-socket, transfer the file and read all data provided by the protocol header. This is really fast, but if i have to spin up each time another channel to get a shell for the touch, this will increase the time each copy needs. Because, a shell depending on the version (v1, v2), has a lot checks you need to perform, specially the shell_v2 because it's like a ssh protocol.
EDIT 2:
Just for completeness, i'm pretty sure your device also sends only a 16 byte header for the stat v1 command, because:
(This is a cut of my implemented "Stat(byte[] bytes)" class)
Code:
if (c == (uint)SyncCmd.STA2 && bytes.Length >= 72)
{
ID = SyncCmd.STA2;
Error = bytes.GetUInt32LE(4);
Dev = bytes.GetUInt64LE(8);
INode = bytes.GetUInt64LE(16);
Mode = bytes.GetUInt32LE(24);
NLink = bytes.GetUInt32LE(28);
UID = bytes.GetUInt32LE(32);
GID = bytes.GetUInt32LE(36);
Size = bytes.GetUInt64LE(40);
ATime = bytes.GetInt64LE(48);
MTime = bytes.GetInt64LE(56);
CTime = bytes.GetInt64LE(64);
}
else if (c == (uint)SyncCmd.STAT && bytes.Length == 16)
{
ID = SyncCmd.STAT;
Mode = bytes.GetUInt32LE(4);
Size = bytes.GetUInt32LE(8);
CTime = bytes.GetUInt32LE(12);
}
As you can see, the both structures differ in there field order, if your device would send a 20 byte header, the test (bytes.Length == 16) wouldn't match. And you couldn't download a file.
EDIT 3:
After playing a while with "stat" and "touch" on some Android versions, i decided to rely on those functions. The next build should restore and write the correct timestamps.
EDIT 4:
Well, setting timestamps on the SD-Card doesn't work, also, setting timestamps on the "internal" SD-Card doesn't work either. Seems that it's related to the underlying FS. If i try to set the timestamp on an ext4 partition, it works. So it doesn't make sense to rewrite the push/pull functions because the return of touch for 99% of the time will be "touch: '/sdcard/TWRP/test.pdf': Operation not permitted". So it's simply a time waste during the copy procedure. BUT, i'll implement it at least for the download, so u'll get the correct timestamps on Windows.
EDIT 5:
Added a screenshot of the new "Properties Window" which also proves that the download timestamps are now correct.
(Btw. C doesn't mean created - it means changed)
Code:
stat /sdcard
File: `/sdcard' -> `/storage/self/primary'
Size: 21 Blocks: 0 IO Blocks: 512 symbolic link
Device: 1h/1d Inode: 4432 Links: 1
Access: (777/lrwxrwxrwx) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 1970-01-01 01:00:00.000000000
Modify: 1970-01-01 01:00:00.000000000
Change: 1970-01-01 01:00:00.360063176
Little update about the "creation time". After a bit research i found this post on Stack Exchange, there is explained that the so called "birth time" is stored since ext4 as part of the INode field. But it seems you need a special version of "stat" to read this info, it's called "statx". But so far i could see, Android doesn't support this feature, maybe some kernel does but it seems that it's more the rare case.
Regards,
Sebastian
Thanks for the update!
I was wondering what could be causing a small delay in copying files over, once the progress finishes, the transfer dialog remains frozen for a 1-2 seconds. I'm copying over a photo, so around 2MB.
squabbi said:
Thanks for the update!
I was wondering what could be causing a small delay in copying files over, once the progress finishes, the transfer dialog remains frozen for a 1-2 seconds. I'm copying over a photo, so around 2MB.
Click to expand...
Click to collapse
Heyho ,
yup i still working on it. It seems that the "Task.Delay()" isn't performed inside the Task itself, instead it's executed on the main thread. The reason for the freeze is, that i try to show the last result, otherwise the copy window would close immediately after the last element and you couldn't see if it's transferred or not. So i keep it like windows, wait 1,5-2,5 sec before closing the window.
The delay you might feel extremely is the "Media-Scanner". It runs on the end of each copy/delete action, the reason for this is, that files pushed/copied by adb are not reported to the MTP interface. So you couldn't see those files if you connect your device after such an adb copy via MTP. Also files/folders deleted by adb are also not reported to the MTP interface. So you will see those elements via MTP if you don't perform manually the "Media-Scanner" lookup. - But if you work only with adb for example, you could turn the "Media-Scanner" off. All device based explorers and of course adb will see those files/folders at any times. (But if you need those files/folders for exchange you should keep the "Media-Scanner" on )
EDIT:
This is executed for every file which is copied/pushed/deleted.
Code:
_adb.Device.Manager.ActivityManager.Broadcast("android.intent.action.MEDIA_SCANNER_SCAN_FILE", "-a", string.Concat("-d 'file://", remotePath, "' > /dev/null"));
EDIT 2 (a bit off-topic):
You could also simply use the "Media-Scanner" with my AndroidCtrl.dll. The calls are:
Code:
//"_adb" is a instance of "ADBClient"
_adb.Device.IO.MediaScanner.CreateScanList(string remoteDirectory, MediaScanMode mode);
_adb.Device.IO.MediaScanner.CreateScanList(string remoteDirectory, MediaScanMode mode, CancellationToken cancellationToken);
_adb.Device.IO.MediaScanner.CreateScanList(string remoteDirectory, IList<string> files, MediaScanMode mode, CancellationToken cancellationToken);
_adb.Device.IO.MediaScanner.ScanDirectory(string remotePath, MediaScanMode mode);
_adb.Device.IO.MediaScanner.ScanDirectory(string remotePath, MediaScanMode mode, CancellationToken cancellationToken);
_adb.Device.IO.MediaScanner.ScanDirectory(IEnumerable<string> remotePaths, MediaScanMode mode);
_adb.Device.IO.MediaScanner.ScanDirectory(IEnumerable<string> remotePaths, MediaScanMode mode, CancellationToken cancellationToken);
_adb.Device.IO.MediaScanner.ScanFile(string remotePath, MediaScanMode mode);
_adb.Device.IO.MediaScanner.ScanFile(IEnumerable<string> remotePaths, MediaScanMode mode);
_adb.Device.IO.MediaScanner.ScanFile(IEnumerable<string> remotePaths, MediaScanMode mode, CancellationToken cancellationToken);
_adb.Device.IO.MediaScanner.ScanObject(ITransferMessage message, MediaScanMode mode);
EDIT 3:
Found the bad boy, seems "Task.Delay()" only works when used in "async" context. Now the "freeze" is gone, you can move the window until it vanishes. So, in the next update those "freezes" are gone.
---
Little Update:
@squabbi
The next update includes a little editor as suggested by @reynard1. A screenshot can be found as attachment.
Regards,
Sebastian
k1ll3r8e said:
**snip**
EDIT 3:
Found the bad boy, seems "Task.Delay()" only works when used in "async" context. Now the "freeze" is gone, you can move the window until it vanishes. So, in the next update those "freezes" are gone.
---
Little Update:
@squabbi
The next update includes a little editor as suggested by @reynard1. A screenshot can be found as attachment.
Regards,
Sebastian
Click to expand...
Click to collapse
Woohoo! Thanks for digging into it! I'm glad you found the culprit haha.
Looking forward to that editor feature! Do you know if it's possible to integrate with Windows Explorer? It's probably a little harder, but something like how WinSCP can drag files from the remote to a local Explorer window.
If that's a little difficult, would this be possible to implement? If I drag and drop a folder/file onto the local pane, it will change directory (and highlight the file if a file was dragged onto the local pane). Just to make it easier to work with folders I have already open.
Still using Windows 7?
squabbi said:
Woohoo! Thanks for digging into it! I'm glad you found the culprit haha.
Looking forward to that editor feature! Do you know if it's possible to integrate with Windows Explorer? It's probably a little harder, but something like how WinSCP can drag files from the remote to a local Explorer window.
If that's a little difficult, would this be possible to implement? If I drag and drop a folder/file onto the local pane, it will change directory (and highlight the file if a file was dragged onto the local pane). Just to make it easier to work with folders I have already open.
Still using Windows 7?
Click to expand...
Click to collapse
Heyho
Yes its definatly possible, we need to use the so called "VirtualFileDataObject". I tried to implement it some time ago, but doesn't worked as expected. But i'll give it another try.
-
Yup, i still use Win 7 as my main system, but i have some VMs running, like my Debian server which serves the documentation and some test sites for my php projects, a few Android x86 Versions and of course a legit Win10 installation to test If everything works.
*Never change a running system! - Currently my main hdd has a uptime of 2689 days with 216 restarts, i think that tells a lot *
---
Little Update:
As the screenshot shows, the editor is working fine so far. (Added also a few more controls.) The only problem i still have is, that if ADB doesn't run as root you can't edit for example the "build.prop". Because ADB can't write the file directly back, so i need to build a kind of "tmp" file. The next problem will be, that you (the user) have to remount the mount point, before you start editing those "root" and "write protected" files. There is also a problem with "binary" files, because the "RichTextBox" screws up when it gets "binary to ASCII/UTF8" transformed data, which ends in an app freeze... So i have to check on some way if the stream contains really text-data, the file extension doesn't help here much because, you know, linux uses also a lot of txt files without any extension.
Update 2:
Just got the "binary" files running... With a super BIG drawback, 248 kb (4069 rows) text results in 269,364 mb memory utilization by the "RichTextBox". - The prob here is, that the ADB filestream doesn't support seek, so i need to load the whole doc in one, which is quiet to much for the "RichTextBox"...
Update 3:
Soo, i wrote a kind of paging for the "RichTextBox" which works so far really nice, at least when it comes to the memory (even during scrolling, with free running wheel, only 15 - 27 mb increase), there is now a fixed amount of rows (40) which will be shown, all other rows are hidden from the "RichTextBox". This opens a few new issues^^ - Currently there is no selection possible which goes beyond the 40 rows. Also insert and delete are a little challenge because, i need to "overwrite" the default behavior with the some "PreviewKeyDown/etc." events... - Looks all a bit hacky, but lets see if it works in the end.
Update 4:
Well, the "RichTextBox" is out of the race^^ - It triggers events more or less random instead when you expect it, it removes blank lines (for example you have 3x "\n", this gets wrapped to 1x "\n") and the best, you remove "\r" during stream reading and the RTB adds it again, also random (some paragraphs get an "\r" some not). Editing text in a solid way without losing something isn't possible with this thing... So i'll try the "TextBox".
Last Update before release:
So, after testing the "RichTextBox" and "TextBox" i ask myself why those controls are there^^. Both can't edit text with more than a few hundert lines, the "TextBox" is at least much better as the "RichTextBox" but it also screws up when i comes to more as 250 kb text. So the "Editor" will be one of your installed applications. I add a little tool window, which offers the temporary download to the windows temp folder, after that i launch the windows "OpenAs" dialog that you can choose the editor you want. Also, i'll attach a "FileSystemWatcher" to the file that the upload automatically happens when you press save in your editor.
Little Info:
It take a few more days for the "edit" update, because i started also to implement the TAP pattern, this increased for example the download speed by factor 6. But to implement it the right way, i have to rewrite a lot of code in the AndroidCtrl.dll and AndroidCtrlUI.dll.
Regards,
Sebastian
k1ll3r8e said:
Heyho
Yes its definatly possible, we need to use the so called "VirtualFileDataObject". I tried to implement it some time ago, but doesn't worked as expected. But i'll give it another try.
-
Yup, i still use Win 7 as my main system, but i have some VMs running, like my Debian server which serves the documentation and some test sites for my php projects, a few Android x86 Versions and of course a legit Win10 installation to test If everything works.
*Never change a running system! - Currently my main hdd has a uptime of 2689 days with 216 restarts, i think that tells a lot *
** snip **
Click to expand...
Click to collapse
That'll be great to see haha, and that does make sense keeping your system as is, if it works, it works.
Thanks for your hard work in checking out what's best for the new edit function. Maybe there's a library out there that can implement a text viewer better? I'm not familiar with WPF libraries, or how many there are.
squabbi said:
That'll be great to see haha, and that does make sense keeping your system as is, if it works, it works.
Thanks for your hard work in checking out what's best for the new edit function. Maybe there's a library out there that can implement a text viewer better? I'm not familiar with WPF libraries, or how many there are.
Click to expand...
Click to collapse
Heyho,
i have had a look on Avalon Texteditor but on StackOverflow is also a discussion about how to open a file bigger than 20 mb. It seems WPF is not that great for such things. I found also another one, written by a lonely dev like me , but it's not maintained since 7 years. So the best way might be, open a installed App which is well designed for that purpose.
A bit off-topic
I nearly finished the TAP implementation for the AndroidCtrl.dll, so far it brought a great speed increase. Also, it consumes less CPU time, for example the remote desktop uses only 3-7% on an Intel I5 with 32 GB memory (but up to 36% on an single-core Intel Pentium M with 1,5 Ghz and 1 GB memory - my old well working Laptop, also with Win7 ). So you might be happy to see all the new "real async" overloads in the lib. (I implemented all from scratch, so there is NO Task.Run() or Task.StartNew() in those functions.)
Edit:
Soo, after a few horrible days, the TAP pattern is now fully integrated! But there is still a little issue with the Remote-Desktop recovery viewer. It seems that everything got a speed boost except the recovery viewer, the viewer is currently nearly 4x slower as before... After i fixed this last problem, i'll release the new asynchronous version.
Regards,
Sebastian

Categories

Resources