I am trying to build a dictionary app . and dictionary api provide me the url for the mp3 file. I am using this code to play the mp3 .
This works in all the versions of android except the API 28.
What happens in API 28 is
- It lake more than 2 minute to hit the setOnPreparedListener (not every time)
- then goes to setOnCompletionListener with out any sound.
Any suggestions about what went wrong is highly appreciated.
mediaPlayer?.apply {
if(isPlaying){
return
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
var builder = AudioAttributes.Builder()
builder.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
builder.setLegacyStreamType(AudioManager.STREAM_MUSIC)
setAudioAttributes(builder.build())
}
setOnBufferingUpdateListener(this#WordHomeVM)
setOnCompletionListener(this#WordHomeVM)
setDataSource(urlString)
setOnPreparedListener { mPlayer ->
if (!isPlaying) {
start()
}
}
prepareAsync()
}
and Here is the only relevant log I get.
2018-12-04 13:22:58.241 5772-5911/ E/MediaPlayerNative: error (1, -2147483648)
2018-12-04 13:22:58.247 5772-5772/E/MediaPlayer: Error (1,-2147483648)
You may meet media player error when playing http live streaming on Android 9 (API 28)
2019-05-14 19:05:31.671 9198-9214/com.xxx.sample E/MediaPlayerNative: error (1, -2147483648)
2019-05-14 19:05:31.672 9198-9198/com.xxx.sample E/MediaPlayer: Error (1,-2147483648)
https://developer.android.com/training/articles/security-config?hl=en-us
The default configuration for apps targeting Android 9 (API level 28) and higher is as follows:
<base-config cleartextTrafficPermitted="false">
<trust-anchors>
<certificates src="system" />
</trust-anchors>
</base-config>
The default configuration for apps targeting Android 7.0 (API level 24) to Android 8.1 (API level 27) is as follows:
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" />
</trust-anchors>
</base-config>
The default configuration for apps targeting Android 6.0 (API level 23) and lower is as follows:
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" />
<certificates src="user" />
</trust-anchors>
</base-config>
So if you want to play http live straming on API 28, you should change your network configuration.
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true">
</base-config>
</network-security-config>
<application
android:label="#string/app_name"
android:usesCleartextTraffic="true"
android:networkSecurityConfig="#xml/network_security_config">
</application>
Ahh.. I found out the reason after spending quite a bit of time.
The problem was, starting with Android 9.0 (API level 28), cleartext http traffic support is disabled by default.
and this code lab helped.
Related
I'm trying to make an app to listen to web-radio directly on the phone.
To do this I'm using this link:
https://webradio.divsi.unimi.it/
However, the result I get is not what I expected, because the error logs are as follows:
E/MediaHTTPConnection: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
at com.android.org.conscrypt.SSLUtils.toSSLHandshakeException(SSLUtils.java:363)
at com.android.org.conscrypt.ConscryptEngine.convertException(ConscryptEngine.java:1134)
at com.android.org.conscrypt.ConscryptEngine.readPlaintextData(ConscryptEngine.java:1089)
at com.android.org.conscrypt.ConscryptEngine.unwrap(ConscryptEngine.java:876)
at com.android.org.conscrypt.ConscryptEngine.unwrap(ConscryptEngine.java:747)
at com.android.org.conscrypt.ConscryptEngine.unwrap(ConscryptEngine.java:712)
at com.android.org.conscrypt.ConscryptEngineSocket$SSLInputStream.processDataFromSocket(ConscryptEngineSocket.java:858)
at com.android.org.conscrypt.ConscryptEngineSocket$SSLInputStream.-$$Nest$mprocessDataFromSocket(Unknown Source:0)
at com.android.org.conscrypt.ConscryptEngineSocket.doHandshake(ConscryptEngineSocket.java:241)
at com.android.org.conscrypt.ConscryptEngineSocket.startHandshake(ConscryptEngineSocket.java:220)
at com.android.okhttp.internal.io.RealConnection.connectTls(RealConnection.java:1450)
at com.android.okhttp.internal.io.RealConnection.connectSocket(RealConnection.java:1399)
at com.android.okhttp.internal.io.RealConnection.connect(RealConnection.java:1343)
at com.android.okhttp.internal.http.StreamAllocation.findConnection(StreamAllocation.java:221)
at com.android.okhttp.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:144)
at com.android.okhttp.internal.http.StreamAllocation.newStream(StreamAllocation.java:106)
at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:400)
at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:333)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:465)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:411)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:542)
at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.getResponseCode(DelegatingHttpsURLConnection.java:106)
at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:30)
at android.media.MediaHTTPConnection.seekTo(MediaHTTPConnection.java:306)
at android.media.MediaHTTPConnection.getMIMEType(MediaHTTPConnection.java:501)
at android.media.IMediaHTTPConnection$Stub.onTransact(IMediaHTTPConnection.java:159)
at android.os.Binder.execTransactInternal(Binder.java:1195)
at android.os.Binder.execTransact(Binder.java:1159)
Caused by: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:654)
at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:503)
at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:423)
at com.android.org.conscrypt.TrustManagerImpl.getTrustedChainForServer(TrustManagerImpl.java:351)
at android.security.net.config.NetworkSecurityTrustManager.checkServerTrusted(NetworkSecurityTrustManager.java:94)
at android.security.net.config.RootTrustManager.checkServerTrusted(RootTrustManager.java:90)
at com.android.org.conscrypt.ConscryptEngineSocket$2.checkServerTrusted(ConscryptEngineSocket.java:163)
at com.android.org.conscrypt.Platform.checkServerTrusted(Platform.java:255)
at com.android.org.conscrypt.ConscryptEngine.verifyCertificateChain(ConscryptEngine.java:1638)
at com.android.org.conscrypt.NativeCrypto.ENGINE_SSL_read_direct(Native Method)
at com.android.org.conscrypt.NativeSsl.readDirectByteBuffer(NativeSsl.java:569)
at com.android.org.conscrypt.ConscryptEngine.readPlaintextDataDirect(ConscryptEngine.java:1095)
at com.android.org.conscrypt.ConscryptEngine.readPlaintextData(ConscryptEngine.java:1079)
2023-02-09 11:30:19.191 12154-14835/com.example.radio E/MediaHTTPConnection: ... 25 more
Caused by: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
... 38 more
I've already read around and tried adding both the network_security_config
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" />
</trust-anchors>
</base-config>
</network-security-config>
and:
android:usesCleartextTraffic="true"
But I just can't figure out why I need the certificate to be able to stream this radio. Trying with other web radios everything works correctly, so the problem is reduced to this link.
Is there any way to fix this error?
Currently I have the following network security config xml file:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<!-- default config that does not allow clear test -->
<base-config cleartextTrafficPermitted="false">
<trust-anchors>
<certificates src="system" />
</trust-anchors>
</base-config>
<!-- trying to get debug override to change this -->
<debug-overrides cleartextTrafficPermitted="true (DOESN'T WORK)">
<trust-anchors>
<certificates src="system" />
<certificates src="user" />
</trust-anchors>
</debug-overrides>
</network-security-config>
All I am trying to do is conditionally enabled global domain clear traffic during development/debug mode.
I thought I had my answer when I discovered the tag <debug-overrides>...</debug-overrides>. But it didn't work.
Unfortunately according to the official documentation, that tag doesn't actually support the desired attribute.
Nevermind. I figured out how to do it using gradle runtime variables instead.
// In your app level gradle file `build.gradle`
android
{
...
buildTypes
{
debug
{
resValue "string", "clear_text_config", "true"
}
release
{
resValue "string", "clear_text_config", "false"
}
}
...
}
// In your network security configuration xml
<base-config cleartextTrafficPermitted="#string/clear_text_config">
<trust-anchors>
<certificates src="system" />
</trust-anchors>
</base-config>
This works because gradle will automatically generate a resource file for you.
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config>
<trust-anchors>
<certificates src="system" />
</trust-anchors>
</base-config>
<debug-overrides>
<trust-anchors>
<certificates src="user" />
</trust-anchors>
</debug-overrides>
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">xxx.xxx.xxx</domain>
</domain-config>
</network-security-config>
Use domain config is the better way.We don't usually use http in a formal environment.
I am trying to call an api in ionic. i get following error in my console.
Access to XMLHttpRequest at
'https://apiresource.com/appservices/get_services' from origin
'http://localhost:8100' has been blocked by CORS policy: No
'Access-Control-Allow-Origin' header is present on the requested
resource.
Below is my code for API call
services.page.ts
import { Component, OnInit } from '#angular/core';
import {HttpClient, HttpClientModule} from '#angular/common/http';
import {NavController} from '#ionic/angular';
#Component({
selector: 'app-services',
templateUrl: './services.page.html',
styleUrls: ['./services.page.scss'],
})
export class ServicesPage implements OnInit {
services: any;
constructor(private http: HttpClient, private navctrl: NavController) {
}
ngOnInit() {
this.http.get('https://apiresource.com/appservices/get_services').subscribe(data => {
console.log('my data: ', data);
alert(JSON.stringify(data));
});
}
}
network_security_config.xml
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" />
</trust-anchors>
</base-config>
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">apiresource.com</domain>
</domain-config>
</network-security-config>
Config.xml
<platform name="android">
<edit-config file="app/src/main/AndroidManifest.xml" mode="merge" target="/manifest/application" xmlns:android="http://schemas.android.com/apk/res/android">
<application android:usesCleartextTraffic="true" />
<application android:networkSecurityConfig="#xml/network_security_config" />
</edit-config>
....................
I have tried on different solutions found from Google and above is all that i have in my code .
Please help
I'm trying to send file to another app for using Intent. I used targetSdkVersion 25 in my gradle. My app works fine on android version < 24. When android version >= 24, i'm using FileProvider for sending file to another app and it's not working here.
This is step I using for FileProvider:
manifest:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="sp.xxx.yyy.fileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_paths"/>
</provider>
file_paths:
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path path="Android/data/sp.xxx.yyy/" name="app_root" />
<external-path path="Android/data/sp.xxx.yyy/files/" name="files_root" />
<external-path path="." name="external_storage_root" />
</paths>
Open intent:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
File file = new File(path);
Log.e("Utils" , "file exists: " + file.exists());
Uri contentUri = FileProvider.getUriForFile(context, "sp.xxx.yyy.fileProvider", file);
intent.setData(contentUri);
} else {
Uri contentUri = Uri.parse(path);
intent.setData(contentUri);
}
context.startActivity(intent);
When use FileProvider for sending file uri to another app, I see that other app receive data like this:
Intent { act=android.intent.action.VIEW dat=content://sp.xxx.yyy.fileProvider/external_storage_root/Android/data/sp.xxx.yyy/files/filetosending.txt flg=0x10400002 cmp=sp.zzz/sp.zzz.MainActivity launchParam=MultiScreenLaunchParams { mDisplayId=0 mFlags=0 } }
Another app not works with data received content://sp.xxx.yyy.fileProvider/external_storage_root/Android/data/sp.xxx.yyy/files/filetosending.txt
What's wrong in my code? Have any suggestion for resolve this problem? Thank your support.
I've been following Android's Creating a Sync Adapter (BasicSyncAdapter) to start out my own sync service logic.
The problem: Upon invoking AccountManager.addAccountExplicitly(), a SecurityException is raised, claiming a mismatch between caller and authenticator UID's:
java.lang.SecurityException: caller uid 10048 is different than the authenticator's uid
at android.os.Parcel.readException(Parcel.java:1425)
at android.os.Parcel.readException(Parcel.java:1379)
at android.accounts.IAccountManager$Stub$Proxy.addAccount(IAccountManager.java:580)
at android.accounts.AccountManager.addAccountExplicitly(AccountManager.java:565)
App / Library Structure: My app is divided into two modules (gradle / android studio projects):
Android Library (com.example.mylib), which contains the sources and xml's necessary for defining a sync service, adapter, authenticator, etc.
Android Application: to test/demo the library functionality (com.example.mylib.app).
This seems relevant, since the two apps are of different packages. For this reason I've set up the sharedUserId property in the two project manifests (and according to the packages.xml snippets below, it seems to be set up correctly).
All required permissions seem to be set up correctly (namely: READ_SYNC_SETTINGS, WRITE_SYNC_SETTINGS, AUTHENTICATE_ACCOUNTS, USE_CREDENTIALS, GET_ACCOUNTS and MANAGE_ACCOUNTS).
I've also set explicit values for manifest properties (and not going through #string/... expansions) - see below.
Also tried clean builds, clean installs, restarts, etc.
Tech details / dumps follow.
Environment / Setup
Using Android Studio (version 1.3)
targetSdkVersion is 22 (for both projects)
Running on an emulator (genymotion)
System logcat dumps
Following the advice mentioned in this question, I've checked Android System Logcat's seem to be alright as well (until the exception is encountered):
Before (clean installation):
08-10 10:43:39.375 9015-9031/system_process D/PackageManager﹕ New package installed in /data/app/example.mylib.app-1.apk
08-10 10:43:39.387 9015-9027/system_process D/PackageManager﹕ generateServicesMap(android.accounts.AccountAuthenticator): 3 services unchanged
08-10 10:43:39.387 9015-9027/system_process D/PackageManager﹕ generateServicesMap(android.content.SyncAdapter): 6 services:
New service added: ServiceInfo: SyncAdapterType {name=com.example.mylib.provider, type=com.example.mylib.provider.ACCOUNT, userVisible=false, supportsUploading=false, isAlwaysSyncable=true, allowParallelSyncs=false, settingsActivity=null}, ComponentInfo{com.example.mylib.app/com.example.mylib.service.SyncService}, uid 10048
08-10 10:43:39.739 9015-9015/system_process I/ActivityManager﹕ START {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.example.mylib.app/.MyActivity u=0} from pid 19237
08-10 10:43:39.791 9015-9025/system_process I/ActivityManager﹕ Start proc com.example.mylib.app for activity com.example.mylib.app/.MyActivity: pid=19247 uid=10048 gids={3003, 1028}
After stepping through addAccountExplicitly():
08-10 10:45:56.479 9015-9270/system_process V/AccountManagerService﹕ addAccount: Account {name=100, type=com.example.mylib.provider.ACCOUNT}, caller's uid 10048, pid 19247
08-10 10:45:56.479 9015-9270/system_process V/AccountManagerService﹕ caller uid 10048 has android.permission.AUTHENTICATE_ACCOUNTS
08-10 10:45:56.479 9015-9270/system_process W/AccountManagerService﹕ caller uid 10048 is different than the authenticator's uid
Packages Dump
The interesting snippets from /data/system/packages.xml seem to be alright:
...
<package name="com.example.mylib.app"
codePath="/data/app/com.example.mylib.app-1.apk"
nativeLibraryPath="/data/data/com.example.mylib.app/lib"
flags="0" ft="14f170308d8" it="14f16d8b51b" ut="14f17030a42" version="1"
sharedUserId="10048">
<sigs count="1">
<cert index="4" />
</sigs>
<perms />
</package>
...
<shared-user name="com.example.mylib" userId="10048">
<sigs count="1">
<cert index="4" />
</sigs>
<perms>
<item name="android.permission.READ_SYNC_SETTINGS" />
<item name="android.permission.MANAGE_ACCOUNTS" />
<item name="android.permission.USE_CREDENTIALS" />
<item name="android.permission.WRITE_SYNC_SETTINGS" />
<item name="android.permission.GET_ACCOUNTS" />
<item name="android.permission.INTERNET" />
<item name="android.permission.AUTHENTICATE_ACCOUNTS" />
</perms>
</shared-user>
Project Manifests
Library project's mylib_authenticator.xml:
<?xml version="1.0" encoding="utf-8"?>
<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
android:sharedUserId="com.example.mylib"
android:accountType="com.example.mylib.provider.ACCOUNT"
android:exported="true"
android:label="#string/service_name"/>
Library project's mylib_syncadapter.xml:
<?xml version="1.0" encoding="utf-8"?>
<sync-adapter xmlns:android="http://schemas.android.com/apk/res/android"
android:sharedUserId="com.example.mylib"
android:contentAuthority="com.example.mylib.provider"
android:accountType="com.example.mylib.provider.ACCOUNT"
android:userVisible="false"
android:exported="true"
android:supportsUploading="false"
android:allowParallelSyncs="false"
android:isAlwaysSyncable="true"
/>
Interesting bits from the library project's AndroidManifest.xml:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.mylib"
android:sharedUserId="com.example.mylib">
<application>
<provider
android:name="com.example.mylib.provider.MyContentProvider"
android:authorities="com.example.mylib.provider"
android:exported="true"
android:syncable="true"/>
<service
android:name="com.example.mylib.service.SyncService"
android:exported="true"
android:process=":sync">
<intent-filter>
<action android:name="android.content.SyncAdapter"/>
</intent-filter>
<meta-data android:name="android.content.SyncAdapter"
android:resource="#xml/mylib_syncadapter" />
</service>
<service android:name="com.example.mylib.service.AccountService"
android:exported="true">
<intent-filter>
<action android:name="android.content.AccountAuthenticator"/>
</intent-filter>
<meta-data android:name="android.content.AccountAuthenticator"
android:resource="#xml/mylib_authenticator" />
</service>
</application>
Interesting bits from app project's AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.mylib.app"
android:sharedUserId="com.example.mylib">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS"/>
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS"/>
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS"/>
<uses-permission android:name="android.permission.USE_CREDENTIALS"/>
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS"/>
<application ...>
<activity ... />
</application>
</manifest>