问:
Android - Stream video from camera into another Android Device
It's already been a month and I am losing hope now.

I am trying to capture a video from device 1 and stream it to device 2.

I can already save a video file but the problem is when I stream it into another phone simultaneously while the device 1 is capturing video using camera.

I've seen many tutorials on streaming videos and applied on mine but the videos are already saved in the device, not being captured and streamed simultaneously.

I hope you can help me with this.

.

UPDATE................................................................

Currently I can send a text through socket. I am just including the image capture there to test saving the data in my phone, but it's not sending it through the socket yet.

This is my current code right now:

CameraActivity.Java (the one that serves both as server and the one that captures the data)

```<code>package com.example.martinlloydjose.shaveyourback;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
//import android.graphics.Camera;
import android.media.MediaRecorder;
import android.net.Uri;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.provider.MediaStore.Files.FileColumns;

//import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import android.os.Bundle;
import android.widget.Toast;

import static android.content.ContentValues.TAG;
import static android.provider.MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE;

public class CameraActivity extends AppCompatActivity{

    //camera --------------------------------------------------------------------------------------------
    /*camera
    private static final int CAMERA_REQUEST = 1888;
    private ImageView imageView;
    */
    private Camera mCamera;
    private SurfaceView mPreview;
    private MediaRecorder mMediaRecorder;
    //end of camera --------------------------------------------------------------------------------------------

    //server ////////////////////////////////////////////////////////////////////////////////////////////
    EditText welcomeMsg;
    TextView infoIp;
    TextView infoMsg;
    String msgLog = "";

    ServerSocket httpServerSocket;
    //end of server ////////////////////////////////////////////////////////////////////////////////////////////

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_camera);

        //camera --------------------------------------------------------------------------------------------

        /*
        this.imageView = (ImageView)this.findViewById(R.id.imageView1);
        Button photoButton = (Button) this.findViewById(R.id.button1);
        photoButton.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
                startActivityForResult(cameraIntent, CAMERA_REQUEST);
            }
        });
        */

        // Create an instance of Camera
        /** Showing current image */
        try {
            new AlertDialog.Builder(this).setTitle("Test").setMessage("Running").setNeutralButton("Close", null).show();
            mCamera = getCameraInstance();

            mCamera.setDisplayOrientation(90);

            // Create our Preview view and set it as the content of our activity.
            mPreview = new CameraPreview(this, mCamera);
            FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
            preview.addView(mPreview);
        }catch (Exception error){
            Toast.makeText(this, "An error occured with your camera: "+error.toString(), Toast.LENGTH_LONG).show();
        }

        /** end of Showing current image */

        /** Capturing Image */
        try {
            Button captureButton = (Button) findViewById(R.id.button_capture);
            captureButton.setOnClickListener(
                    new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            // get an image from the camera
                            mCamera.takePicture(null, null, mPicture);
                        }
                    }
            );
        }catch (Exception error){
            Toast.makeText(this, "An error occured with your camera: "+error.toString(), Toast.LENGTH_LONG).show();
        }
        /** end of Capturing Image */

        //end of camera --------------------------------------------------------------------------------------------

        //server ////////////////////////////////////////////////////////////////////////////////////////////
        welcomeMsg = (EditText) findViewById(R.id.welcomemsg);
        infoIp = (TextView) findViewById(R.id.infoip);
        infoMsg = (TextView) findViewById(R.id.msg);

        infoIp.setText(getIpAddress() + ":" + HttpServerThread.HttpServerPORT + "\n");

        HttpServerThread httpServerThread = new HttpServerThread();
        httpServerThread.start();
        //end of server ////////////////////////////////////////////////////////////////////////////////////////////

    }

    //camera --------------------------------------------------------------------------------------------
    /*
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == CAMERA_REQUEST && resultCode == Activity.RESULT_OK) {
            Bitmap photo = (Bitmap) data.getExtras().get("data");
            imageView.setImageBitmap(photo);
        }
    }
    */

    /** Check if this device has a camera */
    private boolean checkCameraHardware(Context context) {
        if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
            // this device has a camera
            return true;
        } else {
            // no camera on this device
            return false;
        }
    }
    /** end of Check if this device has a camera */

    /** A safe way to get an instance of the Camera object. */
    public static Camera getCameraInstance(){
        Camera c = null;
        try {
            c = Camera.open(); // attempt to get a Camera instance
        }
        catch (Exception e){
            // Camera is not available (in use or does not exist)
        }
        return c; // returns null if camera is unavailable
    }
    /** end of A safe way to get an instance of the Camera object. */

    /** Capture Pictures */
    private PictureCallback mPicture = new PictureCallback() {

        @Override
        public void onPictureTaken(byte[] data, Camera camera) {

            File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
            if (pictureFile == null){
                Log.d(TAG, "Error creating media file, check storage permissions: "
                        /*e.getMessage()*/);
                return;
            }

            try {
                FileOutputStream fos = new FileOutputStream(pictureFile);
                fos.write(data);
                fos.close();
            } catch (FileNotFoundException e) {
                Log.d(TAG, "File not found: " + e.getMessage());
            } catch (IOException e) {
                Log.d(TAG, "Error accessing file: " + e.getMessage());
            }
        }
    };

    /** end of Capture Pictures */

    /** Setting the storage */

    public static final int MEDIA_TYPE_IMAGE = 1;
    public static final int MEDIA_TYPE_VIDEO = 2;

    /** Create a file Uri for saving an image or video */
    private static Uri getOutputMediaFileUri(int type){
        return Uri.fromFile(getOutputMediaFile(type));
    }

    private static File getOutputMediaFile(int type){
        // To be safe, you should check that the SDCard is mounted
        // using Environment.getExternalStorageState() before doing this.

        File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
                Environment.DIRECTORY_PICTURES), "MyCameraApp");
        // This location works best if you want the created images to be shared
        // between applications and persist after your app has been uninstalled.

        // Create the storage directory if it does not exist
        if (! mediaStorageDir.exists()){
            if (! mediaStorageDir.mkdirs()){
                Log.d("MyCameraApp", "failed to create directory");
                return null;
            }
        }

        // Create a media file name
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        File mediaFile;
        if (type == MEDIA_TYPE_IMAGE){
            mediaFile = new File(mediaStorageDir.getPath() + File.separator +
                    "IMG_"+ timeStamp + ".jpg");
        } else if(type == MEDIA_TYPE_VIDEO) {
            mediaFile = new File(mediaStorageDir.getPath() + File.separator +
                    "VID_"+ timeStamp + ".mp4");
        } else {
            return null;
        }

        return mediaFile;
    }
    /** end of Setting the storage */

    /** releasing camera */
    @Override
    protected void onPause() {
        super.onPause();
        //releaseMediaRecorder();       // if you are using MediaRecorder, release it first
        releaseCamera();              // release the camera immediately on pause event
    }

    /*private void releaseMediaRecorder(){
        if (mMediaRecorder != null) {
            mMediaRecorder.reset();   // clear recorder configuration
            mMediaRecorder.release(); // release the recorder object
            mMediaRecorder = null;
            mCamera.lock();           // lock camera for later use
        }
    }*/

    private void releaseCamera(){
        if (mCamera != null){
            mCamera.release();        // release the camera for other applications
            mCamera = null;
        }
    }
    /** end of releasing camera */

    //end of camera --------------------------------------------------------------------------------------------

    //server -001 ////////////////////////////////////////////////////////////////////////////////////////////
    @Override
    protected void onDestroy() {
        super.onDestroy();

        if (httpServerSocket != null) {
            try {
                httpServerSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private String getIpAddress() {
        String ip = "";
        try {
            Enumeration<NetworkInterface> enumNetworkInterfaces = NetworkInterface
                    .getNetworkInterfaces();
            while (enumNetworkInterfaces.hasMoreElements()) {
                NetworkInterface networkInterface = enumNetworkInterfaces
                        .nextElement();
                Enumeration<InetAddress> enumInetAddress = networkInterface
                        .getInetAddresses();
                while (enumInetAddress.hasMoreElements()) {
                    InetAddress inetAddress = enumInetAddress.nextElement();

                    if (inetAddress.isSiteLocalAddress()) {
                        ip += "SiteLocalAddress: "
                                + inetAddress.getHostAddress() + "\n";
                    }
                }
            }

        } catch (SocketException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            ip += "Something Wrong! " + e.toString() + "\n" +e.getMessage();
        }

        return ip;
    }

    private class HttpServerThread extends Thread {

        static final int HttpServerPORT = 8888;

        @Override
        public void run() {
            Socket socket = null;

            try {
                httpServerSocket = new ServerSocket(HttpServerPORT);

                while(true){
                    socket = httpServerSocket.accept();

                    HttpResponseThread httpResponseThread =
                            new HttpResponseThread(
                                    socket,
                                    welcomeMsg.getText().toString());
                    httpResponseThread.start();
                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    private class HttpResponseThread extends Thread {

        Socket socket;
        String h1;

        HttpResponseThread(Socket socket, String msg){
            this.socket = socket;
            h1 = msg;
        }

        @Override
        public void run() {
            BufferedReader is;
            PrintWriter os;
            String request;

            try {
                is = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                request = is.readLine();

                os = new PrintWriter(socket.getOutputStream(), true);

                String response =
                        "<html><head></head>" +
                                "<body>" +
                                "<h1>" + h1 + "</h1>" +
                                "</body></html>";

                os.print("HTTP/1.0 200" + "\r\n");
                os.print("Content type: text/html" + "\r\n");
                os.print("Content length: " + response.length() + "\r\n");
                os.print("\r\n");
                os.print(response + "\r\n");
                os.flush();
                socket.close();

                msgLog += "Request of " + request
                        + " from " + socket.getInetAddress().toString() + "\n";
                CameraActivity.this.runOnUiThread(new Runnable() {

                    @Override
                    public void run() {

                        infoMsg.setText(msgLog);
                    }
                });

            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            return;
        }
    }
    //end of server -001 ////////////////////////////////////////////////////////////////////////////////////////////

}
</code>```

ViewerActivity.java

```<code>package com.example.martinlloydjose.shaveyourback;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.webkit.WebView;

public class ViewerActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_viewer);

        WebView webView = (WebView)findViewById(R.id.webViewStream);
        webView.loadUrl("http://10.0.2.15:8888");
        webView.getSettings().setBuiltInZoomControls(true);
    }
}
</code>```

Activity_Camera.xml

```<code><?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="0dp"
    android:paddingRight="0dp"
    android:paddingTop="0dp"
    android:paddingBottom="0dp"
    tools:context="com.example.martinlloydjose.shaveyourback.CameraActivity">

    <TextView
        android:id="@+id/tvTitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="Connect using the following details"
        android:textStyle="bold" />

    <EditText
        android:id="@+id/welcomemsg"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Test Message"
        android:layout_below="@+id/tvTitle"
        />

    <TextView
        android:id="@+id/infoip"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/welcomemsg"
        />

    <ScrollView
        android:id="@+id/scrollSlider"
        android:layout_width="match_parent"
        android:layout_height="100sp"
        android:layout_below="@+id/infoip">

        <TextView
            android:id="@+id/msg"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    </ScrollView>

    <!--
    <ImageView
        android:id="@+id/imageView1"
        android:layout_height="fill_parent"
        android:src="@drawable/icon"
        android:layout_width="fill_parent"
        android:layout_below="@+id/scrollSlider"
        >
    </ImageView>

    <Button
        android:id="@+id/button1"
        android:layout_below="@id/imageView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="-50sp"
        android:text="capture">
    </Button>
    -->

    <FrameLayout
        android:id="@+id/camera_preview"
        android:layout_below="@+id/scrollSlider"
        android:layout_width="wrap_content"
        android:layout_height="fill_parent"
        android:layout_weight="1"
        />

    <Button
        android:id="@+id/button_capture"
        android:text="Capture"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_below="@+id/camera_preview"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="-50sp"
        />

</RelativeLayout>
</code>```

Activity_Viewer.xml

```<code><?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="0dp"
    android:paddingRight="0dp"
    android:paddingTop="0dp"
    android:paddingBottom="0dp"
    tools:context="com.example.martinlloydjose.shaveyourback.ViewerActivity">

    <WebView
        android:id="@+id/webViewStream"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="0dp"
        android:layout_marginStart="0dp"
        android:layout_marginTop="0dp" />

</RelativeLayout>
</code>```

答:
I assume you already have a server as a mediator. In that case, you can setup an NGINX server environment and install nginx-rtmp-module on top of that. Also, you can use SRS live streaming cluster, which also creates its own server environment.

Since, both of them are open source, they will be cost efficient.

Also, srs 3.0 is unrealistically more advanced than nginx-rtmp-module because of its huge amount of features. But for simple streaming, which I assume is your case, both are equally useful, though i would suggest nginx-rtmo-module because of the power of nginx.

That covers everything for server creation. After that, you can use vlc on android, or any rtmp streaming repo from github to do the streaming. For receiving your streams, most of the major video player support live streaming. So you will just need to enter your streaming rtmp://.... address to it.

The following are some references, though they are outdated, the core is still the same.

Nginx Rtmp 1

Nginx Rtmp 2

Nginx Rtmp 3

Body:
It's already been a month and I am losing hope now.

I am trying to capture a video from device 1 and stream it to device 2.

I can already save a video file but the problem is when I stream it into another phone simultaneously while the device 1 is capturing video using camera.

I've seen many tutorials on streaming videos and applied on mine but the videos are already saved in the device, not being captured and streamed simultaneously.

I hope you can help me with this.

.

UPDATE................................................................

Currently I can send a text through socket. I am just including the image capture there to test saving the data in my phone, but it's not sending it through the socket yet.

This is my current code right now:

CameraActivity.Java (the one that serves both as server and the one that captures the data)

package com.example.martinlloydjose.shaveyourback;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
//import android.graphics.Camera;
import android.media.MediaRecorder;
import android.net.Uri;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.provider.MediaStore.Files.FileColumns;

//import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import android.os.Bundle;
import android.widget.Toast;

import static android.content.ContentValues.TAG;
import static android.provider.MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE;

public class CameraActivity extends AppCompatActivity{

    //camera --------------------------------------------------------------------------------------------
    /*camera
    private static final int CAMERA_REQUEST = 1888;
    private ImageView imageView;
    */
    private Camera mCamera;
    private SurfaceView mPreview;
    private MediaRecorder mMediaRecorder;
    //end of camera --------------------------------------------------------------------------------------------

    //server ////////////////////////////////////////////////////////////////////////////////////////////
    EditText welcomeMsg;
    TextView infoIp;
    TextView infoMsg;
    String msgLog = "";

    ServerSocket httpServerSocket;
    //end of server ////////////////////////////////////////////////////////////////////////////////////////////

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_camera);

        //camera --------------------------------------------------------------------------------------------

        /*
        this.imageView = (ImageView)this.findViewById(R.id.imageView1);
        Button photoButton = (Button) this.findViewById(R.id.button1);
        photoButton.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
                startActivityForResult(cameraIntent, CAMERA_REQUEST);
            }
        });
        */

        // Create an instance of Camera
        /** Showing current image */
        try {
            new AlertDialog.Builder(this).setTitle("Test").setMessage("Running").setNeutralButton("Close", null).show();
            mCamera = getCameraInstance();

            mCamera.setDisplayOrientation(90);

            // Create our Preview view and set it as the content of our activity.
            mPreview = new CameraPreview(this, mCamera);
            FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
            preview.addView(mPreview);
        }catch (Exception error){
            Toast.makeText(this, "An error occured with your camera: "+error.toString(), Toast.LENGTH_LONG).show();
        }

        /** end of Showing current image */

        /** Capturing Image */
        try {
            Button captureButton = (Button) findViewById(R.id.button_capture);
            captureButton.setOnClickListener(
                    new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            // get an image from the camera
                            mCamera.takePicture(null, null, mPicture);
                        }
                    }
            );
        }catch (Exception error){
            Toast.makeText(this, "An error occured with your camera: "+error.toString(), Toast.LENGTH_LONG).show();
        }
        /** end of Capturing Image */

        //end of camera --------------------------------------------------------------------------------------------

        //server ////////////////////////////////////////////////////////////////////////////////////////////
        welcomeMsg = (EditText) findViewById(R.id.welcomemsg);
        infoIp = (TextView) findViewById(R.id.infoip);
        infoMsg = (TextView) findViewById(R.id.msg);

        infoIp.setText(getIpAddress() + ":" + HttpServerThread.HttpServerPORT + "\n");

        HttpServerThread httpServerThread = new HttpServerThread();
        httpServerThread.start();
        //end of server ////////////////////////////////////////////////////////////////////////////////////////////

    }

    //camera --------------------------------------------------------------------------------------------
    /*
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == CAMERA_REQUEST && resultCode == Activity.RESULT_OK) {
            Bitmap photo = (Bitmap) data.getExtras().get("data");
            imageView.setImageBitmap(photo);
        }
    }
    */

    /** Check if this device has a camera */
    private boolean checkCameraHardware(Context context) {
        if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
            // this device has a camera
            return true;
        } else {
            // no camera on this device
            return false;
        }
    }
    /** end of Check if this device has a camera */

    /** A safe way to get an instance of the Camera object. */
    public static Camera getCameraInstance(){
        Camera c = null;
        try {
            c = Camera.open(); // attempt to get a Camera instance
        }
        catch (Exception e){
            // Camera is not available (in use or does not exist)
        }
        return c; // returns null if camera is unavailable
    }
    /** end of A safe way to get an instance of the Camera object. */

    /** Capture Pictures */
    private PictureCallback mPicture = new PictureCallback() {

        @Override
        public void onPictureTaken(byte[] data, Camera camera) {

            File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
            if (pictureFile == null){
                Log.d(TAG, "Error creating media file, check storage permissions: "
                        /*e.getMessage()*/);
                return;
            }

            try {
                FileOutputStream fos = new FileOutputStream(pictureFile);
                fos.write(data);
                fos.close();
            } catch (FileNotFoundException e) {
                Log.d(TAG, "File not found: " + e.getMessage());
            } catch (IOException e) {
                Log.d(TAG, "Error accessing file: " + e.getMessage());
            }
        }
    };

    /** end of Capture Pictures */

    /** Setting the storage */

    public static final int MEDIA_TYPE_IMAGE = 1;
    public static final int MEDIA_TYPE_VIDEO = 2;

    /** Create a file Uri for saving an image or video */
    private static Uri getOutputMediaFileUri(int type){
        return Uri.fromFile(getOutputMediaFile(type));
    }

    private static File getOutputMediaFile(int type){
        // To be safe, you should check that the SDCard is mounted
        // using Environment.getExternalStorageState() before doing this.

        File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
                Environment.DIRECTORY_PICTURES), "MyCameraApp");
        // This location works best if you want the created images to be shared
        // between applications and persist after your app has been uninstalled.

        // Create the storage directory if it does not exist
        if (! mediaStorageDir.exists()){
            if (! mediaStorageDir.mkdirs()){
                Log.d("MyCameraApp", "failed to create directory");
                return null;
            }
        }

        // Create a media file name
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        File mediaFile;
        if (type == MEDIA_TYPE_IMAGE){
            mediaFile = new File(mediaStorageDir.getPath() + File.separator +
                    "IMG_"+ timeStamp + ".jpg");
        } else if(type == MEDIA_TYPE_VIDEO) {
            mediaFile = new File(mediaStorageDir.getPath() + File.separator +
                    "VID_"+ timeStamp + ".mp4");
        } else {
            return null;
        }

        return mediaFile;
    }
    /** end of Setting the storage */

    /** releasing camera */
    @Override
    protected void onPause() {
        super.onPause();
        //releaseMediaRecorder();       // if you are using MediaRecorder, release it first
        releaseCamera();              // release the camera immediately on pause event
    }

    /*private void releaseMediaRecorder(){
        if (mMediaRecorder != null) {
            mMediaRecorder.reset();   // clear recorder configuration
            mMediaRecorder.release(); // release the recorder object
            mMediaRecorder = null;
            mCamera.lock();           // lock camera for later use
        }
    }*/

    private void releaseCamera(){
        if (mCamera != null){
            mCamera.release();        // release the camera for other applications
            mCamera = null;
        }
    }
    /** end of releasing camera */

    //end of camera --------------------------------------------------------------------------------------------

    //server -001 ////////////////////////////////////////////////////////////////////////////////////////////
    @Override
    protected void onDestroy() {
        super.onDestroy();

        if (httpServerSocket != null) {
            try {
                httpServerSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private String getIpAddress() {
        String ip = "";
        try {
            Enumeration<NetworkInterface> enumNetworkInterfaces = NetworkInterface
                    .getNetworkInterfaces();
            while (enumNetworkInterfaces.hasMoreElements()) {
                NetworkInterface networkInterface = enumNetworkInterfaces
                        .nextElement();
                Enumeration<InetAddress> enumInetAddress = networkInterface
                        .getInetAddresses();
                while (enumInetAddress.hasMoreElements()) {
                    InetAddress inetAddress = enumInetAddress.nextElement();

                    if (inetAddress.isSiteLocalAddress()) {
                        ip += "SiteLocalAddress: "
                                + inetAddress.getHostAddress() + "\n";
                    }
                }
            }

        } catch (SocketException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            ip += "Something Wrong! " + e.toString() + "\n" +e.getMessage();
        }

        return ip;
    }

    private class HttpServerThread extends Thread {

        static final int HttpServerPORT = 8888;

        @Override
        public void run() {
            Socket socket = null;

            try {
                httpServerSocket = new ServerSocket(HttpServerPORT);

                while(true){
                    socket = httpServerSocket.accept();

                    HttpResponseThread httpResponseThread =
                            new HttpResponseThread(
                                    socket,
                                    welcomeMsg.getText().toString());
                    httpResponseThread.start();
                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    private class HttpResponseThread extends Thread {

        Socket socket;
        String h1;

        HttpResponseThread(Socket socket, String msg){
            this.socket = socket;
            h1 = msg;
        }

        @Override
        public void run() {
            BufferedReader is;
            PrintWriter os;
            String request;

            try {
                is = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                request = is.readLine();

                os = new PrintWriter(socket.getOutputStream(), true);

                String response =
                        "" +
                                "" +
                                "
" + h1 + "
" +
                                "";

                os.print("HTTP/1.0 200" + "\r\n");
                os.print("Content type: text/html" + "\r\n");
                os.print("Content length: " + response.length() + "\r\n");
                os.print("\r\n");
                os.print(response + "\r\n");
                os.flush();
                socket.close();

                msgLog += "Request of " + request
                        + " from " + socket.getInetAddress().toString() + "\n";
                CameraActivity.this.runOnUiThread(new Runnable() {

                    @Override
                    public void run() {

                        infoMsg.setText(msgLog);
                    }
                });

            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            return;
        }
    }
    //end of server -001 ////////////////////////////////////////////////////////////////////////////////////////////

}

ViewerActivity.java

package com.example.martinlloydjose.shaveyourback;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.webkit.WebView;

public class ViewerActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_viewer);

        WebView webView = (WebView)findViewById(R.id.webViewStream);
        webView.loadUrl("http://10.0.2.15:8888");
        webView.getSettings().setBuiltInZoomControls(true);
    }
}

Activity_Camera.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="0dp"
    android:paddingRight="0dp"
    android:paddingTop="0dp"
    android:paddingBottom="0dp"
    tools:context="com.example.martinlloydjose.shaveyourback.CameraActivity">

    <TextView
        android:id="@+id/tvTitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="Connect using the following details"
        android:textStyle="bold" />

    <EditText
        android:id="@+id/welcomemsg"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Test Message"
        android:layout_below="@+id/tvTitle"
        />

    <TextView
        android:id="@+id/infoip"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/welcomemsg"
        />

    <ScrollView
        android:id="@+id/scrollSlider"
        android:layout_width="match_parent"
        android:layout_height="100sp"
        android:layout_below="@+id/infoip">

        <TextView
            android:id="@+id/msg"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    </ScrollView>

    <FrameLayout
        android:id="@+id/camera_preview"
        android:layout_below="@+id/scrollSlider"
        android:layout_width="wrap_content"
        android:layout_height="fill_parent"
        android:layout_weight="1"
        />

    <Button
        android:id="@+id/button_capture"
        android:text="Capture"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_below="@+id/camera_preview"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="-50sp"
        />

</RelativeLayout>

Activity_Viewer.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="0dp"
    android:paddingRight="0dp"
    android:paddingTop="0dp"
    android:paddingBottom="0dp"
    tools:context="com.example.martinlloydjose.shaveyourback.ViewerActivity">

    <WebView
        android:id="@+id/webViewStream"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="0dp"
        android:layout_marginStart="0dp"
        android:layout_marginTop="0dp" />

</RelativeLayout>


来源: stackexchange

问:
Football game Loops
So I have this program I am trying to build and it is a simple football game. My only question that is puzzling me is how do I get my program to loop through all these questions. The JOptionPane messages on the bottom are out of place and my code is a little messy I am just wondering if anyone can help me on how I just make my program loop through all these questions and letting the user end it. </p>

```<code>package football;

import javax.swing.JOptionPane;

public class Football {

    public static void main(String[] args) {
        JOptionPane.showMessageDialog(null, "Are you ready for some FOOTBALL?!?!?!");

        String StringTeamOption = JOptionPane.showInputDialog("Pick two of the four teams");
        //Input my methods

        String StringBallOption = JOptionPane.showInputDialog("Who has the ball first?");
        //If statement and loop
        String StringPlayOption = JOptionPane.showInputDialog("Did the team pass or run the ball?");
        //If statement and part of loop
        String StringYardage = JOptionPane.showInputDialog("How far did the team throw/run?");
        //If statement and calculation also part of loop
        String StringScoreingPlay = JOptionPane.showInputDialog("Did the team score?");
        //If statement and part of loop
        String StringPlayAgain = JOptionPane.showInputDialog("Do you want to play again");
        //loop

        JOptionPane.showMessageDialog(null, "The ball is on the 20 yard line anything over 80 yards will not count");
        JOptionPane.showMessageDialog(null, "End of the quarter!");
        JOptionPane.showMessageDialog(null, "End of the game!!!");
        //Messages for explanation
</code>```

答:
You could just create a boolean flag and a while or do while loop? </p>

```<code>Boolean keepPlaying = true;

while (keepPlaying) {

// ... All the questions here.
//If input from "Do you want to play again?" is no, set keepPlaying to false.

}
</code>```

ContentLicense: CC BY-SA 3.0

Title: Football game Loops

Body:
So I have this program I am trying to build and it is a simple football game. My only question that is puzzling me is how do I get my program to loop through all these questions. The JOptionPane messages on the bottom are out of place and my code is a little messy I am just wondering if anyone can help me on how I just make my program loop through all these questions and letting the user end it.

package football;

import javax.swing.JOptionPane;

public class Football {

    public static void main(String[] args) {
        JOptionPane.showMessageDialog(null, "Are you ready for some FOOTBALL?!?!?!");

        String StringTeamOption = JOptionPane.showInputDialog("Pick two of the four teams");
        //Input my methods

        String StringBallOption = JOptionPane.showInputDialog("Who has the ball first?");
        //If statement and loop
        String StringPlayOption = JOptionPane.showInputDialog("Did the team pass or run the ball?");
        //If statement and part of loop
        String StringYardage = JOptionPane.showInputDialog("How far did the team throw/run?");
        //If statement and calculation also part of loop
        String StringScoreingPlay = JOptionPane.showInputDialog("Did the team score?");
        //If statement and part of loop
        String StringPlayAgain = JOptionPane.showInputDialog("Do you want to play again");
        //loop

        JOptionPane.showMessageDialog(null, "The ball is on the 20 yard line anything over 80 yards will not count");
        JOptionPane.showMessageDialog(null, "End of the quarter!");
        JOptionPane.showMessageDialog(null, "End of the game!!!");
        //Messages for explanation

Body:
You could just create a boolean flag and a while or do while loop?

Boolean keepPlaying = true;

while (keepPlaying) {

// ... All the questions here.
//If input from "Do you want to play again?" is no, set keepPlaying to false.

}


问:
How do I stack bootstrap grid columns one below the other instead of one beside another?
I am just beginning to learn Bootstrap and I came across the grid system. I was playing around and noticed that the grid columns always start from the left and go towards the right, placing the divs one beside another. How do I make them appear one below the other?
Here's some sample code:

```<code><body>

<div class="container-fluid">
  <h2>Three Equal Columns</h2>
  <div class="row">
    <div class="col-4 bg-success">.col-1</div>
    <div class="col-4 bg-warning">.col-2</div>
    <div class="col-4 bg-success">.col-3</div>
  </div>
</div>

</body>
</code>```

Here's a fiddle.
https://jsfiddle.net/txdqjf8b/2/

How do I make col-1, col-2 and col-3 appear one below the other, so that later if I have a col-4, col-5 and col-6, I want them like this:

```<code>col-1    col-4    col-7
col-2    col-5    col-8
col-3    col-6    col-9
</code>```

答:
```<code><div class="row">
 <div class="col-md-4 col-lg-4 col-sm-4">
   <div class="row">
     <div class="col-md-12 bg-success">col-1</div>
   </div>
   <div class="row">
     <div class="col-md-12 bg-success">col-2</div>
   </div>
   <div class="row">
     <div class="col-md-12 bg-success">col-3</div>
   </div>
 </div>
 <div class="col-md-4 col-lg-4 col-sm-4">
    <div class="row">
     <div class="col-md-12 bg-success">col-4</div>
    </div>
    <div class="row">
     <div class="col-md-12 bg-success">col-5</div>
    </div>
    <div class="row">
      <div class="col-md-12 bg-success">col-6</div>
    </div>
 </div>
 <div class="col-md-4 col-lg-4 col-sm-4">
    <div class="row">
      <div class="col-md-12 bg-success">col-7</div>
    </div>
    <div class="row">
      <div class="col-md-12 bg-success">col-8</div>
    </div>
    <div class="row">
      <div class="col-md-12 bg-success">col-9</div>
    </div>
 </div>
</div>
</code>```

Body:
I am just beginning to learn Bootstrap and I came across the grid system. I was playing around and noticed that the grid columns always start from the left and go towards the right, placing the divs one beside another. How do I make them appear one below the other?
Here's some sample code:

Three Equal Columns

.col-1

.col-2

.col-3

Here's a fiddle.
https://jsfiddle.net/txdqjf8b/2/

How do I make col-1, col-2 and col-3 appear one below the other, so that later if I have a col-4, col-5 and col-6, I want them like this:

col-1    col-4    col-7
col-2    col-5    col-8
col-3    col-6    col-9


问:
mongoDB/mongoose: Is it possible to modify _id when projecting `.find` results?
I tried "_id": "$field", but it doesn't work.

"_id": 0 removes the _id field entirely

答:
using mongoose

```<code>var UserSchema = new mongoose.Schema({
       //other fields
    },{
        minimize: false,
        toJSON: {
            transform: function (doc, ret) {
                ret.newField= ret._id;
                delete ret._id;
            }
        }
    });
</code>```

and query like model.find()

using aggregation

```<code>model.aggregate([
{
$match:{}
},
{
$project:{
 "newField":"$_id",
 "_id":0
}
}
])
</code>```

Body:
using mongoose

var UserSchema = new mongoose.Schema({
       //other fields
    },{
        minimize: false,
        toJSON: {
            transform: function (doc, ret) {
                ret.newField= ret._id;
                delete ret._id;
            }
        }
    });

and query like model.find()

using aggregation

model.aggregate([
{
$match:{}
},
{
$project:{
 "newField":"$_id",
 "_id":0
}
}
])


问:
How can I reformat XAML nicely in VS 2008?
Visual Studio 2008's XAML editor (SP1) cannot reformat the XML into a consistent style.

Which tools can I use to get a nicely formatted XAML file? Studio integration preferred.

答: The only tool I found is Kaxaml, which does nice formatting ("XAML Scrubber" entry in the left menu), but being a stand-alone editor doesn't quite make the cut.</p>

OwnerDisplayName: David Schmitt

ContentLicense: CC BY-SA 2.5

LastEditorDisplayName: David Schmitt


问:
Is there any library does minidump on Mac?
MiniDump is a great feature for debugging crashes on Windows, especially because it is small, so it can be sent via crash reports. (Window Error Reporting).

But it seems Mac OS X and other BSD system only supports full core dump.

Is there any mini-dump implementation on Mac or BSD system? Or how does Mac software developer analyze customer's crash reports?

Thanks!
-Jonny

答: Yes, you can use Google breakpad, which works on Windows, Mac, and Linux. As an added bonus, the file format it creates is the same as the windows minidump format, no matter what platform it's using - so you can apply your current analysis tools to dumps from windows clients.</p>


问:
Export multiple react objects from other dirs
I'm very new to React so please excuse my ignorance. I basically want to know the "way" to export multiple ReactJS objects from directories for larger codebases and best practices. This is not really in the ReactJS tutorial.

Let's say I have a file ./main.js and I want to import a lib (from a dir because I might have other ones).

Let's say I have a library in a dir ./library_dir/my_lib.js and I want to use it in ./main.js like so.

In ./main.js, I might want to use this lib and initialize some ExampleComponent like this:

```<code>var my_lib = require('./library_dir/my_lib.js');

ReactDOM.render(
(<BrowserRouter>
        <Switch>
                <Route exact path="/component_route" component={my_lib.ExampleComponent}>
        </Switch>
</BrowserRouter>)
, document.getElementById("root"));
</code>```

So in ./library_dir/my_lib.js, I want to be able to export MULTIPLE reactjs classes. How would I do this?

Would I want to use export default .... or module.exports? Which one and WHY? I've read that if I import react in this lib, I can't do a module.exports.

Can someone give me an example where in ./library_dir/my_lib.js, I would be able to export multiple react classes that would look something like this?

```<code>import React from 'react';

my_lib = {
        test_function: function() {
                alert("TEST FUNCTION CALLED");
        },
        // How would I do this bellow?
        ExampleComonent: class ExampleComponent extends React.Component {
                constructor(props) {
                        super(props);
                        // doing all thing things...
                }
                render() {
                        return (
                        <h1>This is ExampleComponent.</h1>
                        );
                }
        }
        // I need to be able to export multiple components, so here's another one.
        ExampleComonentTwo: class ExampleComponentTwo extends React.Component {
                constructor(props) {
                        super(props);
                        // doing all thing things...
                }
                render() {
                        return (
                        <h1>This is ExampleComponentTwo.</h1>
                        );
                }
        }
}

export default my_lib;
</code>```

答:
As we know module is a plain JavaScript object with an exports property. exports is a plain JavaScript variable that happens to be set to module.exports. And export default is syntax from ES6.

Many people consider module.exports = ... to be equivalent to export default ... and exports.foo ... to be equivalent to export const foo = .... That's not quite true though, or at least not how Babel does it.

ES6 default exports are actually also named exports, except that default is a "reserved" name and there is special syntax support for it. Lets have a look how Babel compiles named and default exports:

```<code>// input
export const foo = 42;
export default 21;

// output
"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
var foo = exports.foo = 42;
exports.default = 21;
</code>```

Here we can see that the default export becomes a property on the exports object, just like foo.

I would like to suggest to you use one index.js file, where you have to export your components from lib and use them in your actual implementations.

I think following links will help you in more to resolve your problems.

Why es6 react component works only with “export default”?

Multiple React components in a single module

Hope this will help you !!

Body:
I'm very new to React so please excuse my ignorance. I basically want to know the "way" to export multiple ReactJS objects from directories for larger codebases and best practices. This is not really in the ReactJS tutorial.

Let's say I have a file ./main.js and I want to import a lib (from a dir because I might have other ones).

Let's say I have a library in a dir ./library_dir/my_lib.js and I want to use it in ./main.js like so.

In ./main.js, I might want to use this lib and initialize some ExampleComponent like this:

var my_lib = require('./library_dir/my_lib.js');

ReactDOM.render(
(<BrowserRouter>
        <Switch>
                <Route exact path="/component_route" component={my_lib.ExampleComponent}>
        </Switch>
</BrowserRouter>)
, document.getElementById("root"));

So in ./library_dir/my_lib.js, I want to be able to export MULTIPLE reactjs classes. How would I do this?

Would I want to use export default .... or module.exports? Which one and WHY? I've read that if I import react in this lib, I can't do a module.exports.

Can someone give me an example where in ./library_dir/my_lib.js, I would be able to export multiple react classes that would look something like this?

import React from 'react';

my_lib = {
        test_function: function() {
                alert("TEST FUNCTION CALLED");
        },
        // How would I do this bellow?
        ExampleComonent: class ExampleComponent extends React.Component {
                constructor(props) {
                        super(props);
                        // doing all thing things...
                }
                render() {
                        return (

This is ExampleComponent.

                        );
                }
        }
        // I need to be able to export multiple components, so here's another one.
        ExampleComonentTwo: class ExampleComponentTwo extends React.Component {
                constructor(props) {
                        super(props);
                        // doing all thing things...
                }
                render() {
                        return (

This is ExampleComponentTwo.

                        );
                }
        }
}

export default my_lib;

Body:
As we know module is a plain JavaScript object with an exports property. exports is a plain JavaScript variable that happens to be set to module.exports. And export default is syntax from ES6.

Many people consider module.exports = ... to be equivalent to export default ... and exports.foo ... to be equivalent to export const foo = .... That's not quite true though, or at least not how Babel does it.

ES6 default exports are actually also named exports, except that default is a "reserved" name and there is special syntax support for it. Lets have a look how Babel compiles named and default exports:

// input
export const foo = 42;
export default 21;

// output
"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
var foo = exports.foo = 42;
exports.default = 21;

Here we can see that the default export becomes a property on the exports object, just like foo.

I would like to suggest to you use one index.js file, where you have to export your components from lib and use them in your actual implementations.

I think following links will help you in more to resolve your problems.

Why es6 react component works only with “export default”?

Multiple React components in a single module

Hope this will help you !!


问:
C++ Declare Combo Box Identifier
just wondering how to declare a combobox identifier. I've got two comboboxes on my page so I need two identifiers to distinguish them. I enter the following code but Visual Studio 15.5 tells me that IDC_COMBOBOX_LAYER is an undeclared identifier. It's supposed to be an integer but a number like 100 won't work either.

```<code>HWND hWndComboBox = CreateWindow(WC_COMBOBOX, TEXT(""),
    CBS_DROPDOWN | CBS_HASSTRINGS | WS_CHILD | WS_OVERLAPPED | WS_VISIBLE,
    xpos, ypos, nwidth, nheight, parWnd, IDC_COMBOBOX_LAYER, NULL,
    NULL);
</code>```

I've searched Google but I'm resigned to asking you here. How do I declare the identifier?

答:
If this is not being used in a dialog resource I would suggest that you just assign a value and use it:

```<code>enum CHILD_IDs : UINT { IDC_COMBOBOX = 1 };
</code>```

If it is being used in a dialog (but not part of the template for some reason) I suggest you define it through the resource system, go to the resource explorer (ctrl+shift+e) right click on the resource file and select "resource symbols", you then have the ooption of creating a new symbol value.

Title: C++ Declare Combo Box Identifier

Body:
just wondering how to declare a combobox identifier. I've got two comboboxes on my page so I need two identifiers to distinguish them. I enter the following code but Visual Studio 15.5 tells me that IDC_COMBOBOX_LAYER is an undeclared identifier. It's supposed to be an integer but a number like 100 won't work either.

HWND hWndComboBox = CreateWindow(WC_COMBOBOX, TEXT(""),
    CBS_DROPDOWN | CBS_HASSTRINGS | WS_CHILD | WS_OVERLAPPED | WS_VISIBLE,
    xpos, ypos, nwidth, nheight, parWnd, IDC_COMBOBOX_LAYER, NULL,
    NULL);

I've searched Google but I'm resigned to asking you here. How do I declare the identifier?

Body:
If this is not being used in a dialog resource I would suggest that you just assign a value and use it:

enum CHILD_IDs : UINT { IDC_COMBOBOX = 1 };

If it is being used in a dialog (but not part of the template for some reason) I suggest you define it through the resource system, go to the resource explorer (ctrl+shift+e) right click on the resource file and select "resource symbols", you then have the ooption of creating a new symbol value.


问:
How to update an NSUserDefault
I have the following code which should update a value in NSUserDefaults:

```<code>- (id) createBoardWithTitle:(NSString *)pTitle withScores:(NSArray *)pScores andNames:(NSArray *)pNames andDisplayStrings:(NSArray *)pStrings orderBy:(NSString *)pOrder ofType:(NSString *)pType
{

    if((self == [super init]))
    {

        boardEntries = [NSMutableArray arrayWithCapacity:10];

        // Build the data

            for(...){
               // populate boardEntries
            }

        // create an Dictionary to save
        NSDictionary *savedData = [NSDictionary dictionaryWithObjectsAndKeys:pType, @"type", pOrder, @"order", boardEntries, @"entries", nil];

            // Load the old boards
        NSDictionary *existingBoards = [[NSUserDefaults standardUserDefaults] objectForKey:@"BlockDepotLeaderboards"];

            // Create a mutable dictionary to replace the old immutable dictionary
        NSMutableDictionary *newBoards = [NSMutableDictionary dictionaryWithCapacity:[existingBoards count]+1];

            // transfer the old dictionary into the new dictionary
        [newBoards addEntriesFromDictionary:existingBoards];

            // add the new board to the new dictionary
        [newBoards setObject:savedData forKey:pTitle];

            // check to make sure it looks like it should by eye
        NSLog(@"New Boards: %@", newBoards);

            // Replace the old date in NSUserdefaults
        [[NSUserDefaults standardUserDefaults] setObject:newBoards forKey:@"BlockDepotleaderboards"];
            // Update: Do I really need to call this?
        [[NSUserDefaults standardUserDefaults] synchronize];

            // Check to make sure it looks as it should by eye
        NSLog(@" Defaults--- %@", [[NSUserDefaults standardUserDefaults] objectForKey:@"BlockDepotLeaderboards"]);
    }

    return self;

}
</code>```

As far as I can tell, that's the pertinent code. It's probably "wordier" than it needs to be perhaps. But as I understand it, anything returned from NSUserDefaults will be immutable, so I have to recreate it as a Mutable object, add what needs adding then replace the object in NSUserDefaults. And I think what I'm trying above should work.

the output for NSLog(@"New Boards: %@", newBoards) id

```<code>New Boards: {
    "Marathon: Times" =     {
        entries =         (
                        {
                displayString = "10:00";
                name = "Tom Elders";
                score = 600;
            },
                        {
                displayString = "10:30";
                name = "A.R. Elders";
                score = 630;
            },
                        {
                displayString = "11:00";
                name = "L. Lancaster-Harm";
                score = 660;
            },

            // and so on.....

        );
        order = ASC;
        type = TIMES;
    };
    String = Test;
}
</code>```

"String = test" is just a test entry and is set in the AppDelegate.m file like this:

```<code>if(![[NSUserDefaults standardUserDefaults] objectForKey:@"BlockDepotLeaderboards"]){

    NSMutableDictionary *leadboardHolder = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"Test", @"String", nil];
    [[NSUserDefaults standardUserDefaults] setObject:leadboardHolder forKey:@"BlockDepotLeaderboards"];
    [[NSUserDefaults standardUserDefaults] synchronize];

}else{
    NSLog(@"Leaderboards Dict Exists %@", [NSUserDefaults standardUserDefaults]);
}
</code>```

So I know that what I'm after is definitely there. I just know this is going to be something stupid that I'm missing. But I can't see it or figure it out.

Can anyone see what I'm messing up?

答:
At first save anything:

```<code>[[NSUserDefaults standardUserDefaults] setObject:@"Previous Value" forKey:@"Name"];
</code>```

Then run this code again to update value of the same key:

```<code>[[NSUserDefaults standardUserDefaults] setObject:@"Updated Value" forKey:@"Name"];
</code>```

you dont need to call [[NSUserDefaults standardUserDefaults]
  synchronize] due to performance issue.call it only it required. iOS
  manages it well.

You dont need to remove object. Just update the same key. It will update the Value of that particular key.
Hope this helps.

Title: How to update an NSUserDefault

Body:
I have the following code which should update a value in NSUserDefaults:

- (id) createBoardWithTitle:(NSString *)pTitle withScores:(NSArray *)pScores andNames:(NSArray *)pNames andDisplayStrings:(NSArray *)pStrings orderBy:(NSString *)pOrder ofType:(NSString *)pType
{

    if((self == [super init]))
    {

        boardEntries = [NSMutableArray arrayWithCapacity:10];

        // Build the data

            for(...){
               // populate boardEntries
            }

        // create an Dictionary to save
        NSDictionary *savedData = [NSDictionary dictionaryWithObjectsAndKeys:pType, @"type", pOrder, @"order", boardEntries, @"entries", nil];

            // Load the old boards
        NSDictionary *existingBoards = [[NSUserDefaults standardUserDefaults] objectForKey:@"BlockDepotLeaderboards"];

            // Create a mutable dictionary to replace the old immutable dictionary
        NSMutableDictionary *newBoards = [NSMutableDictionary dictionaryWithCapacity:[existingBoards count]+1];

            // transfer the old dictionary into the new dictionary
        [newBoards addEntriesFromDictionary:existingBoards];

            // add the new board to the new dictionary
        [newBoards setObject:savedData forKey:pTitle];

            // check to make sure it looks like it should by eye
        NSLog(@"New Boards: %@", newBoards);

            // Replace the old date in NSUserdefaults
        [[NSUserDefaults standardUserDefaults] setObject:newBoards forKey:@"BlockDepotleaderboards"];
            // Update: Do I really need to call this?
        [[NSUserDefaults standardUserDefaults] synchronize];

            // Check to make sure it looks as it should by eye
        NSLog(@" Defaults--- %@", [[NSUserDefaults standardUserDefaults] objectForKey:@"BlockDepotLeaderboards"]);
    }

    return self;

}

As far as I can tell, that's the pertinent code. It's probably "wordier" than it needs to be perhaps. But as I understand it, anything returned from NSUserDefaults will be immutable, so I have to recreate it as a Mutable object, add what needs adding then replace the object in NSUserDefaults. And I think what I'm trying above should work.

the output for NSLog(@"New Boards: %@", newBoards) id

New Boards: {
    "Marathon: Times" =     {
        entries =         (
                        {
                displayString = "10:00";
                name = "Tom Elders";
                score = 600;
            },
                        {
                displayString = "10:30";
                name = "A.R. Elders";
                score = 630;
            },
                        {
                displayString = "11:00";
                name = "L. Lancaster-Harm";
                score = 660;
            },

            // and so on.....

        );
        order = ASC;
        type = TIMES;
    };
    String = Test;
}

"String = test" is just a test entry and is set in the AppDelegate.m file like this:

if(![[NSUserDefaults standardUserDefaults] objectForKey:@"BlockDepotLeaderboards"]){

    NSMutableDictionary *leadboardHolder = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"Test", @"String", nil];
    [[NSUserDefaults standardUserDefaults] setObject:leadboardHolder forKey:@"BlockDepotLeaderboards"];
    [[NSUserDefaults standardUserDefaults] synchronize];

}else{
    NSLog(@"Leaderboards Dict Exists %@", [NSUserDefaults standardUserDefaults]);
}

So I know that what I'm after is definitely there. I just know this is going to be something stupid that I'm missing. But I can't see it or figure it out.

Can anyone see what I'm messing up?

Body:
At first save anything:

[[NSUserDefaults standardUserDefaults] setObject:@"Previous Value" forKey:@"Name"];

Then run this code again to update value of the same key:

[[NSUserDefaults standardUserDefaults] setObject:@"Updated Value" forKey:@"Name"];

you dont need to call [[NSUserDefaults standardUserDefaults]
  synchronize] due to performance issue.call it only it required. iOS
  manages it well.

You dont need to remove object. Just update the same key. It will update the Value of that particular key.
Hope this helps.


问:
How to create an animation showing an array of ordered numbers with number line?
I have an array var1 of 94 numbers. I want them to be shown in a gif with defined interval (e.g. 0.05 seconds). If possible, I also want to add an number line. I expect to see a picture like this (animated, of course):

========================================================

COV1 = 2.34

----------|-------------------------------------> cov1

_____2.34

========================================================

I just succeeded in using the gganimate package for some plots but then I realized I also needed to animate something that are not plots... Maybe something related to the animation package?

Thanks!

答:
It doesn't seem particularly enlightening (in fact it gives me a headache to look at it), but it's animated.

```<code>library(tidyverse)
library(gganimate)

set.seed(10)
dat = data.frame(x=sort(runif(94, 0, 100)))

p = ggplot(dat) +
  geom_line(data=data.frame(y=rep(c(0.90,0.905,1.095,1.1),each=2), x=rep(range(dat$x), 4)),
            aes(x,y,group=y), size=1, colour="grey40", linetype=2) +
  geom_line(aes(x,y=1), colour="grey60", size=1.5, linetype="11") +
  geom_text(aes(label=paste0("COV1\n", round(x,2)), x=x, y=1.05, frame=x), size=5) +
  geom_segment(aes(x=min(dat$x), xend=x, y=1, yend=1, frame=x),
               arrow=arrow(angle=90, length=unit(0.4, "cm")), size=1.5) +
  scale_y_continuous(limits=c(0.8,1.1)) +
  theme_void() +
  theme(plot.title=element_blank())

gganimate(p, filename="my_gif.gif", interval=0.05)
</code>```

Body:
It doesn't seem particularly enlightening (in fact it gives me a headache to look at it), but it's animated.

library(tidyverse)
library(gganimate)

set.seed(10)
dat = data.frame(x=sort(runif(94, 0, 100)))

p = ggplot(dat) +
  geom_line(data=data.frame(y=rep(c(0.90,0.905,1.095,1.1),each=2), x=rep(range(dat$x), 4)),
            aes(x,y,group=y), size=1, colour="grey40", linetype=2) +
  geom_line(aes(x,y=1), colour="grey60", size=1.5, linetype="11") +
  geom_text(aes(label=paste0("COV1\n", round(x,2)), x=x, y=1.05, frame=x), size=5) +
  geom_segment(aes(x=min(dat$x), xend=x, y=1, yend=1, frame=x),
               arrow=arrow(angle=90, length=unit(0.4, "cm")), size=1.5) +
  scale_y_continuous(limits=c(0.8,1.1)) +
  theme_void() +
  theme(plot.title=element_blank())

gganimate(p, filename="my_gif.gif", interval=0.05)


问:
Building an incremental list of revisions in a git branch
I want to build a list of all revisions that are in a branch (due to having to regularly check things against them). So basically, this is a cache of revisions that branch has. Due to the massive size of the branch, it'd be ideal to incrementally update the cache with only the new commits since the last time we updated the cache. This works well since I incidentally have a way to know when a branch is "dirty".

I can fetch all revisions in chronological order (oldest first) with git rev-list --reverse my-branch. It gets me a nice and easy list of revisions that I can fill into my cache. I then seem to be able to find the new commits since  with git rev-list --reverse my-branch ^<revision>.

Thing is, I note that if I then run my first command (git rev-list --reverse my-branch) again, I get a different result. The same commits seem to be there, but the order is different. Which makes me wonder if my approach described in the paragraph above is really sufficient. I don't actually care about order; I just want a complete set of revisions in that branch. The only thing I require order for is to know what commit is the last one I had (so I can fill in the <revision> in my second command). I make the assumption that the last commit in the previous list is the most recent.

(I actually ask this in part because I've used such a system for a while, but now I have revisions missing in the cache and wonder if my method of building such a cache is insufficient.)

答:
The main issue is defining the phrase revisions in that branch.

Depending on how your branch grows, it may suffice to use git rev-list --topo-order --reverse ^stop start to get a list of commits that are reachable from the name or hash-ID or other starting point start, but not reachable from the name or hash-ID or other starting-point stop.  Then, having done that, you can update the saved hash ID to the hash ID you gave as, or obtained from, start.

Long description

Many people like to imagine Git branches working something like this graphic:

```<code>master:  A--B--C
                \
develop:         D--E
</code>```

Here there are five commits in the repository, and they think of the first three commits—we label commits A through Z rather than by big, ugly, incomprehensible hash IDs here—as "belonging to" branch master, with commits D and E "belonging to" branch develop.

But that's not how Git branches actually work.  The commits do have internal arrows connecting them, but these arrows are all backwards.  They start at the right and work left.  These internal arrows come out of each commit and point back to the commit's parent (or for a merge commit, two or even more parents).  In fact, rather than arrows, each commit stores the raw hash ID of its parent (or parents, in case of merge commits).  The pointers are thus attached to the children—or more accurately, embedded within them and a permanent and unchangeable part of their identity.

(The actual raw hash ID of each commit is determined by computing a cryptographic hash of the contents of the commit, including the spelled-out parent hash or hashes.  This is what makes it impossible to change anything about any commit, ever: if you change even a single bit, the result is a new, different hash, for a new, different commit.)

Meanwhile, names like master and develop serve as moveable arrows, pointing to one specific commit.  So the drawing really should look like this:

```<code>A--B--C   <-- master
       \
        D--E   <-- develop
</code>```

The name master points to commit C, and the name develop points to commit E.  Commit E points back to D; D points back to C; C points to B; and B points to A.  Since commit A is the very first commit ever made, there's nowhere for it to point—so it doesn't, which makes it a root commit.

In the end, this means that all the commits (in this five-commit repository) are on develop; three of those are also on master.

How branches grow, part 1

Now, the typical process for adding commits to a branch is:

```<code>git checkout <name>
... do some work ...
git add -u   # or similar, to copy new versions back into Git's index
git commit
</code>```

The first step, git checkout name, extracts the contents of the commit to which the given branch name name points.  These contents go into Git's index, and also into your work-tree.  Git then sets the name HEAD to record the name name.  (Let's say name is develop and we're in this five-commit repository.)

You now do your work as usual, then use git add to copy updated files back into the index.  Many people think the index is empty until git add-ing to it, but that's not the case either.  (Git's --allow-empty flag is rather misleading.  It's not whether the index itself is empty, but rather whether the diff from HEAD to the index is empty.)

The index is a complicated beastie, and hard to see directly, but the best short description is that it's where you build up the next commit to make.  It starts out with all the same files as the work-tree (but in Git-ized internal form), matching the HEAD commit you just checked out.  You alter these internal-form copies by using git add to copy new versions from the work-tree.  The git commit command then packages up the index contents as a new source snapshot, collects a commit message from you, and writes out a new commit that has:

the snapshot made from the index (technically a tree line);

your name and email address as author and committer, and "now" as the time-stamps for these two items;

the current commit's hash ID as the new commit's parent; and

your commit message as the new commit's message.

You can see these by running git cat-file -p HEAD (try it!).

Having written this out, there is now a sixth commit:

```<code>A--B--C   <-- master
       \
        D--E   <-- develop (HEAD)
            \
             F
</code>```

The new commit points back to the current commit.  The final step in making this commit appear on the branch is to move the branch pointer, by writing the new commit's hash ID into the branch whose name is stored in HEAD.  Since that's develop, the result is:

```<code>A--B--C   <-- master
       \
        D--E
            \
             F   <-- develop (HEAD)
</code>```

(and now there's no reason to put F on a separate line from E; I just kept it that way to make it more obvious what's happening).

How branches grow, part 2

Now, branches need not grow so simply.  For instance, suppose we have our six commits A through F so far.  We then run git checkout master and create a new commit:

```<code>A--B--C------G   <-- master (HEAD)
       \
        D--E--F   <-- develop
</code>```

and then, having done that, we run git merge develop.

Git will now compare commit C (the merge base of the two branches) to both tip commits—HEAD names commit G and develop names commit F, so Git runs git diff --find-renames C G to see what we did, and git diff --find-renames C F to see what they (whoever they are) did on develop.

Git now combines these two sets of changes and applies the combined changes to commit C.  If all goes well—if the changes don't seem to conflict, at least as far as Git is smart, which is not very far at all—Git will make a new commit from the result.  This new commit has not one but two parents, and we can draw it like this:

```<code>A--B--C------G--H   <-- master (HEAD)
       \       /
        D--E--F   <-- develop
</code>```

At this point, suddenly commits D-E-F are all on master.  They are reachable from commit H, to which the name master points.

This is the first secret to git log and git rev-list

Both git log and git rev-list work by finding some starting point—some first (or last, really) commit, usually the tip of some branch.  You can specify any one particular commit, by giving a branch name, or by its raw hash ID, or by any of a huge number of other special syntaxes1 (these are listed in the gitrevisions documentation), as a starting point, and the command will use that commit to find a parent commit, and the use the parent to find another parent, and so on.

The git log command defaults to looking at HEAD, while git rev-list, which is aimed at scripts, has no default: you must explicitly name HEAD if that's what you want.  In this case, if we start the commands with commit H, they will look at H (printing out its hash ID and perhaps some other information about it), then look at its parent.

But commit H has two parents, not just one.  So git log or git rev-list will now look at both commits, G and F, "simultaneously".

They can't actually show you both simultaneously, so they linearize the listing.  The exact linearization method depends on the sorting options you specify.  The default, whenever there is more than one commit in the queue to be shown, is to show whichever commit has the latest committer date, but if you specify --topo-order, the command will be sure not to interleave two different sub-branches: if it goes next to commit F, it will go all the way down to D before showing G.

(You might wonder how Git could pick F next instead of G.  Well, we're assuming for the moment that G was made later, so it wouldn't—but what if the computer clock was wrong when we made one of them?  Or what if G was made first, and we've just labeled it weirdly?)

Since every commit is reachable from H (by starting there and working backwards along both forks), git log will show every commit, by default.  To make it stop early, you can specify a stopping point: it will avoid showing that commit and any commit reachable from that commit, in the same fashion.  So if we tell it not to show commit E, it won't show E, nor will it show D, nor any of C or B or A either.  This won't stop it from showing G though: G is not reachable from E.  Reachability requires going backwards, through the backwards links that Git stores.

Adding --reverse simply tells the command to output the final list in reverse order (which, since the natural order is already backwards, reverses the backwards-ness into forwards-ness).  Git still has to generate the list backwards, though: there is no easy way to go from a commit to its children.  Commits know all their parents, but no commit knows any of its children.

1Not "syntagma", although I like that word, which is a real word.

Sometimes, branches are updated violently / forcefully

We can have all this perfectly normal, natural, one commit at a time growth, or even this sudden "name acquires a lot of new reachable commits along with all the ones it had earlier" from merging (or what Git calls fast forwarding), but we can also have wrenching changes.

Suppose, for instance, after merging develop into master, we remove develop entirely:

```<code>A--B--C------G--H   <-- master (HEAD)
       \       /
        D--E--F
</code>```

None of the commits go away at all, because they are all find-able (reachable) from master.  But now we can make a new develop, unrelated to the old one.  Let's arbitrarily start it at commit G:

```<code>              G   <-- develop
             / \
A--B--C-----'   H   <-- master (HEAD)
       \       /
        D--E--F
</code>```

and add a new commit:

```<code>              G--I   <-- develop
             / \
A--B--C-----'   H   <-- master (HEAD)
       \       /
        D--E--F
</code>```

and maybe relax our drawing a bit:

```<code>A--B--C   <-- master
       \
        D--E   <-- develop
</code>```0

If we start from this new develop and work backwards, then reverse the list to go forwards, we get commits A--B--C--G--I.  Commits D--E--F are no longer in the list at all!

More commonly, but still rather wrenching, we can have "force push" events that deliberately discard commits across a push from one repository to another, or git reset events that discard commits within a repository.  In these cases, an old stop-point may become invalid, or at least, not very useful.  It's up to whoever is defining what it means to select commits that are "on a branch" to determine what to do here.

First parents

In all cases, it's worth thinking about merges, which bring many commits into reachability all at once, and what that means for your task.  There's a very important feature of git merge, though, that can be helpful, provided that everyone who runs git merge does so in a properly disciplined manner.  This is the first parent notion.

When we did our merge that created commit H, above, we were on the branch named master (the name HEAD contained ref: refs/heads/master, and git status said on branch master).  So Git makes sure that the first parent of commit H is commit G, and the second parent of commit H is commit F—the commit to which the name develop pointed, at that time.

If we use this first parent notion, we can follow from commit H back to commit G without having Git follow H back to F as well.  Then G leads back to C, which leads cleanly to A; so our reversed list will be A--B--C--G--H, excluding the merged-in D--E--F entirely.

To get this behavior, simply add --first-parent to your git rev-list or git log command.  But note that it depends on this: whoever did the merge, that brought in commit F and hence the whole D--E--F chain, must have done it properly.  If users carelessly use git pull,2 they will create what some call foxtrot merges, which put the main line commits in as the second parent instead of the first.

2(in Zathras voice) git pull ... is wrong tool. ... Never use this.

Body:
The main issue is defining the phrase revisions in that branch.

Depending on how your branch grows, it may suffice to use git rev-list --topo-order --reverse ^stop start to get a list of commits that are reachable from the name or hash-ID or other starting point start, but not reachable from the name or hash-ID or other starting-point stop.  Then, having done that, you can update the saved hash ID to the hash ID you gave as, or obtained from, start.

Long description

Many people like to imagine Git branches working something like this graphic:

master:  A--B--C
                \
develop:         D--E

Here there are five commits in the repository, and they think of the first three commits—we label commits A through Z rather than by big, ugly, incomprehensible hash IDs here—as "belonging to" branch master, with commits D and E "belonging to" branch develop.

But that's not how Git branches actually work.  The commits do have internal arrows connecting them, but these arrows are all backwards.  They start at the right and work left.  These internal arrows come out of each commit and point back to the commit's parent (or for a merge commit, two or even more parents).  In fact, rather than arrows, each commit stores the raw hash ID of its parent (or parents, in case of merge commits).  The pointers are thus attached to the children—or more accurately, embedded within them and a permanent and unchangeable part of their identity.

(The actual raw hash ID of each commit is determined by computing a cryptographic hash of the contents of the commit, including the spelled-out parent hash or hashes.  This is what makes it impossible to change anything about any commit, ever: if you change even a single bit, the result is a new, different hash, for a new, different commit.)

Meanwhile, names like master and develop serve as moveable arrows, pointing to one specific commit.  So the drawing really should look like this:

A--B--C   <-- master
       \
        D--E   <-- develop

The name master points to commit C, and the name develop points to commit E.  Commit E points back to D; D points back to C; C points to B; and B points to A.  Since commit A is the very first commit ever made, there's nowhere for it to point—so it doesn't, which makes it a root commit.

In the end, this means that all the commits (in this five-commit repository) are on develop; three of those are also on master.

How branches grow, part 1

Now, the typical process for adding commits to a branch is:

git checkout <name>
... do some work ...
git add -u   # or similar, to copy new versions back into Git's index
git commit

The first step, git checkout name, extracts the contents of the commit to which the given branch name name points.  These contents go into Git's index, and also into your work-tree.  Git then sets the name HEAD to record the name name.  (Let's say name is develop and we're in this five-commit repository.)

You now do your work as usual, then use git add to copy updated files back into the index.  Many people think the index is empty until git add-ing to it, but that's not the case either.  (Git's --allow-empty flag is rather misleading.  It's not whether the index itself is empty, but rather whether the diff from HEAD to the index is empty.)

The index is a complicated beastie, and hard to see directly, but the best short description is that it's where you build up the next commit to make.  It starts out with all the same files as the work-tree (but in Git-ized internal form), matching the HEAD commit you just checked out.  You alter these internal-form copies by using git add to copy new versions from the work-tree.  The git commit command then packages up the index contents as a new source snapshot, collects a commit message from you, and writes out a new commit that has:

the snapshot made from the index (technically a tree line);

your name and email address as author and committer, and "now" as the time-stamps for these two items;

the current commit's hash ID as the new commit's parent; and

your commit message as the new commit's message.

You can see these by running git cat-file -p HEAD (try it!).

Having written this out, there is now a sixth commit:

A--B--C   <-- master
       \
        D--E   <-- develop (HEAD)
            \
             F

The new commit points back to the current commit.  The final step in making this commit appear on the branch is to move the branch pointer, by writing the new commit's hash ID into the branch whose name is stored in HEAD.  Since that's develop, the result is:

A--B--C   <-- master
       \
        D--E
            \
             F   <-- develop (HEAD)

(and now there's no reason to put F on a separate line from E; I just kept it that way to make it more obvious what's happening).

How branches grow, part 2

Now, branches need not grow so simply.  For instance, suppose we have our six commits A through F so far.  We then run git checkout master and create a new commit:

A--B--C------G   <-- master (HEAD)
       \
        D--E--F   <-- develop

and then, having done that, we run git merge develop.

Git will now compare commit C (the merge base of the two branches) to both tip commits—HEAD names commit G and develop names commit F, so Git runs git diff --find-renames C G to see what we did, and git diff --find-renames C F to see what they (whoever they are) did on develop.

Git now combines these two sets of changes and applies the combined changes to commit C.  If all goes well—if the changes don't seem to conflict, at least as far as Git is smart, which is not very far at all—Git will make a new commit from the result.  This new commit has not one but two parents, and we can draw it like this:

A--B--C------G--H   <-- master (HEAD)
       \       /
        D--E--F   <-- develop

At this point, suddenly commits D-E-F are all on master.  They are reachable from commit H, to which the name master points.

This is the first secret to git log and git rev-list

Both git log and git rev-list work by finding some starting point—some first (or last, really) commit, usually the tip of some branch.  You can specify any one particular commit, by giving a branch name, or by its raw hash ID, or by any of a huge number of other special syntaxes1 (these are listed in the gitrevisions documentation), as a starting point, and the command will use that commit to find a parent commit, and the use the parent to find another parent, and so on.

The git log command defaults to looking at HEAD, while git rev-list, which is aimed at scripts, has no default: you must explicitly name HEAD if that's what you want.  In this case, if we start the commands with commit H, they will look at H (printing out its hash ID and perhaps some other information about it), then look at its parent.

But commit H has two parents, not just one.  So git log or git rev-list will now look at both commits, G and F, "simultaneously".

They can't actually show you both simultaneously, so they linearize the listing.  The exact linearization method depends on the sorting options you specify.  The default, whenever there is more than one commit in the queue to be shown, is to show whichever commit has the latest committer date, but if you specify --topo-order, the command will be sure not to interleave two different sub-branches: if it goes next to commit F, it will go all the way down to D before showing G.

(You might wonder how Git could pick F next instead of G.  Well, we're assuming for the moment that G was made later, so it wouldn't—but what if the computer clock was wrong when we made one of them?  Or what if G was made first, and we've just labeled it weirdly?)

Since every commit is reachable from H (by starting there and working backwards along both forks), git log will show every commit, by default.  To make it stop early, you can specify a stopping point: it will avoid showing that commit and any commit reachable from that commit, in the same fashion.  So if we tell it not to show commit E, it won't show E, nor will it show D, nor any of C or B or A either.  This won't stop it from showing G though: G is not reachable from E.  Reachability requires going backwards, through the backwards links that Git stores.

Adding --reverse simply tells the command to output the final list in reverse order (which, since the natural order is already backwards, reverses the backwards-ness into forwards-ness).  Git still has to generate the list backwards, though: there is no easy way to go from a commit to its children.  Commits know all their parents, but no commit knows any of its children.

1Not "syntagma", although I like that word, which is a real word.

Sometimes, branches are updated violently / forcefully

We can have all this perfectly normal, natural, one commit at a time growth, or even this sudden "name acquires a lot of new reachable commits along with all the ones it had earlier" from merging (or what Git calls fast forwarding), but we can also have wrenching changes.

Suppose, for instance, after merging develop into master, we remove develop entirely:

A--B--C------G--H   <-- master (HEAD)
       \       /
        D--E--F

None of the commits go away at all, because they are all find-able (reachable) from master.  But now we can make a new develop, unrelated to the old one.  Let's arbitrarily start it at commit G:

              G   <-- develop
             / \
A--B--C-----'   H   <-- master (HEAD)
       \       /
        D--E--F

and add a new commit:

              G--I   <-- develop
             / \
A--B--C-----'   H   <-- master (HEAD)
       \       /
        D--E--F

and maybe relax our drawing a bit:

               I   <-- develop
              /
A--B--C------G--H   <-- master (HEAD)
       \       /
        D--E--F

If we start from this new develop and work backwards, then reverse the list to go forwards, we get commits A--B--C--G--I.  Commits D--E--F are no longer in the list at all!

More commonly, but still rather wrenching, we can have "force push" events that deliberately discard commits across a push from one repository to another, or git reset events that discard commits within a repository.  In these cases, an old stop-point may become invalid, or at least, not very useful.  It's up to whoever is defining what it means to select commits that are "on a branch" to determine what to do here.

First parents

In all cases, it's worth thinking about merges, which bring many commits into reachability all at once, and what that means for your task.  There's a very important feature of git merge, though, that can be helpful, provided that everyone who runs git merge does so in a properly disciplined manner.  This is the first parent notion.

When we did our merge that created commit H, above, we were on the branch named master (the name HEAD contained ref: refs/heads/master, and git status said on branch master).  So Git makes sure that the first parent of commit H is commit G, and the second parent of commit H is commit F—the commit to which the name develop pointed, at that time.

If we use this first parent notion, we can follow from commit H back to commit G without having Git follow H back to F as well.  Then G leads back to C, which leads cleanly to A; so our reversed list will be A--B--C--G--H, excluding the merged-in D--E--F entirely.

To get this behavior, simply add --first-parent to your git rev-list or git log command.  But note that it depends on this: whoever did the merge, that brought in commit F and hence the whole D--E--F chain, must have done it properly.  If users carelessly use git pull,2 they will create what some call foxtrot merges, which put the main line commits in as the second parent instead of the first.

2(in Zathras voice) git pull ... is wrong tool. ... Never use this.


问:
How to set default values in Entity Framework 6 (Database First)
Background: I’m beginning a project to convert a web application using Linq2Sql to use Entity Framework (v6) instead. I have a lot of experience with L2S, but I’m brand-new to EF. Since our application and its database already exist, we’re using the “Database First” approach. Also, the database is evolving, so we’re making changes in the schema and the model is updated from the revised database, which regenerates code for the EF model each time.

For many of our entities (database tables), we set default values in our code whenever an entity is constructed. In Linq2Sql it’s easy: define a partial class for the entity, and add a method to the class like this:

partial void OnCreated() { SomeProperty = SomeDefaultValue; }

Whenever Linq2Sql constructs a new entity object, it calls the OnCreated() method you define, and the default values are set as desired. It works great.

The Problem: In EF, I don’t see a way to do this in a Database First scenario.

If I modify the model code generated by EF, the model code is overwritten whenever we update the model after a database revision.

If I define a partial class for the entity in a separate file and define a constructor, the compiler complains that the constructor is already defined.

There doesn’t seem to be any support for something like L2S's OnCreated() method, either.

Any suggestions?

EDIT: Thanks everyone for the helpful comments, but I think I need to point out an important consideration: My goal is to use the database-first approach and stick with it, rather than switching to code-first. When the database schema changes over time I want the EF Designer (or POCO Generator or whatever tools) to update my EF entity classes to match. All without losing my additions to initialize class properties when the class is constructed in the application. This is easy in Linq2Sql, but I just don’t see a way to accomplish this in EF database-first. All suggestions are welcome!

答:
1 . Open .edmx file

2 . Select the field that has the default value and go to the properties

3 . then select StoreGeneratedPattern

4 . then change the value to Computed

i think it's worked.