I am wondering how to adjust the standard user agent in my http requests. I am using the Volley library and I KNOW how to
set a new user agent
retrieve the default user agent as a string (e.g. "Dalvik/1.6.0 (Linux; U; Android 4.0.2; sdk Build/ICS_MR0") => System.getProperty("http.agent")
What I DON'T know is:
how to get the single elements this user agent is build of, so I can replace only the string "Dalvik/1.6.0" with a custom string.
Is that possible, or do I have to make a string replacement?
Thx
In order to set the user agent globally for all requests sent via volley, here is my solution:
When you are initializing the volley request queue, instead of using the convenient method Volley.newRequestQueue(Context);, use the following snippet:
private RequestQueue makeRequestQueue(Context context) {
DiskBasedCache cache = new DiskBasedCache(new File(context.getCacheDir(), DEFAULT_CACHE_DIR), DISK_CACHE_SIZE);
BasicNetwork network = new BasicNetwork(new MyHurlStack());
RequestQueue queue = new RequestQueue(cache, network);
queue.start();
return queue;
}
public static class MyHurlStack extends HurlStack {
#Override
public HttpResponse executeRequest(Request<?> request, Map<String, String> additionalHeaders) throws IOException, AuthFailureError {
if (additionalHeaders == null || Collections.emptyMap().equals(additionalHeaders) {
additionalHeaders = new HashMap<>();
}
additionalHeaders.put("User-Agent", "test_user_agent_in_volley");
return super.executeRequest(request, additionalHeaders);
}
}
This solution assumes you are targeting api level >= 9, so we use the HurlStack
The reason why this works is because in HurlStack.executeRequest(Request<?> request, Map<String, String> additionalHeaders) method, the stuff you add to the additionalHeaders would later be added to an HttpUrlConnection request property as in connection.addRequestProperty(headerName, map.get(headerName));
Yes,
Build.FINGERPRINT contains all the information you need,
https://developer.android.com/reference/android/os/Build.html
To get the individual parts, use the individual constant strings,
For detailed OS Version information use Build.VERSION
import android.util.Log;
import android.os.Bundle;
import android.os.Build;
public class MainActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i("Build","BOARD = "+Build.BOARD);
Log.i("Build","BOOTLOADER = "+Build.BOOTLOADER);
Log.i("Build","BRAND = "+Build.BRAND);
Log.i("Build","CPU_ABI = "+Build.CPU_ABI);
Log.i("Build","CPU_ABI2 = "+Build.CPU_ABI2);
Log.i("Build","DEVICE = "+Build.DEVICE);
Log.i("Build","DISPLAY = "+Build.DISPLAY);
Log.i("Build","FINGERPRINT = "+Build.FINGERPRINT);
Log.i("Build","HARDWARE = "+Build.HARDWARE);
Log.i("Build","HOST = "+Build.HOST);
Log.i("Build","ID = "+Build.ID);
Log.i("Build","MANUFACTURER = "+Build.MANUFACTURER);
Log.i("Build","MODEL = "+Build.MODEL);
Log.i("Build","PRODUCT = "+Build.PRODUCT);
Log.i("Build","RADIO = "+Build.RADIO);
Log.i("Build","SERIAL = "+Build.SERIAL);
Log.i("Build","TAGS = "+Build.TAGS);
Log.i("Build","TYPE = "+Build.TYPE);
Log.i("Build","USER = "+Build.USER);
Log.i("Build","BASE_OS = "+Build.VERSION.BASE_OS);
Log.i("Build","CODENAME = "+ Build.VERSION.CODENAME);
Log.i("Build","INCREMENTAL = "+ Build.VERSION.INCREMENTAL);
Log.i("Build","RELEASE = "+ Build.VERSION.RELEASE);
Log.i("Build","SDK = "+ Build.VERSION.SDK);
Log.i("Build","SECURITY_PATCH = "+ Build.VERSION.SECURITY_PATCH);
Log.i("$TAG#",Build.FINGERPRINT);
}
}
System.getProperty("http.agent") returns something like:
Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)
It's possible to build all the parts of this using a combination of android.os.Build and java.lang.System.getProperty().
This is an example of what's in android.os.Build running on an emulator:
Build.BOARD = "goldfish_x86"
Build.BOOTLOADER = "unknown"
Build.BRAND = "google"
Build.DEVICE = "generic_x86"
Build.DISPLAY = "sdk_gphone_x86-userdebug 9 PSR1.180720.075 5124027 dev-keys"
Build.FINGERPRINT = "google/sdk_gphone_x86/generic_x86:9/PSR1.180720.075/5124027:userdebug/dev-keys"
Build.HARDWARE = "ranchu"
Build.HOST = "abfarm904"
Build.ID = "PSR1.180720.075"
Build.MANUFACTURER = "Google"
Build.MODEL = "Android SDK built for x86"
Build.PRODUCT = "sdk_gphone_x86"
Build.SUPPORTED_32_BIT_ABIS = {"x86"}
Build.SUPPORTED_64_BIT_ABIS = {}
Build.SUPPORTED_ABIS = {"x86"}
Build.TAGS = "dev-keys"
Build.TIME = 1541887073000
Build.TYPE = "userdebug"
Build.USER = "android-build"
Build.UNKNOWN = "unknown"
Build.VERSION.BASE_OS = ""
Build.VERSION.CODENAME = "REL"
Build.VERSION.INCREMENTAL = "5124027"
Build.VERSION.PREVIEW_SDK_INT = 0
Build.VERSION.RELEASE = "9"
Build.VERSION.SDK_INT = 28
Build.VERSION.SECURITY_PATCH = "2018-09-05"
These properties are always provided by the Dalvik VM, according to Google's documentation:
file.separator = /
java.class.path = .
java.class.version = 50.0
java.compiler = Empty
java.ext.dirs = Empty
java.home = /system
java.io.tmpdir = /sdcard
java.library.path = /vendor/lib:/system/lib
java.vendor = The Android Project
java.vendor.url = http://www.android.com/
java.version = 0
java.specification.version = 0.9
java.specification.vendor = The Android Project
java.specification.name = Dalvik Core Library
java.vm.version = 1.2.0
java.vm.vendor = The Android Project
java.vm.name = Dalvik
java.vm.specification.version = 0.9
java.vm.specification.vendor = The Android Project
java.vm.specification.name = Dalvik Virtual Machine Specification
line.separator = \n
os.arch = armv7l
os.name = Linux
os.version = 2.6.32.9-g103d848
path.separator = :
user.dir = /
user.home = Empty
user.name = Empty
So, the default user agent appears to be composed of:
System.getProperty("java.vm.name") // Dalvik
System.getProperty("java.vm.version") // 2.1.0
System.getProperty("os.name") // Linux
"U" // not sure where to get this
"Android" // or this, probably safe to hard code though
Build.VERSION.RELEASE // 9
Build.MODEL // Android SDK built for x86
Build.ID // PSR1.180720.075
Related
I am trying to add an 802.1x network as a suggested network in Android 10.
When I do the addSuggestedNetwork it returns a code of 0 indicating that it did add it.
I even checked it by trying to add a second time. That returned 3 - network already exists.
Nevertheless, it doesn't fill in any of the parameters of the AP definition:
WifiManager wifiManager = getSystemService(Context.WIFI_SERVICE));
WifiNetworkSuggestion.Builder suggestionBuilder = new WifiNetworkSuggestion.Builder();
String ssid = c8021XAP.getSsid();
WifiNetworkSuggestion suggestion = suggestionBuilder
.setSsid(ssid)
.setWpa3EnterpriseConfig(c8021XAP.eapConfig())
.setPriority(10)
.build();
List<WifiNetworkSuggestion> suggestions = new ArrayList<>();
status = wifiManager.addNetworkSuggestions(suggestions);
Following is the code that creates the eapConfig object:
fun eapConfig(): WifiEnterpriseConfig {
val eap = WifiEnterpriseConfig()
eap.identity = username
eap.password = Base64.encode(password.toByteArray(), Base64.DEFAULT).toString()
eap.anonymousIdentity = anonymousIdentity
eap.phase2Method = phase2
eap.eapMethod = eapMethod
eap.domainSuffixMatch = domainName
return eap
}
I tried changing setWpa3EnterpriseConfig to setWpa2EnterpriseConfig but no change.
I am trying to add a 802.1x network programmatically in my Android app.
On an Android 8 device using addNetwork I see that the network is added with credentials but on Android 10 and above, when using addNetworkSuggestions, the credentials are not added.
I am new in this field so it is possible I am missing something vital.
WifiConfiguration wifiConf = new WifiConfiguration();
wifiConf.allowedAuthAlgorithms.clear();
wifiConf.allowedGroupCiphers.clear();
wifiConf.allowedKeyManagement.clear();
wifiConf.allowedPairwiseCiphers.clear();
wifiConf.allowedProtocols.clear();
wifiConf.SSID = TextUtil.convertToQuotedString(apSsid.toString());
wifiConf.enterpriseConfig = eapConfig.asWifiEnterpriseConfig();
wifiConf.enterpriseConfig.setIdentity(......);
wifiConf.enterpriseConfig.setPassword(......);
wifiConf.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.PEAP);
wifiConf.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.NONE);
wifiConf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
wifiConf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
wifiConfig.status = WifiConfiguration.Status.ENABLED;
wifiConfig.allowedKeyManagement.set(KeyMgmt.WPA_EAP);
wifiConfig.allowedKeyManagement.set(KeyMgmt.IEEE8021X);
wifiConf.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
wifiConf.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
wifiConf.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
wifiConf.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
if (apPass.length() == 64 && WeFiUtilExt.isHex(apPass)) {
// Goes unquoted as hex
wifiConf.preSharedKey = apPass;
}
else {
// Goes quoted as ASCII
wifiConf.preSharedKey = TextUtil.convertToQuotedString(apPass);
}
WifiNetworkSuggestion.Builder wpa2WifiNetworkSuggestionBuilder = new WifiNetworkSuggestion.Builder();
wpa2WifiNetworkSuggestionBuilder.setSsid(ssid).setIsAppInteractionRequired(true);
wpa2WifiNetworkSuggestionBuilder.setWpa2EnterpriseConfig(wifiEnterpriseConfig);
WifiNetworkSuggestion wpa2WifiNetworkSuggestion = wpa2WifiNetworkSuggestionBuilder.build();
WifiNetworkSuggestion.Builder wpa3WifiNetworkSuggestionBuilder = new WifiNetworkSuggestion.Builder();
wpa3WifiNetworkSuggestionBuilder.setSsid(ssid).setIsAppInteractionRequired(false);
wpa3WifiNetworkSuggestionBuilder.setWpa3EnterpriseConfig(wifiEnterpriseConfig);
WifiNetworkSuggestion wpa3WifiNetworkSuggestion = wpa3WifiNetworkSuggestionBuilder.build();
List<WifiNetworkSuggestion> wifiNetworkSuggestionList = new ArrayList<>();
wifiNetworkSuggestionList.add(wpa2WifiNetworkSuggestion);
wifiNetworkSuggestionList.add(wpa3WifiNetworkSuggestion);
int addStatus = m_wifiMngr.addNetworkSuggestions(wifiNetworkSuggestionList);
The return code is 0 implying that the add worked.
Will this not work in Android 10+?
I am trying to create note in a shared notebook which is already shared with me. The notebook is shared with me with priveleges to modify its contents (SharedNotebookPrivilegeLevel.MODIFY_NOTEBOOK_PLUS_ACTIVITY), and I can create notes in that notebook using Evernote web client. But when I trying to create a note using SDK I received an EDAMUserException(errorCode:PERMISSION_DENIED, parameter:authenticationToken). Below is my code
Note note = new Note();
note.setContent(EvernoteUtil.NOTE_PREFIX + content + EvernoteUtil.NOTE_SUFFIX);
note.setTitle(title);
EvernoteSession evernoteSession = EvernoteSession.getInstance();
List<LinkedNotebook> linkedNotebooks = evernoteSession
.getEvernoteClientFactory()
.getNoteStoreClient()
.listLinkedNotebooks();
LinkedNotebook current = null;
for (LinkedNotebook linkedNotebook : linkedNotebooks) {
if (linkedNotebook.getShareName().equals(notebookName)) {
current = linkedNotebook;
}
}
if (current == null)
throw new IllegalStateException();
THttpClient tHttpClient = new THttpClient(current.getNoteStoreUrl());
TBinaryProtocol tBinaryProtocol = new TBinaryProtocol(tHttpClient);
NoteStore.Client client = new NoteStore.Client(tBinaryProtocol, tBinaryProtocol);
AuthenticationResult authenticationResult = client.authenticateToSharedNotebook(current.getShareKey(),
evernoteSession.getAuthToken());
String shareToken = authenticationResult.getAuthenticationToken();
SharedNotebook sharedNotebook = client.getSharedNotebookByAuth(shareToken);
String sharedNotebookGuid = sharedNotebook.getNotebookGuid();
note.setGuid(sharedNotebookGuid);
Note createdNote = client.createNote(shareToken, note);
return createdNote;
I've used this article to create notes.
One mistake I found is that
note.setGuid(sharedNotebookGuid);
has to be
note.setNotebookGuid(sharedNotebookGuid);
Here says the Web audio API works in Chrome for Android, and here I have tested CM Browser, Chrome and CyanogenMod default Android 5.1.1 browsers, and all pass the tests (specially the biquadNode one).
But When I open this codepen with an eq (biquadNode), I can hear the music but not the eq working.
Does biquadNode works in android? any special implementation is needed?
*Code pen required to post
var context = new AudioContext();
var mediaElement = document.getElementById('player');
var sourceNode = context.createMediaElementSource(mediaElement);
// EQ Properties
//
var gainDb = -40.0;
var bandSplit = [360,3600];
var hBand = context.createBiquadFilter();
hBand.type = "lowshelf";
hBand.frequency.value = bandSplit[0];
hBand.gain.value = gainDb;
var hInvert = context.createGain();
hInvert.gain.value = -1.0;
var mBand = context.createGain();
var lBand = context.createBiquadFilter();
lBand.type = "highshelf";
lBand.frequency.value = bandSplit[1];
lBand.gain.value = gainDb;
var lInvert = context.createGain();
lInvert.gain.value = -1.0;
sourceNode.connect(lBand);
sourceNode.connect(mBand);
sourceNode.connect(hBand);
hBand.connect(hInvert);
lBand.connect(lInvert);
hInvert.connect(mBand);
lInvert.connect(mBand);
var lGain = context.createGain();
var mGain = context.createGain();
var hGain = context.createGain();
lBand.connect(lGain);
mBand.connect(mGain);
hBand.connect(hGain);
var sum = context.createGain();
lGain.connect(sum);
mGain.connect(sum);
hGain.connect(sum);
sum.connect(context.destination);
// Input
//
function changeGain(string,type)
{
var value = parseFloat(string) / 100.0;
switch(type)
{
case 'lowGain': lGain.gain.value = value; break;
case 'midGain': mGain.gain.value = value; break;
case 'highGain': hGain.gain.value = value; break;
}
}
createMediaElementSource in Chrome on Android doesn't work in general. But if you have a recent build of Chrome (49 and later?), you can go to chrome://flags and enable the unified media pipeline option. That will make createMediaElementSource work like on desktop.
I'm doing an app that requires Spotify in Android. But when i run libSpotify "sp_session_create" i get a SIGSEGV. The version of libSpotify that i'm using is v12.1.51 BETA - For android ARM
sp_error initialise(const char * asKey,
const char * asFolder,
const char * asUserAgent,
bool isPlaylistCompressed,
bool isMetadataOnPlaylist,
bool isPlaylistInitialUnload)
{
sp_session_callbacks asCallbacks;
memset(&asCallbacks, 0, sizeof(asCallbacks));
asCallbacks.logged_in = Callback::onSessionLogin;
asCallbacks.log_message = Callback::onSessionLog;
sp_session_config asConfiguration;
memset(&asConfiguration, 0, sizeof(asConfiguration));
std::string asDirectory = asFolder;
auto asDirectoryCache = asDirectory + "/cache";
auto asDirectorySetting = asDirectory + "/setting";
const auto asApplicationKey = "Key goes here...";
asConfiguration.api_version = SPOTIFY_API_VERSION;
asConfiguration.application_key = asApplicationKey;
asConfiguration.application_key_size = sizeof(asApplicationKey);
asConfiguration.cache_location = asDirectoryCache.c_str();
asConfiguration.settings_location = asDirectorySetting.c_str();
asConfiguration.user_agent = asUserAgent;
asConfiguration.compress_playlists = isPlaylistCompressed;
asConfiguration.dont_save_metadata_for_playlists = isMetadataOnPlaylist;
asConfiguration.initially_unload_playlists = isPlaylistInitialUnload;
asConfiguration.userdata = this;
asConfiguration.callbacks = &asCallbacks;
sp_error asError = sp_session_create(&asConfiguration, &_asSession);
__android_log_print(ANDROID_LOG_VERBOSE, LIBRARY_NAME, "PASSED");
return asError;
}
The crash was due to cache folder.
Edit: Spotify's new Android SDK is released! You should strongly consider moving your project to the new SDK, since libspotify is now deprecated for that platform.