Giter VIP home page Giter VIP logo

Comments (9)

zengjingfang avatar zengjingfang commented on June 20, 2024 1

3、广播如何被恶意丢弃和Intent拦截,向广播结果塞入恶意数据

image

根据提供的参考链接,找到原文:

Furthermore, if the broadcast is an ordered broadcast then a malicious app could register itself with a high priority so as to receive the broadcast first. Then, it could either cancel the broadcast preventing it from being propagated further, thereby causing a denial of service, or it could inject a malicious data result into the broadcast that is ultimately returned to the sender.

  • 造成服务不可用的方式是,一个恶意软件以高优先级的接收者接收广播然后取消掉广播

避免的方式有三种

  • 方式一:setComponent、setClas

Therefore, receivers of broadcast intents should be restricted. One way to restrict receivers is to use an explicit intent. An explicit intent can specify a component (using setComponent(ComponentName)) or a class (using setClass(Context, Class)) so that only the specified component or class can resolve the intent.

  • 方式二:Intent.setPackage()

It is also possible to restrict the receivers of intents by using permissions, as described below. Alternatively, starting with the Android version ICE_CREAM_SANDWICH (Android API version 4.0), you can also safely restrict the broadcast to a single application by using Intent.setPackage().

  • 方式三:use the LocalBroadcastManager class

Yet another approach is to use the LocalBroadcastManager class. Using this class, the intent broadcast never goes outside of the current process. According to the Android API Reference, LocalBroadcastManager has a number of advantages over Context.sendBroadcast(Intent):

  • You know that the data you are broadcasting won't leave your app, so don't need to worry about leaking private data.
  • It is not possible for other applications to send these broadcasts to your app, so you don't need to worry about having security holes they can exploit.
  • It is more efficient than sending a global broadcast through the system.

from androidbox.

zengjingfang avatar zengjingfang commented on June 20, 2024

1、Activity#onSaveInstanceState() 什么时候调用

image

通过源码追踪:

  • Instrumentation#callActivityOnSaveInstanceState
    public void callActivityOnSaveInstanceState(Activity activity, Bundle outState,
            PersistableBundle outPersistentState) {
       // 此处回调给到我们自己的activity
        activity.performSaveInstanceState(outState, outPersistentState);
    }
  • ActivityThread#callCallActivityOnSaveInstanceState(ActivityClientRecord r)
    private void callCallActivityOnSaveInstanceState(ActivityClientRecord r) {
        r.state = new Bundle();
        r.state.setAllowFds(false);
        if (r.isPersistable()) {
            r.persistentState = new PersistableBundle();
            mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state,
                    r.persistentState);
        } else {
            mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state);
        }
    }

查到源头,真正触发的有三处:

  • ActivityThread#performPauseActivity(ActivityClientRecord r, boolean finished,
    boolean saveState)
final Bundle performPauseActivity(ActivityClientRecord r, boolean finished,
            boolean saveState) {     
        try {
            // Next have the activity save its current state and managed dialogs...
            if (!r.activity.mFinished && saveState) {
              // 此处回调了OnSaveInstanceState
                callCallActivityOnSaveInstanceState(r);
            }
            // Now we are idle.
            r.activity.mCalled = false;
           // 这里回调了生命周期中的 OnPause
            mInstrumentation.callActivityOnPause(r.activity);        
            }
        } catch (SuperNotCalledException e) {
            throw e;
        } catch (Exception e) {
          
            }
        }
        r.paused = true;

        return !r.activity.mFinished && saveState ? r.state : null;
    }
  • ActivityThread#performStopActivityInner(ActivityClientRecord r,
    StopInfo info, boolean keepShown, boolean saveState)
private void performStopActivityInner(ActivityClientRecord r,
            StopInfo info, boolean keepShown, boolean saveState) {
            // 省略代码
            // Next have the activity save its current state and managed dialogs...
            if (!r.activity.mFinished && saveState) {
                if (r.state == null) {
                    // 此处回调了OnSaveInstanceState
                    callCallActivityOnSaveInstanceState(r);
                }
            }
            if (!keepShown) {
                try {
                    // Now we are idle. 回调生命周期中的onStop
                    r.activity.performStop();
                } catch (Exception e) {
          
                }
                r.stopped = true;
            }
            r.paused = true;
        }
    }
  • ActivityThread#handleRelaunchActivity(ActivityClientRecord tmp)
 private void handleRelaunchActivity(ActivityClientRecord tmp) {
        // If we are getting ready to gc after going to the background, well
       // 省略代码
        // If there was a pending configuration change, execute it first.
        if (changedConfig != null) {
            mCurDefaultDisplayDpi = changedConfig.densityDpi;
            updateDefaultDensity();
            handleConfigurationChanged(changedConfig, null);
        }

        ActivityClientRecord r = mActivities.get(tmp.token);
        // Need to ensure state is saved.
        if (!r.paused) {
            performPauseActivity(r.token, false, r.isPreHoneycomb());
        }
        if (r.state == null && !r.stopped && !r.isPreHoneycomb()) {
            // 此处回调了OnSaveInstanceState
            callCallActivityOnSaveInstanceState(r);
        }

        handleDestroyActivity(r.token, false, configChanges, true);

        r.activity = null;
        r.window = null;
        r.hideForNow = false;
        r.nextIdle = null;
       
        handleLaunchActivity(r, currentIntent);
    }

由源码可知,Activity#onSaveInstanceState()在三种情况下会被回调

  • ActivityThread#performPauseActivity
  • ActivityThread#performStopActivityInner
    • handleStopActivity
    • handleWindowVisibility
    • performStopActivity
  • ActivityThread#handleRelaunchActivity

在上述情况中,如果满足条件则回调callCallActivityOnSaveInstanceState

实际使用场景会被回调的情况如下

  • 用户按下HOME按键
  • 按下菜单键或者长按Home键准备切换到其他应用APP的时候
  • 按下电源键关闭屏幕的时候
  • 启动一个新的activity的时候
  • 屏幕切换方向的时候

总之,就是你的操作并不确定要销毁当前的activity,但是由于系统的机制比如回收掉当前的activity,当再次恢复时就可能存在无法正常恢复的风险。通过在OnSaveInstanceState回调中保存临时数据,这样呢在恢复时会走onCreate(Bundle savedInstanceState),把临时保存的数据拿出来。如果你是非常确定要退出当前的activity,比如按下back键,那就不会回调OnSaveInstanceState。

还需要知道的是,系统默认实现了部分activity中的某些状态数据,比如UI控件的状态,比如EditText控件会自动保存和恢复输入的数据,前提是有为这个控件制定唯一的id,即android:id;

参考链接:

from androidbox.

zengjingfang avatar zengjingfang commented on June 20, 2024

2、如果有耗时操作,为什么不应该在BroadcastReceiver内创建子线程去做

image

原因是:BroadcastReceiver正常结束后,进程会被系统优先杀死,无法保证安全的执行完子线程的任务

BroadcastReceiver的onReceive()方法执行完成后,BroadcastReceiver的实例就会被销毁。如果onReceive()方法在10s内没有执行完毕,Android会认为改程序无响应。所以在BroadcastReceiver里不能做一些比较耗时的操作,否则会弹出“Application NoResponse”对话框。

这里不能使用子线程来解决 ,因为BroadcastReceiver的生命周期很短,子线程可能还没有结束BroadcastReceiver就先结束了。BroadcastReceiver一旦结束,此时它所在的进程很容易在系统需要内存时被优先杀死,因为它属于空进程。 【内容来自Broadcast Receiver开启服务而不是子线程处理耗时操作

from androidbox.

zengjingfang avatar zengjingfang commented on June 20, 2024

4、全局的Toast为什么可以避免连续弹出不能取消上次的

image

from androidbox.

zengjingfang avatar zengjingfang commented on June 20, 2024

5、ViewHolder做缓存getView方法内的子控件要显性的设置相关属性

image

from androidbox.

zengjingfang avatar zengjingfang commented on June 20, 2024

6、文本单位使用dp?

image

from androidbox.

zengjingfang avatar zengjingfang commented on June 20, 2024

7、SharedPreferences多进程共享存在什么问题?

image

from androidbox.

zengjingfang avatar zengjingfang commented on June 20, 2024

8、SharedPreference 提交时为何要尽量使用apply,而不是commt?

image

from androidbox.

zengjingfang avatar zengjingfang commented on June 20, 2024

9、操作数据库时,为什么使用事务机制可以保证线程安全,并且效率要高?

image
image

from androidbox.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.