问:
Is there a way to kill a Pygame sprite without having to kill it in a group?
I have a single ball sprite and I don't really have a need for a group. I want to set that sprite to be deleted (or killed) when it reaches the end of the screen, also so it generates another one. I am trying to do this without a group and wanted to know if this is possible. Thank you for your expertise.

I tried self.kill() and kill.self in an update method for the sprite class. That didn't work. I tried to do a kill in the screen update loop for the application. That didn't work. I have done extensive research and all the answer are only when using groups. I also tried to do "if not pygame.surface.rect.contains(Ball())" and that didn't work. (It is something like that, I tried several variations of that expression.)

```<code>def update(self):
    """Move the ball down"""
    self.y = self.y + 1
    self.rect.y = self.y
    #print("Screen is: " + str(pygame.surface.rect()))
    print("Object is: " + str(self.rect))
    if (self.rect.y >= 800):
         self.kill()

def update_screen(screen, ball, lamp):
    #Show on the screen
    screen.fill((135,206,250))
    lamp.blitme()
    ball.blitme()
    ballgen(screen)
    ball.update()
    lamp.update()
    pygame.display.flip()
</code>```

I expected the results to stop counting the rect of the ball, but it keeps counting up, thus making me think that it is not being removed.

答:
If you don't use the Group class, there's no point in calling the Sprite.kill method. All it does is to remove the Sprite from all of its groups. Calling kill does not magically remove the Sprite from your game.

If you want to have a Sprite removed, just stop using it: either stop calling ball.blitme() and ball.update() in your update_screen function, or replace ball with a new instance of your Sprite's class.

But consider starting to actually use the Group class. It'll make your life easier.

To check if the ball is inside the screen, instead of

```<code>if not pygame.surface.rect.contains(Ball())
</code>```

use

```<code>if not pygame.display.get_surface().get_rect().contains(self.rect):
    self.rect.center = (whatever_new_position, ....)
</code>```

in Ball's update method. pygame.display.get_surface() will get you the screen surface, get_rect() will get you the Rect of that Surface, and contains() will check if the Rect of the Ball is still inside the screen.

Then we just set a new position for the ball.

Also note that there's usually no need for an x and y attribute in a sprite class since the position is already stored in the rect attribute.

Body:
I have a single ball sprite and I don't really have a need for a group. I want to set that sprite to be deleted (or killed) when it reaches the end of the screen, also so it generates another one. I am trying to do this without a group and wanted to know if this is possible. Thank you for your expertise.

I tried self.kill() and kill.self in an update method for the sprite class. That didn't work. I tried to do a kill in the screen update loop for the application. That didn't work. I have done extensive research and all the answer are only when using groups. I also tried to do "if not pygame.surface.rect.contains(Ball())" and that didn't work. (It is something like that, I tried several variations of that expression.)

def update(self):
    """Move the ball down"""
    self.y = self.y + 1
    self.rect.y = self.y
    #print("Screen is: " + str(pygame.surface.rect()))
    print("Object is: " + str(self.rect))
    if (self.rect.y >= 800):
         self.kill()

def update_screen(screen, ball, lamp):
    #Show on the screen
    screen.fill((135,206,250))
    lamp.blitme()
    ball.blitme()
    ballgen(screen)
    ball.update()
    lamp.update()
    pygame.display.flip()

I expected the results to stop counting the rect of the ball, but it keeps counting up, thus making me think that it is not being removed.

Body:
If you don't use the Group class, there's no point in calling the Sprite.kill method. All it does is to remove the Sprite from all of its groups. Calling kill does not magically remove the Sprite from your game.

If you want to have a Sprite removed, just stop using it: either stop calling ball.blitme() and ball.update() in your update_screen function, or replace ball with a new instance of your Sprite's class.

But consider starting to actually use the Group class. It'll make your life easier.

To check if the ball is inside the screen, instead of

if not pygame.surface.rect.contains(Ball())

use

if not pygame.display.get_surface().get_rect().contains(self.rect):
    self.rect.center = (whatever_new_position, ....)

in Ball's update method. pygame.display.get_surface() will get you the screen surface, get_rect() will get you the Rect of that Surface, and contains() will check if the Rect of the Ball is still inside the screen.

Then we just set a new position for the ball.

Also note that there's usually no need for an x and y attribute in a sprite class since the position is already stored in the rect attribute.


来源: stackexchange

问:
Not getting location updates when App is removed from background also
"I am trying to get the location in the background but it is showing this error. I am unable to get the location anyway. Notification not working. How should my doMystuff() function look like in the main activity? Can someone please provide how can I register the broadcast receiver in manifest and how to implement the code with onButton Click."
UPDATE[2]: "Here I have just written the run-time permission to be accessed. Now on button click "startButton" in the doStuff function should I write startService or startForegroundService?"
    "MAIN ACTIVITY"</p>

```<code>package com.example.locationrunandall;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;

import android.Manifest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
    private TextView textView;
    private Button butt1, butt2;
    public static final int MY_PERMISSIONS_REQUEST_LOCATION = 99;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = findViewById(R.id.textview);
        butt1 = findViewById(R.id.butt1);
        butt2 = findViewById(R.id.butt2);

    }

    public void startButton(View view) {
        fetchCode();
    }

    private void fetchCode() {
        if (ContextCompat.checkSelfPermission(MainActivity.this,
                Manifest.permission.ACCESS_FINE_LOCATION)
                != PackageManager.PERMISSION_GRANTED) {

            // Permission is not granted
            if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,
                    Manifest.permission.ACCESS_FINE_LOCATION)) {
                // Show an explanation to the user *asynchronously* -- don't block
                new AlertDialog.Builder(this)
                        .setTitle("Required Location")
                        .setMessage("You have to get this permission to access the feature.")
                        .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                ActivityCompat.requestPermissions(MainActivity.this,
                                        new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                                        MY_PERMISSIONS_REQUEST_LOCATION);
                            }
                        })
                        .setNegativeButton("CANCEL", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                dialog.dismiss();
                            }
                        }).create().show();
            } else {
                // No explanation needed; request the permission
                ActivityCompat.requestPermissions(MainActivity.this,
                        new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                        MY_PERMISSIONS_REQUEST_LOCATION);

            }
        } else {
            // Permission has already been granted
            doMyStuff();
        }
    }

    private void doMyStuff() {
        Toast.makeText(this, "Working", Toast.LENGTH_SHORT).show();
        Intent intent = new Intent(this,ForeService.class);
        if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){
            startForegroundService(intent);
        }else{
            startService(intent);
        }
    }
    public void stopButton(View view) {
        Intent intent = new Intent(this,ForeService.class);
        stopService(intent);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
            if(requestCode==MY_PERMISSIONS_REQUEST_LOCATION){
                if(grantResults.length>0 && grantResults[0]==PackageManager.PERMISSION_GRANTED){
                    Intent gpsOptionsIntent = new Intent(
                            android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                    startActivity(gpsOptionsIntent);
                }else
                {
                }
            }
    }
}
</code>```

答:
Service code to get Location update every 10 seconds

```<code>public class LocationService extends Service implements com.google.android.gms.location.LocationListener,
        GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener{

    private GoogleApiClient mGoogleApiClient;
    private LocationRequest mLocationRequest;

    private String mChannelId = "my_service";
    private int mNotificationId = 1;
    private NotificationCompat.Builder mNotifBuilder = new NotificationCompat.Builder(this, mChannelId);
    private Notification mNotif;
    private NotificationManager mNotificationManager;
    private boolean mRestartService = true;
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    private void initGoogleApiClient() {
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();
        mGoogleApiClient.connect();
    }

    @Override
    public void onCreate() {
        super.onCreate();
        initGoogleApiClient();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (intent != null && intent.getAction() != null) {
            String mAction = intent.getAction();
            if(mAction.equals("start_service")){
                startForegroundService();
            }else if(mAction.equals("stop_service")){
                stopForegroundService();
            }
        }
        return START_NOT_STICKY;
    }

    @Override
    public void onConnected(@Nullable Bundle bundle) {
        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(10000);
        mLocationRequest.setFastestInterval(5000);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);

        try {
            LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
        } catch (SecurityException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onConnectionSuspended(int i) {

    }

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

    }

    @Override
    public void onLocationChanged(Location location) {
        Toast.makeText(this, "Location Updated", Toast.LENGTH_SHORT).show();
        //Broadcast Location
    }

    private void createNotificationChannel(){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            String description = "Foreground Service Channel";
            String name = "My Background Channel";
            int importance = NotificationManager.IMPORTANCE_HIGH;
            NotificationChannel channel = new NotificationChannel(mChannelId, name, importance);
            channel.setDescription(description);
            mNotificationManager.createNotificationChannel(channel);
        }
    }

    private void startForegroundService() {
        //Initializing Notifications and intents
        Intent intent = new Intent(this, MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);

        createNotificationChannel();

        mNotifBuilder.setContentText("Notification Content")
                .setContentTitle("Notification Title")
                .setSmallIcon(R.drawable.ic_notify)
                .setContentIntent(pendingIntent)
                .setOngoing(true)
                .setAutoCancel(true);

        mNotif = mNotifBuilder.build();
        startForeground(mNotificationId, mNotif);
    }

    private void stopForegroundService() {
        mRestartService = false;
        if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
            LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
        }
        stopForeground(true);
    }

    /*@Override
    public void onTaskRemoved(Intent rootIntent) {
        super.onTaskRemoved(rootIntent);
        Toast.makeText(this, "Task Removed", Toast.LENGTH_SHORT).show();
        if (mRestartService){
            Intent intent = new Intent(this, RestartService.class);
            intent.setAction("restart_service");
            sendBroadcast(intent);
        }
    }*/
}
</code>```

Then in your Activity add a button or a toggle button to start and stop the service. You can also do it with a button in the Notification.

```<code>private void startService() {
        Intent intent = new Intent(MainActivity.this, LocationService.class);
        intent.setAction("start_service");
        startService(intent);
    }

private void stopService() {
    Intent intent = new Intent(MainActivity.this, LocationService.class);
    intent.setAction("stop_service");
    startService(intent);
}
</code>```

The service should run even the app is killed. In some devices like xiaomi, OPPO, VIVO...etc it might get killed regardless of what you do in the service. In those you can try to restart the service again with a broadcast to start the service when it is killed.

```<code>public class RestartService extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if(action.equals("restart_service")){
            Intent intent1 = new Intent(context, LocationService.class);
            intent.setAction("start_service");
            context.startService(intent1);
        }
    }
}
</code>```

You can add it in onTaskRemoved() if the service is killed when the activity is removed from the background. You can add it in onDestroy() if it is killed sometime after the activity is removed from the background

```<code>public void onTaskRemoved(Intent rootIntent) {
        super.onTaskRemoved(rootIntent);
        Toast.makeText(this, "Task Removed", Toast.LENGTH_SHORT).show();
        if (mRestartService){
            Intent intent = new Intent(this, RestartService.class);
            intent.setAction("restart_service");
            sendBroadcast(intent);
        }
    }
</code>```

Even with this the service might be killed in some mobiles. In those cases you need to ask the user to exclude the service from battery optimizations and also allow other exceptions for it to run freely.

ContentLicense: CC BY-SA 4.0

Body:
"I am trying to get the location in the background but it is showing this error. I am unable to get the location anyway. Notification not working. How should my doMystuff() function look like in the main activity? Can someone please provide how can I register the broadcast receiver in manifest and how to implement the code with onButton Click."
UPDATE[2]: "Here I have just written the run-time permission to be accessed. Now on button click "startButton" in the doStuff function should I write startService or startForegroundService?"
    "MAIN ACTIVITY"

package com.example.locationrunandall;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;

import android.Manifest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
    private TextView textView;
    private Button butt1, butt2;
    public static final int MY_PERMISSIONS_REQUEST_LOCATION = 99;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = findViewById(R.id.textview);
        butt1 = findViewById(R.id.butt1);
        butt2 = findViewById(R.id.butt2);

    }

    public void startButton(View view) {
        fetchCode();
    }

    private void fetchCode() {
        if (ContextCompat.checkSelfPermission(MainActivity.this,
                Manifest.permission.ACCESS_FINE_LOCATION)
                != PackageManager.PERMISSION_GRANTED) {

            // Permission is not granted
            if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,
                    Manifest.permission.ACCESS_FINE_LOCATION)) {
                // Show an explanation to the user *asynchronously* -- don't block
                new AlertDialog.Builder(this)
                        .setTitle("Required Location")
                        .setMessage("You have to get this permission to access the feature.")
                        .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                ActivityCompat.requestPermissions(MainActivity.this,
                                        new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                                        MY_PERMISSIONS_REQUEST_LOCATION);
                            }
                        })
                        .setNegativeButton("CANCEL", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                dialog.dismiss();
                            }
                        }).create().show();
            } else {
                // No explanation needed; request the permission
                ActivityCompat.requestPermissions(MainActivity.this,
                        new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                        MY_PERMISSIONS_REQUEST_LOCATION);

            }
        } else {
            // Permission has already been granted
            doMyStuff();
        }
    }

    private void doMyStuff() {
        Toast.makeText(this, "Working", Toast.LENGTH_SHORT).show();
        Intent intent = new Intent(this,ForeService.class);
        if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){
            startForegroundService(intent);
        }else{
            startService(intent);
        }
    }
    public void stopButton(View view) {
        Intent intent = new Intent(this,ForeService.class);
        stopService(intent);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
            if(requestCode==MY_PERMISSIONS_REQUEST_LOCATION){
                if(grantResults.length>0 && grantResults[0]==PackageManager.PERMISSION_GRANTED){
                    Intent gpsOptionsIntent = new Intent(
                            android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                    startActivity(gpsOptionsIntent);
                }else
                {
                }
            }
    }
}

Body:
Service code to get Location update every 10 seconds

public class LocationService extends Service implements com.google.android.gms.location.LocationListener,
        GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener{

    private GoogleApiClient mGoogleApiClient;
    private LocationRequest mLocationRequest;

    private String mChannelId = "my_service";
    private int mNotificationId = 1;
    private NotificationCompat.Builder mNotifBuilder = new NotificationCompat.Builder(this, mChannelId);
    private Notification mNotif;
    private NotificationManager mNotificationManager;
    private boolean mRestartService = true;
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    private void initGoogleApiClient() {
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();
        mGoogleApiClient.connect();
    }

    @Override
    public void onCreate() {
        super.onCreate();
        initGoogleApiClient();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (intent != null && intent.getAction() != null) {
            String mAction = intent.getAction();
            if(mAction.equals("start_service")){
                startForegroundService();
            }else if(mAction.equals("stop_service")){
                stopForegroundService();
            }
        }
        return START_NOT_STICKY;
    }

    @Override
    public void onConnected(@Nullable Bundle bundle) {
        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(10000);
        mLocationRequest.setFastestInterval(5000);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);

        try {
            LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
        } catch (SecurityException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onConnectionSuspended(int i) {

    }

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

    }

    @Override
    public void onLocationChanged(Location location) {
        Toast.makeText(this, "Location Updated", Toast.LENGTH_SHORT).show();
        //Broadcast Location
    }

    private void createNotificationChannel(){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            String description = "Foreground Service Channel";
            String name = "My Background Channel";
            int importance = NotificationManager.IMPORTANCE_HIGH;
            NotificationChannel channel = new NotificationChannel(mChannelId, name, importance);
            channel.setDescription(description);
            mNotificationManager.createNotificationChannel(channel);
        }
    }

    private void startForegroundService() {
        //Initializing Notifications and intents
        Intent intent = new Intent(this, MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);

        createNotificationChannel();

        mNotifBuilder.setContentText("Notification Content")
                .setContentTitle("Notification Title")
                .setSmallIcon(R.drawable.ic_notify)
                .setContentIntent(pendingIntent)
                .setOngoing(true)
                .setAutoCancel(true);

        mNotif = mNotifBuilder.build();
        startForeground(mNotificationId, mNotif);
    }

    private void stopForegroundService() {
        mRestartService = false;
        if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
            LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
        }
        stopForeground(true);
    }

    /*@Override
    public void onTaskRemoved(Intent rootIntent) {
        super.onTaskRemoved(rootIntent);
        Toast.makeText(this, "Task Removed", Toast.LENGTH_SHORT).show();
        if (mRestartService){
            Intent intent = new Intent(this, RestartService.class);
            intent.setAction("restart_service");
            sendBroadcast(intent);
        }
    }*/
}

Then in your Activity add a button or a toggle button to start and stop the service. You can also do it with a button in the Notification.

private void startService() {
        Intent intent = new Intent(MainActivity.this, LocationService.class);
        intent.setAction("start_service");
        startService(intent);
    }

private void stopService() {
    Intent intent = new Intent(MainActivity.this, LocationService.class);
    intent.setAction("stop_service");
    startService(intent);
}

The service should run even the app is killed. In some devices like xiaomi, OPPO, VIVO...etc it might get killed regardless of what you do in the service. In those you can try to restart the service again with a broadcast to start the service when it is killed.

public class RestartService extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if(action.equals("restart_service")){
            Intent intent1 = new Intent(context, LocationService.class);
            intent.setAction("start_service");
            context.startService(intent1);
        }
    }
}

You can add it in onTaskRemoved() if the service is killed when the activity is removed from the background. You can add it in onDestroy() if it is killed sometime after the activity is removed from the background

public void onTaskRemoved(Intent rootIntent) {
        super.onTaskRemoved(rootIntent);
        Toast.makeText(this, "Task Removed", Toast.LENGTH_SHORT).show();
        if (mRestartService){
            Intent intent = new Intent(this, RestartService.class);
            intent.setAction("restart_service");
            sendBroadcast(intent);
        }
    }

Even with this the service might be killed in some mobiles. In those cases you need to ask the user to exclude the service from battery optimizations and also allow other exceptions for it to run freely.


问:
How to edit the Ajax HTML Editor, that I only need a few buttons of it?
I use the HTML Editor from ASP.NET Ajax AjaxControlToolkit http://www.asp.net/ajax/ajaxcontroltoolkit/Samples/HTMLEditor/HTMLEditor.aspx.

Its like: http://s3.imgimg.de/uploads/2889172fdJPG.jpg

But I want to have it like: http://s3.imgimg.de/uploads/3eda09893JPG.jpg

So the default buttons are much overpowered for my users.
Is there a way to reduce the ajax HTMLEditor to this few buttons?
Or is there another controle you can help me with?

答:
You haven't said which one you're using. I would recommend using TinyMCE: http://tinymce.moxiecode.com/

It will be easy to achieve what you want with it.

ContentLicense: CC BY-SA 3.0


问:
Can I use the Apple watch as an individual device without the iPhone?
In my case, I need to make an in-house communication system using Apple watches (without iPhones) There I'm planning to use UDP or TCP protocol for voice communication.
And is it can able to receive a notification without iPhone?</p>

答:
watch OS 6 and above now allows independent Watch apps.

Check out it's WWDC: Creating Independent Watch Apps

watchOS 6 enables a whole new level of watchOS experiences by allowing
  fully independent apps and apps built just for Apple Watch, and by
  bringing the App Store to Apple Watch. Discover how to leverage the
  power of many iOS frameworks and technologies, now on watchOS, to
  create fully independent experiences on Apple Watch.

For lower versions, an Apple Watch app installs as an extension to an iPhone app. You would need an iPhone to access the AppStore to install an iPhone app, which provides an extension app to the Apple Watch.

In this case, you can create a simply, bare minimum iPhone app but with a complex Apple Watch app extension.


问:
Question for Mocha, using Chai assertion library
I am importing main() from one script into my test file and I'm executing main() as 1 test case although main consists of multiple functions. I was wondering how can I structure my test that each function on main would count as a separate test case instead of 1 as whole

    async function main(config = {}) {
      const url = validateUrl(config.url);
      const origin = validateOrigin(config.origin);
      const bundleId = validateBundleId(config.bundleId);
      const username = validateUsername(config.username);
      const password = validatePassword(config.password);

      let pipeline;
      let message;
      let worker;
      let passthroughWorkerId;

      pipeline = await createPipeline(origin, bundleId, username, password, url);
      if (pipeline.status != "running") {
        throw new Error("Pipeline not started");
      }

      message = await pipelineWait(username, password, url, pipeline);
      if (debug) {
        console.log(`Wait message: ${message}`);
      }

      worker = await updatePassthroughWorker(username, password, url, pipeline, 0);
      // Do something with worker 0
      pipeline = await retreivePipeline(username, password, url, pipeline);
      if (pipeline.status != "waiting") {
        throw new Error("Pipeline didn't wait");
      }
      pipeline = await restartPipeline(username, password, url, pipeline);
      if (pipeline.status != "running") {
        throw new Error("Pipeline didn't restart");
      }

      message = await cancelPipeline(username, password, url, pipeline);
      if (debug) {
        console.log("Pipeline Status:");
        console.log(pipeline.status);
        console.log(`Cancel message: ${message}`);
      }

      worker = await updatePassthroughWorker(username, password, url, pipeline, 1);

      pipeline = await retreivePipeline(username, password, url, pipeline);
      if (pipeline.status != "cancelled") {
        throw new Error("Pipeline didn't cancel");
      }

      return pipeline
    }
```

<p><strong>Test</strong></p>

<pre class="lang-js prettyprint-override"><code>    describe('Pipeline cancellation', () => {

      it('Should trigger pipeline, put it in wait, resume, and the cancel it ', async () => {
        let data = await pipeline.main(config[process.env.TEST_ENV]);
        expect(data).to.be.an('object');
        expect(data).to.have.property('status');
        expect(data.status).to.equal('cancelled');

      });
    });
</code>```

答:
Perhaps you can use before() and put each expectation in it() function.

e.g

```<code>describe('Pipeline cancellation', () => {
  let data;

  before(async () => {
    data = await pipeline.main(config[process.env.TEST_ENV]);
  });

  it('Should trigger pipeline', () => {
    expect(data).to.be.an('object');
    expect(data).to.have.property('status');
    expect(data.status).to.equal('cancelled');
  });

  it('should put it in wait', () => {
    // ...
  });

  it('should resume', () => {
    // ...
  });
});
</code>```

Hope it helps

Body:
I am importing main() from one script into my test file and I'm executing main() as 1 test case although main consists of multiple functions. I was wondering how can I structure my test that each function on main would count as a separate test case instead of 1 as whole

    async function main(config = {}) {
      const url = validateUrl(config.url);
      const origin = validateOrigin(config.origin);
      const bundleId = validateBundleId(config.bundleId);
      const username = validateUsername(config.username);
      const password = validatePassword(config.password);

      let pipeline;
      let message;
      let worker;
      let passthroughWorkerId;

      pipeline = await createPipeline(origin, bundleId, username, password, url);
      if (pipeline.status != "running") {
        throw new Error("Pipeline not started");
      }

      message = await pipelineWait(username, password, url, pipeline);
      if (debug) {
        console.log(`Wait message: ${message}`);
      }

      worker = await updatePassthroughWorker(username, password, url, pipeline, 0);
      // Do something with worker 0
      pipeline = await retreivePipeline(username, password, url, pipeline);
      if (pipeline.status != "waiting") {
        throw new Error("Pipeline didn't wait");
      }
      pipeline = await restartPipeline(username, password, url, pipeline);
      if (pipeline.status != "running") {
        throw new Error("Pipeline didn't restart");
      }

      message = await cancelPipeline(username, password, url, pipeline);
      if (debug) {
        console.log("Pipeline Status:");
        console.log(pipeline.status);
        console.log(`Cancel message: ${message}`);
      }

      worker = await updatePassthroughWorker(username, password, url, pipeline, 1);

      pipeline = await retreivePipeline(username, password, url, pipeline);
      if (pipeline.status != "cancelled") {
        throw new Error("Pipeline didn't cancel");
      }

      return pipeline
    }

Test

    describe('Pipeline cancellation', () => {

      it('Should trigger pipeline, put it in wait, resume, and the cancel it ', async () => {
        let data = await pipeline.main(config[process.env.TEST_ENV]);
        expect(data).to.be.an('object');
        expect(data).to.have.property('status');
        expect(data.status).to.equal('cancelled');

      });
    });

Body:
Perhaps you can use before() and put each expectation in it() function.

e.g

describe('Pipeline cancellation', () => {
  let data;

  before(async () => {
    data = await pipeline.main(config[process.env.TEST_ENV]);
  });

  it('Should trigger pipeline', () => {
    expect(data).to.be.an('object');
    expect(data).to.have.property('status');
    expect(data.status).to.equal('cancelled');
  });

  it('should put it in wait', () => {
    // ...
  });

  it('should resume', () => {
    // ...
  });
});

Hope it helps


问:
Angular routing not working properly ( path: 'blog/add' )
Angular router not working properly

Have a look my part of app-routing.module.js code

```<code>    { path: 'blog', component: BlogComponent},
    { path: 'blog/add', component: BlogPostEditComponent},
</code>```

The problem is

http://localhost:4200/#/blog
  when hit enter it went to BlogComponent that's fine

http://localhost:4200/#/blog/add
  when hit enter for this url also it went to BlogComponent , actually it would go to  BlogPostEditComponent
  I couldn't understand what's going on?

Anyone can explains why is that ?

答:
Routes with matching urls should be related routes. </p>

```<code>{ path: 'blog', component: BlogComponent, children: [
  { path: 'add', component: BlogPostEditComponent},
]},
</code>```

<p>And next time, please provide a working stackblitz, not just a stackblitz to say you have provided one ... </p>

Body:
Angular router not working properly

Have a look my part of app-routing.module.js code

    { path: 'blog', component: BlogComponent},
    { path: 'blog/add', component: BlogPostEditComponent},

The problem is

http://localhost:4200/#/blog
  when hit enter it went to BlogComponent that's fine

http://localhost:4200/#/blog/add
  when hit enter for this url also it went to BlogComponent , actually it would go to  BlogPostEditComponent
  I couldn't understand what's going on?

Anyone can explains why is that ?

Body:
Routes with matching urls should be related routes.

{ path: 'blog', component: BlogComponent, children: [
  { path: 'add', component: BlogPostEditComponent},
]},

And next time, please provide a working stackblitz, not just a stackblitz to say you have provided one ...


问:
JUnit5IdeaTestRunner fails running unit tests
Suddenly Android Studio can't run unit tests for one of my modules.
I get the error:

```<code>Internal Error occurred. java.util.NoSuchElementException
at java.util.ArrayList$Itr.next(ArrayList.java:856)
at java.util.Collections$UnmodifiableCollection$1.next(Collections.java:1042)
at com.intellij.junit5.JUnit5TestRunnerUtil.createSelector(JUnit5TestRunnerUtil.java:181)
at com.intellij.junit5.JUnit5TestRunnerUtil.buildRequest(JUnit5TestRunnerUtil.java:70)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:51)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
</code>```

The only thing I need to know is whether this is a known issue.

Please notice that the unit tests of all the modules succeed if I run them in the external terminal or in the terminal in Android Studio or on the CI.

And if I run on Android Studio the same unit test configuration, changing only the module then everything works fine.

Please don't ask me to post the build.gradle files. Although it is likely that the problem is there, they are too big and more importantly if that is the problem, I wouldn't expect you to debug it.

答: Reported here and here. Actually it's an issue in IntelliJ Idea. There are no workaround for now :(</p>

Body:
Suddenly Android Studio can't run unit tests for one of my modules.
I get the error:

Internal Error occurred. java.util.NoSuchElementException
at java.util.ArrayList$Itr.next(ArrayList.java:856)
at java.util.Collections$UnmodifiableCollection$1.next(Collections.java:1042)
at com.intellij.junit5.JUnit5TestRunnerUtil.createSelector(JUnit5TestRunnerUtil.java:181)
at com.intellij.junit5.JUnit5TestRunnerUtil.buildRequest(JUnit5TestRunnerUtil.java:70)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:51)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

The only thing I need to know is whether this is a known issue.

Please notice that the unit tests of all the modules succeed if I run them in the external terminal or in the terminal in Android Studio or on the CI.

And if I run on Android Studio the same unit test configuration, changing only the module then everything works fine.

Please don't ask me to post the build.gradle files. Although it is likely that the problem is there, they are too big and more importantly if that is the problem, I wouldn't expect you to debug it.


问:
Unable to import maven project in IntelliJ14
I'm trying to import the Maven projects from IntelliJ button (the one with the arrows in circle), but I get the following message "Unable to import maven project. See logs for details", as shown in the following picture

If I go into the log, I see:

```<code>2015-06-01 11:16:46,932 [  89176]  ERROR -      #org.jetbrains.idea.maven - org/apache/maven/execution/MavenExecutionRequestPopulationException
java.lang.NoClassDefFoundError: org/apache/maven/execution/MavenExecutionRequestPopulationException
    at org.jetbrains.idea.maven.server.Maven32ServerImpl.applyProfiles(Maven32ServerImpl.java:81)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:322)
    at sun.rmi.transport.Transport$1.run(Transport.java:177)
    at sun.rmi.transport.Transport$1.run(Transport.java:174)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.Transport.serviceCall(Transport.java:173)
    at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:556)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:811)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:670)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.ClassNotFoundException: org.apache.maven.execution.MavenExecutionRequestPopulationException
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
    ... 16 more
2015-06-01 11:16:46,933 [  89177]  ERROR -      #org.jetbrains.idea.maven - IntelliJ IDEA 14.1.3  Build #IU-141.1010.3
2015-06-01 11:16:46,933 [  89177]  ERROR -      #org.jetbrains.idea.maven - JDK: 1.7.0_71
2015-06-01 11:16:46,933 [  89177]  ERROR -      #org.jetbrains.idea.maven - VM: Java HotSpot(TM) 64-Bit Server VM
2015-06-01 11:16:46,933 [  89177]  ERROR -      #org.jetbrains.idea.maven - Vendor: Oracle Corporation
2015-06-01 11:16:46,933 [  89177]  ERROR -      #org.jetbrains.idea.maven - OS: Linux
2015-06-01 11:16:46,933 [  89177]  ERROR -      #org.jetbrains.idea.maven - Last Action: Maven.Reimport
</code>```

I'm using Maven 3.3.3 and JDK 1.7.0_71 on a 64bit Ubuntu machine.

Strange thing, is that I can use Maven by command line. Any idea?

答:
This worked for me

Go to: File > Settings > Build,Execution,Deployment > Build Tools >
    Maven > Importing

Change: JDK for importer to your installed JDK
    instead of IDEA's internal JRE (Use Internal JRE from
    ../JetBrains/IntelliJ IDEA/jre64)

Also searching in IDEA log files helped me. I found this message:

Caused by: java.io.IOException: Cannot run program "C:\Program Files\JetBrains\IntelliJ IDEA 2017.3.2\jre64\bin\java" (in directory "C:\Program Files\JetBrains\IntelliJ IDEA 2017.3.2\bin"): CreateProcess error=2, File not found

Body:
I'm trying to import the Maven projects from IntelliJ button (the one with the arrows in circle), but I get the following message "Unable to import maven project. See logs for details", as shown in the following picture

If I go into the log, I see:

2015-06-01 11:16:46,932 [  89176]  ERROR -      #org.jetbrains.idea.maven - org/apache/maven/execution/MavenExecutionRequestPopulationException
java.lang.NoClassDefFoundError: org/apache/maven/execution/MavenExecutionRequestPopulationException
    at org.jetbrains.idea.maven.server.Maven32ServerImpl.applyProfiles(Maven32ServerImpl.java:81)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:322)
    at sun.rmi.transport.Transport$1.run(Transport.java:177)
    at sun.rmi.transport.Transport$1.run(Transport.java:174)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.Transport.serviceCall(Transport.java:173)
    at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:556)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:811)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:670)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.ClassNotFoundException: org.apache.maven.execution.MavenExecutionRequestPopulationException
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
    ... 16 more
2015-06-01 11:16:46,933 [  89177]  ERROR -      #org.jetbrains.idea.maven - IntelliJ IDEA 14.1.3  Build #IU-141.1010.3
2015-06-01 11:16:46,933 [  89177]  ERROR -      #org.jetbrains.idea.maven - JDK: 1.7.0_71
2015-06-01 11:16:46,933 [  89177]  ERROR -      #org.jetbrains.idea.maven - VM: Java HotSpot(TM) 64-Bit Server VM
2015-06-01 11:16:46,933 [  89177]  ERROR -      #org.jetbrains.idea.maven - Vendor: Oracle Corporation
2015-06-01 11:16:46,933 [  89177]  ERROR -      #org.jetbrains.idea.maven - OS: Linux
2015-06-01 11:16:46,933 [  89177]  ERROR -      #org.jetbrains.idea.maven - Last Action: Maven.Reimport

I'm using Maven 3.3.3 and JDK 1.7.0_71 on a 64bit Ubuntu machine.

Strange thing, is that I can use Maven by command line. Any idea?


问:
replace new line in a different file with an underscore (without using with)
I posted a question yesterday in similar regards to this but didn't quite gauge the response I wanted because I wasn't specific enough. Basically the function takes a .txt file as the argument and returns a string with all \n characters replaced with an '_' on the same line. I want to do this without using WITH. I thought I did this correctly but when I run it and check the file, nothing has changed. Any pointers?

This is what I did:

```<code>def one_line(filename):
    wordfile = open(filename)
    text_str = wordfile.read().replace("\n", "_")
    wordfile.close()
    return text_str

one_line("words.txt")
</code>```

but to no avail. I open the text file and it remains the same.

The contents of the textfile are:

```<code>I like to eat
pancakes every day

</code>```

and the output that's supposed to be shown is:

```<code>>>> one_line("words.txt")
’I like to eat_pancakes every day_’
</code>```

答:
The fileinput module in the Python standard library allows you to do this in one fell swoop.

```<code>import fileinput

for line in fileinput.input(filename, inplace=True):
    line = line.replace('\n', '_')
    print(line, end='')
</code>```

The requirement to avoid a with statement is trivial but rather pointless. Anything which looks like

```<code>with open(filename) as handle:
    stuff
</code>```

can simply be rewritten as

```<code>try:
    handle = open(filename)
    stuff
finally:
    handle.close()
</code>```

If you take out the try/finally you have a bug which leaves handle open if an error happens. The purpose of the with context manager for open() is to simplify this common use case.

Body:
I posted a question yesterday in similar regards to this but didn't quite gauge the response I wanted because I wasn't specific enough. Basically the function takes a .txt file as the argument and returns a string with all \n characters replaced with an '_' on the same line. I want to do this without using WITH. I thought I did this correctly but when I run it and check the file, nothing has changed. Any pointers?

This is what I did:

def one_line(filename):
    wordfile = open(filename)
    text_str = wordfile.read().replace("\n", "_")
    wordfile.close()
    return text_str

one_line("words.txt")

but to no avail. I open the text file and it remains the same.

The contents of the textfile are:

I like to eat
pancakes every day

and the output that's supposed to be shown is:

>>> one_line("words.txt")
’I like to eat_pancakes every day_’

Body:
The fileinput module in the Python standard library allows you to do this in one fell swoop.

import fileinput

for line in fileinput.input(filename, inplace=True):
    line = line.replace('\n', '_')
    print(line, end='')

The requirement to avoid a with statement is trivial but rather pointless. Anything which looks like

with open(filename) as handle:
    stuff

can simply be rewritten as

try:
    handle = open(filename)
    stuff
finally:
    handle.close()

If you take out the try/finally you have a bug which leaves handle open if an error happens. The purpose of the with context manager for open() is to simplify this common use case.


问:
How to parse html string to JSX client side with variable and function call
```<code>html = "<p>Hello {this.getValue("a")}</p>"
</code>```

Basically what I want to achieve is the value returned by the getValue() function once the html is rendered.

I tried react HTML parser however this shows the function name as it is written in the code.

I also tried dangerouslySetInnerHTML like below:

```<code><div dangerouslySetInnerHTML={{ __html: html }} />
</code>```

The result with "dangerouslySetInnerHTML" is the same string

```<code>Hello {this.getValue("a")}
</code>```

Also the string is from an api response

example: "
Overview

testing testing

{this.getValue('a')}, testing
"

答:
Use template literals - use backticks `` and ${}:

const getValue = arg => arg + arg;
const html = `<p>Hello ${getValue("a")}</p>`;
document.write(html);```

Body:
html = "
Hello {this.getValue("a")}
"

Basically what I want to achieve is the value returned by the getValue() function once the html is rendered.

I tried react HTML parser however this shows the function name as it is written in the code.

I also tried dangerouslySetInnerHTML like below:

The result with "dangerouslySetInnerHTML" is the same string

Hello {this.getValue("a")}

Also the string is from an api response

example: "
Overview

testing testing

{this.getValue('a')}, testing
"


问:
Microsoft.Azure.ServiceBus - SubscriptionClient ignoring RetryPolicy (RetryExponencial)
I'm trying to implement a retry policy but it keeps getting ignored.
Is there properties in SubscriptionClient that overrides the ones I give when I create the client?

Here is the code i tried:

```<code>_retryPolicy = new Microsoft.Azure.ServiceBus.RetryExponential(
                       TimeSpan.FromMinutes(2), // MinBackOff
                       TimeSpan.FromMinutes(5), // MaxBackOff
                       3); // Max Retries

_subscriptionClient = new SubscriptionClient(
               serviceBusPersisterConnection.ServiceBusConnectionStringBuilder,
               subscriptionClientName, retryPolicy: _retryPolicy);
</code>```

So this should make it only retry 3 times with minimun 2min interval.
Result from LOG:

```<code>28 May 2019 16:34:49.928 MessageId: 1d327c9033de4fc69892766084264
28 May 2019 16:34:49.285 MessageId: 1d327c9033de4fc69892766084264
28 May 2019 16:34:48.718 MessageId: 1d327c9033de4fc69892766084264
28 May 2019 16:34:48.075 MessageId: 1d327c9033de4fc69892766084264
28 May 2019 16:34:47.499 MessageId: 1d327c9033de4fc69892766084264
28 May 2019 16:34:46.965 MessageId: 1d327c9033de4fc69892766084264
28 May 2019 16:34:46.511 MessageId: 1d327c9033de4fc69892766084264
28 May 2019 16:34:45.957 MessageId: 1d327c9033de4fc69892766084264
</code>```

As you can see it retried 8 times instead of 3 and the time between retries (this is my main problem) has an interval of half second.

To be sure it was not my retry policies i tried this instead:

```<code>_subscriptionClient = new SubscriptionClient(
              serviceBusPersisterConnection.ServiceBusConnectionStringBuilder,
              subscriptionClientName, retryPolicy: RetryPolicy.NoRetry);
</code>```

And result was exactly the same, so i'm sure it's being ignored.
Any help would be much appreciated.

Keep up the good work.

答:
RetryExponential is intended to be used by the Service bus client when there are transient errors that are not bubbled up to your code right away. I.e. an internal retry mechanism built into the client to perform retries on your behalf before exception is raised. If there are no exceptions and your callback Abandons the message explicitly, retry policy is not even utilized here and the message just goes through the normal delivery up to MaxDeliveryCount times (50 in your scenario), after which is DQed.

Use retry policy to specify to the Service bus client how to deal with transient errors prior to giving up, not how many times a message can be dequeued.

you can read more about here.

Hope it helps.

Body:
I'm trying to implement a retry policy but it keeps getting ignored.
Is there properties in SubscriptionClient that overrides the ones I give when I create the client?

Here is the code i tried:

_retryPolicy = new Microsoft.Azure.ServiceBus.RetryExponential(
                       TimeSpan.FromMinutes(2), // MinBackOff
                       TimeSpan.FromMinutes(5), // MaxBackOff
                       3); // Max Retries

_subscriptionClient = new SubscriptionClient(
               serviceBusPersisterConnection.ServiceBusConnectionStringBuilder,
               subscriptionClientName, retryPolicy: _retryPolicy);

So this should make it only retry 3 times with minimun 2min interval.
Result from LOG:

28 May 2019 16:34:49.928 MessageId: 1d327c9033de4fc69892766084264
28 May 2019 16:34:49.285 MessageId: 1d327c9033de4fc69892766084264
28 May 2019 16:34:48.718 MessageId: 1d327c9033de4fc69892766084264
28 May 2019 16:34:48.075 MessageId: 1d327c9033de4fc69892766084264
28 May 2019 16:34:47.499 MessageId: 1d327c9033de4fc69892766084264
28 May 2019 16:34:46.965 MessageId: 1d327c9033de4fc69892766084264
28 May 2019 16:34:46.511 MessageId: 1d327c9033de4fc69892766084264
28 May 2019 16:34:45.957 MessageId: 1d327c9033de4fc69892766084264

As you can see it retried 8 times instead of 3 and the time between retries (this is my main problem) has an interval of half second.

To be sure it was not my retry policies i tried this instead:

_subscriptionClient = new SubscriptionClient(
              serviceBusPersisterConnection.ServiceBusConnectionStringBuilder,
              subscriptionClientName, retryPolicy: RetryPolicy.NoRetry);

And result was exactly the same, so i'm sure it's being ignored.
Any help would be much appreciated.

Keep up the good work.


问:
How to change the input field's text color in MaterializeCSS?
How can I change the text color entered into the input-field of MaterializeCSS? The documentation demonstrates how to change the color of labels or the underline, but not the color of the text.

```<code> /* label color */
   .input-field label {
     color: #000;
   }
   /* label focus color */
   .input-field input[type=text]:focus + label {
     color: #000;
   }
   /* label underline focus color */
   .input-field input[type=text]:focus {
     border-bottom: 1px solid #000;
     box-shadow: 0 1px 0 0 #000;
   }
   /* valid color */
   .input-field input[type=text].valid {
     border-bottom: 1px solid #000;
     box-shadow: 0 1px 0 0 #000;
   }
   /* invalid color */
   .input-field input[type=text].invalid {
     border-bottom: 1px solid #000;
     box-shadow: 0 1px 0 0 #000;
   }
   /* icon prefix focus color */
   .input-field .prefix.active {
     color: #000;
   }
</code>```

The documentation also states that it's possible to modify the sass variables:

Here is a CSS template for modifying input fields in CSS. With Sass,
  you can achieve this by just changing a variable. The CSS shown below
  is unprefixed. Depending on what you use, you may have to change the
  type attribute selector.

But does not clarify which sass variables are available to change.

答:
```<code><input class="white-text" type="email" id="email" v-model="email">
</code>```

change the class to what ever colour you want

Body:
How can I change the text color entered into the input-field of MaterializeCSS? The documentation demonstrates how to change the color of labels or the underline, but not the color of the text.

 /* label color */
   .input-field label {
     color: #000;
   }
   /* label focus color */
   .input-field input[type=text]:focus + label {
     color: #000;
   }
   /* label underline focus color */
   .input-field input[type=text]:focus {
     border-bottom: 1px solid #000;
     box-shadow: 0 1px 0 0 #000;
   }
   /* valid color */
   .input-field input[type=text].valid {
     border-bottom: 1px solid #000;
     box-shadow: 0 1px 0 0 #000;
   }
   /* invalid color */
   .input-field input[type=text].invalid {
     border-bottom: 1px solid #000;
     box-shadow: 0 1px 0 0 #000;
   }
   /* icon prefix focus color */
   .input-field .prefix.active {
     color: #000;
   }

The documentation also states that it's possible to modify the sass variables:

Here is a CSS template for modifying input fields in CSS. With Sass,
  you can achieve this by just changing a variable. The CSS shown below
  is unprefixed. Depending on what you use, you may have to change the
  type attribute selector.

But does not clarify which sass variables are available to change.

Body:
<input class="white-text" type="email" id="email" v-model="email">

change the class to what ever colour you want


问:
Publishing the Application
I followed the instructions found here...

https://schoolofdevops.github.io/ultimate-kubernetes-bootcamp/quickdive/

As you can see, "NodePort" type do not have external-IP like wordpress. Therefore I can not connect.

```<code>#  /usr/local/bin/kubectl --kubeconfig="padhaku2.yaml" get service
NAME         TYPE           CLUSTER-IP      EXTERNAL-IP    PORT(S)        AGE
kubernetes   ClusterIP      10.245.0.1      <none>         443/TCP        38m
vote         NodePort       10.245.33.151   <none>         81:31876/TCP   6m20s
wordpress    LoadBalancer   10.245.170.65   139.59.49.69   80:31820/TCP   21m
</code>```

How do I publish the app using external IP?

答:
you can access the application using nodeport.

try http://NODEIP:NODEPORT

in your case, http://NODEIP:31876

follow the steps to update the service type

```<code>kubectl delete svc vote
kubectl expose deployment vote --type=LoadBalancer --port 80
</code>```

you might need to deploy rest of the voting services

```<code>kubectl  run redis  --image=redis:alpine

kubectl expose deployment redis --port 6379

kubectl  run worker --image=schoolofdevops/worker

kubectl  run db --image=postgres:9.4

kubectl expose deployment db --port 5432

kubectl run result --image=schoolofdevops/vote-result

kubectl expose deployment result --type=NodePort --port 80
</code>```

Title: Publishing the Application

Body:
I followed the instructions found here...

https://schoolofdevops.github.io/ultimate-kubernetes-bootcamp/quickdive/

As you can see, "NodePort" type do not have external-IP like wordpress. Therefore I can not connect.

#  /usr/local/bin/kubectl --kubeconfig="padhaku2.yaml" get service
NAME         TYPE           CLUSTER-IP      EXTERNAL-IP    PORT(S)        AGE
kubernetes   ClusterIP      10.245.0.1      <none>         443/TCP        38m
vote         NodePort       10.245.33.151   <none>         81:31876/TCP   6m20s
wordpress    LoadBalancer   10.245.170.65   139.59.49.69   80:31820/TCP   21m

How do I publish the app using external IP?

Body:
you can access the application using nodeport.

try http://NODEIP:NODEPORT

in your case, http://NODEIP:31876

follow the steps to update the service type

kubectl delete svc vote
kubectl expose deployment vote --type=LoadBalancer --port 80

you might need to deploy rest of the voting services

kubectl  run redis  --image=redis:alpine

kubectl expose deployment redis --port 6379

kubectl  run worker --image=schoolofdevops/worker

kubectl  run db --image=postgres:9.4

kubectl expose deployment db --port 5432

kubectl run result --image=schoolofdevops/vote-result

kubectl expose deployment result --type=NodePort --port 80


问:
Laravel 5.6 update foreign key in database after storing resource
I have a resource 'imagerequest' and a resource 'events'. For each of these resources I have a Modal and the relationship is as following:

1 Imagerequest can have many Events:

Imagerequest model:

```<code>/**
 * Get the events for an Image Request.
 */
public function events()
{
    return $this->hasMany('App\Event');
}
</code>```

Event model:

```<code>/**
 * Get the Image Request that belongs to the Event
 */
public function imagerequest()
{
    return $this->belongsTo('App\ImageRequest');
}
</code>```

Now in my form when creating a new Imagerequest I have an other form to create multiple events but my problem is when I store a new Event there is no image_request_id because the new image_request_id doesn't exist yet since I haven't created the imagerequest yet.

So in my database image_request_id is always empty

```<code>id user_id image_request_id location trainnr created_at  updated_at
1  53      NULL             location NULL    2019-05-28  10:49:45 2019-05-28 10:49:45
</code>```

Do I need to write an update query after saving the imagerequest to fill up this image_request_id?

How I create a new Event in my EventController:

```<code>$event = Auth::user()->events()->save(new Event($request->all()));
</code>```

How I create a new Imagerequest in my ImagerequestController:

```<code>$imageRequest = new ImageRequest(
    array_merge(
        $request->all(),
        ['status' => self::STATUS_NEW]
    )
);

$imageRequest = Auth::user()->imageRequests()->save($imageRequest);
</code>```

EDIT my front end for adding an event

答:
You need to add the relationship

have a look at the docs for more help with this

From my quick look you can do it something like this:

```<code>$event = Auth::user()->events()->save(new Event($request->all()));

$imageRequest = new ImageRequest(
    array_merge(
        $request->all(),
        ['status' => self::STATUS_NEW]
    )
);

$event->imagerequest()->create($imageRequest);
</code>```

I would also advise that you validate any request data before you update the database also.

EDIT base on more info

you can do something like this then:

```<code>$imageRequest->attach($request->eventIds);
</code>```

Body:
I have a resource 'imagerequest' and a resource 'events'. For each of these resources I have a Modal and the relationship is as following:

1 Imagerequest can have many Events:

Imagerequest model:

/**
 * Get the events for an Image Request.
 */
public function events()
{
    return $this->hasMany('App\Event');
}

Event model:

/**
 * Get the Image Request that belongs to the Event
 */
public function imagerequest()
{
    return $this->belongsTo('App\ImageRequest');
}

Now in my form when creating a new Imagerequest I have an other form to create multiple events but my problem is when I store a new Event there is no image_request_id because the new image_request_id doesn't exist yet since I haven't created the imagerequest yet.

So in my database image_request_id is always empty

id user_id image_request_id location trainnr created_at  updated_at
1  53      NULL             location NULL    2019-05-28  10:49:45 2019-05-28 10:49:45

Do I need to write an update query after saving the imagerequest to fill up this image_request_id?

How I create a new Event in my EventController:

$event = Auth::user()->events()->save(new Event($request->all()));

How I create a new Imagerequest in my ImagerequestController:

$imageRequest = new ImageRequest(
    array_merge(
        $request->all(),
        ['status' => self::STATUS_NEW]
    )
);

$imageRequest = Auth::user()->imageRequests()->save($imageRequest);

EDIT my front end for adding an event

Body:
You need to add the relationship

have a look at the docs for more help with this

From my quick look you can do it something like this:

$event = Auth::user()->events()->save(new Event($request->all()));

$imageRequest = new ImageRequest(
    array_merge(
        $request->all(),
        ['status' => self::STATUS_NEW]
    )
);

$event->imagerequest()->create($imageRequest);

I would also advise that you validate any request data before you update the database also.

EDIT base on more info

you can do something like this then:

$imageRequest->attach($request->eventIds);


问:
joining data based on a moving time window in R
I have weather data that was recorded every hour, and location data (X,Y) that was recorded every 4 hours.  I want to know what the temperature was at location X,Y.  The  weather data isn't exactly at the same time.  So, I have written this loop for every location to scan through the weather data looking for the "closest" in Date/TIME and extracting the data from that time.  The problem is the way Ive written it, for location #2, it scans through the weather data but will not allow the closest time information to be assigned that was assigned for location#1.  Say location #1 & 2 are taken within 10 minutes at 6pm and 6:10pm, the closest weather time is 6pm.  I can't get it to allow the weather data at 6pm as an option.  I kind of set it up like this because 200 locations into my location data set (say 3 months into it), I do not want it starting at time 0 from the weather data, when I know that the closest weather data was just calculated for the last location and that happens to be 3 months into that data set too.  Below is some sample data and my code.  I don't know if this makes sense.

```<code><h6>####Location data</h6>

<p>X   Y   DateTime <br />
1   2   4/2/2003    18:01:01
3   2   4/4/2003    17:01:33
2   3   4/6/2003    16:03:07
5   6   4/8/2003    15:03:08
3   7   4/10/2003   14:03:06
4   5   4/2/2003    13:02:00
4   5   4/4/2003    12:14:43
4   3   4/6/2003    11:00:56
3   5   4/8/2003    10:02:06</p>

<h2>2   4   4/10/2003   9:02:19</h2>

<p>Weather Data
DateTime        WndSp   WndDir  Hgt
4/2/2003 17:41:00   8.17    102.86  3462.43
4/2/2003 20:00:00   6.70    106.00  17661.00
4/2/2003 10:41:00   6.18    106.00  22000.00
4/2/2003 11:41:00   5.78    106.00  22000.00
4/2/2003 12:41:00   5.48    104.00  22000.00
4/4/2003 17:53:00   7.96    104.29  6541.00
4/4/2003 20:53:00   6.60    106.00  22000.00
4/4/2003 19:41:00   7.82    105.00  7555.00
4/4/2003 7:41:00    6.62    105.00  14767.50
4/4/2003 8:41:00    6.70    106.00  17661.00
4/4/2003 9:41:00    6.60    106.00  22000.00
4/5/2003 20:41:00   7.38    106.67  11156.67
4/6/2003 18:07:00   7.82    105.00  7555.00
4/6/2003 21:53:00   6.18    106.00  22000.00
4/6/2003 21:41:00   6.62    105.00  14767.50
4/6/2003 4:41:00    7.96    104.29  6541.00
4/6/2003 5:41:00    7.82    105.00  7555.00
4/6/2003 6:41:00    7.38    106.67  11156.67
4/8/2003 18:53:00   7.38    106.67  11156.67
4/8/2003 22:53:00   5.78    106.00  22000.00
4/8/2003 1:41:00    5.78    106.00  22000.00
4/8/2003 2:41:00    5.48    104.00  22000.00
4/8/2003 3:41:00    8.17    102.86  3462.43
4/10/2003 19:53:00  6.62    105.00  14767.50
4/10/2003 23:53:00  5.48    104.00  22000.00
4/10/2003 22:41:00  6.70    106.00  17661.00
4/10/2003 23:41:00  6.60    106.00  22000.00
4/10/2003 0:41:00   6.18    106.00  22000.00
4/11/2003 17:41:00  8.17    102.86  3462.43</p>

<h2>4/12/2003 18:41:00  7.96    104.29  6541.0</h2>
</code>```

.

```<code>weathrow = 1
for (i in 1:nrow(SortLoc)) {
    t = 0
    while (t < 1) {
        timedif1 = difftime(SortLoc$DateTime[i], SortWeath$DateTime[weathrow], units="auto")
        timedif2 =  difftime(SortLoc$DateTime[i], SortWeath$DateTime[weathrow+1], units="auto")
        if (timedif2 < 0) {
            if (abs(timedif1) < abs(timedif2)) {
                SortLoc$WndSp[i]=SortWeath$WndSp[weathrow]
                SortLoc$WndDir[i]=SortWeath$WndDir[weathrow]
                SortLoc$Hgt[i]=SortWeath$Hgt[weathrow]
            } else {
                SortLoc$WndSp[i]=SortWeath$WndSp[weathrow+1]
                SortLoc$WndDir[i]=SortWeath$WndDir[weathrow+1]
                SortLoc$Hgt[i]=SortWeath$Hgt[weathrow+1]
            }
            t = 1
        }
        if (abs(SortLoc$DateTime[i] - SortLoc$DateTime[i+1] < 50)) {
            weathrow=weathrow
        } else {
            weathrow = weathrow+1
            #if(weathrow = nrow(SortWeath)){t=1}
        }
    } #end while
}
</code>```

答:
Here's an example of one strategy you might use.  This goes through the weather times one-by-one, then takes the absolute value of the difference between that and every location time, then grabs the lowest difference in times.  That solves your look ahead/look back problem.  Your dataset seems small enough that moving to a half-vectorized solution should be all the speed gain you need, but if not it should be relatively simple to add on a moving window which only passes some +/- N observations around the last loc.match.index.

```<code>w <- as.POSIXct(strptime( c("4/2/2003 17:41:00","4/2/2003 20:00:00","4/2/2003 10:41:00","4/2/2003 11:41:00","4/2/2003 12:41:00"),format="%m/%d/%Y %H:%M:%S"))
l <- as.POSIXct(strptime( c("4/2/2003 18:01:01","4/2/2003 17:01:33","4/2/2003 16:03:07","4/2/2003 15:03:08","4/2/2003 14:03:06","4/2/2003 13:02:00"),format="%m/%d/%Y %H:%M:%S"))

window.size <- 5

findClosest <- function(w.i,l) {
    which.min(abs(w.i-l))
}
makeWindow <- function(loc.match.index,i,window.size,n) {
    win.max <- loc.match.index[i-1] + window.size
    if(win.max > n) {
        win.max <- n
    }
    win.min <- loc.match.index[i-1] - window.size
    if(win.min < 1) {
        win.min <- 1
    }
    return(seq(win.min,win.max))
}

loc.match.index <- integer()
n <- length(w)
# Initialize on whole vector
i <- 1
loc.match.index[i] <- findClosest(w[i],l)
# Continue on window
for(i in seq(2,n)) {
    wndw <- makeWindow(loc.match.index,i,window.size,n)
    loc.match.index[i] <- findClosest(w[i],l[wndw])
    # Add the start of the window back to the index that was returned
    loc.match.index[i] <- loc.match.index[i] + min(wndw)-1
}
> loc.match.index
[1] 1 1 5 5 5
</code>```

There are still areas that could be made more efficient here, but this should be reasonably speedy given that the comparisons are vectorized and the window can be tuned.

Body:
I have weather data that was recorded every hour, and location data (X,Y) that was recorded every 4 hours.  I want to know what the temperature was at location X,Y.  The  weather data isn't exactly at the same time.  So, I have written this loop for every location to scan through the weather data looking for the "closest" in Date/TIME and extracting the data from that time.  The problem is the way Ive written it, for location #2, it scans through the weather data but will not allow the closest time information to be assigned that was assigned for location#1.  Say location #1 & 2 are taken within 10 minutes at 6pm and 6:10pm, the closest weather time is 6pm.  I can't get it to allow the weather data at 6pm as an option.  I kind of set it up like this because 200 locations into my location data set (say 3 months into it), I do not want it starting at time 0 from the weather data, when I know that the closest weather data was just calculated for the last location and that happens to be 3 months into that data set too.  Below is some sample data and my code.  I don't know if this makes sense.

####Location data

X   Y   DateTime

1   2   4/2/2003    18:01:01
3   2   4/4/2003    17:01:33
2   3   4/6/2003    16:03:07
5   6   4/8/2003    15:03:08
3   7   4/10/2003   14:03:06
4   5   4/2/2003    13:02:00
4   5   4/4/2003    12:14:43
4   3   4/6/2003    11:00:56
3   5   4/8/2003    10:02:06

2   4   4/10/2003   9:02:19

Weather Data
DateTime        WndSp   WndDir  Hgt
4/2/2003 17:41:00   8.17    102.86  3462.43
4/2/2003 20:00:00   6.70    106.00  17661.00
4/2/2003 10:41:00   6.18    106.00  22000.00
4/2/2003 11:41:00   5.78    106.00  22000.00
4/2/2003 12:41:00   5.48    104.00  22000.00
4/4/2003 17:53:00   7.96    104.29  6541.00
4/4/2003 20:53:00   6.60    106.00  22000.00
4/4/2003 19:41:00   7.82    105.00  7555.00
4/4/2003 7:41:00    6.62    105.00  14767.50
4/4/2003 8:41:00    6.70    106.00  17661.00
4/4/2003 9:41:00    6.60    106.00  22000.00
4/5/2003 20:41:00   7.38    106.67  11156.67
4/6/2003 18:07:00   7.82    105.00  7555.00
4/6/2003 21:53:00   6.18    106.00  22000.00
4/6/2003 21:41:00   6.62    105.00  14767.50
4/6/2003 4:41:00    7.96    104.29  6541.00
4/6/2003 5:41:00    7.82    105.00  7555.00
4/6/2003 6:41:00    7.38    106.67  11156.67
4/8/2003 18:53:00   7.38    106.67  11156.67
4/8/2003 22:53:00   5.78    106.00  22000.00
4/8/2003 1:41:00    5.78    106.00  22000.00
4/8/2003 2:41:00    5.48    104.00  22000.00
4/8/2003 3:41:00    8.17    102.86  3462.43
4/10/2003 19:53:00  6.62    105.00  14767.50
4/10/2003 23:53:00  5.48    104.00  22000.00
4/10/2003 22:41:00  6.70    106.00  17661.00
4/10/2003 23:41:00  6.60    106.00  22000.00
4/10/2003 0:41:00   6.18    106.00  22000.00
4/11/2003 17:41:00  8.17    102.86  3462.43

4/12/2003 18:41:00  7.96    104.29  6541.0

.

weathrow = 1
for (i in 1:nrow(SortLoc)) {
    t = 0
    while (t < 1) {
        timedif1 = difftime(SortLoc$DateTime[i], SortWeath$DateTime[weathrow], units="auto")
        timedif2 =  difftime(SortLoc$DateTime[i], SortWeath$DateTime[weathrow+1], units="auto")
        if (timedif2 < 0) {
            if (abs(timedif1) < abs(timedif2)) {
                SortLoc$WndSp[i]=SortWeath$WndSp[weathrow]
                SortLoc$WndDir[i]=SortWeath$WndDir[weathrow]
                SortLoc$Hgt[i]=SortWeath$Hgt[weathrow]
            } else {
                SortLoc$WndSp[i]=SortWeath$WndSp[weathrow+1]
                SortLoc$WndDir[i]=SortWeath$WndDir[weathrow+1]
                SortLoc$Hgt[i]=SortWeath$Hgt[weathrow+1]
            }
            t = 1
        }
        if (abs(SortLoc$DateTime[i] - SortLoc$DateTime[i+1] < 50)) {
            weathrow=weathrow
        } else {
            weathrow = weathrow+1
            #if(weathrow = nrow(SortWeath)){t=1}
        }
    } #end while
}

Body:
Here's an example of one strategy you might use.  This goes through the weather times one-by-one, then takes the absolute value of the difference between that and every location time, then grabs the lowest difference in times.  That solves your look ahead/look back problem.  Your dataset seems small enough that moving to a half-vectorized solution should be all the speed gain you need, but if not it should be relatively simple to add on a moving window which only passes some +/- N observations around the last loc.match.index.

w <- as.POSIXct(strptime( c("4/2/2003 17:41:00","4/2/2003 20:00:00","4/2/2003 10:41:00","4/2/2003 11:41:00","4/2/2003 12:41:00"),format="%m/%d/%Y %H:%M:%S"))
l <- as.POSIXct(strptime( c("4/2/2003 18:01:01","4/2/2003 17:01:33","4/2/2003 16:03:07","4/2/2003 15:03:08","4/2/2003 14:03:06","4/2/2003 13:02:00"),format="%m/%d/%Y %H:%M:%S"))

window.size <- 5

findClosest <- function(w.i,l) {
    which.min(abs(w.i-l))
}
makeWindow <- function(loc.match.index,i,window.size,n) {
    win.max <- loc.match.index[i-1] + window.size
    if(win.max > n) {
        win.max <- n
    }
    win.min <- loc.match.index[i-1] - window.size
    if(win.min < 1) {
        win.min <- 1
    }
    return(seq(win.min,win.max))
}

loc.match.index <- integer()
n <- length(w)
# Initialize on whole vector
i <- 1
loc.match.index[i] <- findClosest(w[i],l)
# Continue on window
for(i in seq(2,n)) {
    wndw <- makeWindow(loc.match.index,i,window.size,n)
    loc.match.index[i] <- findClosest(w[i],l[wndw])
    # Add the start of the window back to the index that was returned
    loc.match.index[i] <- loc.match.index[i] + min(wndw)-1
}
> loc.match.index
[1] 1 1 5 5 5

There are still areas that could be made more efficient here, but this should be reasonably speedy given that the comparisons are vectorized and the window can be tuned.


问:
php error: Class 'Imagick' not found
I am getting the error "Class 'Imagick' not found".  Somehow I need to make this library accessible to php. I am using Php 5.2.6 on Fedora 8. my php_info has no mention of ImageMagick.

I have tried: yum install ImageMagick and restarted apache, which didn't work.

I also added extension=imagick.ext to my php.ini file and restarted apache, which didn't work.

答:
Docker container installation for php:XXX Debian based images:

```<code>RUN apt-get update && apt-get install -y --no-install-recommends libmagickwand-dev
RUN pecl install imagick && docker-php-ext-enable imagick
RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* || true
</code>```

ContentLicense: CC BY-SA 2.5

Title: php error: Class 'Imagick' not found

Body:
Docker container installation for php:XXX Debian based images:

RUN apt-get update && apt-get install -y --no-install-recommends libmagickwand-dev
RUN pecl install imagick && docker-php-ext-enable imagick
RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* || true


问:
Why does apps like Duo, whatsapp, skype has entries in the RawContact table of native Contacts
I am using ContactContracts API to fetch the entries in RawContacts table

```<code>private void fetchRawContactEntries() {
        String [] mProjectionColumns = new String [] {
            RawContacts.CONTACT_ID, RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_TYPE, RawContacts.DISPLAY_NAME_PRIMARY
        };

        Cursor c = getContentResolver().query(RawContacts.CONTENT_URI, mProjectionColumns, null, null,
                RawContacts.DISPLAY_NAME_PRIMARY + " ASC");
        if(c != null) {
            while(c.moveToNext()) {
                long contactId = c.getLong(0);
                String accountName = c.getString(1);
                String accountType = c.getString(2);
                String displayName = c.getString(3);

                Log.d("Logs", contactId +  ", accountName:" + accountName + ", Display Name : " + displayName);
            }
        }
    }
</code>```

I observe that each contact has multiple entries in the raw_contacts table. (Gmail, Duo etc)

```
2019-05-28 19:21:15.483 5458-5458/com.example.kartikaysingh.cs D/Logs: 2227, accountName:kartikayemail@gmail.com, Display Name : Abhay Y
2019-05-28 19:21:15.483 5458-5458/com.example.kartikaysingh.cs D/Logs: 2227, accountName:WhatsApp, Display Name : Abhay Y
2019-05-28 19:21:15.483 5458-5458/com.example.kartikaysingh.cs D/Logs: 2227, accountName:Duo, Display Name : Abhay Y
2019-05-28 19:21:15.483 5458-5458/com.example.kartikaysingh.cs D/Logs: 2227, accountName:Duo, Display Name : Abhay Y
2019-05-28 19:21:15.483 5458-5458/com.example.kartikaysingh.cs D/Logs: 2140, accountName:kartik@gmail.com, Display Name : Abhayuday
2019-05-28 19:21:15.483 5458-5458/com.example.kartikaysingh.cs D/Logs: 2140, accountName:WhatsApp, Display Name : Abhayuday
2019-05-28 19:21:15.484 5458-5458/com.example.kartikaysingh.cs D/Logs: 2140, accountName:Duo, Display Name : Abhayuday
2019-05-28 19:21:15.484 5458-5458/com.example.kartikaysingh.cs D/Logs: 2140, accountName:Duo, Display Name : Abhayuday
```

Infact Duo make two different entries in the RawContact table. How does native contact app differentiate between these entries.

I know they show the entries of the Contacts table but when modifying a data which raw_contact_id they choose out of Duo or Whatsapp or gmail.
From where they get these original raw_contact_id ?

Here are the things i already know :

Contact Id of the duplicate entries will be same irrespective of the sources which is handled by the Contact Provider. Check this one out ContactsAggregator

Contact table has a column name_raw_contact_id which give the corresponding _ID  of the RawContacts table ( However i am not sure if this can be considered as the primary entry for the contact in RawContacts table).

Given below the list of things i want to know:

We can get the unique contacts from the ContactsContract.Contact table but in order to modify/delete  the data values (like phone, email etc) using Contact provider which raw_contact_id we can pick ? or can i go and modify directly in the ContactContract.Data table.

How do whatsapp detect the addition/modification of the contact. As far as i know Contact Provider doesn't provide the _ID for new contact addition. Do they refresh their contacts list after every app launch or at equal time intervals ?

How to get the original source for a contact (possibly gmail/native in my case) and leave out the copies created by app like Duo, skype, whatsapp using contact provider.

It would be great if anyone help me understand this. Feel free to recommend any other channel where i can ask for these questions

答:
The projection is indeed incorrect.

The Contacts DB is organized in three main tables:

Contacts - each entry represents one contact, and groups together one or more RawContacts

RawContacts - each entry represents data about a contact that was synced in by some SyncAdapter (e.g. Whatsapp, Google, Facebook, Viber), this groups multiple Data entries

Data - The actual data about a contact, emails, phones, etc. each line is a single piece of data that belongs to a single RawContact

Every app on Google Play with sufficient permissions can add a new Contact or a new RawContact and aggregate it into an existing contact, just like Whatsapp / Duo, this allows each app to store information about a specific contact, like it's Whatsapp ID, or any other info that will be useful for the app.

You have a wrong assumption that there is a single "main" RawContact that is the important one, and the others are attached to it.
Instead, the list of RawContacts that represent a single contact can contain multiple Google RawContacts with equal importance, or no Google RawContacts at all, there is one distinction that can help you select a RawContact for editing, that is whether or not the RawContacts created by the app are read-only or writeable.

Here's code to iterate over all accounts on the device, and see which are read-only and which are modifiable (supportsUploading):

```<code>final SyncAdapterType[] syncs = ContentResolver.getSyncAdapterTypes();
for (SyncAdapterType sync : syncs) {
    Log.d(TAG, "found SyncAdapter: " + sync.accountType);
    if (ContactsContract.AUTHORITY.equals(sync.authority)) {
        Log.d(TAG, "found SyncAdapter that supports contacts: " + sync.accountType);
        if (sync.supportsUploading()) {
            Log.d(TAG, "found SyncAdapter that supports contacts and is not read-only: " + sync.accountType);
            // we'll now get a list of all accounts under that accountType:
            Account[] accounts = AccountManager.get(this).getAccountsByType(sync.accountType);
            for (Account account : accounts) {
               Log.d(TAG, account.type + " / " + account.name);
            }
        }
    }
}
</code>```

Explore the other good stuff in SyncAdapterType like isUserVisible that you might help you as well.

Body:
I am using ContactContracts API to fetch the entries in RawContacts table

private void fetchRawContactEntries() {
        String [] mProjectionColumns = new String [] {
            RawContacts.CONTACT_ID, RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_TYPE, RawContacts.DISPLAY_NAME_PRIMARY
        };

        Cursor c = getContentResolver().query(RawContacts.CONTENT_URI, mProjectionColumns, null, null,
                RawContacts.DISPLAY_NAME_PRIMARY + " ASC");
        if(c != null) {
            while(c.moveToNext()) {
                long contactId = c.getLong(0);
                String accountName = c.getString(1);
                String accountType = c.getString(2);
                String displayName = c.getString(3);

                Log.d("Logs", contactId +  ", accountName:" + accountName + ", Display Name : " + displayName);
            }
        }
    }

I observe that each contact has multiple entries in the raw_contacts table. (Gmail, Duo etc)

2019-05-28 19:21:15.483 5458-5458/com.example.kartikaysingh.cs D/Logs: 2227, accountName:kartikayemail@gmail.com, Display Name : Abhay Y
2019-05-28 19:21:15.483 5458-5458/com.example.kartikaysingh.cs D/Logs: 2227, accountName:WhatsApp, Display Name : Abhay Y
2019-05-28 19:21:15.483 5458-5458/com.example.kartikaysingh.cs D/Logs: 2227, accountName:Duo, Display Name : Abhay Y
2019-05-28 19:21:15.483 5458-5458/com.example.kartikaysingh.cs D/Logs: 2227, accountName:Duo, Display Name : Abhay Y
2019-05-28 19:21:15.483 5458-5458/com.example.kartikaysingh.cs D/Logs: 2140, accountName:kartik@gmail.com, Display Name : Abhayuday
2019-05-28 19:21:15.483 5458-5458/com.example.kartikaysingh.cs D/Logs: 2140, accountName:WhatsApp, Display Name : Abhayuday
2019-05-28 19:21:15.484 5458-5458/com.example.kartikaysingh.cs D/Logs: 2140, accountName:Duo, Display Name : Abhayuday
2019-05-28 19:21:15.484 5458-5458/com.example.kartikaysingh.cs D/Logs: 2140, accountName:Duo, Display Name : Abhayuday

Infact Duo make two different entries in the RawContact table. How does native contact app differentiate between these entries.

I know they show the entries of the Contacts table but when modifying a data which raw_contact_id they choose out of Duo or Whatsapp or gmail.
From where they get these original raw_contact_id ?

Here are the things i already know :

Contact Id of the duplicate entries will be same irrespective of the sources which is handled by the Contact Provider. Check this one out ContactsAggregator

Contact table has a column name_raw_contact_id which give the corresponding _ID  of the RawContacts table ( However i am not sure if this can be considered as the primary entry for the contact in RawContacts table).

Given below the list of things i want to know:

We can get the unique contacts from the ContactsContract.Contact table but in order to modify/delete  the data values (like phone, email etc) using Contact provider which raw_contact_id we can pick ? or can i go and modify directly in the ContactContract.Data table.

How do whatsapp detect the addition/modification of the contact. As far as i know Contact Provider doesn't provide the _ID for new contact addition. Do they refresh their contacts list after every app launch or at equal time intervals ?

How to get the original source for a contact (possibly gmail/native in my case) and leave out the copies created by app like Duo, skype, whatsapp using contact provider.

It would be great if anyone help me understand this. Feel free to recommend any other channel where i can ask for these questions

Body:
The projection is indeed incorrect.

The Contacts DB is organized in three main tables:

Contacts - each entry represents one contact, and groups together one or more RawContacts

RawContacts - each entry represents data about a contact that was synced in by some SyncAdapter (e.g. Whatsapp, Google, Facebook, Viber), this groups multiple Data entries

Data - The actual data about a contact, emails, phones, etc. each line is a single piece of data that belongs to a single RawContact

Every app on Google Play with sufficient permissions can add a new Contact or a new RawContact and aggregate it into an existing contact, just like Whatsapp / Duo, this allows each app to store information about a specific contact, like it's Whatsapp ID, or any other info that will be useful for the app.

You have a wrong assumption that there is a single "main" RawContact that is the important one, and the others are attached to it.
Instead, the list of RawContacts that represent a single contact can contain multiple Google RawContacts with equal importance, or no Google RawContacts at all, there is one distinction that can help you select a RawContact for editing, that is whether or not the RawContacts created by the app are read-only or writeable.

Here's code to iterate over all accounts on the device, and see which are read-only and which are modifiable (supportsUploading):

final SyncAdapterType[] syncs = ContentResolver.getSyncAdapterTypes();
for (SyncAdapterType sync : syncs) {
    Log.d(TAG, "found SyncAdapter: " + sync.accountType);
    if (ContactsContract.AUTHORITY.equals(sync.authority)) {
        Log.d(TAG, "found SyncAdapter that supports contacts: " + sync.accountType);
        if (sync.supportsUploading()) {
            Log.d(TAG, "found SyncAdapter that supports contacts and is not read-only: " + sync.accountType);
            // we'll now get a list of all accounts under that accountType:
            Account[] accounts = AccountManager.get(this).getAccountsByType(sync.accountType);
            for (Account account : accounts) {
               Log.d(TAG, account.type + " / " + account.name);
            }
        }
    }
}

Explore the other good stuff in SyncAdapterType like isUserVisible that you might help you as well.


问:
How do you fix this attribute firefox error for selenium using python3
I am trying to use selenium for the first time, but I keep getting errors.

I have tried uninstalling firefox,  changing my path variable so firefox would be recognized but nothing seem to work.
Note: I have added paths with the semicolon but didnt delete anything

Heres some code:

```<code>  from selenium import webdriver

  driver=webdriver.FireFox()
</code>```

The error for the above code:

```<code>AttributeError: module selenium.webdriver has no attribute Firefox
</code>```

I even tried this after typing in: from selenium.webdriver import Firefox
It was suggested by one of the many sources and documentation i consulted.

答:
It should be driver=webdriver.Firefox(), i.e. only one capital F.

here is the sample usage from the docs

Body:
I am trying to use selenium for the first time, but I keep getting errors.

I have tried uninstalling firefox,  changing my path variable so firefox would be recognized but nothing seem to work.
Note: I have added paths with the semicolon but didnt delete anything

Heres some code:

  from selenium import webdriver

  driver=webdriver.FireFox()

The error for the above code:

AttributeError: module selenium.webdriver has no attribute Firefox

I even tried this after typing in: from selenium.webdriver import Firefox
It was suggested by one of the many sources and documentation i consulted.


答:
If your service type is NodePort, you can connect to your service using the address <protocol>://<Node_ip>:<NodePort>, where

```<code>**protocol** may be **http** or **https**
**Node_ip** is the IP of the Node where your application is running
**NodePort** is the value of the **NodePort** field used in your service manifest file
</code>```

Title: Publishing the Application

Body:
If your service type is NodePort, you can connect to your service using the address <protocol>://<Node_ip>:<NodePort>, where

**protocol** may be **http** or **https**
**Node_ip** is the IP of the Node where your application is running
**NodePort** is the value of the **NodePort** field used in your service manifest file


问:
c++ file descriptor (sockets) isopen()?
In C++, is there a way to check if a file descriptor is still open, long after it was initially opened?</p>

答:
fstat is the most portable way I can think of.

If you tell us what platform, we may be able to suggest something better for your particular situation.

Title: c++ file descriptor (sockets) isopen()?


问:
flutter build won't find a dependecy but when i copy the link to my browser it's at the same location
So I've just started flutter with zero experience in mobile development .
and i just created a new project and when i try build it with flutter build apk it give's me this

```<code>Initializing gradle...                                              1.2s
Resolving dependencies...
* Error running Gradle:
ProcessException: Process "/media/OLB/Shared Media/Code Work Space/Visual Studio
Code/flutter_test1/android/gradlew" exited abnormally:

FAILURE: Build failed with an exception.

* What went wrong:
A problem occurred configuring root project 'android'.
> Could not resolve all artifacts for configuration ':classpath'.
   > Could not find builder.jar (com.android.tools.build:builder:3.2.1).
     Searched in the following locations:
         https://dl.google.com/dl/android/maven2/com/android/tools/build/builder/3.2.1/builder-3.2.1.jar

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 1s
  Command: /media/OLB/Shared Media/Code Work Space/Visual Studio Code/flutter_test1/android/gradlew
  app:properties

Please review your Gradle project setup in the android/ folder.
</code>```

but when i copy the provided link

```<code>https://dl.google.com/dl/android/maven2/com/android/tools/build/builder/3.2.1/builder-3.2.1.jar
</code>```

the file is their !

flutter doctor -v

```<code>[✓] Flutter (Channel stable, v1.5.4-hotfix.2, on Linux, locale en_US.UTF-8)
    • Flutter version 1.5.4-hotfix.2 at /media/OBL/Shared Media/Code Work Space/Android/flutter
    • Framework revision 7a4c33425d (4 weeks ago), 2019-04-29 11:05:24 -0700
    • Engine revision 52c7a1e849
    • Dart version 2.3.0 (build 2.3.0-dev.0.5 a1668566e5)

[✓] Android toolchain - develop for Android devices (Android SDK version 28.0.3)
    • Android SDK at /media/OBL/Shared Media/Code Work Space/Android/
    • Android NDK location not configured (optional; useful for native profiling support)
    • Platform android-28, build-tools 28.0.3
    • ANDROID_HOME = /media/OBL/Shared Media/Code Work Space/Android/
    • ANDROID_SDK_ROOT = /media/OBL/Shared Media/Code Work Space/Android/sdk/
    • Java binary at: /usr/lib/jvm/java-8-openjdk-amd64/bin/java
    • Java version OpenJDK Runtime Environment (build 1.8.0_212-8u212-b03-0ubuntu1.18.04.1-b03)
    • All Android licenses accepted.

[!] Android Studio (not installed)
    • Android Studio not found; download from https://developer.android.com/studio/index.html
      (or visit https://flutter.dev/setup/#android-setup for detailed instructions).

[✓] VS Code (version 1.34.0)
    • VS Code at /usr/share/code
    • Flutter extension version 3.0.2

[!] Connected device
    ! No devices available

! Doctor found issues in 2 categories.
</code>```

I know their is no AS but i'v download all required stuff through the Android sdk directly , please help and thanx in advance .

答:
As the Flutter documentation says, Android Studio is required: "Flutter relies on a full installation of Android Studio to supply its Android platform dependencies."

So you have to install Android Studio as well.

Body:
So I've just started flutter with zero experience in mobile development .
and i just created a new project and when i try build it with flutter build apk it give's me this

Initializing gradle...                                              1.2s
Resolving dependencies...
* Error running Gradle:
ProcessException: Process "/media/OLB/Shared Media/Code Work Space/Visual Studio
Code/flutter_test1/android/gradlew" exited abnormally:

FAILURE: Build failed with an exception.

* What went wrong:
A problem occurred configuring root project 'android'.
> Could not resolve all artifacts for configuration ':classpath'.
   > Could not find builder.jar (com.android.tools.build:builder:3.2.1).
     Searched in the following locations:
         https://dl.google.com/dl/android/maven2/com/android/tools/build/builder/3.2.1/builder-3.2.1.jar

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 1s
  Command: /media/OLB/Shared Media/Code Work Space/Visual Studio Code/flutter_test1/android/gradlew
  app:properties

Please review your Gradle project setup in the android/ folder.

but when i copy the provided link

https://dl.google.com/dl/android/maven2/com/android/tools/build/builder/3.2.1/builder-3.2.1.jar

the file is their !

flutter doctor -v

[✓] Flutter (Channel stable, v1.5.4-hotfix.2, on Linux, locale en_US.UTF-8)
    • Flutter version 1.5.4-hotfix.2 at /media/OBL/Shared Media/Code Work Space/Android/flutter
    • Framework revision 7a4c33425d (4 weeks ago), 2019-04-29 11:05:24 -0700
    • Engine revision 52c7a1e849
    • Dart version 2.3.0 (build 2.3.0-dev.0.5 a1668566e5)

[✓] Android toolchain - develop for Android devices (Android SDK version 28.0.3)
    • Android SDK at /media/OBL/Shared Media/Code Work Space/Android/
    • Android NDK location not configured (optional; useful for native profiling support)
    • Platform android-28, build-tools 28.0.3
    • ANDROID_HOME = /media/OBL/Shared Media/Code Work Space/Android/
    • ANDROID_SDK_ROOT = /media/OBL/Shared Media/Code Work Space/Android/sdk/
    • Java binary at: /usr/lib/jvm/java-8-openjdk-amd64/bin/java
    • Java version OpenJDK Runtime Environment (build 1.8.0_212-8u212-b03-0ubuntu1.18.04.1-b03)
    • All Android licenses accepted.

[!] Android Studio (not installed)
    • Android Studio not found; download from https://developer.android.com/studio/index.html
      (or visit https://flutter.dev/setup/#android-setup for detailed instructions).

[✓] VS Code (version 1.34.0)
    • VS Code at /usr/share/code
    • Flutter extension version 3.0.2

[!] Connected device
    ! No devices available

! Doctor found issues in 2 categories.

I know their is no AS but i'v download all required stuff through the Android sdk directly , please help and thanx in advance .