I'm trying to track how many users have replied in my firebase DB, and I'm wondering what the best workflow is. I want to send a notification to the last user to reply.
My firebase Db is organised like so currently
├── chat
│ ├── -M5D96yP5Ac688-ZPU0C << chatId 1
│ │ ├── info
│ │ │ ├── groupName: Breakfast Club
│ │ │ ├── id: -M5D96yP5Ac688-ZPU0C
│ │ │ ├── last_reply_from: 8J7PX3ezjMTuOiAPO1BbOGJGP1g1
│ │ │ ├── no_of_users: 4
│ │ │ └── Users:
│ │ │ ├── 8J7PX3ezjMTuOiAPO1BbOGJGP1g1: true
│ │ │ ├── QvmGG2vPfTrdjZBfWP2ZotajYE3: false
│ │ │ ├── y1EKihfmIJTDCD9OJt0N89WDC643: false
│ │ │ └── zQvmGG2vPfTrdjZBfWP2ZotajYE3: false
│ │ └──Messages
│ │ .....
├── user
And I was going to do the following.
count the amount of users and add to "no_of_users" field uing getChildrenCount()
count how many users have true as their value
subtract one from the other, and if == 1 then send notification
reset all users values to false, and start again.
private void checkReplies() {
final DatabaseReference chatInfoDb = FirebaseDatabase.getInstance().getReference().child("chat").child(mChatObject.getChatId()).child("info").child("users");
final DatabaseReference numberOfUsers = FirebaseDatabase.getInstance().getReference().child("chat").child(mChatObject.getChatId()).child("info").child("no_of_users");
Query query = chatInfoDb.orderByValue().equalTo(true);
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
final long howManyReplies = dataSnapshot.getChildrenCount();
System.out.println("How many users have replied " + howManyReplies);
numberOfUsers.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
long numberOfUser = (long) dataSnapshot.getValue();
long maths = numberOfUser - howManyReplies;
if(maths == 1){
Query query = chatInfoDb.orderByValue().equalTo(false);
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for(DataSnapshot childsnapshot : dataSnapshot.getChildren()) {
String lastToReply = childsnapshot.getKey();
runSomethingElse(lastToReply);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
}
But now I'm wondering if it would be better to have a "replied" node, and add users to it as they reply, then use myRef.removeValue() to clear out all replies. That seems like it'd be easier than looping through all the users to set them to false again.
e.g.
│ ├── -M5D96yP5Ac688-ZPU0C << chatId 1
│ │ ├── info
│ │ │ ├── groupName: Breakfast Club
│ │ │ ├── id: -M5D96yP5Ac688-ZPU0C
│ │ │ ├── last_reply_from: 8J7PX3ezjMTuOiAPO1BbOGJGP1g1
│ │ │ ├── no_of_users: 4
│ │ │ ├── Users:
│ │ │ │ ├── 8J7PX3ezjMTuOiAPO1BbOGJGP1g1: true
│ │ │ │ ├── QvmGG2vPfTrdjZBfWP2ZotajYE3: true
│ │ │ │ ├── y1EKihfmIJTDCD9OJt0N89WDC643: true
│ │ │ │ └── zQvmGG2vPfTrdjZBfWP2ZotajYE3: true
│ │ │ └── replies:
│ │ │ ├── 8J7PX3ezjMTuOiAPO1BbOGJGP1g1: true
│ │ │ └── zQvmGG2vPfTrdjZBfWP2ZotajYE3: true
│ │ └──Messages
│ │ .....
Which of these would be the more efficient workflow for this? Or is there another way to track this.
Many Thanks!
Instead of complicating your nodes like this, have a super node that tracks replies of a certain chat ID, everytime a user replies add their IDs to this super node. Something like that:
Replies
|
|
|-------------M5D96yP5Ac688-ZPU0C << chatId 1
|
-----8J7PX3ezjMTuOiAPO1BbOGJGP1g1: true
-----QvmGG2vPfTrdjZBfWP2ZotajYE3: true
|
|
|-------------QRE36yP5Ac688-ZPU0C << chatId 2
|
-----8J7PX3ezjMTuOiAPO1BbOGJGP1g1: true
Whenever you want to check who didn't reply yet
when you enter the chat loop through the users in the chat and check if there ids exist in this super node, if not then send notification. After that just delete the chatID form the super node. And start over.
UPDATE:
I will explain one more time.
Ofcourse I assume that you have the list of UIDs in the chat from your datbase I see that. Now these are the steps to know which user replied and which didn't:
1) When user replies add his/her UID in the supernode under Replies/chatID.
2) Until now this means the existance of the UID of the user under Replies/chatID means that they replied.
3) When you want to check which user replied, you run a query over the users of the current chat, and loop through them. And check if their UIDs exist under Replies/chatID. If yes they replied, if no they didn't reply.
Related
I need to identify the current connection type (etc 3G, 4G, 5G). I've used the ConnectivityManager but on some phones, the reported connection is 4G even if the download speed is so big that the phone is clearly on 5G.
Here I found a possible way to fix it. I need to check it on different devices.
I was wondering whether there is a way to use Firebase test-lab to do it. I used Firebase test-lab in the past but I was always mocking the network connection to run instrumentation tests so I don't know whether it is possible to actually use a cellular connection and whether it is possible to choose the SIM card used.
EDIT
Following the suggestion I'm using gloud beta. I run gcloud firebase test network-profiles list and I have got the following list:
┌────────────┐
│ PROFILE_ID │
├────────────┤
│ LTE │
└────────────┘
┌──────┬────────┬────────────┬───────────────────┬───────────┬───────┐
│ RULE │ DELAY │ LOSS_RATIO │ DUPLICATION_RATIO │ BANDWIDTH │ BURST │
├──────┼────────┼────────────┼───────────────────┼───────────┼───────┤
│ up │ 0.040s │ 0.001 │ │ 16000.0 │ │
│ down │ 0.040s │ 0.001 │ │ 16000.0 │ │
└──────┴────────┴────────────┴───────────────────┴───────────┴───────┘
┌────────────┐
│ LTE-poor │
└────────────┘
┌──────┬────────┬────────────┬───────────────────┬───────────┬───────┐
│ RULE │ DELAY │ LOSS_RATIO │ DUPLICATION_RATIO │ BANDWIDTH │ BURST │
├──────┼────────┼────────────┼───────────────────┼───────────┼───────┤
│ up │ 0.060s │ 0.0015 │ │ 4000.0 │ │
│ down │ 0.060s │ 0.0015 │ │ 4000.0 │ │
└──────┴────────┴────────────┴───────────────────┴───────────┴───────┘
┌────────────┐
│ HSPA │
└────────────┘
┌──────┬────────┬────────────┬───────────────────┬───────────┬───────┐
│ RULE │ DELAY │ LOSS_RATIO │ DUPLICATION_RATIO │ BANDWIDTH │ BURST │
├──────┼────────┼────────────┼───────────────────┼───────────┼───────┤
│ up │ 0.060s │ 0.001 │ │ 2000.0 │ │
│ down │ 0.060s │ 0.001 │ │ 4000.0 │ │
└──────┴────────┴────────────┴───────────────────┴───────────┴───────┘
┌────────────┐
│ HSPA-poor │
└────────────┘
┌──────┬────────┬────────────┬───────────────────┬───────────┬───────┐
│ RULE │ DELAY │ LOSS_RATIO │ DUPLICATION_RATIO │ BANDWIDTH │ BURST │
├──────┼────────┼────────────┼───────────────────┼───────────┼───────┤
│ up │ 0.100s │ 0.0015 │ │ 500.0 │ │
│ down │ 0.100s │ 0.0015 │ │ 1000.0 │ │
└──────┴────────┴────────────┴───────────────────┴───────────┴───────┘
...
5G is not in the list (yet). And the result is the same with gcloud beta firebase test network-profiles list
Devices in Firebase Test Lab are connected via WiFi by default. There's no guarantee that a device has a SIM at all, and you should not rely on that. Your best choice is to use a specific network profile, which can be configured as part of the test.
You can list all available network profiles and their settings with the command below:
$ gcloud firebase test network-profiles list
You can set the network profile by using gcloud beta, as the setting is not GA yet:
$ gcloud beta firebase test android run \
--network-profile=LTE \
<your other args>
I'm building a library module that might be used in an Android application. In a certain part of the code, I need to load a JavaScript file so the script engine runs it. My file structure looks something like this: https://i.snag.gy/R7hHPI.jpg
└───src
├───main
│ ├───java
│ │ └───calegari
│ │ └───murilo
│ │ └───qacadscrapper
│ │ │ QAcadScrapper.java
│ │ │
│ │ └───utils
│ │ Grade.java
│ │ Subject.java
│ │ User.java
│ │
│ └───resources
│ └───lib
│ Barrett.js
│ BigInt.js
│ RSA.js
│
└───test
├───java
│ └───calegari
│ └───murilo
│ └───qacadtest
│ QAcadTest.java
│
└───resources
When building the artifact, I configure it so IntelliJ puts the contents of the /resources folder on root folder of the Jar file:
https://i.snag.gy/fN4z6t.jpg
These are the contents of the .jar file: https://i.snag.gy/QPR9XK.jpg
├───calegari
│ └───murilo
│ └───qacadscrapper
│ └───utils
├───com
│ └───sun
│ └───script
│ ├───javascript
│ └───util
├───javax
│ └───script
├───lib ---> Here are the JavaScript files
├───META-INF
│ ├───maven
│ │ └───org.jsoup
│ │ └───jsoup
│ └───services
├───org
│ ├───jsoup
│ │ ├───helper
│ │ ├───internal
│ │ ├───nodes
│ │ ├───parser
│ │ ├───safety
│ │ └───select
│ └───mozilla
│ ├───classfile
│ └───javascript
│ ├───annotations
│ ├───ast
│ ├───commonjs
│ │ └───module
│ │ └───provider
│ ├───debug
│ ├───jdk13
│ ├───jdk15
│ ├───json
│ ├───optimizer
│ ├───regexp
│ ├───resources
│ ├───serialize
│ ├───tools
│ │ ├───debugger
│ │ │ └───treetable
│ │ ├───idswitch
│ │ ├───jsc
│ │ ├───resources
│ │ └───shell
│ ├───typedarrays
│ ├───v8dtoa
│ ├───xml
│ └───xmlimpl
└───sun
├───misc
├───reflect
└───security
├───action
└───util
But when I try to install the APK I receive a "INSTALL_FAILED_NO_MATCHING_ABIS" error. I'm pretty sure that what's causing it are these .js files under /lib, since the error disappears if I remove them from the .jar build.
Library is configured using Gradle.
How can I avoid this error? Hope someone can help!
Update
I made IntelliJ add the .js files alongside the Java files inside my jar package, it works when running from the .jar file, but if I try to run some tests in IntelliJ it doesn't work, since gradle isn't adding the files to the compiled code...
Solution
I was able to make it work by moving the files to inside the source path and adding this to the gradle.build file:
sourceSets {
main {
java {
srcDirs = ['src/main/java']
}
resources {
srcDir 'src/main/java'
include '**/*.js'
}
}
test {
java {
srcDirs = ['src/test/java']
}
}
}
i had this problem using bitcoinJ library (org.bitcoinj:bitcoinj-core:0.14.7) added to build.gradle(in module app) a packaging options inside the android scope. it helped me.
android {
...
packagingOptions {
exclude 'lib/x86_64/darwin/libscrypt.dylib'
exclude 'lib/x86_64/freebsd/libscrypt.so'
exclude 'lib/x86_64/linux/libscrypt.so'
}
}
I'm trying to use Firebase Test Lab to run instrumentation tests of my Android app but some tests failed because the currency symbol is not euro (€) but the standard currency sign (¤).
The locale is well defined (French) and it works without problem on my local machine.
Am I supposed to not hard-write the € symbol in the test class and get it dynamically with Currency class ? But the good practise is to always hard-write the expected value...
Expected: with text: is "0,00 €"
Got: "AppCompatTextView{id=2131296465, res-name=total, visibility=VISIBLE, width=1071, height=57, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, layout-params=android.widget.RelativeLayout$LayoutParams#120f8796, tag=null, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, text=0,00 ¤, input-type=0, ime-target=false, has-links=false}"
one can pass the desired locale to test-lab with the --device parameter.
as the documentation for gcloud firebase test android run reads:
--device is now the preferred way to specify test devices and may not be used in conjunction with --devices-ids, --os-version-ids, --locales, or --orientations. Omitting all of the preceding dimension-related flags will run tests against a single device using defaults for all four device dimensions.
--device model=shamu,version=23,locale=fr_FR,orientation=default
else it will just use the default locale en - which results in that ¤ unspecified currency symbol.
to assume that French locale means the € as currency symbol might be wrongful; because when running gcloud firebase test android locales list, it outputs quite a bunch of the colonies:
│ fr │ French │
│ fr_BE │ French │ Belgium
│ fr_BF │ French │ Burkina Faso
│ fr_BI │ French │ Burundi
│ fr_BJ │ French │ Benin
│ fr_BL │ French │ Saint Barthélemy
│ fr_CA │ French │ Canada
│ fr_CD │ French │ Congo (DRC)
│ fr_CF │ French │ Central African Republic
│ fr_CG │ French │ Congo (Republic)
│ fr_CH │ French │ Switzerland
│ fr_CI │ French │ Côte d’Ivoire
│ fr_CM │ French │ Cameroon
│ fr_DJ │ French │ Djibouti
│ fr_DZ │ French │ Algeria
│ fr_FR │ French │ France
│ fr_GA │ French │ Gabon
│ fr_GF │ French │ French Guiana
│ fr_GN │ French │ Guinea
│ fr_GP │ French │ Guadeloupe
│ fr_GQ │ French │ Equatorial Guinea
│ fr_HT │ French │ Haiti
│ fr_KM │ French │ Comoros
│ fr_LU │ French │ Luxembourg
│ fr_MA │ French │ Morocco
│ fr_MC │ French │ Monaco
│ fr_MF │ French │ Saint Martin
│ fr_MG │ French │ Madagascar
│ fr_ML │ French │ Mali
│ fr_MQ │ French │ Martinique
│ fr_MR │ French │ Mauritania
│ fr_MU │ French │ Mauritius
│ fr_NC │ French │ New Caledonia
│ fr_NE │ French │ Niger
│ fr_PF │ French │ French Polynesia
│ fr_PM │ French │ Saint Pierre and Miquelon
│ fr_RE │ French │ Réunion
│ fr_RW │ French │ Rwanda
│ fr_SC │ French │ Seychelles
│ fr_SN │ French │ Senegal
│ fr_SY │ French │ Syria
│ fr_TD │ French │ Chad
│ fr_TG │ French │ Togo
│ fr_TN │ French │ Tunisia
│ fr_VU │ French │ Vanuatu
│ fr_WF │ French │ Wallis and Futuna
│ fr_YT │ French │ Mayotte
I have a bit of a problem with my libGDX project. In class(high school, don't think of too much), we have to make a hangman game. With some of my friends, we started to make it in Scala. Well, it works, kind of.
But the problem is that I cannot read the files from which the words are generated. It's a yaml file(words.yml), inside the android sub-project's assets. It is packed inside the .jar file, I checked it, however when I try to read it using Gdx.files.internal it stops with a NullPointerException. It's bugging me because I was able to read the image files. I thought it is impossible to read using Gdx.files.internal from not the main file from the core project. But that doesn't seem to be the case since it crashes as well if I put it in that file.
The field where it dies:
private val map: (Int, Array[String]) = {
val yaml: Yaml = new Yaml //using the snakeyaml library
//Debug
println("DBG")
println(Gdx.files.local("words.yml").path()) //<-------It crashes here
println("more DBG")
val tmp: util.LinkedHashMap[String, Any] = yaml.load(
scala.io.Source.fromFile(Gdx.files.internal("words.yml").file()) mkString)
//^^^^^or here if I remove the debug part^^^^^^^^^^^^^^^^^^^^^^^^^^^^
(tmp.get("wordCount").asInstanceOf[Int],
tmp.get("words").toString.replaceAll("[\\[\\]]","").split(",")
.map((s: String) => {
if(s(0) == ' ') s.substring(1)
else s
}))
}
Error msg:
Exception in thread "main" java.lang.ExceptionInInitializerError
at com.infosoftcorp.wordpress.ish.Save.<init>(Save.scala:7)
at com.infosoftcorp.wordpress.ish.InfoSoftHangman.<init>(InfoSoftHangman.scala:35)
at com.infosoftcorp.wordpress.ish.desktop.DesktopLauncher.main(DesktopLauncher.java:17)
Caused by: java.lang.NullPointerException
at com.infosoftcorp.wordpress.ish.FileHandler$.<init>(FileHandler.scala:25)
at com.infosoftcorp.wordpress.ish.FileHandler$.<clinit>(FileHandler.scala)
... 3 more
File structure:
.
├── android
│ ├── android.iml
│ ├── AndroidManifest.xml
│ ├── assets
│ │ ├── icon.png
│ │ ├── img
│ │ │ ├── 10.png
│ │ │ ├── 11.png
│ │ │ ├── 1.png
│ │ │ ├── 2.png
│ │ │ ├── 3.png
│ │ │ ├── 4.png
│ │ │ ├── 5.png
│ │ │ ├── 6.png
│ │ │ ├── 7.png
│ │ │ ├── 8.png
│ │ │ ├── 9.png
│ │ │ └── line.png
│ │ └── words.yml
│ ├── build.gradle
│ ├── ic_launcher-web.png
│ ├── libs
│ │ ├── armeabi
│ │ │ ├── libgdx-bullet.so
│ │ │ └── libgdx.so
│ │ ├── armeabi-v7a
│ │ │ ├── libgdx-bullet.so
│ │ │ └── libgdx.so
│ │ └── x86
│ │ ├── libgdx-bullet.so
│ │ └── libgdx.so
│ ├── proguard-project.txt
│ ├── project.properties
│ ├── res
│ │ ├── drawable-hdpi
│ │ │ └── ic_launcher.png
│ │ ├── drawable-mdpi
│ │ │ └── ic_launcher.png
│ │ ├── drawable-xhdpi
│ │ │ └── ic_launcher.png
│ │ ├── drawable-xxhdpi
│ │ │ └── ic_launcher.png
│ │ ├── values
│ │ │ ├── strings.xml
│ │ │ └── styles.xml
│ │ └── values-hu
│ │ └── strings.xml
│ └── src
│ └── com
│ └── infosoftcorp
│ └── wordpress
│ └── ish
│ └── android
│ └── AndroidLauncher.java
├── asd.html
├── bitbucket-pipelines.yml
├── build
│ ├── android-profile
│ │ ├── profile-2018-02-12-00-57-01-965.rawproto
│ │ ├── profile-2018-02-12-00-58-00-422.rawproto
│ │ ├── profile-2018-02-12-00-59-18-263.rawproto
│ │ ├── profile-2018-02-12-00-59-55-075.rawproto
│ │ ├── profile-2018-02-12-01-00-22-650.rawproto
│ │ └── profile-2018-02-12-01-03-02-363.rawproto
│ ├── generated
│ │ ├── mockable-android-26.jar
│ │ └── mockable-android-27.jar
│ └── intermediates
│ ├── lint-cache
│ │ ├── api-versions-6-27.0.1.bin
│ │ ├── typos-en.txt-2.bin
│ │ └── typos-hu.txt-2.bin
│ └── proguard-files
│ ├── proguard-android-optimize.txt-2.3.0
│ └── proguard-android.txt-2.3.0
├── build.gradle
├── core
│ ├── build
│ │ ├── classes
│ │ │ └── main
│ │ │ └── com
│ │ │ └── infosoftcorp
│ │ │ └── wordpress
│ │ │ └── ish
│ │ │ ├── FileHandler$$anonfun$1.class
│ │ │ ├── FileHandler.class
│ │ │ ├── FileHandler$.class
│ │ │ ├── InfoSoftHangman$$anonfun$create$1.class
│ │ │ ├── InfoSoftHangman$$anonfun$drawLines$1$1.class
│ │ │ ├── InfoSoftHangman.class
│ │ │ ├── InfoSoftHangman$InputHandler.class
│ │ │ ├── Parsing$$anonfun$parseString$1.class
│ │ │ ├── Parsing$$anonfun$removeEach$1.class
│ │ │ ├── Parsing.class
│ │ │ ├── Parsing$.class
│ │ │ ├── Parsing$DecLives.class
│ │ │ ├── Parsing$HMSignal.class
│ │ │ ├── Parsing$ParseError.class
│ │ │ ├── Parsing$ParsingResult.class
│ │ │ ├── Save.class
│ │ │ └── Save$.class
│ │ ├── libs
│ │ │ └── core-1.0.jar
│ │ └── tmp
│ │ ├── compileScala
│ │ └── jar
│ │ └── MANIFEST.MF
│ ├── build.gradle
│ ├── core.iml
│ └── src
│ └── com
│ └── infosoftcorp
│ └── wordpress
│ └── ish
│ ├── FileHandler.scala
│ ├── InfoSoftHangman.scala
│ ├── Parsing.scala
│ └── Save.scala
├── desktop
│ ├── build
│ │ ├── classes
│ │ │ └── main
│ │ │ └── com
│ │ │ └── infosoftcorp
│ │ │ └── wordpress
│ │ │ └── ish
│ │ │ └── desktop
│ │ │ └── DesktopLauncher.class
│ │ ├── dependency-cache
│ │ ├── libs
│ │ │ └── desktop-1.0.jar
│ │ └── tmp
│ │ └── <chaos>
│ ├── build.gradle
│ ├── desktop.iml
│ ├── out
│ │ └── production
│ │ └── classes
│ └── src
│ └── com
│ └── infosoftcorp
│ └── wordpress
│ └── ish
│ └── desktop
│ └── DesktopLauncher.java
├── gradle
│ └── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── is-hangman.iml
├── is-hangman.ipr
├── is-hangman.iws
├── local.properties
├── README.md
└── settings.gradle
I added the working directory for the desktop sub-project
So I was really stupid that is what happened.
When the new Save is initialized it wasn't called inside the create() function, but before it
Well, sometimes I do stupid stuff.
Sorry for asking stupid questions you could never answer as I didn't post the code.
I have compiled FFmpeg for Android to suite my needs in terms of codecs, muxers etc.
Now I have an executable that, from what I understand, should be placed in my project dir under <project-root>/external/<arbitrary-folder-name>/data/data/<my-app-package-name>/app_opt. What I have inside app_opt now is:
.
├── bin
│ └── ffmpeg
├── include
│ ├── libavcodec
│ │ ├── avcodec.h
│ │ ├── avfft.h
│ │ ├── dxva2.h
│ │ ├── vaapi.h
│ │ ├── vda.h
│ │ ├── vdpau.h
│ │ ├── version.h
│ │ └── xvmc.h
│ ├── libavdevice
│ │ └── avdevice.h
│ ├── libavfilter
│ │ ├── asrc_abuffer.h
│ │ ├── avcodec.h
│ │ ├── avfiltergraph.h
│ │ ├── avfilter.h
│ │ ├── buffersink.h
│ │ ├── buffersrc.h
│ │ ├── version.h
│ │ └── vsrc_buffer.h
│ ├── libavformat
│ │ ├── avformat.h
│ │ ├── avio.h
│ │ └── version.h
│ ├── libavutil
│ │ ├── adler32.h
│ │ ├── aes.h
│ │ ├── attributes.h
│ │ ├── audioconvert.h
│ │ ├── audio_fifo.h
│ │ ├── avassert.h
│ │ ├── avconfig.h
│ │ ├── avstring.h
│ │ ├── avutil.h
│ │ ├── base64.h
│ │ ├── bprint.h
│ │ ├── bswap.h
│ │ ├── common.h
│ │ ├── cpu.h
│ │ ├── crc.h
│ │ ├── dict.h
│ │ ├── error.h
│ │ ├── eval.h
│ │ ├── fifo.h
│ │ ├── file.h
│ │ ├── imgutils.h
│ │ ├── intfloat.h
│ │ ├── intfloat_readwrite.h
│ │ ├── intreadwrite.h
│ │ ├── lfg.h
│ │ ├── log.h
│ │ ├── lzo.h
│ │ ├── mathematics.h
│ │ ├── md5.h
│ │ ├── mem.h
│ │ ├── opt.h
│ │ ├── parseutils.h
│ │ ├── pixdesc.h
│ │ ├── pixfmt.h
│ │ ├── random_seed.h
│ │ ├── rational.h
│ │ ├── samplefmt.h
│ │ ├── sha.h
│ │ ├── timecode.h
│ │ └── timestamp.h
│ ├── libpostproc
│ │ └── postprocess.h
│ ├── libswresample
│ │ └── swresample.h
│ └── libswscale
│ └── swscale.h
├── lib
│ ├── libavcodec.a
│ ├── libavdevice.a
│ ├── libavfilter.a
│ ├── libavformat.a
│ ├── libavutil.a
│ ├── libpostproc.a
│ ├── libswresample.a
│ ├── libswscale.a
│ └── pkgconfig
│ ├── libavcodec.pc
│ ├── libavdevice.pc
│ ├── libavfilter.pc
│ ├── libavformat.pc
│ ├── libavutil.pc
│ ├── libpostproc.pc
│ ├── libswresample.pc
│ └── libswscale.pc
└── share
└── ffmpeg
├── examples
│ ├── decoding_encoding.c
│ ├── filtering_audio.c
│ ├── filtering_video.c
│ ├── Makefile
│ ├── metadata.c
│ └── muxing.c
├── ffprobe.xsd
├── libvpx-1080p50_60.ffpreset
├── libvpx-1080p.ffpreset
├── libvpx-360p.ffpreset
├── libvpx-720p50_60.ffpreset
├── libvpx-720p.ffpreset
├── libx264-ipod320.ffpreset
└── libx264-ipod640.ffpreset
Do I need just the ffmpeg under bin to place in my project's <project-root>/res/raw dir?
And what is the easiest way to call ffmpeg and feed it with a command string?
I compiled FFmpeg with limited decoders and demuxers, because I need audio extraction only.
See: How can I get FFmpeg to locate installed libraries when --sysroot is pointing to another directory?
I would use it in background and notify the user in notification bar on completion.
I know that, here on SO, other similar questions are present, but they are a bit vague or confusing, at least for me. I understand at this point I lack of competences (actually my App is a jigsaw made of java-code-snippets from the Net that work together).
I'd appreciate some guidance.
Thanks.
Although an executable 'ffmpeg' placed in a bin folder will run on a rooted phone, its actually not the best way to distribute ffmpeg in an app which will be suitable for general distribution.
The better interface is to use a standard JNI interface where android loads a shared lib permitting an invocation of ffmpeg and then calls the shell, android method serving as a wrapper for a CLI exec of ffmpeg.
For a great sample , see "android-ffmpeg-x264" project on github.
The android JNI interface is here
The project linked above is no longer supported. A newer alternative can be found at http://writingminds.github.io/ffmpeg-android-java/