Offline sideloading with Mapbox - android

So I'm trying to use the Mapbox SDK in an offline mode by merging tiles in a local DB file I created from my own tile server by using
./mbgl-offline --north [north coordinate] --west [west coordinate] --south [south coordinate] --east [east coordinate] --minZoom [minimum zoom] --maxZoom [maximum zoom] --output [output file path] --style [style URL] --token [mapbox token]
command from the mapbox-gl-native library.
I put the file in the /path/to/file/files directory and I implemented the merging code as shown in the example : merge offline tiles example
When I open the app I get a toast says the merging went successfully but I can't see the map. all I see is a blank surface with the background color of my map style.
As shown in the example, I make sure the app is not connected to the internet and then I merge the DB file before I load the style:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Mapbox access token is configured here. This needs to be called either in your application
// object or in the same activity which contains the map view.
Mapbox.getInstance(this, getString(R.string.access_token));
// This contains the MapView in XML and needs to be called after the access token is configured.
setContentView(R.layout.activity_main);
mapView = findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
Mapbox.setConnected(false);
mergeDb();
mapView.getMapAsync(this);
}
#Override
public void onMapReady(#NonNull final MapboxMap mapboxMap) {
MainActivity.this.mapboxMap = mapboxMap;
mapboxMap.setStyle( new Style.Builder().fromUrl("http://<my_server_ip>/styles/klokantech-basic/style.json")
, new Style.OnStyleLoaded() {
#Override
public void onStyleLoaded(#NonNull Style style) {
// enableLocationComponent(style);
}
});
}
My mergeDb function:
private void mergeDb(){
System.out.println(FileSource.getResourcesCachePath(this));
OfflineManager.getInstance(this).mergeOfflineRegions(FileSource.getResourcesCachePath(this) + "/myfile.db", new OfflineManager.MergeOfflineRegionsCallback() {
#Override
public void onMerge(OfflineRegion[] offlineRegions) {
mapView.getMapAsync(new OnMapReadyCallback() {
#Override
public void onMapReady(#NonNull MapboxMap mapboxMap) {
mapboxMap.setStyle(new Style.Builder().fromUrl("http://<my_server_ip>/styles/klokantech-basic/style.json"));
}
});
Toast.makeText(
MainActivity.this,
String.format("Merged %d regions.", offlineRegions.length),
Toast.LENGTH_LONG).show();
}
#Override
public void onError(String error) {
Toast.makeText(
MainActivity.this,
String.format("Offline DB merge error." ),
Toast.LENGTH_LONG).show();
System.out.println(error);
}
});
}
Any idea what could be the problem?

Related

Azure Adb2c Custom Web view for Loading User Flows in Native Android using MSAL

I was integrating azure adb2c on my native android app using MSAL. Currently I'm using createSingleAccountPublicClientApplication for my application. I have created sign-up and sign-in user flow and integrated with my application which is working perfectly. When the application is launched, it redirects to the Web view ,since I have mentioned the BrowserTabActivity inside the manifest file. But as per our requirement, we have to create our own custom webview and show all the userflows and get the callback as necessary . Is it possible to create custom webview for android and show the userflows?
Second issue is, When user taps on back button from SignUp Page , error code AADB2C90091 is thrown, not going back to signIn UserFlow Page . How can I show the signIn UserFlow Pag on back pressed?
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.microsoft_azure);
context = MicrosoftAzureActivity.this;
initializeUI();
// Creates a PublicClientApplication object with res/raw/auth_config_single_account.json
PublicClientApplication.createSingleAccountPublicClientApplication(MicrosoftAzureActivity.this,
R.raw.auth_config_single_account,
new IPublicClientApplication.ISingleAccountApplicationCreatedListener() {
#Override
public void onCreated(ISingleAccountPublicClientApplication application) {
/**
* This test app assumes that the app is only going to support one account.
* This requires "account_mode" : "SINGLE" in the config json file.
**/
mSingleAccountApp = application;
loadAccount();
}
#Override
public void onError(MsalException exception) {
displayError(exception);
}
});
}
loadAccount::
private void loadAccount() {
if (mSingleAccountApp == null) {
return;
}
mSingleAccountApp.getCurrentAccountAsync(new ISingleAccountPublicClientApplication.CurrentAccountCallback() {
#Override
public void onAccountLoaded(#Nullable IAccount activeAccount) {
// You can use the account data to update your UI or your app database.
mAccount = activeAccount;
if (activeAccount != null) {
mSingleAccountApp.acquireTokenSilentAsync(getScopes(), B2CConfiguration.getAuthorityFromPolicyName("B2C_1_SignInSignUp"), getAuthSilentCallback());
}
}
#Override
public void onAccountChanged(#Nullable IAccount priorAccount, #Nullable IAccount currentAccount) {
if (currentAccount == null) {
// Perform a cleanup task as the signed-in account changed.
showToastOnSignOut();
}
}
#Override
public void onError(#NonNull MsalException exception) {
displayError(exception);
}
});
}
auth_config_single_account::
{
"client_id" : "cfsttrtkg-4545-fsrdh-822d-53453423-0",
"redirect_uri" : "msauth://**********/***********,
"account_mode" : "SINGLE",
"broker_redirect_uri_registered": false,
"authorization_user_agent" : "WEBVIEW",
"authorities": [
{
"type": "B2C",
"authority_url": "SIGNIN_SIGNUP_POLICY",
"default": true
},
{
"type": "B2C",
"authority_url": "PASSWORD_RESET_POLICY"
}
]
}

'MyApp' has stopped and forcing to close

I'm developing Android app on Android studio using Opencv library and when I try to open my app it opens then right after that it closes and displaying crash message. I'm new on mobile development
Using : OpenCV310, Android Studio 3.0,
public class ScanLicensePlateActivity extends AppCompatActivity {
protected AnylineOcrScanView scanView;
private LicensePlateResultView licensePlateResultView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Set the flag to keep the screen on (otherwise the screen may go dark during scanning)
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.activity_anyline_ocr);
String license = getString(R.string.anyline_license_key);
// Get the view from the layout
scanView = (AnylineOcrScanView) findViewById(R.id.scan_view);
// Configure the view (cutout, the camera resolution, etc.) via json
// (can also be done in xml in the layout)
scanView.setConfig(new AnylineViewConfig(this, "license_plate_view_config.json"));
// Copies given traineddata-file to a place where the core can access it.
// This MUST be called for every traineddata file that is used
// (before startScanning() is called).
// The file must be located directly in the assets directory
// (or in tessdata/ but no other folders are allowed)
scanView.copyTrainedData("tessdata/GL-Nummernschild-Mtl7_uml.traineddata",
"8ea050e8f22ba7471df7e18c310430d8");
scanView.copyTrainedData("tessdata/Arial.traineddata", "9a5555eb6ac51c83cbb76d238028c485");
scanView.copyTrainedData("tessdata/Alte.traineddata", "f52e3822cdd5423758ba19ed75b0cc32");
scanView.copyTrainedData("tessdata/deu.traineddata", "2d5190b9b62e28fa6d17b728ca195776");
// Configure the OCR for license plate scanning via a custom script file
// This is how you could add custom scripts optimized by Anyline for your use-case
AnylineOcrConfig anylineOcrConfig = new AnylineOcrConfig();
anylineOcrConfig.setCustomCmdFile("license_plates.ale");
// set the ocr config
scanView.setAnylineOcrConfig(anylineOcrConfig);
// initialize with the license and a listener
scanView.initAnyline(license, new AnylineOcrListener() {
#Override
public void onReport(String identifier, Object value) {
// Called with interesting values, that arise during processing.
// Some possibly reported values:
//
// $brightness - the brightness of the center region of the cutout as a float value
// $confidence - the confidence, an Integer value between 0 and 100
// $thresholdedImage - the current image transformed into black and white
// $sharpness - the detected sharpness value (only reported if minSharpness > 0)
}
#Override
public boolean onTextOutlineDetected(List<PointF> list) {
// Called when the outline of a possible text is detected.
// If false is returned, the outline is drawn automatically.
return false;
}
#Override
public void onResult(AnylineOcrResult result) {
// Called when a valid result is found
String results[] = result.getText().split("-");
String licensePlate = results[1];
licensePlateResultView.setLicensePlate(licensePlate);
licensePlateResultView.setVisibility(View.VISIBLE);
}
#Override
public void onAbortRun(AnylineOcrError code, String message) {
// Is called when no result was found for the current image.
// E.g. if no text was found or the result is not valid.
}
});
// disable the reporting if set to off in preferences
if (!PreferenceManager.getDefaultSharedPreferences(this).getBoolean(
SettingsFragment.KEY_PREF_REPORTING_ON, true)) {
// The reporting of results - including the photo of a scanned meter -
// helps us in improving our product, and the customer experience.
// However, if you wish to turn off this reporting feature, you can do it like this:
scanView.setReportingEnabled(false);
}
addLicensePlateResultView();
}
private void addLicensePlateResultView() {
RelativeLayout mainLayout = (RelativeLayout) findViewById(R.id.main_layout);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.CENTER_HORIZONTAL, RelativeLayout.TRUE);
params.addRule(RelativeLayout.CENTER_VERTICAL, RelativeLayout.TRUE);
licensePlateResultView = new LicensePlateResultView(this);
licensePlateResultView.setVisibility(View.INVISIBLE);
mainLayout.addView(licensePlateResultView, params);
licensePlateResultView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startScanning();
}
});
}
private void startScanning() {
licensePlateResultView.setVisibility(View.INVISIBLE);
// this must be called in onResume, or after a result to start the scanning again
scanView.startScanning();
}
#Override
protected void onResume() {
super.onResume();
startScanning();
}
#Override
protected void onPause() {
super.onPause();
scanView.cancelScanning();
scanView.releaseCameraInBackground();
}
#Override
public void onBackPressed() {
if (licensePlateResultView.getVisibility() == View.VISIBLE) {
startScanning();
} else {
super.onBackPressed();
}
}
#Override
protected void onDestroy() {
super.onDestroy();
}}
source code is here.
If possible please help.
Logcat error shown here
Ideally more information regarding the error would be best i.e the opencv library version etc. Given it seems to be an Android issue, I would advise
File and issue or view issues pertaining to this error on their github page. Search for related Android errors to see if they match.
IF you cannot find a related error, file an issue there.

Google Drive Api implementation from SherlockFragmentActivity action bar

I have the following scenario in my app -
SherlockFragmentActivity hosting a ViewPager containing 3 individual fragments. There is a sherlockactionbar on top, with backup and restore options, which should basically backup the app data to google drive account (connected to the user).
Now, everything works fine, wrt the backup-restore as well, by opening up the Google Api Client connection and uploading / downloading file, but as soon as the device rotates, the Activity is restarted from scratch and the google api client instance created and instantiated ealier (may be upload / download is also still in progress) becomes orphan.
I get a IllegalStateException (due to the activity restart, while the instance still needs an original activity to tie back to).
Knowing, that the Fragments themselves can be retained across activity restarts, I can put the drive api implementation in fragment, but having a common action bar icon on top, wouldn't it be a repetition to just put drive implementation on all 3 fragments??
Also, when the ViewPager swipe occurs, the fragment will be changed, so wouldn't I face the same issue again, wherein the original drive api client instance creator fragment is no longer in scope.?
What is a good way to implement such a thing? Any ideas would help me to research in given direction.
I have a viewpager and several fragments, just as your case. I let the my activity class extend the BaseDriveActivity from the Google-drive-exapmle, but letting it extend FragmentActivity instead of Activity.
The rotation was not any problem, even if onResume is called during rotation, sinde it is checking if mGoogleApiClient is null:
#Override
protected void onResume() {
super.onResume();
if (mGoogleApiClient == null) {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Drive.API).addScope(Drive.SCOPE_FILE)
.addScope(Drive.SCOPE_APPFOLDER)
// required for App Folder sample
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this).build();
}
if (!mGoogleApiClient.isConnected() && !mGoogleApiClient.isConnecting())
mGoogleApiClient.connect();
}
There is some logic for errorhandling as well. You can use it as is.
The operations for creating a folder, creating a folder inside a foldet etc I added to my main class like this:
protected void createFolder(String folderName){
MetadataChangeSet changeSet = new MetadataChangeSet.Builder()
.setTitle(folderName).build();
Drive.DriveApi.getRootFolder(getGoogleApiClient()).createFolder(
getGoogleApiClient(), changeSet).setResultCallback(createFolderCallback);
}
final ResultCallback<DriveFolderResult> createFolderCallback = new ResultCallback<DriveFolderResult>() {
#Override
public void onResult(DriveFolderResult result) {
if (!result.getStatus().isSuccess()) {
showMessage("Error while trying to create the folder");
return;
}
showMessage("Created a folder: " + result.getDriveFolder().getDriveId());
}
};
private String folderName;
protected void createFolderInFolder(String exsistingDriveId, String folderName){
Drive.DriveApi.fetchDriveId(getGoogleApiClient(), exsistingDriveId).setResultCallback(idCallback);
this.folderName=folderName;
}
final ResultCallback<DriveIdResult> idCallback = new ResultCallback<DriveIdResult>() {
#Override
public void onResult(DriveIdResult result) {
if (!result.getStatus().isSuccess()) {
showMessage("Cannot find DriveId. Are you authorized to view this file?");
return;
}
DriveFolder folder = Drive.DriveApi
.getFolder(getGoogleApiClient(), result.getDriveId());
MetadataChangeSet changeSet = new MetadataChangeSet.Builder()
.setTitle(folderName).build();
folder.createFolder(getGoogleApiClient(), changeSet)
.setResultCallback(createFolderCallback);
}
};
private DriveId mFolderDriveId;
protected void createFileInFolder(String exsistingDriveId, String folderName){
Drive.DriveApi.fetchDriveId(getGoogleApiClient(), exsistingDriveId).setResultCallback(fileIdCallback);
this.folderName=folderName;
}
final private ResultCallback<DriveIdResult> fileIdCallback = new ResultCallback<DriveIdResult>() {
#Override
public void onResult(DriveIdResult result) {
if (!result.getStatus().isSuccess()) {
showMessage("Cannot find DriveId. Are you authorized to view this file?");
return;
}
mFolderDriveId = result.getDriveId();
Drive.DriveApi.newDriveContents(getGoogleApiClient())
.setResultCallback(driveContentsCallback);
}
};
final private ResultCallback<DriveContentsResult> driveContentsCallback =
new ResultCallback<DriveContentsResult>() {
#Override
public void onResult(DriveContentsResult result) {
if (!result.getStatus().isSuccess()) {
showMessage("Error while trying to create new file contents");
return;
}
DriveFolder folder = Drive.DriveApi.getFolder(getGoogleApiClient(), mFolderDriveId);
MetadataChangeSet changeSet = new MetadataChangeSet.Builder()
.setTitle(folderName)
.setMimeType("text/plain")
.setStarred(true).build();
folder.createFile(getGoogleApiClient(), changeSet, result.getDriveContents())
.setResultCallback(fileCallback);
}
};
final private ResultCallback<DriveFileResult> fileCallback =
new ResultCallback<DriveFileResult>() {
#Override
public void onResult(DriveFileResult result) {
if (!result.getStatus().isSuccess()) {
showMessage("Error while trying to create the file");
return;
}
showMessage("Created a file: " + result.getDriveFile().getDriveId());
}
};
EDIT:
I have found the following:
if createFolderInFolder (or any other of the api-funcions) is called, just before an intent is used to call an activity, the result-callback will not be called while the called activity is running. When the main activity is receiving control, the onResume is called, and giving an exception, since connect is called again. Then the result-callback is never called.
This means that the api-call and the result-callback must be able to run without any other calls being run.
New Edit:
Step1: You need a callback function in your Fragment
private Callbacks mCallbacks;
interface Callbacks {
public void onSaveToDrive(byte[] filecontent);
}
Step2: The main activity must implement the fragment callback-methods
Step3: Call the api-function, and add the fragment-update call in the result-callback
If you would like to store the driveid, you should use DriveId.encodeFromString(exsistingDriveId) and DriveId.decodeFromString(exsistingDriveId) in this way you can store the existingDriveId, and safely refer to it again at a later stage, even if the drive has been disconnected and reconnected.
Remember one api-call must be done without calling other classes, since that may cause the onResume() to be called.

Error when displaying the map using Skobbler in Android

I want to integrate a map in my android application. But I'm just starting form the basics and I'm already encountering a crash/error.
I just copied some codes from the demo project but still no luck.
Logcat :
08-14 16:19:55.703: E/AndroidRuntime(30065): FATAL EXCEPTION: GLThread 787
08-14 16:19:55.703: E/AndroidRuntime(30065): java.lang.NullPointerException
08-14 16:19:55.703: E/AndroidRuntime(30065): at com.skobbler.ngx.map.MapRenderer.onSurfaceCreated(SourceFile:487)
08-14 16:19:55.703: E/AndroidRuntime(30065): at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1509)
08-14 16:19:55.703: E/AndroidRuntime(30065): at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1248)
I researched already but I haven;t found any solution yet.
Please help.
Here's my code:
MainActivity.java
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SKLogging.enableLogs(true);
File externalDir = getExternalFilesDir(null);
if (externalDir != null) {`enter code here`
mapresDirPath = externalDir + "/SKMaps/";
} else {
mapresDirPath = getFilesDir() + "/SKMaps/";
}
if (!new File(mapresDirPath).exists()) {
new SKPrepareMapTextureThread(this, mapresDirPath, "SKMaps.zip", this).start();
copyOtherResources();
prepareMapCreatorFile();
} else {
Toast.makeText(MainActivity.this, "Map resources copied in a previous run", Toast.LENGTH_SHORT).show();
prepareMapCreatorFile();
initializeLibrary();
finish();
startActivity(new Intent(MainActivity.this, MapActivity.class));
}
}
private void initializeLibrary() {
SKMapsInitSettings initSettings = new SKMapsInitSettings();
initSettings.setMapResourcesPaths(mapresDirPath, new SKMapViewStyle(mapresDirPath + "daystyle/", "daystyle.json"));
final SKAdvisorSettings advisorSettings = initSettings.getAdvisorSettings();
advisorSettings.setLanguage("en");
advisorSettings.setAdvisorVoice("en");
advisorSettings.setPlayInitialAdvice(true);
advisorSettings.setPlayAfterTurnInformalAdvice(true);
advisorSettings.setPlayInitialVoiceNoRouteAdvice(true);
initSettings.setAdvisorSettings(advisorSettings);
SKVersioningManager.getInstance().setMapUpdateListener(this);
SKMaps.getInstance().initializeSKMaps(this, initSettings, API_KEY);
}
#Override
public void onMapTexturesPrepared(boolean prepared) {
initializeLibrary();
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(MainActivity.this, "Map resources were copied", Toast.LENGTH_SHORT).show();
finish();
startActivity(new Intent(MainActivity.this, MapActivity.class));
}
});
}
MapActivity.java
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map);
SKMapViewHolder mapViewHolder = (SKMapViewHolder) findViewById(R.id.map_surface_holder);
mapView = mapViewHolder.getMapSurfaceView();
mapView.getMapSettings().setMapPanningEnabled(true);
mapView.getMapSettings().setMapZoomingEnabled(true);
mapView.getMapSettings().setInertiaPanningEnabled(true);
SKVersioningManager.getInstance().setMapUpdateListener(this);
}
I had the same problem, and I posted an answer on their support forum :
Hi,
Implementing Skobbler in my android app, I stucked half an hour with a crash I couldn't understand.
Following the DemoApp for the initialization part, I kept crashing just before map was displayed with error:
java.lang.NullPointerException
at com.skobbler.ngx.map.MapRenderer.onSurfaceCreated( SourceFile:487)
at android.opengl.GLSurfaceView$GLThread.guardedRun(G LSurfaceView.java:1509)
at android.opengl.GLSurfaceView$GLThread.run(GLSurfac eView.java:1248)
As the error wasn't self explanatory at all, I investigated file MapRenderer from package com.skobbler.ngx.map, and found
that I was crashing because I didn't implement a map listener (this.s, in line below), which classname was trying to be displayed on log.
public final void onSurfaceCreated(GL10 arg1, EGLConfig paramEGLConfig)
{
SKLogging.writeLog("MapRenderer", "onSurfaceCreated before LOCK ", 2);
synchronized (V) {
SKLogging.writeLog("MapRenderer", "onSurfaceCreated" + this.s.getClass().getName(), 2); // <== Line 487
You might have forgot to check non-nullity of this.s before logging it, and as it wasn't described as mandatory in your doc to
implement this listener,I think you should correct that, or otherwise precise it in documentation.
http://forum.skobbler.com/showthread.php/6554-Android-Resolution-for-NullPointerException-onSurfaceCreated(SourceFile-487)?p=17601#post17601
Hope that helps !
tl:dr :
SKMapSurfaceView mapView = mapViewContainer.getMapSurfaceView();
mapView.setMapSurfaceListener(new SKMapSurfaceListener() {...});

Unable to find the error in logcat

I am unable to find the error in my android application. I have read guides on how to read logcat errors but the problem with my error is that it is not from my classes. Could someone give me some idea on how I could debug this?
I have a two spinners in my layout. One of which has an string array fixed for its list of items inside. The other spinner's items are generated dynamically with some code. The program actually runs fine on the emulator. But when I run on my device, a toggle button which doesnt uses the spinner crashes the application. If there is any more detail or information that I need to share to debug, do let me know.
Sorry I did post the logcat but the image disappeared. The complete logcat is below now.
And here is the toggle button which crashed the application when pressed.
public void onToggleClicked(View view) {
Context context = getApplicationContext();
if (checkConnectivity()) {
// Is the toggle on?
boolean on = tglbtn.isChecked();
if (on) {
startRepeatingTask();
} else {
stopRepeatingTask();
}
}
else {
Toast.makeText(context, "Please check your internet connection.", Toast.LENGTH_LONG).show();
}
}
These are the two methods....
Runnable mStatusChecker = new Runnable() {
#Override
public void run() {
//updateStatus(); //this function can change value of mInterval.
new updateBuses().execute();
mHandler.postDelayed(mStatusChecker, mInterval);
}
};
void startRepeatingTask() {
mStatusChecker.run();
}
void stopRepeatingTask() {
mHandler.removeCallbacks(mStatusChecker);
}
The updateBuses class is an Asynctask which has nothing to do with my spinners. This is the method which populates my spinner.
private void plotBuses(ArrayList<MyMarker> markers) {
Log.d("Checking Array", mMyMarkersArray.toString());
if(markers.size() > 0)
{
for (MyMarker myMarker : markers)
{
// Create bus marker with custom icon and other options
Log.d("plotting", myMarker.getmLabel());
MarkerOptions markerOption = new MarkerOptions().position(new LatLng(myMarker.getmLatitude(), myMarker.getmLongitude()));
markerOption.title(myMarker.getmLabel());
markerOption.icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_bus));
Marker currentMarker = map.addMarker(markerOption);
mMarkersHashMap.put(currentMarker, myMarker);
}
Log.d("check hashmap:", mMarkersHashMap.toString());
ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>
(this, android.R.layout.simple_spinner_item,spinnerList);
dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner1.setAdapter(dataAdapter);
}
}
The spinnerList is not null because my spinner populates with the items inside my spinner.
According to documentation the purpose of the method makeAndAddView() that throws NullPointerException:
Obtain a view, either by pulling an existing view from the recycler or by getting a new one from the adapter.
This method tries to get the View by accessing adapter that is bound to this Spinner.
P.S.
What API version do you use during building? What are the AVD and actual phone Android versions you are testing on?

Categories

Resources