一次在Safari上播放多个音频文件

时间:2017-11-09 14:14:17

标签: ios html5 audio html5-audio web-audio-api

我想在iOS上同时播放多个音频文件。

点击一个按钮,我创建了一个音频文件的多个实例并将它们放入一个数组中。

let audio = new Audio('path.wav')
audio.play().then(() => {
   audio.pause();
   possibleAudiosToPlay.push(audio);
});

过了一会儿我全都玩了:

possibleAudiosToPlay.forEach(el => {
    el.currentTime = 0;
    el.play();
});

虽然这会播放所有音频文件:当新的音频文件开始时,它会停止旧文件。 (在iOS上)

Apples开发人员指南说HTML5音频根本不可能:

  

也不支持播放多个同步音频流。

但这可以通过Web Audio API实现吗? 在Apples开发人员指南中没有任何关于它的文章。

1 个答案:

答案 0 :(得分:0)

是的,您可以使用Web Audio API。您必须为每个音频源创建AudioBufferSourceNode,因为每个音源只能播放一次(您无法停止并再次播放)。

@Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.location_provider_layout);
        Intent intent = getIntent();              
        checkPlayServices();
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addApi(LocationServices.API)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .build();
        mGoogleApiClient.connect();

        mLocationRequest= LocationRequest.create()
                                         .setInterval(10000)
                                         .setFastestInterval(5000)
                                         .setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);


    }



    private boolean checkPlayServices() {
        GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance();
        int resultCode = apiAvailability.isGooglePlayServicesAvailable(this);
        if (resultCode != ConnectionResult.SUCCESS) {
            if (apiAvailability.isUserResolvableError(resultCode)) {
                apiAvailability.getErrorDialog(this, resultCode, PLAY_SERVICES_RESOLUTION_REQUEST)
                        .show();
            } else
                finish();

            return false;
        }
        return true;
    }


    @Override
    public void onConnected(@Nullable Bundle bundle) {
        if (mGoogleApiClient.isConnected())
            Log.d(LOCATION_TAG, "Google api is connected");


        LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
                .addLocationRequest(mLocationRequest);

        PendingResult<LocationSettingsResult> result = LocationServices.SettingsApi.checkLocationSettings(mGoogleApiClient, builder.build());
        result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
            @Override
            public void onResult(@NonNull LocationSettingsResult locationSettingsResult) {
                final Status status = locationSettingsResult.getStatus();
                switch (status.getStatusCode()) {

                    case LocationSettingsStatusCodes.SUCCESS:;
                        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
                            boolean isLocationOn = ActivityCompat.checkSelfPermission(LocationProviderClass.this, Manifest.permission_group.LOCATION) != PackageManager.PERMISSION_GRANTED;

                            if (!(isLocationOn)) {
                                String [] runTimePermission=new String[]{Manifest.permission_group.SMS};
                                requestPermissions(runTimePermission, LOCATION_REQUESTCODE);
                            }
                            else
                                computeLocation();
                        } else
                            computeLocation();
                        break;
                    case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
                        try {
                            status.startResolutionForResult(LocationProviderClass.this, STATUS_INT);
                        } catch (IntentSender.SendIntentException e) {
                            Log.d(LOCATION_TAG, "error in startResolutionForResult");
                        }
                        break;
                    case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
                        Log.d(LOCATION_TAG, "Location setting is canceled");
                        break;
                    default:
                        Log.d(LOCATION_TAG,"Location setting enters into default");

                }
            }
        });


        computeLocation();
    }

    @Override
    public void onConnectionSuspended(int i) {
        Log.d("PERMISSION_TAG","connection suspended");

    }

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {

        if (!mGoogleApiClient.isConnected())
            Log.d(PERMISSION_TAG, "ON connection failed error");
        if (connectionResult.hasResolution()) {
            try {
                // Start an Activity that tries to resolve the error
                connectionResult.startResolutionForResult(this, CONNECTION_FAILURE_RESOLUTION_REQUEST);
            } catch (IntentSender.SendIntentException e) {
                e.printStackTrace();
            }
        } else {
            Log.i(TAG, "Location services connection failed with code " + connectionResult.getErrorCode());
        }

    }


    private void computeLocation() {

        if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.M) {
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                Toast.makeText(getApplicationContext(), "Fine access location is not granted", Toast.LENGTH_LONG).show();
            }
        }

        location=LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
        if(location==null) {
            Toast.makeText(getApplicationContext(), "getLastLocation return null", Toast.LENGTH_LONG).show();
            LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
        }
        else {
            Toast.makeText(getApplicationContext(), "getLastLocation return"+location.getLatitude()+" "+location.getLongitude(), Toast.LENGTH_LONG).show();
           //do what ever you want here
        }


    }


    @RequiresApi(api = Build.VERSION_CODES.M)
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
        switch (requestCode) {
            case  LOCATION_REQUESTCODE: {

                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                    computeLocation();

                }
                else {

                    Log.d(RUNTIME_PERMISSION_ERROR,"Error in runtime error");
                    Toast.makeText(getApplication(),"The app need location permission", Toast.LENGTH_LONG).show();

                }
                break;
            }



        }
    }



    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {

        if (requestCode == STATUS_INT) {
            switch (resultCode) {
                case Activity.RESULT_OK: {
                    Toast.makeText(getApplicationContext(), "User enabled location permission", Toast.LENGTH_LONG).show();
                    computeLocation();
                    break;
                }
                case Activity.RESULT_CANCELED: {
                    Toast.makeText(getApplication(), "You canceled the permission the app is not going to work", Toast.LENGTH_LONG).show();
                    break;
                }
                default:
                    Toast.makeText(getApplication(), "Permission error", Toast.LENGTH_LONG).show();
            }

        }
    }


    @Override
    public void onLocationChanged(Location location) {
        Log.d(LOCATION_TAG, "onLocationChanged method called");
        Toast.makeText(getApplicationContext(), "onLocationChanged method called"+location.getLongitude()+" "+location.getLatitude(), Toast.LENGTH_LONG).show();

    }


    @Override
    public void onStart() {
        super.onStart();

    }
    @Override
     protected void onResume()
    {
       super.onResume();
        this.mGoogleApiClient.connect();
    }
    @Override
    public void onPause() {
        super.onPause();
        if (this.mGoogleApiClient.isConnected())
         LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient,this);
            this.mGoogleApiClient.disconnect();

    }

}