问:
how to get the path of selected PDF/doc from file manager in android programmatically
I have written this code to open my Document manager and select any PDF/Doc file.

```<code>Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
            intent.addCategory(Intent.CATEGORY_OPENABLE);
            intent.setType("*/*");
            Intent i = Intent.createChooser(intent, "File");
            startActivityForResult(i, 1);
</code>```

When I select any Pdf/Doc file I am unable to get path of that select file.

I tried this code also but it give me null as output

```<code>protected void onActivityResult(int requestCode, int resultCode,
        Intent intent) {
    if (requestCode == 1) {
        if (resultCode == RESULT_OK) {
            Uri uri = intent.getData();
            String fileImagePath = getRealPathFromURI(uri);
            String type = intent.getType();

            Log.d("Hello", fileImagePath + "");
            if (uri != null) {
                String path = uri.toString();
                if (path.toLowerCase().startsWith("file://")) {
                    // Selected file/directory path is below
                    path = (new File(URI.create(path))).getAbsolutePath();
                    Log.d("Hel", path);
                }

            }
        } else
            Log.d("Hello", "Back from pick with cancel status");
    }
}

public String getRealPathFromURI(Uri uri) {
    String[] projection = { MediaStore.Files.FileColumns.DATA };
    Cursor cursor = managedQuery(uri, projection, null, null, null);
    int column_index = cursor
            .getColumnIndexOrThrow(MediaStore.Files.FileColumns.DATA );
    cursor.moveToFirst();
    return cursor.getString(column_index);
}
</code>```

Please help me thanks in advance.

答:
Please use below code for any sort of file :</p>

```<code>/*
 * Copyright (C) 2007-2008 OpenIntents.org
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.yourpackage;

import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.util.Log;
import android.webkit.MimeTypeMap;

import java.io.File;
import java.io.FileFilter;
import java.text.DecimalFormat;
import java.util.Comparator;
import java.util.List;

/**
 * @author Peli
 * @author paulburke (ipaulpro)
 * @version 2013-12-11
 */
public class FileUtils {
    private FileUtils() {
    } //private constructor to enforce Singleton pattern

    /**
     * TAG for log messages.
     */
    static final String TAG = "FileUtils";
    private static final boolean DEBUG = true; // Set to true to enable logging

    public static final String MIME_TYPE_AUDIO = "audio/*";
    public static final String MIME_TYPE_TEXT = "text/*";
    public static final String MIME_TYPE_IMAGE = "image/*";
    public static final String MIME_TYPE_VIDEO = "video/*";
    public static final String MIME_TYPE_APP = "application/*";

    public static final String HIDDEN_PREFIX = ".";

    /**
     * Gets the extension of a file name, like ".png" or ".jpg".
     *
     * @param uri
     * @return Extension including the dot("."); "" if there is no extension;
     * null if uri was null.
     */
    public static String getExtension(String uri) {
        if (uri == null) {
            return null;
        }

        int dot = uri.lastIndexOf(".");
        if (dot >= 0) {
            return uri.substring(dot);
        } else {
            // No extension.
            return "";
        }
    }

    /**
     * @return Whether the URI is a local one.
     */
    public static boolean isLocal(String url) {
        if (url != null && !url.startsWith("http://") && !url.startsWith("https://")) {
            return true;
        }
        return false;
    }

    /**
     * @return True if Uri is a MediaStore Uri.
     * @author paulburke
     */
    public static boolean isMediaUri(Uri uri) {
        return "media".equalsIgnoreCase(uri.getAuthority());
    }

    /**
     * Convert File into Uri.
     *
     * @param file
     * @return uri
     */
    public static Uri getUri(File file) {
        if (file != null) {
            return Uri.fromFile(file);
        }
        return null;
    }

    /**
     * Returns the path only (without file name).
     *
     * @param file
     * @return
     */
    public static File getPathWithoutFilename(File file) {
        if (file != null) {
            if (file.isDirectory()) {
                // no file to be split off. Return everything
                return file;
            } else {
                String filename = file.getName();
                String filepath = file.getAbsolutePath();

                // Construct path without file name.
                String pathwithoutname = filepath.substring(0,
                        filepath.length() - filename.length());
                if (pathwithoutname.endsWith("/")) {
                    pathwithoutname = pathwithoutname.substring(0, pathwithoutname.length() - 1);
                }
                return new File(pathwithoutname);
            }
        }
        return null;
    }

    /**
     * @return The MIME type for the given file.
     */
    public static String getMimeType(File file) {

        String extension = getExtension(file.getName());

        if (extension.length() > 0)
            return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension.substring(1));

        return "application/octet-stream";
    }

    /**
     * @return The MIME type for the give Uri.
     */
    public static String getMimeType(Context context, Uri uri) {
        File file = new File(getPath(context, uri));
        return getMimeType(file);
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is {@link LocalStorageProvider}.
     * @author paulburke
     */
    public static boolean isLocalStorageDocument(Uri uri) {
        return LocalStorageProvider.AUTHORITY.equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is ExternalStorageProvider.
     * @author paulburke
     */
    public static boolean isExternalStorageDocument(Uri uri) {
        return "com.android.externalstorage.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is DownloadsProvider.
     * @author paulburke
     */
    public static boolean isDownloadsDocument(Uri uri) {
        return "com.android.providers.downloads.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is MediaProvider.
     * @author paulburke
     */
    public static boolean isMediaDocument(Uri uri) {
        return "com.android.providers.media.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is Google Photos.
     */
    public static boolean isGooglePhotosUri(Uri uri) {
        return "com.google.android.apps.photos.content".equals(uri.getAuthority());
    }

    /**
     * Get the value of the data column for this Uri. This is useful for
     * MediaStore Uris, and other file-based ContentProviders.
     *
     * @param context       The context.
     * @param uri           The Uri to query.
     * @param selection     (Optional) Filter used in the query.
     * @param selectionArgs (Optional) Selection arguments used in the query.
     * @return The value of the _data column, which is typically a file path.
     * @author paulburke
     */
    public static String getDataColumn(Context context, Uri uri, String selection,
                                       String[] selectionArgs) {

        Cursor cursor = null;
        final String column = "_data";
        final String[] projection = {
                column
        };

        try {
            cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
                    null);
            if (cursor != null && cursor.moveToFirst()) {
                if (DEBUG)
                    DatabaseUtils.dumpCursor(cursor);

                final int column_index = cursor.getColumnIndexOrThrow(column);
                return cursor.getString(column_index);
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if (cursor != null)
                cursor.close();
        }
        return null;
    }

    /**
     * Get a file path from a Uri. This will quickGet the the path for Storage Access
     * Framework Documents, as well as the _data field for the MediaStore and
     * other file-based ContentProviders.<br>
     * <br>
     * Callers should check whether the path is local before assuming it
     * represents a local file.
     *
     * @param context The context.
     * @param uri     The Uri to query.
     * @author paulburke
     * @see #isLocal(String)
     * @see #getFile(Context, Uri)
     */
    public static String getPath(final Context context, final Uri uri) {

        if (DEBUG)
            Log.d(TAG + " File -",
                    "Authority: " + uri.getAuthority() +
                            ", Fragment: " + uri.getFragment() +
                            ", Port: " + uri.getPort() +
                            ", Query: " + uri.getQuery() +
                            ", Scheme: " + uri.getScheme() +
                            ", Host: " + uri.getHost() +
                            ", Segments: " + uri.getPathSegments().toString()
            );
        // DocumentProvider
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && DocumentsContract.isDocumentUri(context, uri)) {
            // LocalStorageProvider
            if (isLocalStorageDocument(uri)) {
                // The path is the id
                return DocumentsContract.getDocumentId(uri);
            }
            // ExternalStorageProvider
            else if (isExternalStorageDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

//                if ("primary".equalsIgnoreCase(type)) {
//                    return Environment.getExternalStorageDirectory() + "/" + split[1];
//                }
                return Environment.getExternalStorageDirectory() + "/" + split[1];

                // TODO handle non-primary volumes
            }
            // DownloadsProvider
            else if (isDownloadsDocument(uri)) {
                try {
                    final String id = DocumentsContract.getDocumentId(uri);
                    Log.d(TAG, "getPath: id= " + id);
                    final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
                    return getDataColumn(context, contentUri, null, null);
                }catch (Exception e){
                    e.printStackTrace();
                    List<String> segments = uri.getPathSegments();
                    if(segments.size() > 1) {
                        String rawPath = segments.get(1);
                        if(!rawPath.startsWith("/")){
                            return rawPath.substring(rawPath.indexOf("/"));
                        }else {
                            return rawPath;
                        }
                    }
                }
            }
            // MediaProvider
            else if (isMediaDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

                Uri contentUri = null;
                if ("image".equals(type)) {
                    contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                } else if ("video".equals(type)) {
                    contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                } else if ("audio".equals(type)) {
                    contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                }

                final String selection = "_id=?";
                final String[] selectionArgs = new String[]{
                        split[1]
                };

                return getDataColumn(context, contentUri, selection, selectionArgs);
            }
        }
        // MediaStore (and general)
        else if ("content".equalsIgnoreCase(uri.getScheme())) {

            // Return the remote address
            if (isGooglePhotosUri(uri))
                return uri.getLastPathSegment();

            return getDataColumn(context, uri, null, null);
        }
        // File
        else if ("file".equalsIgnoreCase(uri.getScheme())) {
            return uri.getPath();
        }

        return null;
    }

    /**
     * Convert Uri into File, if possible.
     *
     * @return file A local file that the Uri was pointing to, or null if the
     * Uri is unsupported or pointed to a remote resource.
     * @author paulburke
     * @see #getPath(Context, Uri)
     */
    public static File getFile(Context context, Uri uri) {
        if (uri != null) {
            String path = getPath(context, uri);
            if (path != null && isLocal(path)) {
                return new File(path);
            }
        }
        return null;
    }

    /**
     * Get the file size in a human-readable string.
     *
     * @param size
     * @return
     * @author paulburke
     */
    public static String getReadableFileSize(int size) {
        final int BYTES_IN_KILOBYTES = 1024;
        final DecimalFormat dec = new DecimalFormat("###.#");
        final String KILOBYTES = " KB";
        final String MEGABYTES = " MB";
        final String GIGABYTES = " GB";
        float fileSize = 0;
        String suffix = KILOBYTES;

        if (size > BYTES_IN_KILOBYTES) {
            fileSize = size / BYTES_IN_KILOBYTES;
            if (fileSize > BYTES_IN_KILOBYTES) {
                fileSize = fileSize / BYTES_IN_KILOBYTES;
                if (fileSize > BYTES_IN_KILOBYTES) {
                    fileSize = fileSize / BYTES_IN_KILOBYTES;
                    suffix = GIGABYTES;
                } else {
                    suffix = MEGABYTES;
                }
            }
        }
        return String.valueOf(dec.format(fileSize) + suffix);
    }

    /**
     * Attempt to retrieve the thumbnail of given File from the MediaStore. This
     * should not be called on the UI thread.
     *
     * @param context
     * @param file
     * @return
     * @author paulburke
     */
    public static Bitmap getThumbnail(Context context, File file) {
        return getThumbnail(context, getUri(file), getMimeType(file));
    }

    /**
     * Attempt to retrieve the thumbnail of given Uri from the MediaStore. This
     * should not be called on the UI thread.
     *
     * @param context
     * @param uri
     * @return
     * @author paulburke
     */
    public static Bitmap getThumbnail(Context context, Uri uri) {
        return getThumbnail(context, uri, getMimeType(context, uri));
    }

    /**
     * Attempt to retrieve the thumbnail of given Uri from the MediaStore. This
     * should not be called on the UI thread.
     *
     * @param context
     * @param uri
     * @param mimeType
     * @return
     * @author paulburke
     */
    public static Bitmap getThumbnail(Context context, Uri uri, String mimeType) {
        if (DEBUG)
            Log.d(TAG, "Attempting to quickGet thumbnail");

        if (!isMediaUri(uri)) {
            Log.e(TAG, "You can only retrieve thumbnails for images and videos.");
            return null;
        }

        Bitmap bm = null;
        if (uri != null) {
            final ContentResolver resolver = context.getContentResolver();
            Cursor cursor = null;
            try {
                cursor = resolver.query(uri, null, null, null, null);
                if (cursor.moveToFirst()) {
                    final int id = cursor.getInt(0);
                    if (DEBUG)
                        Log.d(TAG, "Got thumb ID: " + id);

                    if (mimeType.contains("video")) {
                        bm = MediaStore.Video.Thumbnails.getThumbnail(
                                resolver,
                                id,
                                MediaStore.Video.Thumbnails.MINI_KIND,
                                null);
                    } else if (mimeType.contains(FileUtils.MIME_TYPE_IMAGE)) {
                        bm = MediaStore.Images.Thumbnails.getThumbnail(
                                resolver,
                                id,
                                MediaStore.Images.Thumbnails.MINI_KIND,
                                null);
                    }
                }
            } catch (Exception e) {
                if (DEBUG)
                    Log.e(TAG, "getThumbnail", e);
            } finally {
                if (cursor != null)
                    cursor.close();
            }
        }
        return bm;
    }

    /**
     * File and folder comparator. TODO Expose sorting option method
     *
     * @author paulburke
     */
    public static Comparator<File> sComparator = new Comparator<File>() {
        @Override
        public int compare(File f1, File f2) {
            // Sort alphabetically by lower case, which is much cleaner
            return f1.getName().toLowerCase().compareTo(
                    f2.getName().toLowerCase());
        }
    };

    /**
     * File (not directories) filter.
     *
     * @author paulburke
     */
    public static FileFilter sFileFilter = new FileFilter() {
        @Override
        public boolean accept(File file) {
            final String fileName = file.getName();
            // Return files only (not directories) and skip hidden files
            return file.isFile() && !fileName.startsWith(HIDDEN_PREFIX);
        }
    };

    /**
     * Folder (directories) filter.
     *
     * @author paulburke
     */
    public static FileFilter sDirFilter = new FileFilter() {
        @Override
        public boolean accept(File file) {
            final String fileName = file.getName();
            // Return directories only and skip hidden directories
            return file.isDirectory() && !fileName.startsWith(HIDDEN_PREFIX);
        }
    };

    /**
     * Get the Intent for selecting content to be used in an Intent Chooser.
     *
     * @return The intent for opening a file with Intent.createChooser()
     * @author paulburke
     */
    public static Intent createGetContentIntent() {
        // Implicitly allow the user to select a particular kind of data
        final Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        // The MIME data type filter
        intent.setType("*/*");
        // Only return URIs that can be opened with ContentResolver
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        return intent;
    }
}
</code>```

Body:
I have written this code to open my Document manager and select any PDF/Doc file.

Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
            intent.addCategory(Intent.CATEGORY_OPENABLE);
            intent.setType("*/*");
            Intent i = Intent.createChooser(intent, "File");
            startActivityForResult(i, 1);

When I select any Pdf/Doc file I am unable to get path of that select file.

I tried this code also but it give me null as output

protected void onActivityResult(int requestCode, int resultCode,
        Intent intent) {
    if (requestCode == 1) {
        if (resultCode == RESULT_OK) {
            Uri uri = intent.getData();
            String fileImagePath = getRealPathFromURI(uri);
            String type = intent.getType();

            Log.d("Hello", fileImagePath + "");
            if (uri != null) {
                String path = uri.toString();
                if (path.toLowerCase().startsWith("file://")) {
                    // Selected file/directory path is below
                    path = (new File(URI.create(path))).getAbsolutePath();
                    Log.d("Hel", path);
                }

            }
        } else
            Log.d("Hello", "Back from pick with cancel status");
    }
}

public String getRealPathFromURI(Uri uri) {
    String[] projection = { MediaStore.Files.FileColumns.DATA };
    Cursor cursor = managedQuery(uri, projection, null, null, null);
    int column_index = cursor
            .getColumnIndexOrThrow(MediaStore.Files.FileColumns.DATA );
    cursor.moveToFirst();
    return cursor.getString(column_index);
}

Please help me thanks in advance.

Body:
Please use below code for any sort of file :

/*
 * Copyright (C) 2007-2008 OpenIntents.org
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.yourpackage;

import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.util.Log;
import android.webkit.MimeTypeMap;

import java.io.File;
import java.io.FileFilter;
import java.text.DecimalFormat;
import java.util.Comparator;
import java.util.List;

/**
 * @author Peli
 * @author paulburke (ipaulpro)
 * @version 2013-12-11
 */
public class FileUtils {
    private FileUtils() {
    } //private constructor to enforce Singleton pattern

    /**
     * TAG for log messages.
     */
    static final String TAG = "FileUtils";
    private static final boolean DEBUG = true; // Set to true to enable logging

    public static final String MIME_TYPE_AUDIO = "audio/*";
    public static final String MIME_TYPE_TEXT = "text/*";
    public static final String MIME_TYPE_IMAGE = "image/*";
    public static final String MIME_TYPE_VIDEO = "video/*";
    public static final String MIME_TYPE_APP = "application/*";

    public static final String HIDDEN_PREFIX = ".";

    /**
     * Gets the extension of a file name, like ".png" or ".jpg".
     *
     * @param uri
     * @return Extension including the dot("."); "" if there is no extension;
     * null if uri was null.
     */
    public static String getExtension(String uri) {
        if (uri == null) {
            return null;
        }

        int dot = uri.lastIndexOf(".");
        if (dot >= 0) {
            return uri.substring(dot);
        } else {
            // No extension.
            return "";
        }
    }

    /**
     * @return Whether the URI is a local one.
     */
    public static boolean isLocal(String url) {
        if (url != null && !url.startsWith("http://") && !url.startsWith("https://")) {
            return true;
        }
        return false;
    }

    /**
     * @return True if Uri is a MediaStore Uri.
     * @author paulburke
     */
    public static boolean isMediaUri(Uri uri) {
        return "media".equalsIgnoreCase(uri.getAuthority());
    }

    /**
     * Convert File into Uri.
     *
     * @param file
     * @return uri
     */
    public static Uri getUri(File file) {
        if (file != null) {
            return Uri.fromFile(file);
        }
        return null;
    }

    /**
     * Returns the path only (without file name).
     *
     * @param file
     * @return
     */
    public static File getPathWithoutFilename(File file) {
        if (file != null) {
            if (file.isDirectory()) {
                // no file to be split off. Return everything
                return file;
            } else {
                String filename = file.getName();
                String filepath = file.getAbsolutePath();

                // Construct path without file name.
                String pathwithoutname = filepath.substring(0,
                        filepath.length() - filename.length());
                if (pathwithoutname.endsWith("/")) {
                    pathwithoutname = pathwithoutname.substring(0, pathwithoutname.length() - 1);
                }
                return new File(pathwithoutname);
            }
        }
        return null;
    }

    /**
     * @return The MIME type for the given file.
     */
    public static String getMimeType(File file) {

        String extension = getExtension(file.getName());

        if (extension.length() > 0)
            return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension.substring(1));

        return "application/octet-stream";
    }

    /**
     * @return The MIME type for the give Uri.
     */
    public static String getMimeType(Context context, Uri uri) {
        File file = new File(getPath(context, uri));
        return getMimeType(file);
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is {@link LocalStorageProvider}.
     * @author paulburke
     */
    public static boolean isLocalStorageDocument(Uri uri) {
        return LocalStorageProvider.AUTHORITY.equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is ExternalStorageProvider.
     * @author paulburke
     */
    public static boolean isExternalStorageDocument(Uri uri) {
        return "com.android.externalstorage.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is DownloadsProvider.
     * @author paulburke
     */
    public static boolean isDownloadsDocument(Uri uri) {
        return "com.android.providers.downloads.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is MediaProvider.
     * @author paulburke
     */
    public static boolean isMediaDocument(Uri uri) {
        return "com.android.providers.media.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is Google Photos.
     */
    public static boolean isGooglePhotosUri(Uri uri) {
        return "com.google.android.apps.photos.content".equals(uri.getAuthority());
    }

    /**
     * Get the value of the data column for this Uri. This is useful for
     * MediaStore Uris, and other file-based ContentProviders.
     *
     * @param context       The context.
     * @param uri           The Uri to query.
     * @param selection     (Optional) Filter used in the query.
     * @param selectionArgs (Optional) Selection arguments used in the query.
     * @return The value of the _data column, which is typically a file path.
     * @author paulburke
     */
    public static String getDataColumn(Context context, Uri uri, String selection,
                                       String[] selectionArgs) {

        Cursor cursor = null;
        final String column = "_data";
        final String[] projection = {
                column
        };

        try {
            cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
                    null);
            if (cursor != null && cursor.moveToFirst()) {
                if (DEBUG)
                    DatabaseUtils.dumpCursor(cursor);

                final int column_index = cursor.getColumnIndexOrThrow(column);
                return cursor.getString(column_index);
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if (cursor != null)
                cursor.close();
        }
        return null;
    }

    /**
     * Get a file path from a Uri. This will quickGet the the path for Storage Access
     * Framework Documents, as well as the _data field for the MediaStore and
     * other file-based ContentProviders.<br>
     * <br>
     * Callers should check whether the path is local before assuming it
     * represents a local file.
     *
     * @param context The context.
     * @param uri     The Uri to query.
     * @author paulburke
     * @see #isLocal(String)
     * @see #getFile(Context, Uri)
     */
    public static String getPath(final Context context, final Uri uri) {

        if (DEBUG)
            Log.d(TAG + " File -",
                    "Authority: " + uri.getAuthority() +
                            ", Fragment: " + uri.getFragment() +
                            ", Port: " + uri.getPort() +
                            ", Query: " + uri.getQuery() +
                            ", Scheme: " + uri.getScheme() +
                            ", Host: " + uri.getHost() +
                            ", Segments: " + uri.getPathSegments().toString()
            );
        // DocumentProvider
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && DocumentsContract.isDocumentUri(context, uri)) {
            // LocalStorageProvider
            if (isLocalStorageDocument(uri)) {
                // The path is the id
                return DocumentsContract.getDocumentId(uri);
            }
            // ExternalStorageProvider
            else if (isExternalStorageDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

//                if ("primary".equalsIgnoreCase(type)) {
//                    return Environment.getExternalStorageDirectory() + "/" + split[1];
//                }
                return Environment.getExternalStorageDirectory() + "/" + split[1];

                // TODO handle non-primary volumes
            }
            // DownloadsProvider
            else if (isDownloadsDocument(uri)) {
                try {
                    final String id = DocumentsContract.getDocumentId(uri);
                    Log.d(TAG, "getPath: id= " + id);
                    final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
                    return getDataColumn(context, contentUri, null, null);
                }catch (Exception e){
                    e.printStackTrace();
                    List<String> segments = uri.getPathSegments();
                    if(segments.size() > 1) {
                        String rawPath = segments.get(1);
                        if(!rawPath.startsWith("/")){
                            return rawPath.substring(rawPath.indexOf("/"));
                        }else {
                            return rawPath;
                        }
                    }
                }
            }
            // MediaProvider
            else if (isMediaDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

                Uri contentUri = null;
                if ("image".equals(type)) {
                    contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                } else if ("video".equals(type)) {
                    contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                } else if ("audio".equals(type)) {
                    contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                }

                final String selection = "_id=?";
                final String[] selectionArgs = new String[]{
                        split[1]
                };

                return getDataColumn(context, contentUri, selection, selectionArgs);
            }
        }
        // MediaStore (and general)
        else if ("content".equalsIgnoreCase(uri.getScheme())) {

            // Return the remote address
            if (isGooglePhotosUri(uri))
                return uri.getLastPathSegment();

            return getDataColumn(context, uri, null, null);
        }
        // File
        else if ("file".equalsIgnoreCase(uri.getScheme())) {
            return uri.getPath();
        }

        return null;
    }

    /**
     * Convert Uri into File, if possible.
     *
     * @return file A local file that the Uri was pointing to, or null if the
     * Uri is unsupported or pointed to a remote resource.
     * @author paulburke
     * @see #getPath(Context, Uri)
     */
    public static File getFile(Context context, Uri uri) {
        if (uri != null) {
            String path = getPath(context, uri);
            if (path != null && isLocal(path)) {
                return new File(path);
            }
        }
        return null;
    }

    /**
     * Get the file size in a human-readable string.
     *
     * @param size
     * @return
     * @author paulburke
     */
    public static String getReadableFileSize(int size) {
        final int BYTES_IN_KILOBYTES = 1024;
        final DecimalFormat dec = new DecimalFormat("###.#");
        final String KILOBYTES = " KB";
        final String MEGABYTES = " MB";
        final String GIGABYTES = " GB";
        float fileSize = 0;
        String suffix = KILOBYTES;

        if (size > BYTES_IN_KILOBYTES) {
            fileSize = size / BYTES_IN_KILOBYTES;
            if (fileSize > BYTES_IN_KILOBYTES) {
                fileSize = fileSize / BYTES_IN_KILOBYTES;
                if (fileSize > BYTES_IN_KILOBYTES) {
                    fileSize = fileSize / BYTES_IN_KILOBYTES;
                    suffix = GIGABYTES;
                } else {
                    suffix = MEGABYTES;
                }
            }
        }
        return String.valueOf(dec.format(fileSize) + suffix);
    }

    /**
     * Attempt to retrieve the thumbnail of given File from the MediaStore. This
     * should not be called on the UI thread.
     *
     * @param context
     * @param file
     * @return
     * @author paulburke
     */
    public static Bitmap getThumbnail(Context context, File file) {
        return getThumbnail(context, getUri(file), getMimeType(file));
    }

    /**
     * Attempt to retrieve the thumbnail of given Uri from the MediaStore. This
     * should not be called on the UI thread.
     *
     * @param context
     * @param uri
     * @return
     * @author paulburke
     */
    public static Bitmap getThumbnail(Context context, Uri uri) {
        return getThumbnail(context, uri, getMimeType(context, uri));
    }

    /**
     * Attempt to retrieve the thumbnail of given Uri from the MediaStore. This
     * should not be called on the UI thread.
     *
     * @param context
     * @param uri
     * @param mimeType
     * @return
     * @author paulburke
     */
    public static Bitmap getThumbnail(Context context, Uri uri, String mimeType) {
        if (DEBUG)
            Log.d(TAG, "Attempting to quickGet thumbnail");

        if (!isMediaUri(uri)) {
            Log.e(TAG, "You can only retrieve thumbnails for images and videos.");
            return null;
        }

        Bitmap bm = null;
        if (uri != null) {
            final ContentResolver resolver = context.getContentResolver();
            Cursor cursor = null;
            try {
                cursor = resolver.query(uri, null, null, null, null);
                if (cursor.moveToFirst()) {
                    final int id = cursor.getInt(0);
                    if (DEBUG)
                        Log.d(TAG, "Got thumb ID: " + id);

                    if (mimeType.contains("video")) {
                        bm = MediaStore.Video.Thumbnails.getThumbnail(
                                resolver,
                                id,
                                MediaStore.Video.Thumbnails.MINI_KIND,
                                null);
                    } else if (mimeType.contains(FileUtils.MIME_TYPE_IMAGE)) {
                        bm = MediaStore.Images.Thumbnails.getThumbnail(
                                resolver,
                                id,
                                MediaStore.Images.Thumbnails.MINI_KIND,
                                null);
                    }
                }
            } catch (Exception e) {
                if (DEBUG)
                    Log.e(TAG, "getThumbnail", e);
            } finally {
                if (cursor != null)
                    cursor.close();
            }
        }
        return bm;
    }

    /**
     * File and folder comparator. TODO Expose sorting option method
     *
     * @author paulburke
     */
    public static Comparator<File> sComparator = new Comparator<File>() {
        @Override
        public int compare(File f1, File f2) {
            // Sort alphabetically by lower case, which is much cleaner
            return f1.getName().toLowerCase().compareTo(
                    f2.getName().toLowerCase());
        }
    };

    /**
     * File (not directories) filter.
     *
     * @author paulburke
     */
    public static FileFilter sFileFilter = new FileFilter() {
        @Override
        public boolean accept(File file) {
            final String fileName = file.getName();
            // Return files only (not directories) and skip hidden files
            return file.isFile() && !fileName.startsWith(HIDDEN_PREFIX);
        }
    };

    /**
     * Folder (directories) filter.
     *
     * @author paulburke
     */
    public static FileFilter sDirFilter = new FileFilter() {
        @Override
        public boolean accept(File file) {
            final String fileName = file.getName();
            // Return directories only and skip hidden directories
            return file.isDirectory() && !fileName.startsWith(HIDDEN_PREFIX);
        }
    };

    /**
     * Get the Intent for selecting content to be used in an Intent Chooser.
     *
     * @return The intent for opening a file with Intent.createChooser()
     * @author paulburke
     */
    public static Intent createGetContentIntent() {
        // Implicitly allow the user to select a particular kind of data
        final Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        // The MIME data type filter
        intent.setType("*/*");
        // Only return URIs that can be opened with ContentResolver
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        return intent;
    }
}


来源: stackexchange

问:
How to add new item to hyperlink menu in Outlook 2007 with VBA?
I need to add new item to the hyperlink menu in Outlook 2007 (now it contains items like Copy, Select Hyperlink, Open Hyperlink, Copy Hyperlink, Who is).

How can I do it?
(it should be a VBA macro added to Outlook)

答:
Sorry I don't have a definite answer for you, but hopefully I can point you in the right direction.

This forum will hopefully be useful, it looks like they're doing the same thing there (albeit with a different menu).

And if you need some basics help, here are two MSDN blogs talking about Outlook and VBA macros in general:

http://blogs.msdn.com/b/synergist/archive/2007/05/23/adding-a-vba-macro-to-outlook.aspx

http://blogs.msdn.com/b/swiss_dpe_team/archive/2007/12/11/office-2007-outlook2007-macros-vba-how-to-work-better-with-categories.aspx

Hope this helps!

ContentLicense: CC BY-SA 3.0


问:
Errors running sqlite through adb shell
Running from the command-line on a Windows 10 PC, and I'm having a problem with quotation marks:

adb shell su -c "sqlite3 /data/data/com.android.chrome/app_chrome/Default/Cookies 'select count(*) from cookies;'"

sush: syntax error: '(' unexpected

adb shell su -c sqlite3 /data/data/com.android.chrome/app_chrome/Default/Cookies 'select count(*) from cookies;'

sush: syntax error: '(' unexpected

adb shell su -c sqlite3 /data/data/com.android.chrome/app_chrome/Default/Cookies "select count(*) from cookies;"

/system/bin/sh: syntax error: '(' unexpected

I tried a query which didn't contain parens, but that wouldn't run either:

adb shell su -c "sqlite3 /data/data/com.android.chrome/app_chrome/Default/Cookies 'select * from cookies;'"

Error: near "select": syntax error

I can run other sqlite3 commands from the adb shell

adb shell su -c "sqlite3 /data/data/com.android.chrome/app_chrome/Default/Cookies .schema"

that works with or without quotation marks.

And going into ADB shell works:

```<code>>adb shell
/ $ su
/ # sqlite3 /data/data/com.android.chrome/app_chrome/Default/Cookies 'select count(*) from cookies;'
3238
</code>```

I simply want to get the results of a query from the command-line.

What am I missing?

答:
Try this:

```<code>adb shell su -c sqlite3 /data/data/com.android.chrome/app_chrome/Default/Cookies "\"select count(*) from cookies;\""
</code>```

or

```<code>query="\"select count(*) from cookies;\""
adb shell su -c sqlite3 /data/data/com.android.chrome/app_chrome/Default/Cookies "$query"
</code>```

I guess the problem is with the double quotes. I am still not quite sure why those double quotes are needed within the query, but this is most certainly to work.

ContentLicense: CC BY-SA 4.0

Title: Errors running sqlite through adb shell

Body:
Running from the command-line on a Windows 10 PC, and I'm having a problem with quotation marks:

adb shell su -c "sqlite3 /data/data/com.android.chrome/app_chrome/Default/Cookies 'select count(*) from cookies;'"

sush: syntax error: '(' unexpected

adb shell su -c sqlite3 /data/data/com.android.chrome/app_chrome/Default/Cookies 'select count(*) from cookies;'

sush: syntax error: '(' unexpected

adb shell su -c sqlite3 /data/data/com.android.chrome/app_chrome/Default/Cookies "select count(*) from cookies;"

/system/bin/sh: syntax error: '(' unexpected

I tried a query which didn't contain parens, but that wouldn't run either:

adb shell su -c "sqlite3 /data/data/com.android.chrome/app_chrome/Default/Cookies 'select * from cookies;'"

Error: near "select": syntax error

I can run other sqlite3 commands from the adb shell

adb shell su -c "sqlite3 /data/data/com.android.chrome/app_chrome/Default/Cookies .schema"

that works with or without quotation marks.

And going into ADB shell works:

>adb shell
/ $ su
/ # sqlite3 /data/data/com.android.chrome/app_chrome/Default/Cookies 'select count(*) from cookies;'
3238

I simply want to get the results of a query from the command-line.

What am I missing?

Body:
Try this:

adb shell su -c sqlite3 /data/data/com.android.chrome/app_chrome/Default/Cookies "\"select count(*) from cookies;\""

or

query="\"select count(*) from cookies;\""
adb shell su -c sqlite3 /data/data/com.android.chrome/app_chrome/Default/Cookies "$query"

I guess the problem is with the double quotes. I am still not quite sure why those double quotes are needed within the query, but this is most certainly to work.


问:
Angular typescript:combine 2 api calls in one promise
So at the minute I have two methods in my service that make API calls as below.
They both return the same type of object as JSON, which is a Control

How can I combine them in a way that the method does do "getControls", then do "getControlsECC" and then add them together and return?

```<code>getControls(): Promise<Control[]> {
    return this.http.get(this.controlsUrl)
           .toPromise()
           .then(response => response.json() as Control[])
           .catch(this.handleError);
}

getControlsECC(): Promise<Control[]> {
  return this.http.get(this.controlsECC)
         .toPromise()
         .then(response => response.json() as Control[])
         .catch(this.handleError);
</code>```

}

答:
```<code>doBoth() {
  return forkJoin(
    this.getControls().pipe(map(response => response.json())),
    this.getControlsECC().pipe(map(response => response.json())),
  ).toPromise()
    .catch(this.handleError);
}

getControls() {
    return this.http.get<Control[]>(this.controlsUrl);
}

getControlsECC() {
  return this.http.get<Control[]>(this.controlsECC);
}
</code>```

Body:
So at the minute I have two methods in my service that make API calls as below.
They both return the same type of object as JSON, which is a Control

How can I combine them in a way that the method does do "getControls", then do "getControlsECC" and then add them together and return?

getControls(): Promise<Control[]> {
    return this.http.get(this.controlsUrl)
           .toPromise()
           .then(response => response.json() as Control[])
           .catch(this.handleError);
}

getControlsECC(): Promise<Control[]> {
  return this.http.get(this.controlsECC)
         .toPromise()
         .then(response => response.json() as Control[])
         .catch(this.handleError);

}


问:
How to set a default value using Select?
How to set a default value using the select event? Currently in EDIT mode I just hardcoded selectedKey="USD", thus when the user clicks on another value (eg: CAD) it does not update the value to CAD in the VIEW mode.

```<code><Select id="idCurrency" items="{/VH_CurrencySet}" selectedKey="USD">
    <items>
        <core:Item text="{Text}" key="{Code}" />
    </items>
    <layoutData>
        <l:GridData span="XL2 L3 M3 S5" />
    </layoutData>
</Select>
</code>```

In VIEW Mode, the currency should appear as CAD.

答:
You need to setup a change function for the control:

```<code><Select id="idCurrency" items="{/VH_CurrencySet}" selectedKey="USD" change="yourfunction">
    <items>
        <core:Item text="{Text}" key="{Code}"/>
    </items>
    <layoutData>
        <l:GridData span="XL2 L3 M3 S5"/>
    </layoutData>
</Select>
</code>```

After that you implement the yourfunction function inside your controller.

Body:
How to set a default value using the select event? Currently in EDIT mode I just hardcoded selectedKey="USD", thus when the user clicks on another value (eg: CAD) it does not update the value to CAD in the VIEW mode.

<Select id="idCurrency" items="{/VH_CurrencySet}" selectedKey="USD">
    <items>
        <core:Item text="{Text}" key="{Code}" />
    </items>
    <layoutData>
        <l:GridData span="XL2 L3 M3 S5" />
    </layoutData>
</Select>

In VIEW Mode, the currency should appear as CAD.

Body:
You need to setup a change function for the control:

<Select id="idCurrency" items="{/VH_CurrencySet}" selectedKey="USD" change="yourfunction">
    <items>
        <core:Item text="{Text}" key="{Code}"/>
    </items>
    <layoutData>
        <l:GridData span="XL2 L3 M3 S5"/>
    </layoutData>
</Select>

After that you implement the yourfunction function inside your controller.


问:
Hover over button while still having hover effect of element behind it
I have created an element where when you hover within the area of the element a hover effect is applied (change background colour), on top of this element is a button.
When I hover over the button it causing the other hover effect to disappear, I want to be able to keep the hover for the whole time that the mouse is within the area of the first element.

Example Code Here

So when I hover over the button in the example, I still want the background of the a tag to be black. At the moment when I hover over the button it causes the black background to disappear. I also still want to be able to click on the button.

To achieve what I want to achieve would I need to use js? Or can it be done in CSS?

答:
Put #label in front, and use + select next slibing dom

#button1 {
  position: absolute;
  z-index: 100;
  top: 10%;
  left: 15%;
}
#label {
  position: absolute;
  z-index: -10;
  border: 1px solid red;
  width: 200px;
  height: 200px;
  text-align: center;
}
#label span {
  color: white;
}
#label:hover {
  background-color: black;
}
#button1:hover + #label {
  background-color: black;
}```
<pre class="snippet-code-html lang-html prettyprint-override"><code><button id="button1">Test Button</button>
<span>Hidden Until Hover</span></code>```

Body:
Put #label in front, and use + select next slibing dom

#button1 {
  position: absolute;
  z-index: 100;
  top: 10%;
  left: 15%;
}
#label {
  position: absolute;
  z-index: -10;
  border: 1px solid red;
  width: 200px;
  height: 200px;
  text-align: center;
}
#label span {
  color: white;
}
#label:hover {
  background-color: black;
}
#button1:hover + #label {
  background-color: black;
}

<button id="button1">Test Button</button>
<a id="label"><span>Hidden Until Hover</span></a>


问:
How to make RichTextValue catalog full text search for Plone 4
I created dexterity content type with Rich Text Field - "body text". I'd like to make "body text" full text searchable for my Plone 4.0.2.

I added catalog.xml in my theme, code below

I got error message from ZMI/portal/portal_catalog "body_text RichTextValue object. (Did you mean .raw or .output?) "

How can I change catalog.xml to use .output, I tried , but it doesn't work.

Thanks.

答:
You could use plone.indexer and provide your own indexer inside your dexterity type to add your custom body text to the SearchableText index (including default title and description for example) like so:

```<code>@indexer(IMyTypeInterface)
def SearchableText(obj):
    return ' '.join([obj.Title(), obj.Description(), obj.bodytext.output])
</code>```

Body:
You could use plone.indexer and provide your own indexer inside your dexterity type to add your custom body text to the SearchableText index (including default title and description for example) like so:

@indexer(IMyTypeInterface)
def SearchableText(obj):
    return ' '.join([obj.Title(), obj.Description(), obj.bodytext.output])


问:
How to update only clicked item at Recyclerview adapter not the last visible one?
I have asked this question previously and after some investigation I got to know that my onBindViewHolder updates the wrong item of my list. What does it mean? For example I pressed 0 item of my list and it will update the view of 6-th item. I don't know why does it happen because I thought previously that notifyItemChanged() will change clicked item not  the last visible item of my list.My adapter class:

```<code>open class JobsAdapter(private val jobs: ArrayList<JobModel>, private val ctx: Context, private val click: Click) : RecyclerView.Adapter<JobsAdapter.JobsHolder>() {
    lateinit var view: View

    override fun onCreateViewHolder(viewGroup: ViewGroup, p1: Int): JobsHolder {
        view = LayoutInflater.from(viewGroup.context).inflate(R.layout.job_list_item, viewGroup, false)
        return JobsHolder(view)
    }

    override fun getItemCount(): Int {
        return jobs.size
    }

    override fun onBindViewHolder(holder: JobsHolder, position: Int) {
        val jobModel = jobs[position]
        holder.tvPosition.text = jobModel.position
        holder.tvAddress.text = jobModel.location
        holder.tvCompany.text = jobModel.company_name

        holder.itemView.setOnClickListener {
            if (!jobModel.isSeen) {
                    Singleton.clickReq(jobModel.id, ctx)

            }

            holder.itemView.background = ContextCompat.getDrawable(ctx, R.drawable.message_list_item_bg)

            click.sendData(Uri.parse(jobModel.job_link).toString(), holder.adapterPosition, jobModel.position!!)
        }

        holder.ivAddTo.setOnClickListener {
            holder.progressBar.visibility = View.VISIBLE
            holder.ivAddTo.setBackgroundResource(R.drawable.added_to_notepad)
            holder.ivAddTo.visibility = View.GONE
            holder.ivAddTo.isClickable = false
            Singleton.jobLstPos = position

                saveToNotepad(jobModel.id)
        }

        if (jobModel.isSeen) {
            holder.itemView.background = ContextCompat.getDrawable(ctx, R.drawable.message_list_item_bg)
        } else {
            holder.itemView.setBackgroundColor(Color.parseColor("#fafafa"))
        }
    }

    override fun onBindViewHolder(holder: JobsHolder, position: Int, payloads: List<Any>) {
        if (payloads.isNotEmpty()) {
            when (payloads[0]) {
                1 -> {
                    holder.ivAddTo.visibility = View.GONE
                }
            }
        } else {
            super.onBindViewHolder(holder, position, payloads)
        }
    }

    private fun saveToNotepad(id: Int) {
        Singleton.apiService(ctx).saveTo("Bearer " + ctx.getSharedPreferences("appD", 0).getString("access_token", ""), id).enqueue(object : Callback<SaveTo> {
            override fun onResponse(call: Call<SaveTo>, response: Response<SaveTo>) {
                if (response.isSuccessful) {
                    notifyItemChanged(view.getTag(R.id.tag_3) as Int, 1)
                }
            }

            override fun onFailure(call: Call<SaveTo>, t: Throwable) {
            }
        })
    }

    class JobsHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        var tvCompany = itemView.findViewById<TextView>(R.id.tv_company)!!
        var tvDate = itemView.findViewById<TextView>(R.id.tv_date)!!
        var tvPosition = itemView.findViewById<TextView>(R.id.tv_job_title)!!
        var tvAddress = itemView.findViewById<TextView>(R.id.tv_address)!!
        var ivAddTo = itemView.findViewById<ImageView>(R.id.add_to_notepad)!!
        var progressBar = itemView.findViewById<ProgressBar>(R.id.progressBar)
    }
}
</code>```

After clicking add button I send request and if it is successful I would like to stop progress bar, change its visibility and change background of clicked btn. So, why does it happen and how I can solve this problem?

答:
I managed to solve my problem by adding special function for updating view:

```<code>fun changeView(position: Int, permission: Boolean) {
        notifyItemChanged(position, permission)
    }
</code>```

and then onBindViewHolder():

```<code>override fun onBindViewHolder(holder: JobsHolder, position: Int, payloads: List<Any>) {
        if (payloads.isNotEmpty()) {
            when (payloads[0]) {
                true -> {
                    holder.ivAddTo.setBackgroundResource(R.drawable.added_to_notepad)
                    holder.progressBar.visibility = View.GONE
                    holder.ivAddTo.visibility = View.VISIBLE
                }
                false->{
                    holder.progressBar.visibility = View.GONE
                    holder.ivAddTo.visibility = View.VISIBLE
                }
            }
        } else {
            super.onBindViewHolder(holder, position, payloads)
        }
    }
</code>```

maybe it will help smb else.

Body:
I have asked this question previously and after some investigation I got to know that my onBindViewHolder updates the wrong item of my list. What does it mean? For example I pressed 0 item of my list and it will update the view of 6-th item. I don't know why does it happen because I thought previously that notifyItemChanged() will change clicked item not  the last visible item of my list.My adapter class:

open class JobsAdapter(private val jobs: ArrayList<JobModel>, private val ctx: Context, private val click: Click) : RecyclerView.Adapter<JobsAdapter.JobsHolder>() {
    lateinit var view: View

    override fun onCreateViewHolder(viewGroup: ViewGroup, p1: Int): JobsHolder {
        view = LayoutInflater.from(viewGroup.context).inflate(R.layout.job_list_item, viewGroup, false)
        return JobsHolder(view)
    }

    override fun getItemCount(): Int {
        return jobs.size
    }

    override fun onBindViewHolder(holder: JobsHolder, position: Int) {
        val jobModel = jobs[position]
        holder.tvPosition.text = jobModel.position
        holder.tvAddress.text = jobModel.location
        holder.tvCompany.text = jobModel.company_name

        holder.itemView.setOnClickListener {
            if (!jobModel.isSeen) {
                    Singleton.clickReq(jobModel.id, ctx)

            }

            holder.itemView.background = ContextCompat.getDrawable(ctx, R.drawable.message_list_item_bg)

            click.sendData(Uri.parse(jobModel.job_link).toString(), holder.adapterPosition, jobModel.position!!)
        }

        holder.ivAddTo.setOnClickListener {
            holder.progressBar.visibility = View.VISIBLE
            holder.ivAddTo.setBackgroundResource(R.drawable.added_to_notepad)
            holder.ivAddTo.visibility = View.GONE
            holder.ivAddTo.isClickable = false
            Singleton.jobLstPos = position

                saveToNotepad(jobModel.id)
        }

        if (jobModel.isSeen) {
            holder.itemView.background = ContextCompat.getDrawable(ctx, R.drawable.message_list_item_bg)
        } else {
            holder.itemView.setBackgroundColor(Color.parseColor("#fafafa"))
        }
    }

    override fun onBindViewHolder(holder: JobsHolder, position: Int, payloads: List<Any>) {
        if (payloads.isNotEmpty()) {
            when (payloads[0]) {
                1 -> {
                    holder.ivAddTo.visibility = View.GONE
                }
            }
        } else {
            super.onBindViewHolder(holder, position, payloads)
        }
    }

    private fun saveToNotepad(id: Int) {
        Singleton.apiService(ctx).saveTo("Bearer " + ctx.getSharedPreferences("appD", 0).getString("access_token", ""), id).enqueue(object : Callback<SaveTo> {
            override fun onResponse(call: Call<SaveTo>, response: Response<SaveTo>) {
                if (response.isSuccessful) {
                    notifyItemChanged(view.getTag(R.id.tag_3) as Int, 1)
                }
            }

            override fun onFailure(call: Call<SaveTo>, t: Throwable) {
            }
        })
    }

    class JobsHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        var tvCompany = itemView.findViewById<TextView>(R.id.tv_company)!!
        var tvDate = itemView.findViewById<TextView>(R.id.tv_date)!!
        var tvPosition = itemView.findViewById<TextView>(R.id.tv_job_title)!!
        var tvAddress = itemView.findViewById<TextView>(R.id.tv_address)!!
        var ivAddTo = itemView.findViewById<ImageView>(R.id.add_to_notepad)!!
        var progressBar = itemView.findViewById<ProgressBar>(R.id.progressBar)
    }
}

After clicking add button I send request and if it is successful I would like to stop progress bar, change its visibility and change background of clicked btn. So, why does it happen and how I can solve this problem?

Body:
I managed to solve my problem by adding special function for updating view:

fun changeView(position: Int, permission: Boolean) {
        notifyItemChanged(position, permission)
    }

and then onBindViewHolder():

override fun onBindViewHolder(holder: JobsHolder, position: Int, payloads: List<Any>) {
        if (payloads.isNotEmpty()) {
            when (payloads[0]) {
                true -> {
                    holder.ivAddTo.setBackgroundResource(R.drawable.added_to_notepad)
                    holder.progressBar.visibility = View.GONE
                    holder.ivAddTo.visibility = View.VISIBLE
                }
                false->{
                    holder.progressBar.visibility = View.GONE
                    holder.ivAddTo.visibility = View.VISIBLE
                }
            }
        } else {
            super.onBindViewHolder(holder, position, payloads)
        }
    }

maybe it will help smb else.


问:
How can I group MySQL Workbench connections?
During several years of activity, I accumulated dozens of Database Connections in MySQL Workbench. So many that finding the right one is becoming more and more a challenge. Is there a way to group connections, tidying up the home screen ?</p>

答:
It's incredible I could not find this on StackOverflow, but googling for a while I arrived to this page: https://dev.mysql.com/doc/workbench/en/wb-home.html

Under MySQL Connections we read

Connection Groups.  You may also create groups of connections. Create a group by either right-clicking a connection and choosing the Move to group context menu option, or you may prefix your connection name with the group name separated by a forward slash (for example, "QA/TestBox") when you create or configure the connection.

So basically changing the connection name from

```<code>MySystem Connection - Production
</code>```

to

```<code>MySystem Connection/Production
</code>```

it created a Group Folder in the home screen.

Body:
It's incredible I could not find this on StackOverflow, but googling for a while I arrived to this page: https://dev.mysql.com/doc/workbench/en/wb-home.html

Under MySQL Connections we read

Connection Groups.  You may also create groups of connections. Create a group by either right-clicking a connection and choosing the Move to group context menu option, or you may prefix your connection name with the group name separated by a forward slash (for example, "QA/TestBox") when you create or configure the connection.

So basically changing the connection name from

MySystem Connection - Production

to

MySystem Connection/Production

it created a Group Folder in the home screen.


问:
Is there a general consensus in the C++ community on when exceptions should be used?
I just spent a few hours reading through SO questions on the topic of when to use exceptions, and it seems like there are two camps with different point of views:

Use exceptions over error codes

Use error codes most of the time, and exceptions only when some catastrophic error occurs

Is this just a controversial topic with no widely accepted best practice?

答:
No consensus, but as the replies indicate, many people hold to the view to throw exceptinos only in exceptional circumstances. I don't much like that advice, because then the question becomes "what is an exceptional circumstance?". I prefer the following advice

A function must throw an exception if, and only if, the alternative would be failure to meet a post-condition (including all invariants as implicit post-conditions).

The implementation decision of whether to write throw in your code is then tied to the design decisions of the post-conditions for the function.

See C++ Coding Standards by Herb Sutter and Andrei Alexandrescu, items 70 (Distinguish between errors and non-errors) and 72 (Prefer to use exceptions to report errors).


问:
Android bottomNavigationView Styling by Theme
I want my users to be able to change the (color) theme of my App. So we create multiple themes.

```<code><resources>
<!-- First Theme -->
<style name="themeOne" parent="Theme.AppCompat.NoActionBar">
    <item name="colorPrimary">@color/themeOneColorPrimary</item>
    <item name="colorPrimaryDark">@color/themeOneColorPrimaryDark</item>
    <item name="colorAccent">@color/themeOneAccent</item>
    <item name="android:background">@color/themeOneBackground</item>
    ...
</style>

<!-- Second Theme -->
<style name="themeTwo" parent="Theme.AppCompat.Light.NoActionBar">
    ...
</style>
</code>```

Now I want to change the looks of the BottomNavigationView. But cannot find an example on how to do so.

```<code><android.support.design.widget.BottomNavigationView
    android:id="@+id/nav_bottom"
    app:menu="@menu/nav_bottom"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"/>
</code>```

But I want to set the following depending on the Theme:

```<code>app:itemBackground="@color/colorPrimary"
app:itemIconTint="@color/white"
app:itemTextColor="@color/white"
</code>```

答:
this isn't quite the answer you were looking for, but as I was trying to do the same thing with no success I found a workaround, so by making your themes in styles.xml inherit from  material components (if they arent quite right you can use the .bridge to make them more like appcompat themes) you can change the background of the bottom nav so for instance my yellow theme

```<code><style name="MyAppYellowTheme" parent="Theme.MaterialComponents.Light.Bridge">
    <item name="colorPrimary">@color/primary_yellow</item>
    <item name="colorPrimaryDark">@color/primary_dark_yellow</item>
    <item name="colorAccent">@color/accent_yellow</item>
    <item name="android:textColorPrimary">@color/primary_text_yellow</item>
    <item name="android:colorBackground">@color/background_light</item>
    <item name="tabLayoutStyle">@style/Yellow.TabLayout</item>
</style>
</code>```

will make my bottom nav background color = colorPrimary if i add a material style to it like this

```<code><com.google.android.material.bottomnavigation.BottomNavigationView
  android:id="@+id/navigation"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  style="@style/Widget.MaterialComponents.BottomNavigationView.Colored"
  app:layout_constraintBottom_toBottomOf="parent"
  app:menu="@menu/navigation" />
</code>```

there are different versions of this style that can be found here this works but you will still need to do something for the icons and text so i have a switch statement and based on the color, (dark or light) i switch the color state list like this

```<code>ColorStateList colorStateList = getBottomNavColor(theme, getActivity());
navigationView.setItemIconTintList(colorStateList);
navigationView.setItemTextColor(colorStateList);
</code>```

getBottomNavController

```<code>private ColorStateList getBottomNavColor(String theme, Context context){
        switch (theme) {
          case Constants.THEME_BLUE:
            return ContextCompat.getColorStateList(context,R.drawable.bottom_nav_selector_blue);
          case Constants.THEME_YELLOW:
            return ContextCompat.getColorStateList(context,R.drawable.bottom_nav_selector_yellow);
          case Constants.THEME_GREEN:
            return ContextCompat.getColorStateList(context,R.drawable.bottom_nav_selector_green);
          case Constants.THEME_RED:
            return ContextCompat.getColorStateList(context,R.drawable.bottom_nav_selector_red);
          case Constants.THEME_PURPLE:
            return ContextCompat.getColorStateList(context,R.drawable.bottom_nav_selector_purple);
          case Constants.THEME_PINK:
            return ContextCompat.getColorStateList(context,R.drawable.bottom_nav_selector_pink);

        }
        return ContextCompat.getColorStateList(context,R.drawable.bottom_nav_selector_blue);
      }
</code>```

again not what you or I were looking for but does work and could be worse, hope it helps

Body:
I want my users to be able to change the (color) theme of my App. So we create multiple themes.

<resources>

Now I want to change the looks of the BottomNavigationView. But cannot find an example on how to do so.

<android.support.design.widget.BottomNavigationView
    android:id="@+id/nav_bottom"
    app:menu="@menu/nav_bottom"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"/>

But I want to set the following depending on the Theme:

app:itemBackground="@color/colorPrimary"
app:itemIconTint="@color/white"
app:itemTextColor="@color/white"

Body:
this isn't quite the answer you were looking for, but as I was trying to do the same thing with no success I found a workaround, so by making your themes in styles.xml inherit from  material components (if they arent quite right you can use the .bridge to make them more like appcompat themes) you can change the background of the bottom nav so for instance my yellow theme

<style name="MyAppYellowTheme" parent="Theme.MaterialComponents.Light.Bridge">
    <item name="colorPrimary">@color/primary_yellow</item>
    <item name="colorPrimaryDark">@color/primary_dark_yellow</item>
    <item name="colorAccent">@color/accent_yellow</item>
    <item name="android:textColorPrimary">@color/primary_text_yellow</item>
    <item name="android:colorBackground">@color/background_light</item>
    <item name="tabLayoutStyle">@style/Yellow.TabLayout</item>
</style>

will make my bottom nav background color = colorPrimary if i add a material style to it like this

<com.google.android.material.bottomnavigation.BottomNavigationView
  android:id="@+id/navigation"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  style="@style/Widget.MaterialComponents.BottomNavigationView.Colored"
  app:layout_constraintBottom_toBottomOf="parent"
  app:menu="@menu/navigation" />

there are different versions of this style that can be found here this works but you will still need to do something for the icons and text so i have a switch statement and based on the color, (dark or light) i switch the color state list like this

ColorStateList colorStateList = getBottomNavColor(theme, getActivity());
navigationView.setItemIconTintList(colorStateList);
navigationView.setItemTextColor(colorStateList);

getBottomNavController

private ColorStateList getBottomNavColor(String theme, Context context){
        switch (theme) {
          case Constants.THEME_BLUE:
            return ContextCompat.getColorStateList(context,R.drawable.bottom_nav_selector_blue);
          case Constants.THEME_YELLOW:
            return ContextCompat.getColorStateList(context,R.drawable.bottom_nav_selector_yellow);
          case Constants.THEME_GREEN:
            return ContextCompat.getColorStateList(context,R.drawable.bottom_nav_selector_green);
          case Constants.THEME_RED:
            return ContextCompat.getColorStateList(context,R.drawable.bottom_nav_selector_red);
          case Constants.THEME_PURPLE:
            return ContextCompat.getColorStateList(context,R.drawable.bottom_nav_selector_purple);
          case Constants.THEME_PINK:
            return ContextCompat.getColorStateList(context,R.drawable.bottom_nav_selector_pink);

        }
        return ContextCompat.getColorStateList(context,R.drawable.bottom_nav_selector_blue);
      }

again not what you or I were looking for but does work and could be worse, hope it helps


问:
Separate Tr from responsive table
I have a table that I am creating with CSS Grid for responsive layout. But on small screensizes the column-headers overlap even if you are using overflow-x: auto;

How could I get it to not turn on?

Code:

```<code><div class="table container">

    <table>
        <thead>
            <tr>
            <th>Month</th>
            <th>Savings</th>
            <th>Savings</th>
            <th>Savings</th>
            <th>Savings</th>
            </tr>
        </thead>
        <tbody style="overflow-x:auto;">
            <tr>
            <td>January</td>
            <td>$100</td>
            <td>$100</td>
            <td>$100</td>
            <td>$100</td>
            </tr>
        </tbody>
    </table>
</div>
</code>```

CSS:

```<code>  table {
    margin: 2rem 0 2rem 0;
    border-collapse: collapse;
    border-spacing: 0;
    width: fit-content;
    overflow-x: auto;
    display:grid;
    grid-template-columns: 100px 1fr;

        thead {

            tr {
              display:grid;
              grid-gap: 1rem;
              grid-auto-flow: column;
              grid-template-rows: repeat(5, .5fr);
              justify-content: center;
              align-items: center;
              text-align: center;
              font-size: .9rem;
            }
        }

        tbody {
          display:grid;
          grid-template-columns: repeat(auto-fit, minmax(10px, 1fr));

          tr {
            display:grid;
            grid-auto-flow: column;
            grid-template-rows: repeat(5, 1fr);
            justify-content: center;
            align-items: center;
            text-align: center;
            font-size: .9rem;
          }
        }
      }
</code>```

Here is an image of what happens:

Image.

答:
A CSS-grid already displays like a HTML table.

Simplifying the design by using a single grid instead of two grids nested inside a parent grid removes the problematic behaviour:

Code:

```<code><div class="grid-table">
  <div>Month</div>
  <div>Savings</div>
  <div>Savings</div>
  <div>Savings</div>
  <div>Savings</div>
  <div>January</div>
  <div>$100</div>
  <div>$100</div>
  <div>$100</div>
  <div>$100</div>
</div>
</code>```

CSS:

```<code>.grid-table {
  margin: 2rem 0 2rem 0;
  border-collapse: collapse;
  border-spacing: 0;
  width: fit-content;
  overflow-x: auto;
  display:grid;
  grid-template-columns: 100px 1fr;
  grid-gap: 1rem;
  grid-auto-flow: column;
  grid-template-rows: repeat(5, .5fr);
  justify-content: center;
  align-items: center;
  text-align: center;
  font-size: .9rem;
}
</code>```

Title: Separate Tr from responsive table

Body:
I have a table that I am creating with CSS Grid for responsive layout. But on small screensizes the column-headers overlap even if you are using overflow-x: auto;

How could I get it to not turn on?

Code:

            Month
            Savings
            Savings
            Savings
            Savings

            January
            $100
            $100
            $100
            $100

CSS:

  table {
    margin: 2rem 0 2rem 0;
    border-collapse: collapse;
    border-spacing: 0;
    width: fit-content;
    overflow-x: auto;
    display:grid;
    grid-template-columns: 100px 1fr;

        thead {

            tr {
              display:grid;
              grid-gap: 1rem;
              grid-auto-flow: column;
              grid-template-rows: repeat(5, .5fr);
              justify-content: center;
              align-items: center;
              text-align: center;
              font-size: .9rem;
            }
        }

        tbody {
          display:grid;
          grid-template-columns: repeat(auto-fit, minmax(10px, 1fr));

          tr {
            display:grid;
            grid-auto-flow: column;
            grid-template-rows: repeat(5, 1fr);
            justify-content: center;
            align-items: center;
            text-align: center;
            font-size: .9rem;
          }
        }
      }

Here is an image of what happens:

Image.

Body:
A CSS-grid already displays like a HTML table.

Simplifying the design by using a single grid instead of two grids nested inside a parent grid removes the problematic behaviour:

Code:

<div class="grid-table">
  <div>Month</div>
  <div>Savings</div>
  <div>Savings</div>
  <div>Savings</div>
  <div>Savings</div>
  <div>January</div>
  <div>$100</div>
  <div>$100</div>
  <div>$100</div>
  <div>$100</div>
</div>

CSS:

.grid-table {
  margin: 2rem 0 2rem 0;
  border-collapse: collapse;
  border-spacing: 0;
  width: fit-content;
  overflow-x: auto;
  display:grid;
  grid-template-columns: 100px 1fr;
  grid-gap: 1rem;
  grid-auto-flow: column;
  grid-template-rows: repeat(5, .5fr);
  justify-content: center;
  align-items: center;
  text-align: center;
  font-size: .9rem;
}


问:
Least repeating chararcter in a string
I'm trying to find the least repeating character in a string ,it works for some input but it fails for some input.

```<code>Map<Character, Integer> map = new HashMap<Character, Integer> ();

    String s = "abcdabcdabcdacd";
    char[] chars = s.toCharArray();

    for (Character ch: chars) {
        if (map.containsKey(ch)) {
            map.put(ch, map.get(ch) + 1);
        } else {
            map.put(ch, 1);
        }
    }

    Set<Character> keys = map.keySet();

    for (Character ch: keys) {
        if (map.get(ch) ==1) {
            System.out.println(ch + " ");
        }
    }
</code>```

I expect the output to be b but it doesn't show anything.
If i give aabaa as the input then it shows b and that's correct.

答:
As I commented already, you only check for characters which only occur once, not for the least occurrence.

You can change your code by this:

```<code>public class PrintB {

    public static void main(String[] args) {
        Map<Character, Integer> map = new HashMap<>();

        String s = "abcdabcdabcdacd";
        char[] chars = s.toCharArray();

        for (Character ch: chars) {
            if (map.containsKey(ch)) {
                map.put(ch, map.get(ch) + 1);
            } else {
                map.put(ch, 1);
            }
        }

        Set<Character> keys = map.keySet();
        boolean broken = false;
        for ( int i = 0; i < s.length(); i++ ) { // the max will be s.length()

            for (Character ch : keys) {
                if (map.get(ch) == i) { // this amount is checked for each char
                    System.out.println(ch + " ");
                    broken = true;
                }
            }
            if ( broken ) {
                i = s.length(); // sure, there are other ways to break out of the loop
            }
        }
    }
}
</code>```

Title: Least repeating chararcter in a string

Body:
I'm trying to find the least repeating character in a string ,it works for some input but it fails for some input.

Map<Character, Integer> map = new HashMap<Character, Integer> ();

    String s = "abcdabcdabcdacd";
    char[] chars = s.toCharArray();

    for (Character ch: chars) {
        if (map.containsKey(ch)) {
            map.put(ch, map.get(ch) + 1);
        } else {
            map.put(ch, 1);
        }
    }

    Set<Character> keys = map.keySet();

    for (Character ch: keys) {
        if (map.get(ch) ==1) {
            System.out.println(ch + " ");
        }
    }

I expect the output to be b but it doesn't show anything.
If i give aabaa as the input then it shows b and that's correct.

Body:
As I commented already, you only check for characters which only occur once, not for the least occurrence.

You can change your code by this:

public class PrintB {

    public static void main(String[] args) {
        Map<Character, Integer> map = new HashMap<>();

        String s = "abcdabcdabcdacd";
        char[] chars = s.toCharArray();

        for (Character ch: chars) {
            if (map.containsKey(ch)) {
                map.put(ch, map.get(ch) + 1);
            } else {
                map.put(ch, 1);
            }
        }

        Set<Character> keys = map.keySet();
        boolean broken = false;
        for ( int i = 0; i < s.length(); i++ ) { // the max will be s.length()

            for (Character ch : keys) {
                if (map.get(ch) == i) { // this amount is checked for each char
                    System.out.println(ch + " ");
                    broken = true;
                }
            }
            if ( broken ) {
                i = s.length(); // sure, there are other ways to break out of the loop
            }
        }
    }
}


问:
Is there a ways for cinemachine to retarget player after it is destroyed and instantiated as a clone?
I am working on a 2D platformer and I am using cinemachine to follow my player.

When a player drops off a platform under -20 y, the player is destroyed and instantiated as a clone to the spawn point as expected, but the camera is not following, as the original player is destroyed: it says missing on the "Follow" Slot.

Is there any way to solve it? I prefer using Destroy and Instantiate as respawning instead of teleporting the original player to the respawn point.

This is the respawn script (GameMaster)

public class GameMaster : MonoBehaviour
{

    public static GameMaster gm;

    void Start()
    {
        if (gm == null)
        {
            gm = GameObject.FindGameObjectWithTag("GM").GetComponent<GameMaster>();
        }
    }
    public Transform playerPrefab, spawnPoint;
    public int spawnDelay = 2;

    public void RespawnPlayer() {
        //yield return new WaitForSeconds(spawnDelay);

        Instantiate(playerPrefab, spawnPoint.position, spawnPoint.rotation);
        Debug.Log("ADD SPAWN PARITCAL");
    }

    public static void Killplayer(Player player) {
        Destroy(player.gameObject);
        gm.RespawnPlayer();
    }
}
```

<p>here is the player script if it is needed</p>

```public class Player : MonoBehaviour
{
    [System.Serializable]
    public class PlayerStats
    {
        public int Health = 100;

    }
    public PlayerStats playerStats = new PlayerStats();
    public int FallBoundary = -20;
    void FixedUpdate()
    {
        if (transform.position.y <= FallBoundary)
        {
            DamagePlayer(1000);
        }
    }

    public void DamagePlayer(int damage) {
        playerStats.Health -= damage;
        if (playerStats.Health<=0)
        {
            Debug.Log("Kill Player");
            GameMaster.Killplayer(this);
        }
    }
}
```

答:
You can cache the cinemachine inside your start method and then assign to follow the player at respawn.

Your code will become

using Cinemachine;

public class GameMaster : MonoBehaviour
{
    public static GameMaster gm;
    public CinemachineVirtualCamera myCinemachine;

    void Start()
    {
        if (gm == null)
        {
            gm = GameObject.FindGameObjectWithTag("GM").GetComponent<GameMaster>();
        }

        myCinemachine = GetComponent<CinemachineVirtualCamera>();
    }
    public Transform playerPrefab, spawnPoint;
    public int spawnDelay = 2;

    public void RespawnPlayer() {
        //yield return new WaitForSeconds(spawnDelay);

        var newPlayer = Instantiate(playerPrefab, spawnPoint.position, spawnPoint.rotation);
        Debug.Log("ADD SPAWN PARITCAL");

        myCinemachine.m_Follow = newPlayer;
    }

    public static void Killplayer(Player player) {
        Destroy(player.gameObject);
        gm.RespawnPlayer();
    }
}
```

Body:
I am working on a 2D platformer and I am using cinemachine to follow my player.

When a player drops off a platform under -20 y, the player is destroyed and instantiated as a clone to the spawn point as expected, but the camera is not following, as the original player is destroyed: it says missing on the "Follow" Slot.

Is there any way to solve it? I prefer using Destroy and Instantiate as respawning instead of teleporting the original player to the respawn point.

This is the respawn script (GameMaster)

public class GameMaster : MonoBehaviour
{

    public static GameMaster gm;

    void Start()
    {
        if (gm == null)
        {
            gm = GameObject.FindGameObjectWithTag("GM").GetComponent<GameMaster>();
        }
    }
    public Transform playerPrefab, spawnPoint;
    public int spawnDelay = 2;

    public void RespawnPlayer() {
        //yield return new WaitForSeconds(spawnDelay);

        Instantiate(playerPrefab, spawnPoint.position, spawnPoint.rotation);
        Debug.Log("ADD SPAWN PARITCAL");
    }

    public static void Killplayer(Player player) {
        Destroy(player.gameObject);
        gm.RespawnPlayer();
    }
}

here is the player script if it is needed

public class Player : MonoBehaviour
{
    [System.Serializable]
    public class PlayerStats
    {
        public int Health = 100;

    }
    public PlayerStats playerStats = new PlayerStats();
    public int FallBoundary = -20;
    void FixedUpdate()
    {
        if (transform.position.y <= FallBoundary)
        {
            DamagePlayer(1000);
        }
    }

    public void DamagePlayer(int damage) {
        playerStats.Health -= damage;
        if (playerStats.Health<=0)
        {
            Debug.Log("Kill Player");
            GameMaster.Killplayer(this);
        }
    }
}


问:
Index or size is negative or greater than the allowed amount" code: "1 [Break On This Error] return selector.options[selector.selectedIndex].value;
Index or size is negative or greater than the allowed amount" code: "1 [Break On This Error] return selector.options[selector.selectedIndex].value;
Line 38
I keep getting the error and not sure why. here is the js code

http://pastebin.com/H66NTvrU

And here is my template code

```<code>        <form id="selector">
            <select id="book" onchange="initChapSelector();"></select>
            <select id="chap" onchange="initPageSelector();"></select>
            <select id="page" onchange="initDisplay();"></select>
            <select id="scale" onchange="setScale(this.options[this.selectedIndex].value);">
                <option value="">Original Width</option>
                <option value="100%">Page Width</option>
                <option value="50%">Half Page</option>
            </select>
            <a href="javascript:void(0)" onclick="alert('Arrow up/down: scroll\nArrow left/right: prev/next page'); return false;">Help</a>
        </form>
</code>```

Am very new to coding so please forgive me if any of the above is wrong
It would be nice if someone could help me out on this as I seem to have been sitting here ages trying to work this out, Am sure some one will spot the mistake in a few seconds lol...

Thanks alot

答:
I copied your code into jsfiddle, here: http://jsfiddle.net/dMcyg/

I get an error right away when changing the pick list value "setScale is not defined." I can see it is, but there are many syntax problems in the script, so I am guessing there's a parsing issue serious enough that it never gets that far.

You have functions defined inside inner braces, which is illegal. There are lots of missing semicolons (though most browsers other than IE will let these pass).

Go through it with jsLint and fix all the syntax problems first, then see where you are.

Oh - jsLint complains that "interface is a reserved word" for your variable interface. I have never heard of an "interface" keyword in Javascript before, so I am not sure what this is all about, but I changed it so jsLint would continue parsing.

Body:
Index or size is negative or greater than the allowed amount" code: "1 [Break On This Error] return selector.options[selector.selectedIndex].value;
Line 38
I keep getting the error and not sure why. here is the js code

http://pastebin.com/H66NTvrU

And here is my template code

        <form id="selector">
            <select id="book" onchange="initChapSelector();"></select>
            <select id="chap" onchange="initPageSelector();"></select>
            <select id="page" onchange="initDisplay();"></select>
            <select id="scale" onchange="setScale(this.options[this.selectedIndex].value);">
                <option value="">Original Width</option>
                <option value="100%">Page Width</option>
                <option value="50%">Half Page</option>
            </select>
            Help
        </form>

Am very new to coding so please forgive me if any of the above is wrong
It would be nice if someone could help me out on this as I seem to have been sitting here ages trying to work this out, Am sure some one will spot the mistake in a few seconds lol...

Thanks alot


问:
In Android, how do I set margins in dp programmatically?
In this, this and this thread I tried to find an answer on how to set the margins on a single view. However, I was wondering if there isn't an easier way. I'll explain why I rather wouldn't want to use this approach:

I have a custom Button which extends Button. If the background is set to something else than the default background (by calling either setBackgroundResource(int id) or setBackgroundDrawable(Drawable d)), I want the margins to be 0. If I call this:

```<code>public void setBackgroundToDefault() {
    backgroundIsDefault = true;
    super.setBackgroundResource(android.R.drawable.btn_default);
    // Set margins somehow
}
</code>```

I want the margins to reset to -3dp (I already read here how to convert from pixels to dp, so once I know how to set margins in px, I can manage the conversion myself). But since this is called in the CustomButton class, the parent can vary from LinearLayout to TableLayout, and I'd rather not have him get his parent and check the instanceof that parent. That'll also be quite inperformant, I imagine.

Also, when calling (using LayoutParams) parentLayout.addView(myCustomButton, newParams), I don't know if this adds it to the correct position (haven't tried however), say the middle button of a row of five.

Question: Is there any easier way to set the margin of a single Button programmatically besides using LayoutParams?

EDIT: I know of the LayoutParams way, but I'd like a solution that avoids handling each different container type:

```<code>ViewGroup.LayoutParams p = this.getLayoutParams();
    if (p instanceof LinearLayout.LayoutParams) {
        LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)p;
        if (_default) lp.setMargins(mc.oml, mc.omt, mc.omr, mc.omb);
        else lp.setMargins(mc.ml, mc.mt, mc.mr, mc.mb);
        this.setLayoutParams(lp);
    }
    else if (p instanceof RelativeLayout.LayoutParams) {
        RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams)p;
        if (_default) lp.setMargins(mc.oml, mc.omt, mc.omr, mc.omb);
        else lp.setMargins(mc.ml, mc.mt, mc.mr, mc.mb);
        this.setLayoutParams(lp);
    }
    else if (p instanceof TableRow.LayoutParams) {
        TableRow.LayoutParams lp = (TableRow.LayoutParams)p;
        if (_default) lp.setMargins(mc.oml, mc.omt, mc.omr, mc.omb);
        else lp.setMargins(mc.ml, mc.mt, mc.mr, mc.mb);
        this.setLayoutParams(lp);
    }
}
</code>```

Because this.getLayoutParams();returns a ViewGroup.LayoutParams, which do not have the attributes topMargin, bottomMargin, leftMargin, rightMargin.
The mc instance you see is just a MarginContainer which contains offset (-3dp) margins and (oml, omr, omt, omb) and the original margins (ml, mr, mt, mb).

答:
You can use this method and put static dimen like 20 it converts according your device

```<code> public static int dpToPx(int dp)
      {
          float scale = context.getResources().getDisplayMetrics().density;
       return (int) (dp * scale + 0.5f);
  }
</code>```

Body:
In this, this and this thread I tried to find an answer on how to set the margins on a single view. However, I was wondering if there isn't an easier way. I'll explain why I rather wouldn't want to use this approach:

I have a custom Button which extends Button. If the background is set to something else than the default background (by calling either setBackgroundResource(int id) or setBackgroundDrawable(Drawable d)), I want the margins to be 0. If I call this:

public void setBackgroundToDefault() {
    backgroundIsDefault = true;
    super.setBackgroundResource(android.R.drawable.btn_default);
    // Set margins somehow
}

I want the margins to reset to -3dp (I already read here how to convert from pixels to dp, so once I know how to set margins in px, I can manage the conversion myself). But since this is called in the CustomButton class, the parent can vary from LinearLayout to TableLayout, and I'd rather not have him get his parent and check the instanceof that parent. That'll also be quite inperformant, I imagine.

Also, when calling (using LayoutParams) parentLayout.addView(myCustomButton, newParams), I don't know if this adds it to the correct position (haven't tried however), say the middle button of a row of five.

Question: Is there any easier way to set the margin of a single Button programmatically besides using LayoutParams?

EDIT: I know of the LayoutParams way, but I'd like a solution that avoids handling each different container type:

ViewGroup.LayoutParams p = this.getLayoutParams();
    if (p instanceof LinearLayout.LayoutParams) {
        LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)p;
        if (_default) lp.setMargins(mc.oml, mc.omt, mc.omr, mc.omb);
        else lp.setMargins(mc.ml, mc.mt, mc.mr, mc.mb);
        this.setLayoutParams(lp);
    }
    else if (p instanceof RelativeLayout.LayoutParams) {
        RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams)p;
        if (_default) lp.setMargins(mc.oml, mc.omt, mc.omr, mc.omb);
        else lp.setMargins(mc.ml, mc.mt, mc.mr, mc.mb);
        this.setLayoutParams(lp);
    }
    else if (p instanceof TableRow.LayoutParams) {
        TableRow.LayoutParams lp = (TableRow.LayoutParams)p;
        if (_default) lp.setMargins(mc.oml, mc.omt, mc.omr, mc.omb);
        else lp.setMargins(mc.ml, mc.mt, mc.mr, mc.mb);
        this.setLayoutParams(lp);
    }
}

Because this.getLayoutParams();returns a ViewGroup.LayoutParams, which do not have the attributes topMargin, bottomMargin, leftMargin, rightMargin.
The mc instance you see is just a MarginContainer which contains offset (-3dp) margins and (oml, omr, omt, omb) and the original margins (ml, mr, mt, mb).

Body:
You can use this method and put static dimen like 20 it converts according your device

 public static int dpToPx(int dp)
      {
          float scale = context.getResources().getDisplayMetrics().density;
       return (int) (dp * scale + 0.5f);
  }


问:
How to convert HTML

 to MS document Heading3 in Docx4j?
I've been generating word document from HTML content.

using below code.

```<code>ordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.createPackage(PageSizePaper.LETTER, false);

XHTMLImporterImpl XHTMLImporter = new XHTMLImporterImpl(wordMLPackage);
XHTMLImporter.setRunFormatting(FormattingOption.CLASS_PLUS_OTHER);
NumberingDefinitionsPart ndp = new NumberingDefinitionsPart();

wordMLPackage.getMainDocumentPart().addTargetPart(ndp);
ndp.unmarshalDefaultNumbering();

wordMLPackage.getMainDocumentPart().getContent().addAll(XHTMLImporter.convert("<h3> SAMPLE HEADING</h3>", null));

File exportFile = new File(somepath/sample.docx);
wordMLPackage.save(exportFile);
</code>```

Above code works fine and generate the Document, but the HTML
 SAMPLE HEADING
 doesn't converted to MS word Heading 3 it shows as Normal text in document.

Later I'll generate Table of Content TOC using those headings using below code.

```<code>tocGenerator.generateToc( 1,    "TOC \\o \"1-3\" \\h \\z \\u ", false);
</code>```

However some how this code doesn't support normal text to generate TOC.

答:
We need to change the Heading setting by using below code.

```<code>ImportXHTMLProperties.setProperty("docx4j-ImportXHTML.Element.Heading.MapToStyle", true);
</code>```

Here the updated code which is working for the requirement.

```<code>//  activating Headings property for MS Word Heading Mapping
ImportXHTMLProperties.setProperty("docx4j-ImportXHTML.Element.Heading.MapToStyle", true);
ordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.createPackage(PageSizePaper.LETTER, false);

XHTMLImporterImpl XHTMLImporter = new XHTMLImporterImpl(wordMLPackage);
XHTMLImporter.setRunFormatting(FormattingOption.CLASS_PLUS_OTHER);
NumberingDefinitionsPart ndp = new NumberingDefinitionsPart();

wordMLPackage.getMainDocumentPart().addTargetPart(ndp);
ndp.unmarshalDefaultNumbering();

wordMLPackage.getMainDocumentPart().getContent().addAll(XHTMLImporter.convert("<h3> SAMPLE HEADING</h3>", null));

File exportFile = new File(somepath/sample.docx);
// adding TOC - TABLE OF CONTENTS
TocGenerator tocGenerator = new TocGenerator(wordMLPackage);
tocGenerator.generateToc(0, "TOC \\o \"1-3\" \\h \\z \\u ", false);

wordMLPackage.save(exportFile);
</code>```

Title: How to convert HTML <h3> </h3> to MS document Heading3 in Docx4j?

Body:
I've been generating word document from HTML content.

using below code.

ordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.createPackage(PageSizePaper.LETTER, false);

XHTMLImporterImpl XHTMLImporter = new XHTMLImporterImpl(wordMLPackage);
XHTMLImporter.setRunFormatting(FormattingOption.CLASS_PLUS_OTHER);
NumberingDefinitionsPart ndp = new NumberingDefinitionsPart();

wordMLPackage.getMainDocumentPart().addTargetPart(ndp);
ndp.unmarshalDefaultNumbering();

wordMLPackage.getMainDocumentPart().getContent().addAll(XHTMLImporter.convert("
 SAMPLE HEADING
", null));

File exportFile = new File(somepath/sample.docx);
wordMLPackage.save(exportFile);

Above code works fine and generate the Document, but the HTML
 SAMPLE HEADING
 doesn't converted to MS word Heading 3 it shows as Normal text in document.

Later I'll generate Table of Content TOC using those headings using below code.

tocGenerator.generateToc( 1,    "TOC \\o \"1-3\" \\h \\z \\u ", false);

However some how this code doesn't support normal text to generate TOC.

Body:
We need to change the Heading setting by using below code.

ImportXHTMLProperties.setProperty("docx4j-ImportXHTML.Element.Heading.MapToStyle", true);

Here the updated code which is working for the requirement.

//  activating Headings property for MS Word Heading Mapping
ImportXHTMLProperties.setProperty("docx4j-ImportXHTML.Element.Heading.MapToStyle", true);
ordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.createPackage(PageSizePaper.LETTER, false);

XHTMLImporterImpl XHTMLImporter = new XHTMLImporterImpl(wordMLPackage);
XHTMLImporter.setRunFormatting(FormattingOption.CLASS_PLUS_OTHER);
NumberingDefinitionsPart ndp = new NumberingDefinitionsPart();

wordMLPackage.getMainDocumentPart().addTargetPart(ndp);
ndp.unmarshalDefaultNumbering();

wordMLPackage.getMainDocumentPart().getContent().addAll(XHTMLImporter.convert("<h3> SAMPLE HEADING</h3>", null));

File exportFile = new File(somepath/sample.docx);
// adding TOC - TABLE OF CONTENTS
TocGenerator tocGenerator = new TocGenerator(wordMLPackage);
tocGenerator.generateToc(0, "TOC \\o \"1-3\" \\h \\z \\u ", false);

wordMLPackage.save(exportFile);