We would like to begin from crediting people, who gave us ideas, inspiration and, most importantly, their free time, in order to make v2.0 a reality.
To our dearest friends and talented developers, @tdunham and @DaOldMan: Guys, you OWN this. You made this happen. You pushed us and we pushed you, and together, you, us and rom control, have grown to be what we are today.
No thanks can ever be enough for long nights of applying patches, merging sources, connecting through teamviewer and working out kinks together. @Wuby986 and I are forever in your debt.
Why different thread?
1. The entire application is different. It barely qualifies as an update anymore.
2. All the preferences are different. The way they work is different. It requires new way of doing things. Radically new.
3. new support library and new basic structure.
4. To sum it up... it's too different to maintain same thread for both versions
1. Rom control is an open source project, designed to provide rom builders with a core code for compiling android application for controlling core functions of their roms and mods through Content Provider of Settings.System sqlite table
2. Rom control is designed with consideration of the fact that most rom builders do not have sufficient skills in original android development to build application with this functionality on their own
3. The emphasis is given in this version (even more than previous one) to outsource most conditions and attributes to xml, and so to minimize the need of the user (rom builder) to be subjected to java programming
4. In addition to familiar utilization of ContentResolver to pass data between RomControl and system, the project offers additional properties, such as file based preference, URI selection preference, Direct intent to shortcut app preference, preference listing image thumbnails for previews, script running preference, automated template for "About Us" section, automated dialog for changelog, backup and restore finctionality and more.
5. The project is designed to be compiled in Android Studio using the latest sdk tools and gradle tools.
6. The project essentially is designed to be a system application with privileged access, and therefore needs to be installed in /system/priv-app to be granted some of its permissions
7. The project requires root access for some of its functionality. Mainly running shell scripts with su and killing some app processes.
License and sharing policy:
1. This project is distributed under GNU General Public License as open source code. The copy of said license can be obtained and reviewed here
2. As such, this project is protected from claiming exclusivity by anyone.
3. Any developer wishing to use this code, with accordance to the license, must provide full source code for each updated version. That means, for any new version of the rom including updated RomControl application, a link to full source code of the latest version must be provided.
4. By modifying and using this code, you automatically accept the License conditions and must be compliant with GPL, as stated below:
You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.
5. You're under no obligation to thank us, credit us or tag us in your official postings while distributing your copy.
6. You ARE, however, prohibited from removing our copyright information from our source code.
7. You are obligated to keep the code open under GPL. Failure to provide sources for updated copies of your work will result in complaint first to XDA officials for license infringement and further to GPL legal department.
8. Using the source code on any other forum outside of xda is of course allowed with accordance to the license and sharing policy, provided the sources are kept open and obtainable by anyone.
9. Using apktool to compile a copy of this code after making changes in the decompiled form of someone else's application is strictly prohibited, as the developer will not be able to provide full open source of their version. Any illegal use of any copy of this project can be and should be legally stopped by the owner of the code copy.
10. This voids rule number 12 of xda promising a developer exclusivity over their product. This product is yours, but the code belongs to the public. You are NOT TO HOLD COPY OF ROM CONTROL EXCLUSIVE.
To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others.
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.
1. Installed and updated android sdk, including but not limited to: Android SDK Build-Tools 24
Android SDK Platform-Tools 24
Android support repository 33
Google repository, rev 29
Latest android support library
2. Android studio version AT LEAST the latest stable version (currently 2.1.2), you can use the canary channel as well, currently on 2.2.0 preview 5.
3. Updated gradle tools
4. Working knowledge of importing project into Android Studio and troubleshooting gradle sync. If you don't know how to, Google it.
5. EXTENSIVE knowledge in android modding:
This project is for rom developers and modders. It helps coordinate between your users and your mods. If you don't build roms or don't have mods, this project means nothing to you.
What support you can expect to get:
1. Code explanation regarding major functionality
2. Adding new preferences and navigation items
What support you CANNOT expect:
1. Setting up android studio
2. Debugging gradle issues and compiling
3. Changing colors, strings, adding themes, design, changing setup... - Android documentation is vast and Stackoverflow is even vaster.
4. Smali modding
5. Private messaging support - DO NOT EVEN TRY
6. Asking for compiled apk file.
This is NOT an application thread. This is NOT an application. This is a SOURCE CODE for MAKING application.
The answer to a question "Can someone give me a compiled version" is "And what are you going to do with it?"
1. Perform full installation of the latest stable version of Android Studio in your environment. You can find info about stable and canary releases here
2. You can have more than one version of android studio installed on single platform. For more information please read further on the same page in section Using Multiple Android Studio Versions. I personally do recommend the latest canary build, which is currently AndroidStudio 2.2.0 preview 5. But you can always go with the stable release. Or beta channel.
3. Make sure your sdk is updated, including sdk for platform 24 (nougat). The compile sdk for this project is 24.
4. Make sure your support repositories are configured and updated.
5. Click on our github repository link on the OP first post and make sure you're connected with your github account. If you don't have one - create it! Why? because you will need to share your sources for this project. And because you all use as mantra that you can mod android apps because it's open source. So BE OPEN SOURCE. Have your name on github.
6. Once you're logged in into github, fork our repository. In the right upper corner of our main git repository you have those buttons:
Click "fork" to make a copy of this repository in your own repositories. Now you have your own repository.
7. On YOUR repository find this green button on the top right above the code, which says "Clone and Download". DO NOT DOWNLOAD ZIP. Instead, click the little "clipboard" icon to copy the .git uri and return to studio.
8. In studio: File > New >Project from Version Control > Git
9. Paste the git uri and choose destination. Click ok. Android studio will import the project from git and open it for you.
10. At this point if you're asked to update gradle build tools or anything else, do it. Wait for gradle to sync with project files. If you get errors, resolve them as referenced. If you cannot, google is your friend.
We WILL provide some support for initial importing of the project and setting it up for a very limited period of time. Gradle can be a tricky business. Please be sure to provide us with specific error from gradle log and a line in the gradle script on which the error is made.
11. We WILL know if your errors are because you didn't update sdk and build tools. And we will kick your butts for posting without following instructions. Remember, our time is valuable and given to you for free. Our instructions are clear and we made a huge effort to write them. If you can't be bothered with following them, beware.
12. Once the gradle is done syncing without errors, just in case, click Build > Rebuild Project. Once that is done without errors and it says BUILD SUCCESSFUL, you can start building your project following the instructions on the next post.
It will be easier for you to navigate through project files. For that:
On the left panel on top, below the android studio menu, find this:
This is what your project will look right after you import it. This is module view. By default it is categorized and to work with it you need some understanding of this view.
Click the 2 arrow icon which is circled in blue and select "project"
Your structure will now change.
Navigate into the project by the following path: Project name > app > src > main
Now you will see directories, like: java, res, assets... and so on.
This is your working directory. You will be making your code changes here.
2. Find a file called nav_drawer_arrays.xml. It is located in res/values folder. Double click on it to open.
You will see the following 3 arrays inside. The first one is a reference array (simple typed array) and the other 2 are strings arrays.
Those are WORKING ARRAYS. When you run the app as it is now, you will see all the items created in the navigation drawer based on this info.
Please read the comments we wrote in the xml file for you:
<!--The following array is for icons you want to use for your items
You can create new icons bu right clicking the drawable folder and choosing
New vector drawable
You have a great selection of items in xml vector format.
Those are supported starting lollipop.
YOU SHOULD NOT USE PNG. not even material one. Vectors will work best with any device density.
Once you have created the vector, reference it as regular drawable in the array below.
MAKE SURE THE ITEMS IN ALL 3 ARRAYS CORRESPOND IN ORDER AND ALL 3 ARRAYS ARE SAME LENGTH-->
<!--This array is for your items titles.
Use @string reference, so later on your app can be translated with ease
KEEP THE ORDER BETWEEN ALL YOUR ARRAYS-->
<!--This array is the most valuable one
Here you put the file names of the preference files you create in your xml directory
THEY MUST BE PRECISE AND CASE SENSITIVE!!! DO NOT ADD .xml SUFFIX-->
<string-array name="nav_menu_xml_file_names" translatable="false">
3. Let's say you have 10 preference files in directory called xml. That means you will want to have 10 items referring to your preference files in the navigation drawer. That means you will need to have 10 items in EACH array. Create 10 empty preference files. DO NOT COPY THE ONES FROM RC v1.0. Just right click the xml folder, choose "New" and choose "New XML resource file". Give it a name and click ok. Leave them empty for now. create all the icons you need for them in the navigation drawer.
4. Populate the arrays with titles, icons and xml names. You're done. You now have a working items in the navigation drawer. You do not need any changes in java files. the items are being generated on run time and their onClicks redirected accordingly. If you run the app right now you should have 10 empty preference files.
We strongly encourage you to keep the ui_prefs.xml file and references to it in your project while you're working on it. It contains most valuable information about the kinds of preferences we have included and their various usages. You can remove it from arrays before making the release version. You can have it as last item in your arrays and use it as test dummy to see how things should work properly
Installing and running your builds in Android Studio:
First of all - data or system app?
The simple answer is SYSTEM. And not just system - we need some high level permissions, so definitely /system/priv-app. Why?
So for that we dig deeper into android permission system.
1. Writing settings into settings storage database:
This permission was revoked from data apps on Marshmallow. Meaning, THEORETICALLY, that only system apps can write into Settings.System. So how come we can write when the app is installed as data app? Oh, this is where THEORETICALLY part comes in. Permission to write system settings is declaired in framework in such a way, that it allows data apps to write there if they target sdk lower than 23 in their build. That permission level is called "pre23". That is why in our gradle we have a somewhat peculiar sdk division for building. Let's look at the image:
As you can see, target sdk is set to 22. This is not by mistake. This is by design so if you want to test the basic functionality of the app by installing debug version in data, it will not crash every time you flip a switch.
This is the definition of pre23, we target sdk 22 so the pre MM permissions can be achieved by running the app in data.
Although all of you will be including this app in your roms in system priv-app, you will be working with it quite alot as you build it. We want you to be able to run it from data if you wish so. if we target sdk 23 and up it will never run from data, unless installed also in system.
You are free to change this to 23 or 24. But NEVER run it while installed only in data then. It will crash like a drunken monkey.
Also, changing it to 23 or 24 for TARGET sdk is meaningless. It's not better because it's a higher number. For target sdk it makes no difference.
2. Running reboot
We run reboot functions in a proper android shutdown sequence. Any of you that are familiar enough with linux kernel based platforms KNOW the system should not be shut down by killing it's process.
Therefore all reboot functionality in our app is native android reboot. For THAT we absolutely need the app to have an initial copy in priv-app. If the app is only installed in data, clicking on any reboot option, either from reboot menu or from reboot dialogs, will result in FC in your face. the following permissions cannot be obtained by data apps NEVER EVER.
Android doesn't give a damn about root permissions. When we run command under su we talk to the linux kernel through shell. We do not run it on android level. Android is NOT linux. There is NO android permission which is compiant with su.
When we are talking about android application permissions, we are talking about PackageManager, which is android framework system service, that grants the permissions to perform certain action. Package manager does not know su. It is not part of linux platform. It is android. Android is not designed to have root access. Not on any level. it does not recognize unix commands by default.
So when we execute your scripts, android doesn't do it. Our application code doesn't do it. We just pass it to the kernel as runtime command. Remember that, when you come complaining that your scripts don't run. We can't help it. If the kernel refuses to execute them, something is WRONG in the script syntax or structure.
4. So data or system? The answer is - when you build and test run your app - BOTH
Can you run apps from android studio while one of the copies is installed in system? Absolutely. As any system app, app is allowed to have an update.
The most important thing is for that update to have same signature and same package as the app in system. Once the app is installed in priv-app it has privileged permissions. You can after that, as oyu build, install updates in data, so you don't have to push every single test build into system and reboot, and all privileged permissions will work.
Gradle is a build tool. You can read on history of gradle online. It was not developed with any relation with android. Google decided to adopt gradle as their primary build tool for their primary development environment for android and hence, android gradle plugin was born.
Build tool is a way to "put things together in orderly fashion". In essence, android application is a bunch of files in folders. Making it into a running product is a matter of some complexity. Connecting java to resources, signing, packaging, updating manifest, setting primary configs and build related configs, compiling java, compiling dependencies, including multiple modules, being able to have several builds and flavors in one project - this is what gradle does for us.
Gradle, in a manner of speaking, is a bunch of tasks. Tasks are executed in specific order. Files are being copied, deleted, compiled and packaged as result of single button click.
Android gradle plugin comes with specific predifined tasks. We can also write our own tasks, which we usually do, for our own usage. We will talk about OUR specific tasks later on in the advanced section.
For now we will talk about basic android gradle tasks, such as assembleRelease, assembleDebug, installRelease, installDebug and so on.
1. Clicking RUN button
If you have a look on the top panel of android studio you have this green "play" button next to a selection box which, usually, says "app". Like this:
This is what will appear on the run menu when you first open the project and it's done syncing with gradle. If the "app" selection box has a red "X" on it, means gradle is syncing now or has failed to sync and you need to find out WHY and fix it. Once there is no red "x" current configuration is ready to run.
When you click the green run button, it will run whatever task is in the selection box. When it says "app" in the selection box and you click run, it will do the following:
1. Compile debug build
2. Install it on your connected device
3. Run it
So what is "app"? App is the main of the module we want to run. It is the only module in our project. So by running "app", we run the RomControl application on a device in DEBUG mode.
Why is it good to run in debug mode? For 2 reasons:
1. Run "app" configuration supports instant run. You can read more on instant run here. This will push the code changes into your running app on device and apply immediately. It's very handy if you add a preference or 2 and want to test how it looks or works. If instant run is impossible for your current build tools, android studio will tell you and it will tell you why. It usually means that you need to upgrade android gradle plugin. This can be done with ease.
2. Running app module in debug mode will give you full stack trace if there is an error. It will be easier for you to copy the log here for us to have a look at and debug. Or debug yourselves.
The downside of running debug mode?
1. It's somewhat slow. Meaning the app on the device is a little slow in debug mode (although now it's not as slow as it used to be)
2. Debug mode by definition runs from data. So none of the reboot options will work. So if you want to test actual changes that require reboot from our app, you need to have a system priv-app version installed. You can have a debug version installed in priv-app and then you can use instant run, like we spoke before.
2. So how do we make a release version?
1. Generating signing key
For that we need a signing key. We already made a full prepared platform for you to run release build in our app gradle build file. All you need to do is create a signature and make some little edits. So, let's roll.
To create a signature please follow these instructions
Please remember or write down the following:
1. Path where you create the signature
2. Key password
3. Store password
4. Key alias
You do not need to generate the release build just yet. Just finish creating your own keystore and remember where you put it.
Now go to the parent folder where your rom control project sits. For example if you put it in AndroidStudioProjects folder, in the same folder create a folder called "keys" (no caps, just "keys"). Copy your keystore there. Or originally create it there.
Now go back to android studio. to the left project panel (provided it is in project view, like we asked you to make it) and scroll down... You will see at the very bottom some singleton files, like gradlew, gradlew.bat, gradle.properties and so on. One of the files there is called key.properties. Double click on it to open.
Inside you will see 4 strings. Like this:
Out in your actual key information. The one you used to create your key. you need to make changes to all 4 fields.
As you can see we used relative path to the keystore. Which is why it's supposed to be in the parent folder of your folder containing your project in direcroty called "keys".
2. Telling gradle to use our signing key for release builds
On the left project panel look inside the "app" module folder. On the bottom of it, after the AndroidManifest.xml file, you will see a builg.gradle file. Double click to open it.
This is a gradle file for building our app module. You will see there are alot of configurations related to android build there. It will look something like this:
You need to un-comment the sections pointed to with red arrows. To comment or un-comment the section in android studio, select the section and click "ctrl + /"
Now you should be ready to build the release version. Let's test that:
1. On the right upper corner of the studio window you will see little vertical "gradle" tab. Like this
Click on it. A side window till open with gradle tasks. Like this:
2. Open app > tasks > build
3. Find a task called assembleRelease and double click on it.
4. Wait for it to finish. You will see tons of things running in the gradle console window on the bottom. Provided you didn't mess up any of the previous steps, it will work fine.
5. Once it's done, check that you did now have errors and that build was successfull.
6. If all is good, open in file manager your project folder > app > build > outputs > apk. There you should see your freshly compiled release version. Release version is called simply RomControl.apk. it is already zipaligned and signed. You can go ahead and use it in your rom, push it into priv-app and test. So on.
3. So every time I need to run assembleRelease and push the apk into priv-app and reboot? NO!!!
1. Once you run your first assembleRelease, take that apk and push it into system priv-app. Reboot your device.
2. Now look again into the app > tasks in the gradle window on the right. You also have there "install" tasks. Open it and find "installRelease". Connect your device with app installed already in priv-app and double click on installRelease. This will install the release as UPDATE in the DATA apps. This is so you don't need to push the app to device as you're building and testing. You can make code changes, install release as data and run it FULLY. Becasue you have the original sitting in the system, it will have all the premissions for the reboots. So you can build and test from data.
3. Please remember that as you build and test only the data version of your app is updated. So once you are done testing and the build is final, run assembleRelease and take the final apk from the outpute/apk folder to include in your rom.
4. Do I need to go to the gradle menu on the right all the time to run installRelease? NO!!!
After you run a task from the gradle menu have a look at the run button on the top panel. Surprise! It doesn't have "app" selected anymore. it has the latest task you ran!!! Look:
Now if you click the "run" button it will run the selected task. If you want to select another task from the tasks you used in the past, Just select from the selection box menu and click run.
So which build to run and when?
1. If you're building and testing continuously, we recommend keeping the app as debug in data only and NOT TO USE the reboot options.
For adding preferences and building your ui you don't need to use reboot options. Just click LATER on reboot dialogs if you include reboot options.
So you can use instant run, switch to "app" configuration and keep running in debug mode from data as you build.
2. When you go further into preference testing, we recommend uninstaling the debug version. creating signed release version and push into priv-app. From this point on run installRelease task to instal release update in data as you build and correct and test scripts and reboot options.
3. When ready to go final release with your rom, use task assembleRelease to build your final version and include it in your rom zip
4. Commit latest changes to your github repository
Uploading sources to git
1. Provided you followed our instructions and forked the project source code and then cloned it to studio, it is now connected to your forked git project.
2. Any new file you add will ask if you want to add it to git. And will turn it's color to green if added. Any file that is not added will have brown color.
3. To add brown colored file to github, right click it, choose git > add
4. You should have the following available on the top panel:
The green arrow is for commiting and pushing changes to github. Once you push it the following window will open:
5. Check what files you would like to commit. For example, never commit key.properties file which contains your key password.
6. Write description of your commit and choose from the blue button selector box commit and push.
7. Make a habit of committing your work daily or at least on a new feature basis. It easier to follow for you and also serves as backup.
We would be happy to talk more about gradle and various tasks, but this post had a specific purpose. To teach you how to manipulate build types and use it to you advantage. Please ask us specific questions about gradle tasks related to your build.
1. For this release we made a major change in how preferences are handled. They are not handled anymore. They handle themselves.
2. For that to happen we needed to subclass ALL native android preferences except PreferenceScreen and PreferenceCategory.
3. What does it mean to subclass? That means we created java classses which extend (resemble) native android preferences and we wrote our own implementation of how they should behave, how they should load their values and write their values.
4. That being said - there is no more standard android preferences in this project. No more SwitchPreference, no more CheckboxPreference, no ListPreference... None of those.
5. Two reasons for that:
1. We didn't want you to get lost in special conditions anymore. We wanted you to be able to set if the preference should restart systemui from xml file when you declare preference. For that we needed to add custom xml attributes. For that we needed a preference class to be able to acknowledge that. So we needed a custom preference class.
2. We wanted the preference to manage itself in by reading and writing from and to database. Instead of fragment running endless iterations and conditions. When our new preferences are born (attached to the screen), they get their value from the database directly. No one needs to set values to them. When they are changed, they know to write into database directly. From their own class. Not containing fragment doing that for them.
4. What happens if we use regular android preferences? Like SwitchPreference or ListPreference?
Nothing! Absolutely nothing will happen nor to this project, nor to your database and, MOST IMPORTANTLY, nor to your mods.
It will act like normal preference. It will not write to database. Your mods will not be affected and WILL NOT WORK.
5. Custom attributes for value changing preferences and RunScriptPreference
1. app: packageNameToKill
This attribute is of type string and you will need to provide which app you want to restart when this preference changes value.
This is a boolean type attribute, which is by default set to true. That means that if you don't set this attribute and you DO set the package name to kill, it will restart the app you want without warning as soon as the value has been changed. If it is set to "false", upon value change a dialog will appear with app icon and test informing user that for this action to take effect an app restart is required. They can then choose to kill app now or cancel the dialog and kill it later.
This is also a boolean type of preference which by default is set to false. If you set it to "true", upon preference value change a dialog will appear, informing the user that reboot is required for this action to take effect. good example for that is changing the default app intent to open on home button double click. That needs framework reload.
If rebootRequired is set to true and you ALSO set package name to kill, reboot takes preference. Package to kill will be ignored.
1. Two state preferences (meaning - can be true or false)
MySwitchPreference & MyCheckboxPreference
<!--Following category shows variety of two state preferences-->
android:title="Two stated preferences test category">
<!--Normal Switch preference-->
android:title="Normal test switch"/>
<!--Switch preference which will throw a dialog that app reboot is required-->
android:title="Kill app with dialog switch"
<!--Switch preference which will in ADDITION to actual work, also silently restart app with given package-->
<!--Note, that isSilent attribute is by default TRUE. So you don't need to specify it if you want silent app restart-->
android:title="Kill app silently test switch"
<!--Switch preference which will throw a dialog that following it's action device reboot is required-->
<!--Please note, even if you specify the need to kill app, once the rebootDevice attribute is TRUE, kill app attributes are ignored-->
android:title="Switch reminding of need to reboot"
<!--We can use kill app on checkboxes as well. Same goes for rebootDevice-->
android:title="Kill app checkbox"
<!--File preference is a very special kind of preference, which works like switch but has different output.
Normal switch preference, like any two state preference, write boolean true/false into preferences.
In our app it also writes 1/0 into database.
File preference doesn't write into database. If it is switched on, it creates a file in our app directory in data.
That name of that file is what you set as key.
This is widely used by @tdunham for global boolean needs in systemui.
Please refer to his guide about setting global boolean to see appropriate smali application for this preference.
This is most useful for mods in smali files where you do not have context access to get content resolver.
Because File class is native java class and checking for it's existence does not require android context.
File preferences can have attribute to kill app or reboot device.--> <!--This is a simple file preference. Note that once it's switched on, a file with the name identical to key is created in
When it's switched off the file is deleted.-->
android:title="New file preference"/>
<!--This file preferences upon change will prompt to kill app-->
android:title="Kill app file preference"
2. Dialog preferences
Custom attributes: alphaSlider, hexValue - both booleans, TRUE by default
<!--The following category demonstrates various ways of using ColorPickerPreference-->
android:title="Color pickers test category">
<!--Normal color picker preference-->
<!--Please note, the hexValue and the alpha are there by default now. If you want to cancel them, you need to specify false-->
android:title="Normal test color picker"/>
<!--Color picker preference without the alpha slider and without the hex value
You can set false to both or one of them-->
android:title="Color picker with no alpha or hex"/>
<!--Color picker preference with kill app option
Note, you can also use rebootDevice attribute, like with two stated preferences-->
android:title="Color picker with app kill"
Custom attributes: app:dependentValue - will enable you to set dependencies upon choosing selected value. If a dependent value is selected by user, the dependent preference will become disabled.
<!--Example of simple list preference with radio button items
You absolutely HAVE to set dafaultValue and it has to be one of your entryValues string arrays
You can use any of the following with kill app attributes or rebootDevice attribute
Note, that you can now use dependency on list preference.
Custom attribute app:dependentValue will allow you to decide which list item, if selected,
will set dependent preferences disabled.-->
android:title="Choose items from the list preference"/>
Custom attributes: app:dependentValue - will enable you to set dependencies upon choosing selected value. If a dependent value is selected by user, the dependent preference will become disabled. app:drawableArray - references array which provides resources for the thumbnail images for each list item app:entryList - references array of strings to provide names for actual list items app:entryValuesList - references array of strings for the entry values to be written to preferences and database for selected list item
<!--Thumbnail list preference is a special kind of preference which allows you to show preview of the selected image
This can be useful f.e. for setting custom bg to toggles in systemui
Needless to say you need to put the same images you put in systemui in Rom Control in drawables
And you need to create 3 kinds of arrays in arrays.xml file. 2 string arrays for entryList and entryValuesList and one simple array
for drawable references. You can see the arrays for the following preferences inside arrays.xml
You have to set default and the default has to be one of entryValuesList strings-->
<!--Example of simple Thumbnail preference with no additional attributes-->
android:title="Simple thumbnail preference"
<!--Example of Thumbnail preference which calls to kill app upon selected item-->
android:title="Kill app thumbnail preference"
Custom attributes: app:intentSeparator - to allow you to set the char which will separate the package name from activity name in the intent component name app:showSearch - boolean attribute which determines whether search field will be available in the dialog window. By default it's TRUE. If you want no search, set to FALSE
<!--The following preference is a special preference that's called IntentDialogPreference
This preference allows you to choose an app from the list. it also conveniently includes search field
This preference writes into database what's called component name for specific system needs.
When we want to call an app in android, we need to provide some information as to which app we want to launch
and which activity inside that app we want to lunch.
Launching app by combination of those is called explicit intent. Explicit intent needs 2 things to run an app:
1. Package name
2. Activity or service name
This preference is most useful for launching an specific app based on info you can fetch from database
For example on double click on home key
Intent dialog preference puts the info for explicit intent in a string. First package name, then separator, then activity name
You can use any separator you want. The default separator is "##"
But as you can see in following example we set the separator to be forward slash "/"
The separator depends on how you build the mod in smali for your needs.
Any kill app or reboot device attributes are applicable here as well-->
<!--This specific IntentDialogPreference has defaultValue set to Settings app.
You DO NOT need to set default. Only if you want to. But it is in most cases not necessary and even not that good.
This is just an example. When you run this, you will see that the preference has an icon of the chosen app on the right
and a name of the app set as summary. When you choose a new app, those things change-->
android:title="Select Test App with default"
<!--This IntentDialogPreference comes with no default and no separator. So default separator will be applied "##"
and it also has no search showing-->
android:title="Select app, no default, no search, ## separator"
<!--This preference will prompt to reboot device upon selection
This is useful if f.e. you use it to set default app to open when home button is double clicked
Reboot is advised but not necessary immediately. So user will be shown a dialog to let them know they need to reboot
And they can reboot immediately or later-->
android:title="Select app and reboot device"
<!--Edit text preference is a dialog preference that allows you to enter custom text-->
android:title="Input custom text"/>
3. Special Preferences
Custom attributes: app:componentName - string type attribute to provide package name and desired activity name to open installed app. Please pay attention to instructions in code.
<!--The following category shows usage of special preference we use to open an app based on component info
All you need to provide for this preference is package name and activity name separated by forward slash "/" like shown below
We will split the component info into components and check if the app is installed
if it's installed, we will show the app icon as preference icon and app name as title
If the app is not installed the preference is automatically removed from the list.
You can set your own summary to explain about the app.
If you wish to show a custom icon for that app shortcut or have custom title,
if you wish to use custom icon or custom title, like you would do normally with preference,
You are free to use android:title and android:icon attributes.
Our class will then use the items you chose instead of the application title and icon.
This WILL NOT affect the intent for opening application. It's a cosmetic measure for your convenience.-->
android:title="Shortcut to apps preferences">
<!--Example of simple app shortcuts. If those apps are not installed, the preferences will not show-->
android:summary="Application to browse your files, including root files"
android:summary="Control samsung's toolbox, turn it on or off, choose available apps and rearrange them"
<!--Example of OpenAppPreference with custom title and icon-->
android:summary="Choose what app or shortcut to open when TW launcher is being swiped to the magazine page"
android:title="Shortcut to GearTWSwipe"
<!--Open app preference with only cuctom title and the icon which is loaded from the app-->
android:title="Chainfire's SuperSu App"
android:summary="Manage root permissions for apps and services"/>
android:title="Select image preferences">
<!--Select image preferences allow the user to select any image from the gallery.
The uri for that image will be written into the database
Android can fetch images based on their uri (universal resource identifier).
A type of uri that you all know is called URL, which is a web address.
Uri for database is the "address" of an item inside the database.
In android we have Media database, which hosts info about media items. In our case we are interested in images.
Upon clicking this preference a Gallery will launch, upon selecting image, it's uri will be written into database.
In your mods you can fetch the string, convert it to Uri and set that image as background to anything you want.
We use this method for setting custom image in our mod for background to notification panel-->
<!--Those are examples of simple uri selection preference. The icon for them will be the selected image preview
You need to set title and key. That's it.-->
android:title="Select Image 2"/>
Custom attributes: app:scriptFileName - string type attribute to provide script name to run, including the .sh extension. app:showConfirmDialog - a boolean type preference, dtetermining whether a warning dialog will be shown before executing the script. we have had this request for previous version, since users sometimes hit script preference by mistake and it executes immidiately. By default this boolean is TRUE. So for any script a warning dialog will show. Youc an set it to FALSE to execute without warning. app:rebootOptions - enum type attribute:
Sometimes you will perform actions in script which will require a device reboot to take effect
For this purpose we created this attribute, which can take 3 values:
1. None - this is default. You do not need to specify "none". if you don't specify rebootOptions it will always be "none"
This means reboot is not required upon running script
2. Optional - this means that the execution of this script is ok without immediate reboot,
but for the action to take effect, reboot is required. if you set rebootOption to "optional",
upon successful script execution a user will be presented with a dialog.
A dialog has 2 buttons: reboot now or reboot later.
Use this option ONLY if reboot is required for action to take effect and reboot is not VITAL. Meaning no app will FC without reboot.
3. Imminent- sometimes you will want to run scripts which replace key system components, such as entire apk
or even jar files. When a script like that is executed, you want immediate reboot. Because other wise the app in question
can throw FC. Most of you from what we have seen, use reboot option for scripts like these at the end of the script.
You NO LONGER HAVE TO. We will handle the reboot for you ONLY if the script is executed successfully and "imminent" option was chosen.
It is nice to WARN the user that their phone will reboot after running the script.
That is why if you choose app:rebootOptions="imminent" a dialog will be shown to the user once they click on preference.
This dialog will warn them that upon script execution their device will reboot
If you use this option, once the script is done we will execute the reboot. Make sure you have your app in priv-app before testing this. It will need reboot permissions. Please read the gradle explanation 2 posts above, regarding those permissions.
DO NOT use "reboot" or "kill zygote" commands at the end your scripts. Do yourselves and your users a favour and stop using those all together.
<!--Running scripts in rom modding is no silly business.
We need shell scripts for purposes that can vary from writing a line into a file on sd,
through replacing sound files and host files,
to as far as replacing entire apk and jar files.
Because shell scripts can vary in their complexity, we created a special preference that runs shell scripts.
The major component in this preference is the scriptName attribute. The script name should be given in full,
as string, including extension (.sh).
The code for the preference knows where your scripts are found. It will locate the script if it's found there
and execute it.
if script execution fails, a number is being shown. That means the exit code of a script is not 0.
That means something is wrong in the script.
If the script is executed properly, a toast will be shown saying "Executed successfully"-->
android:title="Run script preferences">
<!--This is the basic script preference. It will jujst run a script.-->
android:title="Execute script with prompt"
android:summary="This action will throw warning dialog before executing script"/>
<!--Because of the radical nature of running shall scripts with su,
We included a dialog which is shown when a user clicks on script preference
By default confirm dialog will be shown before executing eny script. If you wish to run a script without the warning dialog,
You need to specify the custom attribute that a dialog should not be shown.
We strongly encourage you to keep the dialog. It's better for your users to be sure they clicked on the right option-->
android:title="Execute without prompt"
android:summary="This action will execute script without warning"/>
<!--Script preference with optional reboot-->
android:title="Script with optional reboot"
android:summary="This action will write into a file on sd card and show dialog that reminds the user to reboot their phone at this time or later for the action to take effect"/>
<!--Script preference with imminent reboot-->
android:title="Script with imminent reboot"
android:summary="This action will run script which has reboot command at the end and warn user that reboot of device will follow the script execution immediately"
<!--We were asked by some developers to make a kill app option available for script preference
Therefore, you can also use the kill package attributes now, silent or with dialog,
for your script preferences.
The following RunScriptPreference will prompt killing contacts app f.e
P.s. you can set icons to your run script preferences like any other preference-->
android:title="Execute and kill app + icon"
android:summary="Upon finishing, this script preference will prompt a user to kill app, since we set the isSilent attribute to false"
Custom attributes: app:imageSource - reference type of attribute to set the image to show as header preference. The default size for image is width match_parent and height 200dp.
This is just one of those little things we made for fun, but it ended up being @tdunham 's favourite toy
<!--This is one of those little bonus thingies what we made for our beta-testers
and you all get to inherit it. It's a little preference class called ImageHeaderPreference
It allows you to choose and image as header for your preference screen.
Just to bring a little color and life into all those switches and checkboxes...-->
1. There 2 built in themes: light and dark. In the navigation drawer, much like in previous version, you have a section under More options which is called "Set Theme".
2. Upon clicking it a dialog will pop up to allow theme selection.
3. The default theme is the light one. If you wish your default theme to be the dark one, please navigate to res/values/styles and find the following line (at the very bottom):
(yes, we put integer in styles (because we CAN), we're weird like that... LOL. It's for your convenience.
4. To make the default theme the dark one, change 0 to 1.
2. About Us activity - how to populate it:
1. Navigate to values/about_us_resources.xml
2. When you open it you have 3 sets of 3 arrays each. This idea is very similar to how you populated the navigation drawer items. Let's have a look:
<!--Contact info arrays--> <!--In this array you will put the icons for contact information,
for example xda icon for your xda thread, site icon for your site, facebook icon and so on-->
<!--In this array you will put the titles for your contact info items. Keep the order consistent between all 3 arrays-->
<!--In this array you will put the titles for the URL strings that will open once a user clicked on the item-->
<string-array name="about_contact_us_links" translatable="false">
<!--Team info arrays-->
<item>Master Yoda - wise and talented lead developer</item>
<item>Luke Skywalker - one handed theme master</item>
<item>Darth Vader - dark theme master</item>
<string-array name="about_team_links" translatable="false">
<!--Credits and thanks info arrays-->
<item>Star Trek - for being ultimately better than Star Wars</item>
<item>Jean-Luc Picard - for making us crave hot earl-grey tea even in the middle of the summer</item>
<item>Data - for running on the best rom. Google, we still are waiting for THAT android version</item>
<item>Janeway - for being a normal person and drinking black coffee</item>
<item>Q - for reminding us that you can live forever and still look great</item>
<item>Worf - for teaching us to love Klingons. It was NOT easy</item>
<string-array name="about_credits_links" translatable="false">
3. As you can see from the code above it's very simple. Find images you want to use, You don't need to make them round. They will be made round on runtime.
4. Replace the demo information in our arrays with your own, including images reference, titles and links. Make sure the lenghts of 3 arrays in each category are equal.
5. You can make as many or as little items as you want. As long as the length of drawable array equals to length of titles array and equals to length of links array in single category.
6. All the magic is done in java for you. Just populate arrays and RUNNNN
3. Changelog Dialog - how to populate it:
1. Navigate to /res/values/changelog_resources.xml
2. Inside you will find 1 string and 1 string array. Let's have a look:
<!--Do not forget to include this in any locale specific folders for translation--><!--In the following array put your changelog items
Take as many lines as you need.
Add as many items as you want or delete some if those are too many
This order is how they will appear in the dialog
Make any order you want from top to bottom-->
<item>Some changelog thing lkjh l lkjh slkjh lkjh s,mnb lkjhs lkjh poiuy slkjh</item>
<item>Another changelog thing ;lkj d;lkj ;lkjs ;lkj ;lkj s;lkj ;lkj s;lkj ;lkj ;lks ;lkj ;lkj</item>
<item>Some more changelog things</item>
<item>Some even more changelog thing</item>
<item>And another changelog thing ;lsj; lkjs ;lkj ; lkj;lsjk ;sklj s;lkj s;lk js;lkj s;lkj</item>
<item>How many changelog things</item>
<item>What a long changelog!!!</item>
<item>Is it twenty already?</item>
<item>Are we there yet?</item>
<item>Live long and prosper</item>
<item>So say we all</item>
<item>Patience you must have</item>
<item>Done with changelog</item>
<!--This will be the dialog title.
Put your own rom version and name.
<string name="rom_version_for_changelog">build v1.0 6thgearrom</string>
a. Current date and time up to munites
b. The display id from the build.prop
c. suffix RCBackup
That is so the users can differentiate between different backups from different roms or versions
6. It also backs up the file preferences (see the preference explanation post for that)
7. The service finishes and throws a toast that it's done and the file can be found in the backup directory
2. How does that work - RESTORE:
1. During restoring action, the main activity closes. It also says so in the warning dialog which appears right before restore is activated.
2. We made it so to make sure no onPreferenceChangeListener is triggered for any of your preferences. We also want a clean restart of the activity once the restore is done, so all the items can be loaded from the database, which has been updated by the restore process.
3. During restore we read the selected backup file, break it into pieces and write the values to database. When the activity is reloaded, preferences read from databases and update their own values.
4. For file preferences, during restore process we delete the files saved previously and only create the ones contained in backup file.
XDA Developers was founded by developers, for developers. It is now a valuable resource for people who want to make the most of their mobile devices, from customizing the look and feel to adding new functionality. Are you a developer? | Terms of Service