在屏幕上顯示日誌的Android類庫

Galgo是Android日誌類庫,用於在屏幕上顯示應用的日誌信息。這對於測試人員和開發人員很是有用,能夠根據屏幕上的日誌文件瞭解應用出現BUG時發生的事情。 java

 

能夠定義屏幕上顯示日誌的背景顏色、文本顏色、文本大小和日誌顯示的行數。 android

https://github.com/inaka/galgo
git


public class ExampleActivity extends Activity {

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

        // add some customization to the log messages
        GalgoOptions options = new GalgoOptions.Builder()
                .numberOfLines(15)
                .backgroundColor(Color.parseColor("#D9d6d6d6"))
                .textColor(Color.BLACK)
                .textSize(15)
                .build();
        Galgo.enable(this, options);

        Galgo.log("I am a log message");
    }

    public void onDestroy() {
        super.onDestroy();

        // always call disable to avoid memory leaks
        Galgo.disable(this);
    }
}




其實就是一個Service上面顯示了一個window Menifest中須要有權限
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.inaka.galgo">

    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

    <application android:allowBackup="true" android:label="@string/app_name">

        <service android:name=".GalgoService" />

    </application>

</manifest>


改造了一下代碼,  github

1.把Service作成一個全局的, 而不是bind到惟一的Activity , 這纔是全局的Log express

2.把GalgoOptions 放到了Galgo.java中 apache

/*
 * Copyright (C) 2014 Inaka.
 *
 * 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.
 *
 * @author Henrique Boregio (henrique@inakanetworks.com)
 */
package com.kookong.tv.debug;

import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;

import com.hzy.tvmao.TmApp;

public class Galgo
{
    
    private static final Handler UI_HANDLER = new Handler(Looper.getMainLooper())
    {
        @Override
        public void handleMessage(Message msg) {
            if (!isServiceRunning) {//service 中止了就不要往service發消息了
                return;
            }
            String message = (String) msg.obj;
            Intent intent = new Intent(TmApp.getContext(), GalgoService.class);
            intent.putExtra(MESSAGE, message);
            TmApp.getContext().startService(intent);
        }
    };
    public static final String MESSAGE = "galgo.message";
    public static final String ARG_OPTIONS = "galgo.options";
    private static final String TAG = "Galgo";
    private static GalgoOptions sOptions;
    private static Context sContext;
    private static boolean isServiceRunning;
    
    /**
     * * Starts a new Galgo with custom {@link com.inaka.galgo.GalgoOptions}
     * 
     * @param context
     *            Context
     * @param options
     *            Custom {@link com.inaka.galgo.GalgoOptions}
     */
    public static void enable(GalgoOptions options) {
        sOptions = options;
        init();
    }
    
    /**
     * Starts a new Galgo with default {@link com.inaka.galgo.GalgoOptions}
     * 
     * @param context
     *            Context
     */
    public static void enable() {
        enable(new GalgoOptions.Builder().build());
    }
    
    private static void init() {
        sContext = TmApp.getContext();
        checkPermission(sContext);
        // start a new service with our options
        Intent intent = new Intent(sContext, GalgoService.class);
        intent.putExtra(ARG_OPTIONS, sOptions);
        TmApp.getContext().startService(intent);
        isServiceRunning = true;
    }
    
    public static void disable() {
        Intent intent = new Intent(sContext, GalgoService.class);
        sContext.stopService(intent);
        sContext = null;
        isServiceRunning = false;
        
    }
    
    /**
     * Logs a String message to the screen. This String will be overlayed on top
     * of the UI elements currently displayed on screen. As a side effect, this
     * message will also be logged to the standard output via
     * {@link android.util.Log}.
     *
     * @param message
     *            String to be displayed
     */
    public static void log(String message) {
        Log.i(TAG, message);
        Message msg = UI_HANDLER.obtainMessage(0, message);
        msg.sendToTarget();
    }
    
    private static void checkPermission(Context context) {
        String permission = "android.permission.SYSTEM_ALERT_WINDOW";
        int status = context.checkCallingOrSelfPermission(permission);
        if (status == PackageManager.PERMISSION_DENIED) {
            throw new IllegalStateException("in order to use Galgo, " + "please add the permission " + permission + " to your AndroidManifest.xml");
        }
    }
    
    public static final class GalgoOptions implements Parcelable
    {
        
        public final int numberOfLines;
        public final int backgroundColor;
        public final int textColor;
        public final int textSize;
        
        /**
         * Contains options for Galgo. Defines
         * 
         * @param builder
         */
        private GalgoOptions(Builder builder) {
            numberOfLines = builder.numberOfLines;
            backgroundColor = builder.backgroundColor;
            textColor = builder.textColor;
            textSize = builder.textSize;
        }
        
        /**
         * Builder for {@link com.inaka.galgo.GalgoOptions}
         */
        public static class Builder
        {
            private int numberOfLines = 10;
            private int backgroundColor = 0xD993d2b9;
            private int textColor = 0xFFFFFFFF;
            private int textSize = 10;
            
            /**
             *
             * @param n
             *            number of lines
             * @return
             */
            public Builder numberOfLines(int n) {
                ensurePositiveInt(n, "number of lines must be > 0");
                numberOfLines = n;
                return this;
            }
            
            /**
             * Sets the background color of the log messages
             * 
             * @param color
             * @return
             */
            public Builder backgroundColor(int color) {
                backgroundColor = color;
                return this;
            }
            
            /**
             * Sets the text color of the log messages
             * 
             * @param color
             * @return
             */
            public Builder textColor(int color) {
                textColor = color;
                return this;
            }
            
            /**
             * Sets the text size of the messages
             * 
             * @param size
             * @return
             */
            public Builder textSize(int size) {
                ensurePositiveInt(size, "text size must be > 0");
                textSize = size;
                return this;
            }
            
            /**
             * Creates a {@link com.inaka.galgo.GalgoOptions} with the
             * customized parameters
             * 
             * @return
             */
            public GalgoOptions build() {
                return new GalgoOptions(this);
            }
        }
        
        private static void ensurePositiveInt(int value, String msg) {
            if (value <= 0) {
                throw new IllegalArgumentException(msg);
            }
        }
        
        // Parcelable implementation
        private GalgoOptions(Parcel source) {
            numberOfLines = source.readInt();
            backgroundColor = source.readInt();
            textColor = source.readInt();
            textSize = source.readInt();
        }
        
        public static final Creator<GalgoOptions> CREATOR = new Creator<GalgoOptions>()
        {
            @Override
            public GalgoOptions createFromParcel(Parcel source) {
                return new GalgoOptions(source);
            }
            
            @Override
            public GalgoOptions[] newArray(int size) {
                return new GalgoOptions[size];
            }
        };
        
        @Override
        public int describeContents() {
            return 0; // No special content.
        }
        
        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeInt(numberOfLines);
            dest.writeInt(backgroundColor);
            dest.writeInt(textColor);
            dest.writeInt(textSize);
        }
        
    }
}



/*
 * Copyright (C) 2014 Inaka.
 *
 * 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.
 *
 * @author Henrique Boregio (henrique@inakanetworks.com)
 */
package com.kookong.tv.debug;

import java.util.ArrayDeque;
import java.util.Collection;
import java.util.Queue;

import android.app.Service;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.os.Binder;
import android.os.IBinder;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.TextUtils;
import android.text.style.BackgroundColorSpan;
import android.view.Gravity;
import android.view.WindowManager;
import android.widget.TextView;

import com.hzy.tvmao.utils.LogUtil;
import com.hzy.tvmao.utils.SystemUtil;
import com.kookong.tv.debug.Galgo.GalgoOptions;

public class GalgoService extends Service
{
    
    private TextView mTextView;
    private GalgoOptions mOptions;
    private final Queue<String> mLines = new ArrayDeque<>();
    
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        LogUtil.d("onStartCommand");
        //首次建立有options
        GalgoOptions options = intent.getExtras().getParcelable(Galgo.ARG_OPTIONS);
        if (options != null) {
            mOptions = options;
        }
        //顯示log的時候有Message
        String message = intent.getExtras().getString(Galgo.MESSAGE);
        if (!TextUtils.isEmpty(message)) {
            displayText(message);
        }
        return super.onStartCommand(intent, flags, startId);
    }
    
    @Override
    public void onCreate() {
        super.onCreate();
        
        mTextView = new TextView(this);
        
        WindowManager.LayoutParams params = new WindowManager.LayoutParams(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSLUCENT);
        WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
        wm.addView(mTextView, params);
    }
    
    public void displayText(String text) {
        mLines.add(text);
        if (mLines.size() > mOptions.numberOfLines) {
            mLines.poll();
        }
        
        redraw(mLines);
    }
    
    private void redraw(Collection<String> texts) {
        mTextView.setTextSize(mOptions.textSize);
        mTextView.setTextColor(mOptions.textColor);
        mTextView.setPadding(SystemUtil.getScreenWH()[0] / 4, 0, 0, 0);
        Spannable spannable = new SpannableString(TextUtils.join("\n", texts));
        spannable.setSpan(new BackgroundColorSpan(mOptions.backgroundColor), 0, spannable.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        
        mTextView.setText(spannable);
    }
    
    @Override
    public void onDestroy() {
        super.onDestroy();
        if (mTextView != null) {
            WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
            wm.removeView(mTextView);
        }
    }
    
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}




另外一個開源項目, 顯示全部日誌 app

https://github.com/jgilfelt/GhostLog less

相關文章
相關標籤/搜索